Installing Arch Linux On EeePC 701 4G

I know, I know, a lot of you are asking, "Why on earth would you want to do anything with a machine that's 5 years old?!" The hardware is crap now, and it was crap when the EeePC came out. Well, my friends, that's one of the great things about Linux! It will put new life into old hardware. Granted, the EeePC 701 4G came with Linux on it and all that, but I'm talking about putting something modern on it. Regardless, this guide will hopefully be useful for others who are trying to get Linux installed using LVM that uses something like an SD card as part of the primary volume group.

I've had Arch Linux installed on my EeePC for quite a while, but I only recently began to appreciate the benefits of LVM. The key requirement for this installation was to use LVM partitioning instead of traditional partitioning. I wanted the built-in 4GB SSD and the 8GB SD card to appear as one hard drive to the operating system so I would have that much more space to actually use.

Another key requirement for this installation was that I wanted to do it using a PXE server instead of the usual USB/external CD drive method. I've used PXE servers in the past, but I never really did much with them. I wanted to use this as an excuse to learn a bit more about them.


If you're following along at home, I'm assuming that you have (access to) the following:

  • An EeePC 701 4G
  • An SD card that will be a permanent fixture in your EeePC
  • A router running DD-WRT that serves as the DHCP server for your network (I am running v24-sp2). Alternatively, just use a USB/CD to install.

PXE Setup

If you want to save some time and just use a USB/CD to install Arch, go ahead and skip to the Arch Installation section.

For those who are unfamiliar with PXE servers, PXE stands for "Preboot eXecution Environment." It allows you to boot your computer over the network using images stored on a different machine. Since I didn't want to plug in my USB key or external DVD drive, this was a perfect option.

I used my main laptop as the PXE server. All I really did was install atftp from the AUR, copy ipxe.pxe from the Arch Linux Netboot page (from the "Using an iPXE image" section), and put it in /var/tftpboot. After that, it was a matter of running atftpd:

rc.d start atftpd

The next step required tweaking the dnsmasq configuration on my router. Here's what I did:

  • Login to router

  • Go to the Services tab

  • Find the DNSMasq section (mine is already enabled for other purposes, so I assume you will want to make sure yours is enabled)

  • In the "Additional DNSMasq Options" box, make sure you have something like:

    dhcp-boot=ipxe.pxe,[your PXE server's name],[your PXE server's IP]
  • Apply the changes. I rebooted my router just to be sure.

That's all there really is to the PXE side of things.

EeePC Setup

You'll want to make sure that booting from the network is enabled in your BIOS. I'll post a list of my BIOS settings later.

Then you should be able to boot your EeePC from the network. If your EeePC isn't configured to boot from the network first, you can simply hit Escape while the BIOS POST screen is still showing and select it from the menu that appears.

If all goes according to plan, your EeePC should receive an IP address and download the boot images from your PXE server. Once you select the appropriate Arch Install option from the menu, it should go out and download the ISO and boot it up. It's pretty neat to see in action. Maybe one day I'll try to tweak this to use an ISO image that's available on the local network instead of downloading it from the Internet every time.

Arch Installation

Installing Arch Linux should be fairly simple if you follow the installation guide (which is also available during installation these days at /root/install.txt). The key thing to remember, if you want to use the built-in SSD and a permanent SD card as one hard drive, is to use LVM partitioning.

LVM Partitioning

The Arch Linux LVM guide will likely be an invaluable resource if you're new to LVM. Here I will simply give a short list of commands that I think I used to get my EeePC setup (I did this several days ago, so I might miss something along the way...sorry)

