Friday, February 16, 2007

Gumstick Gentoo - Consolidated Links

I know that it might be difficult to find the location in my tutorial you'd like to start/end, so I decided to consolidate the links with a brief overview of what's covered in each section. Hopefully, this will aid the readers.

Part 1: Know thy Enemy - Portage

  • Basic Difficulties of squashing Gentoo into a small space
  • Identification of Directories holding much of the storage space
  • Overview of tools we will need

Part 2: Always two, there are. A Master and an Apprentice
  • Basic definition of Embedded System Development (host, target)
  • How to setup your Host for development
  • Extracting the Base Gentoo Stage 3 setup

Part 3: Fattening the Turkey
  • Developing the core Gentoo system for deployment
  • Building kernel with needed options for USB boot
  • Editing grub menu.lst for USB boot
  • Installing X-windows and fluxbox

Part 4: Go forth and Multiply (except for snakes... they're adders)
  • Partitioning/Formatting USB Device
  • Mounting for deployment
  • Deployment of Gentoo onto thumbdrive
  • Final setup of Grub.

Sunday, February 11, 2007

Debian Sarge on USB Thumbdrive

Honestly, I was quite surprised with Debian Sarge. It literally took just installing the OS on a thumb drive for it to work like a charm.

Personally, I downloaded the "businesscard" iso:

This is a core system that boots your host computer, sets up your network devices, and installs a debian system over the internet. Amazingly, it works like a charm.

The only thing I did to minimize the installation size was to choose "manually select packages" when queried about the type of system I would be using.

At the end I had an ~300MB rootfs with no gui. Adding in Xwindows server and a personally selcted KDE bumped this up to ~650MB (in other words, don't just ad in the KDE meta-package. Choose which parts you really need).

It's sad how simple it really becomes when a Distro like Debian uses an initramfs. I will definitely be looking into iniramfs for my PXE-Based Linux Test Software for work.

Sunday, February 04, 2007

Request for Topics

If anyone reading this has a suggestion for Linux topics to cover, I'd be happy to entertain them. I currently am developing multiple root file systems for a new distribution I'm calling "THLinux". All of them will be embedded in nature and fit into as small a footprint as possible.

Currently, I've been working on a ~600-750MB Debian USB drive with KDE and a tar-gziped deployment archive(~256MB download).

Feedback is definitely welcome!

Saturday, February 03, 2007

Part 1: Gumstick Gentoo

I redid the time stamps so this flows more logically down the page.

To recap: I have been able to fit a full Gentoo distribution (with X server and Fluxbox) into a 1GB, bootable USB thumb drive. This is from a standard Stage3 install of full glibc (not the experimental uClibc/busybox distributions).

Part 1: Know thy enemy.

The major difficulty surrounding any "embedded" install of Gentoo lies in one of its greatest strengths:


Most people who have installed a Stage3 system without really delving into the particulars of Gentoo probably have one simple question rolling around in their heads:

"Why is Gentoo SOOOOO big when it's a custom-compiled Linux Distribution?!?!?!"

Well, the short answer to this is quite direct. Portage is freaking HUGE! So, what is a Linux Embedded OS Developer (who REALLY likes Gentoo) to do? Why, take out your enemy of course! Figuratively speaking....

Portage has several directories in the file system that it directly manipulates:

  • /usr/portage (duh)
  • /var/cache
  • /var/db
  • /var/tmp/portage
Well, that's nice. But there is also another major culprit in shrinking a Gentoo install
  • /usr/src

Now that you know the major "hogs" to a Gentoo system, what is one to do? Why quickly, quietly, and methodically "take them out of the picture", of course!

As a teaser... I will let you know some of the standard Linux utilities that you will be using to make this Gumstick Gentoo work:
  • mount
  • chroot
  • emerge
  • nano/vim(my tool of choice)

Is that it, you ask? Why yes Virginia, that's all you really need!

On to Part 2

Part 2: Gumstick Gentoo

Now that we know the enemy, what are we going to do about it? Now, we need to setup our Gumstick Environment.

Part 2: Always two, there are. A Master and an Apprentice

The trick with making an "embedded" system is that you develop it on a full-fledged host system and deploy the results to your target device. Well, we apply that same idea here. The main difference is that we're keeping our emerge environment separate from our final system. Since it's unlikely that you will often update software in an embedded environment, this is a safe assumption. But, the way I do it preserves that emerge tree so that you can hook it back into your Gentoo system for any needed updates/additions.

So, you're asking... how in the HELL do we do that? With some simple tricks I've picked up on my travels through Linux.

The Environment:

I have a two-tiered Gentoo environment for this project. First, find a directory to do some work in. You will need the ability to use all the commands listed in Part 1. I usually do the following in my home directory:

# mkdir gentoo portage_tree

For this setup, gentoo/ will hold my target file system, and portage_tree/ will hold, you guessed it, Portage! Now, we need to populate these directories with their skeleton directories.

Portage Tree Directories:
# mkdir -p portage_tree/usr_portage
# mkdir -p portage_tree/usr_src
# mkdir -p portage_tree/var_cache
# mkdir -p portage_tree/var_db
# mkdir -p portage_tree/var_tmp_portage

Target File System Directories:
# mkdir -p gentoo/usr/portage
# mkdir -p gentoo/usr/src
# mkdir -p gentoo/var/cache
# mkdir -p gentoo/var/db
# mkdir -p gentoo/var/tmp/portage

Notice much symmetry to that?? Well, that's because we're effectively mirroring our portage tree to a remote directory. Since we have access to the mount command, we can abstract this quite well. This remote file system can eventually be mounted from a local machine like we are about to do, or it can be mounted on an entirely DIFFERENT machine that is accessible through NFS.

Now, we need to prep our environment for extraction of the Stage 3 tarball. I'm assuming, at this point, you actually know a bit about Gentoo and how to get hold of the stages and the portage snapshots.

Linking our Portage Tree to our System:
# mount -o bind ~/portage_tree/usr_portage \
# mount -o bind ~/portage_tree/usr_src \
# mount -o bind ~/portage_tree/var_cache \
# mount -o bind ~/portage_tree/var_db \
# mount -o bind ~/portage_tree/var_tmp_portage \

Now, I'm sure you're wondering, "what the hell is -o bind". Well, that is a nice option to mount. It allows you to statically link or "bind" one directory to a different one. Therefore, what ever happens in, for instance, ~/gentoo/var/cache is actually STORED in ~/portage_tree/var_cache. Neat trick, eh?

Now that we have our environment setup, how bout we extract those Stage 3 and Portage tarballs?

Extracting the Gentoo System:
# tar -jxvf ~/stage3-.tar.bz2 -C ~/gentoo
# tar -jxvf ~/portage-latest.tar.bz2 -C ~/gentoo/usr

For those of you who have never seen the -C option here, it copies the resulting extraction into the specified directory.

At this point, your Gentoo system is ready for a workout.

# cp /etc/resolve.conf ~/gentoo/etc
# mount -t proc none ~/gentoo/proc
# mount -t sysfs none ~/gentoo/sys
# chroot ~/gentoo

Now my that hands are getting tired, I'll end this section here. If you've ever done a Gentoo installation before, you should be able to start tinkering as you wish. You might not even need the rest of the guide!!

On to Part 3

Part 3: Gumstick Gentoo

To recap, we've identified our trouble (portage tree); we've removed it from our final system; and, we have entered our Stage 3 install via chroot

Part 3: Fattening the Turkey

I am assuming that you know how to setup your USE, MAKEOPTS, and CFLAGS options with Gentoo. If not, go read their documentation. They are usually very good.

First things first, we need to be sure we are running the latest and greatest.

# emerge --sync
# emerge portage (if suggested)
# etc-update (if needed)

Ok, now we have the most up-to-date portage and portage tree. What to do? Why make sure we can boot this puppy! That means kernel and bootloader.

Since we will be using this stick on multiple computers, I'd definitely reccommend a microkernel approach except for a few particular modules. Namely, we expect to be putting this on a USB Drive. That means that genkernel would be a great choice since it turns most everything into modules. So:

# emerge gentoo( or vanilla)-sources genkernel grub vim(my editor of choice)
# genkernel --menuconfig all

Note: All the following is from memory, so be lenient on me for minor errors. But, please to notify me of problems!

In your menuconfig, you need to traverse through the tree to both the SCSI the USB Drivers section. Say yes(not M) to the following modules:

EHCI (usb 2.0)
UHCI (the OTHER usb 1.1)
OHCI (usb 1.1)
USB Mass Storage (and all sub modules)
USB HID (and all sub modules)

SCSI devices(your thumb drive will look like a scsi device.)

Exit and save your kernel. From here, genkernel can will take control. However, since you don't have a boot loader configured AND you're in a chroot environment, you'll have to do some boot loader config manually. Also, lets make some easy to use symbolic links in /boot.

# cd /boot
# ln -s {kernel image} vmlinuz
# ln -s
{initrd image} initrd.img

Boot Loader:

Now, you notice that I chose grub as that is my most familiar. So everything in this section is dependant on that.

First thing with grub is that you need to specify what device map to what identifier. For instance.

#vim /boot/grub/ (you probably don't have one of these, so this will also create it)

Inside VIM:
- /dev/sda (hd0) #USB Thumbdrive
- /dev/hda (hd1) #in case you have a kernel on the primary IDE drive you wan to use
- /dev/fd0 (fd0) #floppy disk

Now, we also need to create a menu for grub.

#vim /boot/grub/menu.lst (also, you probably don't have this one)

Inside VIM:
- defalut 0 #which "title" option to boot by default... 0-based
- timeout 5 #5 seconds to change your mind
- title Gentoo Stick
- root (hd0,0)
- kernel /boot/vmlinuz ro quiet rootdelay=10
- initrd /boot/initrd.img

Some explaining:

root - in this case, specifies that any "/"(root) directory is on the first partition on the first device in

kernel - path to your kernel... relative to "root" plus any other options

initrd - path to your initrd... relative to "root"

rootdelay=10 - this is a bit of a hack built into 2.6 kernels. It pauses for 10 seconds just before it tries to load your root file system specified on the kernel line. This allows your usb device to actually be detected by drivers that may be a bit slow on the uptake.

NOTE: we have yet to do a "# grub-install" for a very good reason; ie We're ina chroot environment and we don't have our target drive mounted... So, DON'T try it yet.

Now, we just need the fun stuff... a GUI

# emerge fluxbox x11 xfree86-vesa xdm
# echo "exec fluxbox" >> ~.xinitrc
# passwd

Now, we should have a base system configured ready to deploy... What's one to do? Why exit our chroot.

# exit
# umount ~/gentoo/proc
# umount ~/gentoo/sys
# umount ~/gentoo/dev
# umount ~/gentoo/usr/src
# umount ~/gentoo/usr/portage
# umount ~/gentoo/var/cache
# umount ~/gentoo/var/db
# umount ~/gentoo/var/tmp/portage

On to the final Part 4

Part 4: Gumstick Gentoo

To recap, we've built a basic stage3 Gentoo system in a chroot environment. Now, we are ready to deploy that image.

Part 4: Go forth and Multiply (except for snakes... they're adders)

Now, we've got a nice prepared stage3 Gentoo ready for deployment. It's even nicer because we have removed our portage tree and have it available for later upgrades.

So now, what do we do? Why deploy our image.

First we need to prep our disk drive. Since Ext3 fs is compiled as a module, this will be a good choice for our final file system. The first step is to create a partitioning scheme. Since flash disk have a limited life span and are damn slow to access, we do NOT want to create a swap partition there. However as a teaser, I'll let you know that it's possible to steal ram from your video card (that's not in use) and turn it into a block device... i.e. perfect swap space.

#fdisk /dev/sd{a,b,c,d}(your drive goes here... and alwas specify it without a number)
fdisk> d(elete all partitions currently on the system)
fdisk> n(ew, create a primary partition that takes up your entire drive)
fdisk> a( set the boot flag on partition 1)
fdisk> w(rite the partition table and exit)

Ok, now we need to create our file system on the new partition, mount the new fs, and deploy our image.

#mkfs.ext3 /dev/sd{a,b,c,d}1 (this time we specify a number because we need the partition)
#tune2fs -c0 -i0 /dev/sd{a,b,c,d}1 (disable error checking... these do have limited writes...

#mount /dev/sd{a,b,c,d}1 /mnt
#cd ~/gentoo
#find . | cpio -pdm{u}{v} /mnt

The command that includes cpio is useful for many reasons. CPIO is an extremely useful backup utility as it can take a stream from FIND and copy the files anywhere you want them. Also, the {u} allows you do to an unconditional overwrite, and the {v} will tell you all about your progress. It should be noted that {p,d,m} are required to maintain your permissions, create needed directories and accept piped names.

Now you have to edit your grub file in such a way that is knowledgeable of the fact that your USB hard drive is trying to be loaded at the same time as you are trying to execute "/sbin/init". I will leave the rest of the configuration up to you except for the usb-specific kernel parameters. The parameter that you will specifically need is "rootdelay={5,10}". This rootdelay command does exactly what it says. It delays trying to activate your root partition for x seconds (5 or 10 as shown above). This will give your kernel enough time to recognize the thumb drive and activate it before the concurrent thread tries to load up your root file system.

After you have configured grub, you can execute the following to attempt an automatic setup.

#grub-install --root-directory=/mnt /dev/sd{a,b,c,}

The root directory tells grub where to look for /boot/grub/ and the other part specifies the MBR of the usb drive you are attempting to set up. If this fails for any reason, you're like going to need to do a manual grub install. That's something for another article.

Now if all went well, you should be able to #umount /mnt and attempt a reboot of your new Gumstick Gentoo.