TinyGentoo

Goal
This article will show how to build a very minimal Gentoo installation, considerably smaller than 64MB. To reach this goal, 'busybox' and 'uClibc' will be used. The finished installation will be bootable, and can be put for example on small portable media such as an USB-stick or SD-card.

Why this Wiki was created
I've got a 64MB USB flash disk, and I wanted Gentoo on it, but to still have plenty of room for other files. Because there wasn't anything already out there, I figured it out for myself, and this is pretty much a HOWTO make a Tiny Gentoo (under 5MB) using uClibc and busybox (what the embedded guys use). Links to other (larger) projects and pages that were very helpful for me are at the section.

Process overview
The steps to reach the goal are:
 * Download files
 * Setup chroot for building environment
 * Chroot to building environment
 * Build building environment
 * Create the final environment, /tinygentoo is assumed in this document
 * Package the final environment into an initramfs image
 * Create partitions, copy files and install bootloader (GRUB)

Requirements

 * USB flash disk or flash card (min. 8MB)
 * About 500MB free on your HDD (depends on how you decide to go on about things)
 * A motherboard/laptop that supports booting from a USB flash disk
 * Root privileges (chroot as unprivileged user will not work)
 * Some free time

Download stage-files
Choose a Gentoo mirror close to you, then hop into experimental/x86/embedded/stages, if your arch is x86. Download the Stage3 file, as an alternative you may choose Stage 1 or 2 if you want to play around more than what is necessary.

You can choose different file and folder names than in this document, I'm just using ones that will explain what they are for. Basically we're just following the Gentoo Handbook Chapter 5, but with a few differences, most of the stuff we don't need to do because we'll only be chrooting into it.

You can consult a more detailed guide for creating the chroot if you want.

Entering the chroot
The build environment will be put in /mnt/gentoo_uclibc.

And what you'll need to repeat every time when entering the chroot:

Basic setup
We do want all the symlinks for busybox, and ccache, and only minimal versions of packages that support that use flag.

The uclibc stages on the mirrors are quite old, so you will need to change the profile to a newer version. Emerge ccache first so that portage can use it for all the other packages. Then update all the packages, emerge the 2.6 kernel sources and copy the default bash login scripts to root's home directory.

# ln -snf /usr/portage/profiles/uclibc/x86 /etc/make.profile If you get sandbox violation errors when upgrading coreutils just do
 * 1) emerge ccache
 * 2) emerge -au portage
 * 3) emerge -auDN world
 * 4) emerge vanilla-sources
 * 5) cp /etc/skel/.bash_profile /etc/skel/.bashrc /root/
 * 6) mkdir /tinygentoo

FEATURES="-sandbox" emerge coreutils

If you get errors while running the ancient emerge against the new portage tree use the following work-around:

On your parent Gentoo system create a package containing a working portage:

You now have a package file at '/usr/portage/packages/All/portage-#.#.#.#.tbz2'. Chroot back into the subsystem as explained above and type 'cd /' to go to the root. Now extract the working portage over the embedded system chroot by typing:
 * 1) quickpkg --include-config=y portage

Finally you should emerge portage itself using the new emerge (from the parent system) to make sure everything is fine: 'emerge portage'
 * 1) tar xvjf /usr/portage/packages/All/portage-#.#.#.#.tbz2

If fails, see. Copy to. Then add the following after line 403 in :

After a successful emerge world you may want to emerge and run. If this fails because it wants to emerge an old python that is no longer supported(?), try to find out which version you have, and then unemerge all old versions by using. Replace X.Y.Z by the version you have, and don't forget the single quotes to prevent misinterpretation of the '<' sign by the shell. After this, do and try the  again.

If the fails on busybox, then first, then retry emerging world.

If after the above fails with error: '__NR_clock_gettime' undeclared you need to upgrade. For the current version (1.8.2 as well as 1.7.4) uclibc-0.9.29 is needed, which is not in portage. See for updated ebuilds.

Alternatively, to work around the busybox problem, you can do the following

FEATURES="keepwork" emerge busybox cd /var/tmp/portage/sys-apps/busybox-1.x.y/work/busybox-1.x.y make menuconfig Deselect "BusyBox Settings"->"BusyBox Library Tuning"->"Use Clock Gettime" Exit configuration mkdir -p /etc/portage/savedconfig/sys-apps/busybox cp .config /etc/portage/savedconfig/sys-apps/busybox cd $HOME USE="savedconfig" emerge busybox
 * 1) this will fail with the __NR_clock_gettime error

Final environment
An initramfs will be booted after the kernel. This initramfs will hold the full environment. Everything that will finally be turned into this initramfs will be in. Using before emerge commands will emerge the packages into that directory. This way you do not need portage or gcc in there, but only the packages you really want will end up in the final environment.

Emerge the base packages
Emerge lines that do not have will be installed into the chroot so that it will be able to compile the other packages without errors. We do not add to  because that would interfere with later updating the baselayout-2, which will need to be unmasked first. See if you're not sure what the options used do. Please note that at the time of writing, baselayout 2.0.0 is the most recent version. You can choose to unmask newer versions (and their dependencies) when needed.