It's important to note that, while it's supposedly possible, I've never had any luck keeping my boot partition in an LVM setup. As such, I first partition my SSD and SD cards using fdisk. There are plenty of resources for fdisk and cfdisk out there, so I'll skip over the specifics of how to use each one and just give you an idea of what needs to be done.

  • Wipe all partitions from both /dev/sda (the SSD) and /dev/sdb (the SD card)
  • Create a 50-100MB primary partition at the beginning of /dev/sda. Mark it as bootable. Set the partition type to 83 (Linux).
  • Create another primary partition on /dev/sda that consumes the remaining disk space. Set the partition type to 8e (Linux LVM).
  • Create a primary partition on /dev/sdb that consumes all space on the SD card. Set the partition type to 8e (Linux LVM).

Now that we have some "Linux LVM" partitions to deal with, we can begin using LVM. Each partition we wish to use (both /dev/sda2 and /dev/sdb1) needs to be configured as an LVM "physical volume":

pvcreate /dev/sda2
pvcreate /dev/sdb1

Next, we create an LVM volume group that uses both of our physical volumes:

vgcreate vg0 /dev/sda2
vgextend vg0 /dev/sdb1

Lastly, create the LVM logical volumes. It's up to you how you setup your partitions, but I chose to create a swap partition (since my EeePC only has 512MB RAM) and a root partition. To create a swap partition, you simply do something like this:

lvcreate -C y -l 1G vg0 -n swap

And here's what the arguments mean:

  • -C y: make the partition contiguous
  • -l 1G: number of logical extents to allocate for the new logical drive
  • vg0: the name of the volume group we created earlier
  • -n swap: the name of the new logical volume

I created my root partition to fill the remaining space in the volume group as follows:

lvcreate -l +100%FREE vg0 -n root

Then it's just a matter of formatting your partitions. I'm not up-to-date on the debate regarding which FS is ideal for solid state media, so I just chose ext2:

mkfs.ext2 /dev/sda1
mkfs.ext2 /dev/mapper/vg0-root
mkswap /dev/mapper/vg0-swap

It's probably worth noting that you now have several ways to reference your newly-created LVM volumes. Here are my favorites:

  • /dev/[volume group name]/[volume name]
  • /dev/mapper/[volume group name]-[volume name]

Install Arch

I really don't want to duplicate the Arch Linux installation guide, so I'll just leave you to follow along there. Go ahead and mount your new partitions, pacstrap everything you want, and arch-chroot your heart away. But you might want to come back before you exit the chroot, otherwise your EeePC might not boot and you'll have to waste some time trying to figure out why.

Help The EeePC Boot With LVM

Before you reboot, you'll probably want to modify your /etc/mkinitcpio.conf to let your EeePC understand your LVM setup. The two key lines are MODULES and HOOKS. Here's what I have:

MODULES="usb-storage scsi-mod sd-mod libata usbcore uhci-hcd ehci-hcd"
HOOKS="base udev autodetect pata scsi sata lvm2 filesystems usbinput fsck"

The key here is to ensure that lvm2 appears before filesystems in your HOOKS list. Also, you want to load some modules to allow the SD card to be detected before the LVM hook attempts to find your partitions. I'm not sure if you need all of those modules, but they worked on the first try for me. To make the changes useful, rebuild your boot images:

mkinitcpio -p linux

To go along with detecting your SD card at boot, you want to give it enough time to settle before LVM tries to use it. In my case, 3 seconds is sufficient, so I added this to my /boot/syslinux/syslinux.cfg:

lvmwait=/dev/vg0/root rootdelay=3

You should be able to add that to the APPEND lines in your syslinux.cfg or the kernel line in your GRUB configuration file. Or whatever it is with GRUB these days.

Also, while you're editing your bootloader configuration, be sure to change the root partition to /dev/vg0/root (or whatever you chose when you did your LVM partitioning). The default syslinux.cfg includes root=/dev/sda3, so I just changed that to root=/dev/vg0/root. Most bootloaders allow you to modify the boot line before you actually boot into Linux if you forgot this step.

Tweak Arch

I'll leave you to install and configure the packages that you find useful. I plan on using my EeePC as a jump box into my home network, so it doesn't need a GUI of any sort. Just OpenSSH and some other goodies.

You might also be interested in my previous article about bonding eth0 and wlan0 now that you have Arch on your EeePC though!