mkdir -p /etc/portage echo "=sys-apps/baselayout-2.0.0 **" >> /etc/portage/package.keywords echo "=sys-apps/openrc-0.2.1-r1 **" >> /etc/portage/package.keywords echo "=sys-fs/udev-118-r2 **" >> /etc/portage/package.keywords echo "=sys-apps/baselayout-2.0.0" >> /etc/portage/package.unmask echo "=sys-apps/openrc-0.2.1-r1" >> /etc/portage/package.unmask ROOT=/tinygentoo USE=make-symlinks emerge -avkN =sys-apps/baselayout-2.0.0 uclibc busybox

Setting up users
chroot into and change the root password.

Please note, the shell shipped with busybox is, not :

chroot /tinygentoo /bin/ash passwd Add a regular user. Change foo to your username:

addgroup -g 100 users adduser -h /home/foo -s /bin/ash -G users foo

exit the chroot:

exit

Set the hostname
Replace TinyGentoo if you would like to use some other hostname. is read by, see. .

Writing fstab
The root filesystem will be mounted as ramfs by the kernel. The only downside to this is that unlike tmpfs it does not have a size limit, so writing a lot to could fill up your ram. Anything that is on tmpfs uses nearly no ram when empty and grows when needed but wont use up all of the ram, leaving room for applications to run.

Feel free to be creative, just remember that flash doesnt like being written to lots and lots (incorrect, see notes), so do not mount or  onto it. sda1 is the partiton on the USB stick that will contain the bootloader files, the kernel and the initrd. will be the partition that you see when in windows, and you can use it to store any settings/files from TinyGentoo too.

Make the two directories that do not yet exist

Writing /init
This step is optional. Instead of having this file you could add to the grub kernel line.

is the file that the kernel executes right after loading the content of the initramfs. If you are using initrd instead of initramfs, rename this file to

Remember to make it executable

If you would like to be able to use the same script with both initrd or initramfs, you can symlink one to.

cd /tinygentoo ln -s init linuxrc Optional, but if you would like to change the timezone, edit. For example,.

Emerging the wanted packages into /tinygentoo
Choose what packages you want. in your regular Gentoo to easily find out what the packages are. The examples will provide you with an installation that can browse the web (lynx), connect to IRC (scrollz), run and connect to SSH servers (dropbear) and screen, that I don't know how some people live without. ROOT=/tinygentoo emerge -avk lynx scrollz dropbear screen

That's it for /tinygentoo. chroot back in if you want to get a feel for it.

Kernel
In theory you could just use a kernel built outside the uClibc chroot, but that would get confusing.

Kernel configuration
Not very hard really, and because we will be using an initramfs image most things can be compiled as modules if you wish to do so. Disable everything that you don't want or need to keep the size of the kernel image down.

cd /usr/src/linux make menuconfig

As a final touch, you may also need something else than the default us keymap for your future system. If you need it, you can build the proper keymap for your keyboard layout inside the kernel issuing the following command from within the /usr/src/linux directory:

loadkeys -m  > drivers/char/defkeymap.c An example for french layout:

loadkeys -m /usr/share/keymaps/i386/azerty/fr.map.gz > drivers/char/defkeymap.c

Compiling the kernel
Now just:

make -j2 && make modules_install cp arch/i386/boot/bzImage /tmp/vmlinuz-tinygentoo If you go back to menuconfig and change things, clean out the old modules so there wont be any extra ones taking up space:

rm -r /lib/modules/* make modules_install

or if you don't want do the next step (coping modules) you can launch this command:

make INSTALL_MOD_PATH=/tinygentoo modules_install

Copying the modules
We want all the modules inside the initrd, so they'll need to be copied there.

mkdir -p /tinygentoo/lib/modules cp -vr /lib/modules/* /tinygentoo/lib/modules/

Packaging /tinygentoo
We want everything under /tinygentoo to be turned into a single initramfs image. Don't forget to copy the kernel modules to /tinygentoo before this step!

Cleaning up
Copy the files to some other place so you can easily restart if you mess up, then remove all the files you don't need or want.

cp -r /tinygentoo /tmp/ rm -r /tmp/tinygentoo/var/*/* /tmp/tinygentoo/tmp/* If you want to see how much space its using:

du -hs /tmp/tinygentoo

Creating the initramfs image
To create the initramfs image we will use cpio to create an archive of the files that the kernel can understand, and gzip it to make it smaller.

cd /tmp/tinygentoo && find. | cpio -H newc -o | gzip -9 > /tmp/initramfs-tinygentoo.igz

Preparing the USB flash disk
Basically we just want one partiton for the TinyGentoo boot files, and one partiton for saving files that you want to keep even after a reboot, and that will also be accessable from Windows.

Backing up the old data
Just in case you don't like it or just want to try it or.... something else, back up what you have got on your dongle (USB flash disk) right now. Make sure that you use the correct device, it might not be /dev/sda if you have other drives showing up as SCSI. Those could be a SATA hdd, a camera or an MP3 player. fdisk -l will show you what partitions are seen by linux.

Preferably do all the partitioning stuff outside the uClibc chroot, but you could do it from in there too if you've fallen in love with it :P

We'll just raw copy the whole disk. Note: sda is the whole disk, sda1 is only the first partition, it does not include the MBR/partiton table. Gzip it too to save space. 4K blocks to read to make it slightly faster, but its still slow..

cd /root dd if=/dev/sda of=dongle_backup.img bs=4K gzip dongle_backup.img

Creating the partitions
Clear the partition table and use fdisk (or something else if you don't like fdisk) to create the partitions.

dd if=/dev/zero of=/dev/sda bs=1 count=512 fdisk /dev/sda Change the size of the boot partition so that it will fit your kernel + initrd.img + 1-2MB, though you could make it larger if you would like to use it for other stuff too.

Command (m for help): n Command action e  extended p  primary partition (1-4) p Partition number (1-4): 1 First cylinder (1-1024, default 1):   Using default value 1 Last cylinder or +size or +sizeM or +sizeK (1-1024, default 1024): +6M

To make it bootable:

Command (m for help): a Partition number (1-4): 1

Then the vfat partition. Your cylinder numbers propably will not match mine, don't worry bout that.

Command (m for help): n Command action e  extended p  primary partition (1-4) p Partition number (1-4): 2 First cylinder (95-1024, default 95):   Last cylinder or +size or +sizeM or +sizeK (95-1024, default 1024):   Using default value 1024

Change the type to FAT32 so that Windows will see it correctly

Command (m for help): t Partition number (1-4): 2 Hex code (type L to list codes): b Changed system type of partition 2 to b (W95 FAT32)

Then to check everything is OK

Command (m for help): p

If yes, write and exit

Command (m for help): w

Formatting the partitions
There isn't really any good reason to use something other than ext2 for the boot partition. You may need to for vfat formatting support. The -F 32 makes it FAT32 to support longer filenames and stuff. Change label to what name you would like the partition to have.

mke2fs /dev/sda1 mkfs.vfat -v -F 32 -n label /dev/sda2

Installing GRUB
If you do not yet have grub,.

First you will need to copy the stages. e2fs_stage1_5 is optional, and you may delete it after grub has embedded it. Make sure you have /boot mounted to be able to copy the files from there.

mkdir /mnt/dongle mount /dev/sda1 /mnt/dongle mkdir /mnt/dongle/grub cp /boot/grub/stage? /boot/grub/e2fs_stage1_5 /mnt/dongle/grub/ umount /mnt/dongle grub grub> device (hd0) /dev/sda grub> root (hd0,0) grub> setup (hd0) grub> quit mount /dev/sda1 /mnt/dongle rm /mnt/dongle/grub/e2fs_stage1_5

Alternative GRUB configuration
In my case, I had to do use the following commands.

mkdir /mnt/dongle mount /dev/sda1 /mnt/dongle mkdir /mnt/dongle/grub cp /boot/grub/stage? /boot/grub/e2fs_stage1_5 /mnt/dongle/grub/ touch /mnt/dongle/grub/usb_flag umount /mnt/dongle grub grub> find /grub/usb_flag (hd1,0) grub> root (hd1,0) grub> setup (hd1) grub> setup (hd1,0) grub> quit mount /dev/sda1 /mnt/dongle rm /mnt/dongle/grub/usb_flag

The difference being that I had to setup BOTH the MBR and the boot partition's MBR. Until I did this, my BIOS would not boot from the USB stick.

Writing menu.lst (for GRUB)
GRUB looks for menu.lst, not grub.conf, but you may make a symlink to grub.conf from menu.lst and then edit grub.conf.

Add init=/sbin/init to the kernel line if you do not have a linuxrc file.

Set vga=ask to get a prompt to be able to select the resolution for your console. With the ramdisk_size= option you can set how large you would like your / to be, in KB. Don't set it too high if because you will also need RAM for applications to run, but you've got to set it large enough for the uncompressed initrd.img and dynamic files that will be created.

Copying the important files
Something you need to do to get it working..

cp /tmp/vmlinuz-tinygentoo /tmp/initramfs-tinygentoo.igz /mnt/dongle/ umount /mnt/dongle

BIOS Setup, Reboot and Enjoy!
Reboot, hit Del, F2 or whatever it is that you need to do to enter the BIOS configuration. Find the section where you can change the boot order, and select USB-HDD, USB-ZIP or something similar to have the highest priority. Save and exit, and reboot with the USB stick attached.

Where to go from here?
If all goes well, you'll be in your shiny new TinyGentoo, that you will still need to learn to use though.. You will propably want to write a script to get the net going and maybe something to save your settings.

TODO
 udev and hotplug  xorg + wm and stuff  Getting sectors and cylinders right on the disk  Scripts and hopefully an ebuild to make life easier  Boot floppy to get boot the actual TinyGentoo for those whose BIOS's don't support booting directly from USB (see http://mirror.slitaz.org/floppies/builder/ or http://mirror.slitaz.org/boot/floppy-grub4dos)  Syslinux instead of GRUB 