Bonding eth0 and wlan0 on Arch Linux

Bonding eth0 and wlan0 on Arch Linux

Yesterday at work, a couple of my coworkers were trying to bond two ethernet ports on a Synology NAS. For whatever reason, this made me want to play with bonding network interfaces on my own computers. So I began trying to come up with a good reason to use valuable time to play with interface bonding.

One thing that has always driven me nuts about laptops is that connections are severed when I have to unplug my ethernet cable and take the laptop elsewhere. It never seemed to matter if I was using NetworkManager or anything else--connections were dropped, and the resulting annoyances ranged from minor to much rage. Having Pidgin drop connections and reconnect was a minor annoyance. Downloading a 4.2GB linux ISO and having the connection cut at 96% caused much rage.

Anyway, I decided to see if I could use bonding to reduce the frustration with such situations. Since my laptop is usually plugged into the ethernet, I wanted to use eth0 as my primary interface. It's faster and more reliable than wireless. When my ethernet connection fails, for whatever reason, I wanted it to fall back to wlan0. Ideally, things like downloads or streaming music/movies would continue uninterrupted.

Furthermore, I wanted my KVM to be able to use the bonded interfaces inside of my virtual machines. This called for a bridge.

To quickly see this in action, check the videos below!


I configured this on a relatively new Arch Linux installation. Here's the software I used:

  • linux: 3.4.8-1
  • initscripts: 2012.08.2-1
  • netcfg: 2.8.9-1
  • netcfg-bonding: 1.5.1-1
  • ifenslave: 1.1.0-7
  • bridge-utils: 1.5-1


The first thing you need to do to get this working, after installing all of the above packages, is load the bonding kernel module. In my particular case, as I mentioned earlier, I wanted to use eth0 when available and use wlan0 otherwise. As such, I used the active-backup bonding mode. If you're interested in the other bonding modes, I would suggest reading up on bonding. I'm pretty new to all of this bonding magic, so I can't guarantee that I'll be of any use if you don't follow my instructions :)

Back to configuration. I placed my bonding configuration in /etc/modprobe.d/bonding.conf. The only thing that may not be self-explanatory is the miimon setting. I learned from this bonding article that this option "specifies the MII link monitoring frequency in milliseconds." In other words, this is how often the system will check to see if a failover is necessary.


options bonding mode=active-backup
options bonding miimon=100
options bonding primary=eth0

After creating that file, you simply insert the module into the kernel:

modprobe bonding

To get bonding to work when you reboot your machine, you should either add bonding to your MODULES array in /etc/rc.conf or, if you're using more recent initscripts stuff, place a file in /etc/modules-load.d. I chose the latter solution.



Next, you must create some network profiles for netcfg. Prior to this bonding project, I had been using wicd or networkmanager to handle most of my networking needs. It seems like a bad idea to try using either of these, or the standard network daemon even, if you plan to use a configuration similar to what follows. Just FYI.

I created a network profile for the bonded interfaces as such:



Notice that wlan0 isn't in the SLAVES list. This is because I also have a network profile for my home wireless connection to handle the authentication and whatnot:


DESCRIPTION="Home connection"


PRE_UP="ifenslave bond0 wlan0"
PRE_DOWN="ifenslave -d bond0 wlan0"

I have one more network profile for the bridged interface that allows my KVM guests to live on the same network as everything else. If you're not using KVM or don't want a bridged interface, you don't need this one.


DESCRIPTION="KVM Bridge Connection"
POST_UP="brctl setfd br0 0"

Finally, I added these profiles to my /etc/conf.d/netcfg:

NETWORKS=(bonded home br0)

Again, if you don't need a bridged interface, you don't need to include the br0 profile in there.

You may or may not want to test your individual network profiles by doing something like:

netcfg -u home # try to bring the profile up
netcfg -d home # bring the profile down

If you have problems connecting to your wireless access point, I suggest tweaking and testing your profile until it works. If you use MAC address filtering for wireless security on your router, you might want to make sure that the MAC of your ethernet interface is in the list of permitted MAC addresses. When you setup bonding, all of the bonded interfaces seem to share the same MAC.

Try It Out

Pretty much all that's left is starting up the new network configuration! To do this, first make sure your previous networking daemon is turned off. For example, you might run one of the following commands:

rc.d stop network
rc.d stop wicd
rc.d stop networkmanager

Once you've done that, you simply run:

rc.d start net-profiles

If your setup is anything like mine, you might see ifconfig output similar to this (notice that my MAC addresses have been changed, but that they're identical for bond0, br0, eth0, and wlan0):

        ether 00:24:be:00:24:be  txqueuelen 0  (Ethernet)
        RX packets 7318719  bytes 8578112000 (7.9 GiB)
        RX errors 0  dropped 33241  overruns 0  frame 0
        TX packets 3404477  bytes 3562828808 (3.3 GiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

br0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet  netmask  broadcast
        inet6 fe80::224:beff:fec7:9895  prefixlen 64  scopeid 0x20<link>
        ether 00:24:be:00:24:be  txqueuelen 0  (Ethernet)
        RX packets 4759641  bytes 4771378631 (4.4 GiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 2119926  bytes 3491247232 (3.2 GiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

eth0: flags=6211<UP,BROADCAST,RUNNING,SLAVE,MULTICAST>  mtu 1500
        ether 00:24:be:00:24:be  txqueuelen 1000  (Ethernet)
        RX packets 7243938  bytes 8512402737 (7.9 GiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 3388055  bytes 3561344335 (3.3 GiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
        device interrupt 18

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 16436
        inet  netmask
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 0  (Local Loopback)
        RX packets 338869  bytes 263959385 (251.7 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 338869  bytes 263959385 (251.7 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

virbr0: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        inet  netmask  broadcast
        ether 36:11:59:de:92:73  txqueuelen 0  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

wlan0: flags=6211<UP,BROADCAST,RUNNING,SLAVE,MULTICAST>  mtu 1500
        ether 00:24:be:00:24:be  txqueuelen 1000  (Ethernet)
        RX packets 74781  bytes 65709263 (62.6 MiB)
        RX errors 0  dropped 33241  overruns 0  frame 0
        TX packets 16422  bytes 1484473 (1.4 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

Also, if you haven't been using netcfg already, you will probably want to update your DAEMONS array in /etc/rc.conf. Again, be sure you disable your previous networking daemon (if necessary) by placing a ! before the daemon's name (or just remove it from the array). Then add net-profiles into the array somewhere, probably closer to the beginning of the array.

Hopefully that works for you! Please share your experiences (both good and bad) in the comments! If you run into troubles, I will try to be of use, and hopefully others will chime in too.


Here are a couple of videos for those of you who are interested. The first is a lower-quality, but maybe easier-to-read-on-small-screens video. The second is just shy of 1080p size-wise.

Arduino-Powered Webcam Mount

Earlier this month, I completed yet another journey around the biggest star in our galaxy. Some of my beloved family members thought this would be a good occasion to send me some cash, and I also got a gift card for being plain awesome at work. Even though we really do need a bigger car and whatnot, my wife insisted that I only spend this money on myself and whatever I wanted.

Little did she know the can of worms she just opened up.

I took pretty much all of the money and blew it on stuff for my electronics projects. Up to this point, my projects have all been pretty boring simply because nothing ever moved--it was mostly just lights turning on and off or changing colors. Sure, that's fun, but things really start to get interesting when you actually interact with the physical world. With the birthday money, I was finally able to buy a bunch of servos to begin living out my childhood dream of building robots.

My first project since getting all of my new toys was a motorized webcam mount. My parents bought me a Logitech C910 for my birthday because they were tired of trying to see their grandchildren with the crappy webcam that is built into my laptop. It was a perfect opportunity to use SparkFun's tutorial for some facial tracking (thanks to OpenCV) using their Pan/Tilt Servo Bracket.

It took a little while to get everything setup properly, but SparkFun's tutorial explains perfectly how you can get everything setup if you want to repeat this project.

The problem I had with the SparkFun tutorial, though, is that it basically only gives you a standalone program that does the facial tracking and displays your webcam feed. What good is that? I actually wanted to use this rig to chat with people!! That's when I set out to figure out how to do this.

While the Processing sketch ran absolutely perfect on Windows, it didn't want to work on my Arch Linux system due to some missing dependencies that I didn't know how/care to satisfy. As such, I opted to rewrite the sketch using Python so I could do the facial tracking in Linux.

This is still a work in progress, but here's the current facial tracking program which tells the Arduino where the webcam should be pointing, along with the Arduino sketch.

Now that I could track a face and move my webcam in Linux, I still faced the same problem as before: how can I use my face-tracking, webcam-moving program during a chat with my mom? I had no idea how to accomplish this. I figured I would have to either intercept the webcam feed as it was going to Skype or the Google Talk Plugin, or I'd have to somehow consume the webcam feed and proxy it back out as a V4L2 device that the Google Talk Plugin could then use.

Trying to come up with a way of doing that seemed rather impossible (at least in straight Python), but I eventually stumbled upon a couple little gems.

So the GStreamer tutorial walks you step-by-step through different ways of using a gst-launch utility, and I found this information very useful. I learned that you can use tee to split a webcam feed and do two different things with it. I wondered if it would be possible to split one webcam feed and send it to two other V4L2 devices.

Enter v4l2loopback.

I was able to install this module from Arch's AUR, and using it was super easy (you should be root for this):

modprobe v4l2loopback devices=2

This created two new /dev/video* devices on my system, which happened to be /dev/video4 and /dev/video5 (yeah... been playing with a lot of webcams and whatnot). One device, video4, is for consumption by my face-tracking program. The other, video5, is for VLC, Skype, Google+ Hangouts, etc. After creating those devices, I simply ran the following command as a regular user:

gst-launch-0.10 v4l2src device=/dev/video1 ! \
    'video/x-raw-yuv,width=640,height=480,framerate=30/1' ! \
    tee name=t_vid ! queue ! \
    v4l2sink sync=false device=/dev/video4 t_vid. ! \
    queue ! videorate ! 'video/x-raw-yuv,framerate=30/1' ! \
    v4l2sink device=/dev/video5

There's a whole lot of stuff going on in that command that I honestly do not understand. All I know is that it made it so both my face-tracking Python program AND VLC can consume the same video feed via two different V4L2 devices! A co-worker of mine agreed to have a quick Google+ Hangout with me to test this setup under "real" circumstances (thx man). It worked :D Objective reached!

I had really hoped to find a way to handle this stuff inside Python, but I have to admit that this is a pretty slick setup. A lot of things are still hardcoded, but I do plan on making things a little more generic soon enough.

So here's my little rig (why yes, I did mount it on top of an old Kool-Aid powder thingy lid):

And a video of it in action. Please excuse the subject of the webcam video, I'm not sure where that guy came from or why he's playing with my webcam.

GIT-SVN on Slackware 12.2

With all of the hype that git has been receiving lately, I started playing with it a while back to see if it suited me and my wants/needs. I found it to be an interesting utility. I won't go into any details simply because I'm not really all that knowledgeable about all the ins and outs of version control systems, but I will say that I have decided I like it. I'm still not sure whether I prefer GIT over SVN or SVN over GIT.

My problem is that basically all of my projects are based on SVN repositories. I don't want to have to start up a new GIT repository for each of my past projects. Fortunately, there is an interface for GIT to use SVN repositories called git-svn. I use this utility primarily on my EeePC because it saves a good amount of space on my small disk (the git-svn versions of the working copies are typically about half the size of their svn counterparts). Sometimes it's a little wacky, but it works well enough for my needs.

I started using this git-svn utility on a Debian-based distribution. That meant it was insanely simple to get up and running: sudo apt-get install git-svn. I recently installed Slackware 12.2, and I was surprised to find out that the git-svn utility wasn't immediately available to me.

I did some googling to see if others had encountered the same problem. There were several accurate hits, but I couldn't quite find the solution I needed. In the end, I finally got things working. The following information describes what I did to achieve this monumental success.

Trying git svn

The first roadblock that I encountered, obviously, was finding out that git-svn didn't work on my shiny new Slackware installation. After doing a bit of research, I learned that I could substitute the familiar git-svn command with git svn and continue using it as I previously had.

Installing Dependencies

Once I learned about git svn and tried it out, I got a nasty error about Alien/SVN. I've lost track of the original error, and for that I apologize. Doing a little bit of research led me to execute this command as root:

cpan Alien::SVN

I'm not sure exactly whether that step is required, but you might as well do it :).

Next, I downloaded a couple SlackBuilds to create my own Slackware packages suited for my computer.

For each SlackBuild, you must download the original source code along with the actual SlackBuild itself. For example, when retrieving the necessary files for swig, I must download both swig-1.3.35.tar.gz and swig.tar.gz from the link specified. Here are some example commands, which should be run as root:

mkdir -p ~/downloads/slackbuilds; cd ~/downloads/slackbuilds
tar zxf swig.tar.gz
cd swig/
installpkg /tmp/swig-1.3.35-i486-1_SBo.tgz

The commands above should create a new directory in /root/ called downloads/slackbuilds. Next, the SlackBuild for swig will be downloaded and extracted, after which the swig source code will be downloaded. The SlackBuild is executed, rendering an installable Slackware package. Finally, the package is installed onto the system.

The process is basically the same for the subversion-bindings SlackBuild. On my system, however, I had to modify the stock SlackBuild slightly. I didn't install Apache on my EeePC because I don't use it and it would just be taking up space. When I tried to execute the SlackBuild for subversion-bindings straight from the archive, it complained about a missing apxs file, which has something to do with Apache.

To avoid the error, I modified the subversion-bindings.SlackBuild script to ignore the apxs thingy. The original ./configure section looked like this:

./configure \
  --prefix=/usr \
  --mandir=/usr/man \
  --enable-shared \
  --disable-static \
  --with-apr=/usr \
  --with-apr-util=/usr \
  --with-apxs=/usr/sbin/apxs \
  --with-neon=/usr \
  --with-zlib=/usr \
  --with-pic \
  --with-ssl \

I just removed the line that says --with-apxs=/usr/sbin/apxs \ and ran the SlackBuild script again. Worked like a charm.

At this point everything appeared to be able to work properly. Running git svn from the command line no longer spit out that nasty error I mentioned earlier. Instead it gave me the options I would expect to see.

That's when I tried to update an existing working copy of an SVN repository. It gave me this error:

$ git svn rebase
Authentication realm: <> Subversion - code
Password for 'myuser': Can't locate Term/ in @INC (@INC contains:
/usr/lib/perl5/site_perl/5.10.0/i486-linux-thread-multi /usr/lib/perl5
/site_perl/5.10.0 /usr/lib/perl5/5.10.0/i486-linux-thread-multi /usr/lib
/perl5/5.10.0 /usr/lib/perl5/site_perl /usr/lib/perl5/vendor_perl/5.10.0
/i486-linux-thread-multi /usr/lib/perl5/vendor_perl/5.10.0 /usr/lib/perl5
/vendor_perl .) at /usr/libexec/git-core/git-svn line 3071.

That's not very nice, now is it? The solution was fairly simple: install Perl's Term::ReadKey module. As root, execute the following command:

cpan Term::ReadKey

After doing that I was able to happily update my working copy and move on.

I don't envision that this article will be the all-knowing, all-powerful resource for how to use git-svn on Slackware, but I sure hope it will help some other folks who run into the same problems as me.