Showing posts with label Epia. Show all posts
Showing posts with label Epia. Show all posts

Saturday, June 9, 2012

How to recompile the linux kernel for specific hardware in Debian 6

I have Debian 6 installed on my mini-ITX system.

I want to try recompiling the kernel to speed up boot and reduce the footprint on the slow, old system. Eventually, I want to use the lessons learned to recompile Ubuntu 12.04 to work on the system. Currently, 12.04 will not boot, since the old VIA 32-bit processor does not fully support x686 nor pae.

If the kernel and modules are small enough, and customized for the equipment, we can even get rid of the initrd at boot. That will also speed up the boot a lot!

Step 1: Collect CPU and module information 

We can compile the CPU for the specific processor and modules we actually use. On such a resource-constrained system, getting rid of a lot of unused bloat is welcome.

The following command shows that we have a VIA Samuel 2 processor, 533MHz, 32-bit system.

$ cat /proc/cpuinfo 
processor : 0
vendor_id : CentaurHauls
cpu family : 6
model  : 7
model name : VIA Samuel 2
stepping : 3
cpu MHz  : 533.370
cache size : 64 KB
fdiv_bug : no
hlt_bug  : no
f00f_bug : no
coma_bug : no
fpu  : yes
fpu_exception : yes
cpuid level : 1
wp  : yes
flags  : fpu de tsc msr cx8 mtrr pge mmx 3dnow
bogomips : 1066.74
clflush size : 32
cache_alignment : 32
address sizes : 32 bits physical, 32 bits virtual
power management:

The following command lists most of the modules used (modules used during boot then unloaded do not show up here).

$ lsmod
Module                  Size  Used by
fuse                   43213  1 
snd_via82xx            15020  0 
gameport                6105  1 snd_via82xx
snd_ac97_codec         79248  1 snd_via82xx
ac97_bus                 710  1 snd_ac97_codec
snd_mpu401_uart         4155  1 snd_via82xx
snd_rawmidi            12737  1 snd_mpu401_uart
snd_pcm                46098  2 snd_via82xx,snd_ac97_codec
snd_seq_device          3661  1 snd_rawmidi
snd_timer              12304  1 snd_pcm
via_ircc               13188  0 
snd                    34142  7 snd_via82xx,snd_ac97_codec,snd_mpu401_uart,snd_rawmidi,snd_pcm,snd_seq_device,snd_timer
vt8231                  8678  0 
irda                   71690  1 via_ircc
snd_page_alloc          5021  2 snd_via82xx,snd_pcm
i2c_viapro              4387  0 
shpchp                 21168  0 
parport_pc             15747  0 
evdev                   5520  4 
parport                22170  1 parport_pc
button                  3578  0 
processor              23003  1 
pcspkr                  1235  0 
serio_raw               2912  0 
i2c_core               12739  1 i2c_viapro
soundcore               3294  1 snd
crc_ccitt               1039  1 irda
pci_hotplug            18493  1 shpchp
ext3                   92928  3 
jbd                    28166  1 ext3
mbcache                 3482  1 ext3
sd_mod                 25961  5 
crc_t10dif              1012  1 sd_mod
ata_generic             2239  0 
fan                     2590  0 
pata_via                5721  4 
uhci_hcd               16021  0 
libata                117427  2 ata_generic,pata_via
via_rhine              14427  0 
thermal                 9210  0 
ehci_hcd               28859  0 
thermal_sys             9346  3 processor,fan,thermal
scsi_mod              105921  2 sd_mod,libata
mii                     2654  1 via_rhine
usbcore                99061  3 uhci_hcd,ehci_hcd
nls_base                4445  1 usbcore

The following command tells us that the current version of the kernel in use is 2.6.32-5-486:

$ uname -a
Linux mini-deb6 2.6.32-5-486 #1 Sun May 6 03:29:22 UTC 2012 i686 GNU/Linux


Step 2: Install the kernel source

The kernel source code is needed. "Recompiling" a kernel actually just means compiling a new version of the kernel from source. The process is covered very well in this forum post. We will install all the needed packages for the recompile, install the linux source code too /usr/src, and copy the existing old kernel config so we have a nice baseline if we mess it up.

# apt-get install ncurses-dev kernel-package cpio initramfs-tools linux-base module-init-tools udev linux-source-2.6.32-5-486
# cd /usr/src
# tar -xjf linux-source-*.tar.bz2
# ln -s linux-source-* linux
# cd linux
# cp .config .config-original-2.6.32

One tiny extra step - we'll be manually rebooting at the end of the process, so I reset my grub timeout to 15 seconds so I have time to select the kernel I want without rushing. Grub will grab this new value when it automatically updates in Step 4.

# nano /etc/default/grub
(change the line GRUB TIMEOUT= )


Step 3: Edit the config file, then compile

Now we're ready to modify the .config file.

# make menuconfig 

Menuconfig takes about an hour, perhaps more. To build a really minimal kernel, go through and switch all of the options off. Next, go back and look at the list of modules. Search for each module (search is the forward-slash key '/'), and turn each back on. Make sure each is compiled into the kernel, not added as a module. Some options require you to search for prerequisites and turn those on first. Like I said, it took me over an hour to work through all the modules on the list.

When finished, save the config. Then we're ready to compile:

# make-kpkg clean
# make-kpkg --append-to-version=-custom1 kernel_image kernel_headers

Iterate the version number (-custom1 to -custom2) or you'll lose track of progress very quickly! If you want an initrd, add --initrd to the line.

Compiling on my slow machine takes about 2.5 hours. I run make-kpkg inside a screen session. I can ssh in, start compiling, detach the screen, and return in a few hours to see the result.


Step 4: Install the new kernel

The make-kpkg command creates a lovely new package for us in /usr/src. Install it.

# ls -l /usr/src
total 97892
lrwxrwxrwx  1 root root       19 Jun  2 19:20 linux -> linux-source-2.6.32
-rw-r--r--  1 root root  6060196 Jun  2 13:56 linux-headers-2.6.32-custom1_2.6.32-custom1-10.00.Custom_i386.deb
-rw-r--r--  1 root root  4170548 Jun  2 13:47 linux-image-2.6.32-custom1_2.6.32-custom1-10.00.Custom_i386.deb
drwxr-xr-x 25 root root     4096 Jun  9 14:02 linux-source-2.6.32
-rw-r--r--  1 root root 65220157 May  5 18:19 linux-source-2.6.32.tar.bz2
drwx------  2 root root    16384 May 27 17:36 lost+found

# dpkg -i  /usr/src/linux-image-2.6.32-custom1_2.6.32-custom1-10.00.Custom_i386.deb

The install will also create an updated initrd (if you asked for one) and add the appropriate grub entries. If you changed the Grub Timeout value in Step 2, the update will reflect that, too.

Change one setting in the new /etc/grub/grub.cfg. Normally, grub tells the kernel to load the boot drive read-only, then initrd unmounts it and remounts it read-write. Since we don't have an initrd, we must change that grub behavior. For the first few iterations of kernel testing, this doesn't matter - it wont affect anything until you reach busybox prompts because the root filesystem cannot be loaded:

# nano /etc/grub/grub.cfg

Look for the root=/dev/sda1 ro stanza in the last line of the appropriate menuentry, and change ro (read only) to rw (read/write). Here's an example of an unchanged menuentry:

menuentry 'Debian GNU/Linux, with Linux 2.6.32-custom8' --class debian --class gnu-linux --class gnu --class os {
        insmod part_gpt
        insmod ext2
        set root='(hd0,gpt1)'
        search --no-floppy --fs-uuid --set 89b0fb32-b7e3-46e8-878b-5da4cd69fbdd
        echo    'Loading Linux 2.6.32-custom8 ...'
        linux   /boot/vmlinuz-2.6.32-custom8 root=/dev/sda1 ro console=tty1 console=ttyS0,115200n8
}


Reboot into the new kernel.

# shutdown -r now


Step 5: Lather, Rinse, Repeat

Keep the hardware handy - you need to see the console boot messages, and you need access to the power switch.

The first few times you try this, the kernel is likely to fail. Either you forgot to add a module, or you set something wrong. Record the error off the screen, and jump into a search engine to see what it means.

Kernel failures fall into several broad categories. Each is usually due to the same cause - a misconfigured kernel .config file. Happily, these are sequential. As you move down the list, you're getting closer to final success.
- The easiest to diagnose is the simple refusal to start. The kernel fails a basic start test, and tells you in plain language that it won't start because it doesn't support this processor or the processor doesn't support this service, etc.
- Once the kernel passes those start tests, the next set of failures are kernel panics. This means that the kernel has loaded, but some piece of hardware or initrd instruuction or filesystem has mystified it, so it barfs a bunch of diagnostic information and freezes.
- Once the kernel is over its panic attacks, the next set of failures are dropping to the busybox prompt when the root filesystem fails to be recognized or loaded. This usually means either a misconfigured root= or UUID= in grub, or a missing or incorrect filesystem module.
- Finally, the system boots and works...mostly. Some application or piece of hardware doesn't work, though.

Reboot into the original working kernel (hard reboot, using the power switch).

Remove the non-working kernel. This will also remove the appropriate initrd (if any), and appropriate grub entries.

# apt-get remove linux-image-2.6.32-custom1

Return to Step 3, change the config file to fix the problem, and compile again.


Step 6: The new kernel works!

Once the new kernel works, clean up. Backup the working config file, remove the source code package, and delete the 'linux' symlink so a future recompile doesn't accidentally overwrite this working version.

# cp .config .config-2.6.32-custom5   # or whatever custom iteration number you want
# apt-get remove linux-source-2.6.32
# cd /usr/src
# rm linux

Now you can brag to your friends about how easy it was...

Let's take a quick look at the old and new kernels side-by-side:

$ ls -l /boot
total 17052
-rw-r--r-- 1 root root  110922 May  6 07:49 config-2.6.32-5-486
-rw-r--r-- 1 root root   55311 Jun 10 08:54 config-2.6.32-custom8
drwxr-xr-x 3 root root    4096 Jun 10 11:48 grub
-rw-r--r-- 1 root root 8722934 May 27 15:54 initrd.img-2.6.32-5-486
-rw-r--r-- 1 root root 1249814 May  6 07:49 System.map-2.6.32-5-486
-rw-r--r-- 1 root root 1333763 Jun 10 11:00 System.map-2.6.32-custom8
-rw-r--r-- 1 root root 2192352 May  6 07:48 vmlinuz-2.6.32-5-486
-rw-r--r-- 1 root root 3734224 Jun 10 11:00 vmlinuz-2.6.32-custom8

The actual kernel, vmlinuz, is 1.5MB (70%) larger, but no longer has an initrd (saves 8.7 MB) or /lib/modules directory (saves 67 kB). Boot time savings seems negligible so far

Here is the final working config file.




Sunday, May 27, 2012

Installing Debian 6 onto a VIA Epia 5000-L and IDE HDD

First boot with GUI
LXDE + Debian 6.0.5 on 10-year-old Epia 5000-L motherboard
I have a 10-year-old mini-ITX motherboard that I'm cobbling with a few parts into a useful system.

In this post, I discussed testing the old motherboard, and getting it to boot.

Since it arrived without any storage attached, in this post I discussed the hurdles getting it to boot Debian 6 from a USB drive. That wasn't easy, since the motherboard predated most forms of USB-boot, and the BIOS didn't support USB-HDD, the current standard for bootable USB.

Next, in this post, I discussed the adventure of using that USB boot to bootstrap a Debian install into an IDE-connected SD card. This didn't work out - one bootable IDE connector was defective, and a second worked...but wasn't bootable. I may return to this, since 3.5-inch HDDs are enormous - almost as big as the motherboard!

So I finally broke down and spent a few dollars on a 40GB HDD. This has the big advantage that the HDD can be partitioned for experimentation. Installing to the HDD is essentially the same process as installing to the SD card.




Lessons Learned

Hooked up:
Left: PS/2 Mouse, PS/2 Keyboard, VGA Monitor,
           USB Wireless-g dongle
Bottom: Power button
Right: Power to HDD, Power from wall, IDE to HDD
1) The -i486 architecture is important. This motherboard is too old to support cmov, cx8, and pae. All three of those are in the latest Ubuntu kernels. cmov and cx8 are part of the i686 instruction set, so specifying a i486 kernel gets rid of them. pae is a new default since Debian 6.0. So a Debian 6.0 kernel compiled for x486 will be useful on the motherboard...until I get better at compiling my own kernels.

2) Debootstrap does not include the wireless-tools package, so a bootstrapped system won't have wireless access. Adding wireless-tools is trivial if you remember to do it: During the chroot session when installing the kernel and grub and configuring the accounts and fstab and hostname, install wireless-tools and configure /etc/network/interfaces too.




For the first HDD experiment, I installed Debian 6 + LXDE onto a partition of the HDD.

Startup test: 45 Seconds from power-on to text-login prompt, 95 seconds to power-on to GDM login prompt.

Next tests: I want to try Debian Live for running the whole system in RAM. And I want to try modding the latest Ubuntu kernel to remove those three features and try Unity on it.

Sunday, January 8, 2012

Creating a bootable USB drive when the BIOS supports only USB-ZIP

Mini-ITX Epia 5000-L motherboard, ready to boot.
The red USB stick is the boot medium,
1GB USB stick with a complete Debian 6 install
masquerading as a 250MB USB-ZIP drive.

My used mini-ITX motherboard has a BIOS limitation that prevents it from booting from ordinary hybrid-iso images. The BIOS doesn't recognize USB-HDD (the popular type used today), but only older USB-FDD (USB floppy drive, limited to 1.4MB) or USB-ZIP (USB Zip Drive, limited to 250MB).

Who today has useful systems that fit in 250MB?

This is a demonstration of how to use a chainloader to get around the 250MB restriction. Here is how to build a working full install of Debian 6 on a bootable USB Stick. It's a full install (not a live-install that uses a ramdisk), so all the slow read/writes to the USB stick will make the system very slow and wear out the USB stick prematurely. Again, this is just a demo of how to use a chainloader to get around that 250MB restriction.

1) Create the Linux system

This is the long and complicated part. Use debootstrap to create a complete system somewhere else. I explained how I did it in this post for an SD card, and it's almost exactly the same.

Creating the complete system in, say, /var/usb-env should include creating /boot/initrd.img.version# and vmlinuz.version# , but not grub. We will use initrd.img and vmlinuz in Step #3, and this demo uses the simpler syslinux instead of grub.

2) Prepare the USB Stick

To be understood by the old BIOS, the USB stick needs an MBR up front, followed by a FAT boot partition of less than 250MB and labeled as the 4th partition (though it's really the first partition). After that, we can do whatever we like.

The best tool for creating a USB-ZIP bootable partition is 'mkdiskimage', part of the syslinux package. Everything below should be done as root to the unmounted USB-stick:
MAKE SURE you are using the right /dev/DEVICE
    /dev/sdb was mine, but probably won't be yours!

# mkdiskimage -Mz4 -i usb-zip /dev/sdb 15 64 32
    -M and 15: Create a 15 MB partition (I only needed 12 MB)
    -z4: Create a zip-disk geometry on partition 4 (normal for zip disks)
    -i usb-zip: Name of the partition. Use any name you wish
    Of course, your /dev/DEVICENODE may vary. BE SURE you are using the right node!
    15 64 32: 15 MB (see -M), 64 heads, 32 sectors (62 and 32 are required for zip)

After the USB-ZIP partition is made, you can do the rest of the partitions in your favorite editor. I used Gparted to create a 700MB Linux partition and the remaining space on the device as a swap partition.

3) Install files onto the boot partition

The install files consist of the bootloader, and the Linux /boot/initrd.img.version# and vmlinuz.version# files. The bootloader simply tells the system to load the linux kernel (vmlinuz), then to load the temporary system startup files (initrd.img) that the kernel can understand. One of the appended command options tells initrd where to find the final system root mountpoint on the other partition.

There are many bootloaders that can be used here, including grub. For simplicity, I'm using syslinux instead of grub. I don't need all of grub's configuration options - I just want the bootloader to immediately start loading the kernel and initrd.

For syslinux, we only need four files on the boot partition: The syslinux binary, syslinux.cfg, vmlinuz, and initrd.img. We also need to know the UUID of the other partitions for the syslinux.cfg file.
Once again, MAKE SURE you are using the right /dev/DEVICE
    /dev/sdb was mine, but probably won't be yours!

    Check the USB stick partitions before mounting
# fsck -f /dev/sdb1  # Blank linux, -f forces a check
# fsck -f /dev/sdb4  # Blank boot

    Get the UUIDs of the various partitions
# blikd   # Get the UUIDs of the newly created partitions

    Install Syslinux 
# syslinux --install /dev/sdb4

    Mount the boot partition
# mount -t vfat /dev/sdb4 /mnt

    Copy vmlinuz and initrd.img from the prepared system.
    Rename the files to comply with MSDOS 8.3 format
# cp /var/usb-env/vmlinuz.version /mnt/vmlinuz
# cp /var/usb-env/initrd.img.version /mnt/initrd.img

    Create the syslinux.cfg file
# nano /mnt/syslinux.cfg    # Use any editor you wish

##### Begin File
Default USB-Stick

display syslinux.msg
F1      syslinux.f1

prompt 40
timeout 30

Label USB-Stick
  kernel vmlinuz
  append initrd=initrd.img root=UUID=>UUID of the root partition<
##### End file

    Unount the boot partition
# umount /mnt

4) Copy the linux system onto the USB Stick

Once again, MAKE SURE you are using the right /dev/DEVICE
    /dev/sdb was mine, but probably won't be yours!

    Mount the Linux partition
# mount /dev/sdb1 /mnt

    Copy the system files
# cp -r /var/usb-env/{bin,etc,home,lib,media,mnt,opt,root,sbin,selinux,srv,tmp,usr,var} /mnt/

    Create the system mountpoints
# mkdir /mnt/{boot,dev,proc,sys}

    Edit /etc/fstab to add the correct UUIDs for the root, boot, and swap partitions
    and remove the cruft from the creating-system disks.
If you need to discover a UUID, use the 'blkid' command.
# nano /mnt/etc/fstab     # Use any editor you wish, of course

#####Begin File
# <file system> <mount point> <type> <options> <dump>  <pass>
UUID=<UUID of the main system> / ext3 defaults,errors=remount-ro,noatime 0 1
UUID=<UUID of the boot partition> /boot vfat defaults,errors=remount-ro,noatime 0 2 
UUID=<UUID of the swap partition> none  swap sw 0 0 
#####End File

    Unmount the linux partition, check the USB stick for damage once more
# umount /mnt
# fsck -f /dev/sdb4
# fsck -f /dev/sdb1

Successful boot to Debian 6 login prompt!
5) You're Done

Unplug the USB stick, walk over to the system you want to boot, plug in the USB stick, and....well, boot.

Friday, January 6, 2012

Installing Debian 6 onto an SD card, installing into an old VIA EPIA-5000L motherboard

In this post I discussed my new-to-me fanless motherboard, and how I got it to turn on/off, and test the boot.

Next step is to install a hard drive and install Debian 6.

Hardware

This hardware will eventually become a router or light-duty server, so the OS doesn't need huge storage. I used:
  • SD-to-IDE adapter (ebay, $8.88)
  • The adapter reqires a FDD (floppy disk) power connector. Since my power supply doesn't have that connector, I picked up a molex (IDE HDD power) to FDD adapter (amazon, $3.92)
  • 8GB SD card (left over from a now-dead camera). An SD card can also be plugged in to my Ubuntu 11.10 laptop. This turned out to be critically useful for me

Install Failures

Using the same method as this post to make bootable USB drives, I tried the latest Debian 6 businesscard and netinstall disks. Both failed at various points. Sometimes the iso was corrupted during download. Sometimes there was a failure writing the new partition table. Sometimes the table was successfully written, but the new partition couldn't be mounted for install. Sometimes the install was successful, but grub failed to install.

One by one, I winnowed through the issues. MD5 for the iso downloads. Pull the card and reformat it in my laptop to fix the partition table. Finally, I got consistent failures: The businesscard iso failed during the install debootstrap, and the netinstall iso failed to create an initramfs and grub.

The businesscard iso could successfully drop to a working shell, so I used these instructions to manually install debootstrap and see if I could bypass the installer failures. This worked well, though slowly (writing to the SD card is much slower than to a real hard drive), and my many mistakes after this point were a learning experience in filesystem corruption, chroot, initramfs, and grub.

fsck, chroot, initramfs, and grub

Booting to a live environment, dropping to a shell, debootstrapping to an installed system, and then rebooting to test it...only to discover it's unbootable...take a long time for each cycle, mostly due to the SD card slow write speed, and the SD card's seeming love of getting it's filesystem corrupted somewhere in the process each time.

I sped up the process and injected filesystem checks by moving most of it onto a Debian VM on my laptop. The SD card mounts as a USB drive, so the VM must be USB-capable. Lesson Learned: Before mounting/unmounting the card, fsck it! Every time! This is how I got rid of the filesystem corruption, which seemed to be happening from something unclean during shutdown (almost true - I'll tell you the real story later). On some occasions the filesystem was so messed up that I simply wiped it and copied a new system over from the VM.

Now, I could reliably build a system that would boot...but grub would complain or initramfs would drop to a shell. On two occasions it successfully booted, then froze (and corrupted the filesystem). Testing with variations in /boot/grub/grub.cfg fixed grub to boot reliably...only to later learn that grub 'error' wasn't an error at all, but a different configuration problem I had caused somewhere else.

That left a frustrating initramfs refusal to mount the card. I could mount it manually, but that resulted in kernel panic. After a lot of digging through initramfs scripts, I discovered a packaging bug - initramfs relies on klibc-tools...but the dependency is not listed in Debian 6! (It is correct in Ubuntu 10.10). One apt-get later and the system booted reliably every time...but the filesystem was frequently corrupting.

Apt activities that triggered man-db began returning "fopen: Permission denied" errors. Fixed with chown -R man:root /var/cache/man


And the result...

I finally determined that the frequent filesystem corruptions were due to a defective SD-to-IDE adapter. I tested the card reader on my laptop - no problems, so it wasn't the laptop, the card, or my handling. The proof was when the SD card was freshly installed, fsck'd before removal from the laptop, fsck'd again upon insertion to the Epia system, and run for an hour. Missing and corrupted file errors began to proliferate. Still need to check the RAM.


Lessons Learned
1) fsck the SD card before every mount and after every unmount
2) Manually check for the existence of /boot/grub/grub.cfg, /boot/grub/normal.mod, and /sbin/init
3) Use blkid to get the UUID of the root partition. Check that against /boot/grub/grub.cfg

Steps to succesfully creating the SD card
Without wandering down my many blind paths, here is the final process to install a bootable Debian 6 onto an SD card.

1) Use a VM (I used Virtualbox) with USB access on a fast machine (my laptop).
2) Within the VM, create a chroot environment and use debootstrap to create the new linux system that will be copied onto the card.
3) Prepare the SD card, copy the environment, and install grub.
4) Ensure a good system after the first boot from the card.

Creating a VM is beyond the scope of this discussion.

Creating the new linux system happens entirely on the VM. Create the base debian install
# mkdir /var/card-env
# debootstrap --arch=i386 squeeze /var/card-env
Depending on your network connection, debootstrap may take a long time.


Mount the system-required stuff
# mkdir /var/card-env/proc
# mount --bind /proc /var/card-env/proc
# mkdir /var/card-env/dev
# mount --bind /dev /var/card-env/dev
# mount --bind /dev/pts /var/card-env/dev-pts
# mkdir /var/card-env/sys
# mount --bind /sys /var/card-env/sys
Copy useful stuff before chrooting


These files must be edited later in the process
# cp /etc/fstab /var/card-env/etc/
# cp /etc/network/interfaces /var/card-env/etc/network/
# cp /etc/hosts /var/card-env/etc/
Chroot into the card-env
# chroot /var/card-env
Set up the package manager. Do these in the chroot environment.
# echo "deb-src http://ftp.us.debian.org/debian squeeze main" >> /etc/apt/sources.list
# echo "deb http://security.debian.org/ squeeze/updates main" >> /etc/apt/sources.list
# echo "deb-src http://security.debian.org/ squeeze/updates main" >> /etc/apt/sources.list
# apt-get update
If any apt-get errors pop up, take time and fix them now. Do these in the chroot environment.

If any command-not-found errors occur:
Use 'which commandname' to find the full path
for example, 'which date' returns '/bin/date'
Use dpkg -S full-path to find the package name
for example, 'dpkg -S /bin/date' returns 'coreutils'
Reinstall that package
for example, 'apt-get remove coreutils && apt-get install coreutils'

Edit hostname, hosts, and interfaces. Do these in the chroot environment
# echo MyNewHostName > /etc/hostname
# nano /etc/hosts                # Change the hostname
# nano /etc/network/interfaces   # Reduce interfaces to just to loopback device
                               # udev will add the rest anyway upon boot

Add your root and user accounts. Do these in the chroot environment
# passwd root
# adduser MyName

Add essential elements to the new filesystem. Do these in the chroot environment
# apt-get install locales
# dpkg-reconfigure locales     # Choose a UTF-8 in your preferred language
# apt-cache search linux-image # Choose a kernel that matches your architecture
# apt-get install klibc-tools initramfs-tools linux-image-VERSION-i486 grub-pc

Take a few minutes and troubleshoot any kernel-install or initramfs issues. Do this in the chroot environment. Grub will have a lot of incorrect information, and we'll fix that after we plug in the SD card.

Add desired optional packages. Do this in the chroot environment
# apt-get install openssh-server     # For example

Exit the chroot environment, then unmount the system-essentials
# exit
# umount /var/card-env/proc
# umount /var/card-env/dev-pts
# umount /var/card-env/dev
# umount /var/card-env/sys

You now have a complete Debian environment (except for grub and fstab), ready to copy from the VM onto the SD card.

Plug in the SD card to the VM machine, and add the SD card (as a USB) to the VM. Leave it unmounted. udev assigned my card as /dev/sdb.

Partition the card as desired. I created /dev/sdb1 (bootable ext3), and /dev/sdb5 (swap). Do these steps as root. Card must be plugged in but unmounted for these steps:
# mke2fs -j /dev/sdb1   # Assuming you haven't formatted it yet
# mkswap /sev/sdb5   # Assuming you haven't formatted it yet

Mount the card
# fsck /dev/sdb1
# mount /dev/sdb1 /mnt

Change grub's device map to the SD Card
# ls /dev/disk/by_id    # Note the SD Card's ID string
# nano /var/card-env/boot/grub/device.map  # Change HD0 to the SD card

Change grub's config file and fstab to the SD Card partition
# blkid        # Note the linux partition's UUID string
# nano /var/card-env/boot/grub/grub.cfg    # Change all the UUID strings to the SD Card Partition
# nano /var/card-env/etc/fstab             # Change the UUID strings on the root and swap lines

Copy the environment over to the card
# cp /var/card-env/* /mnt/
# grub-install --root-directory /mnt /dev/sdb

Final checks
# blkid   # Note the UUID of the card boot partition
# nano /mnt/boot/grub/grub.cfg   # Check for the same UUID
# ls -l /mnt/sbin/init    # Check for existence
# ls /mnt/boot            # Check for an initrd.img file and a vmlinuz file

Unmount and fsck the SD card
# umount /mnt
# fsck /dev/sdb1
You now have a complete bootable Debian 6 installed on the SD card, ready to try booting from.

During the first boot from the SD card, do the following:
# update-initramfs -u  # Get rid of "Can't find disk" errors
# tune2fs -c 1 /dev/sda # Set the flag to run fsck every boot until further notice
# ifconfig -a   # Note the MAC address and interface of the ethernet port

Keep the current system interfaces, delete leftovers from the laptop environment
# nano /etc/udev/rules.d/70-persistent-net-rules

Bring up the network and prepare apt-get
# ifconfig up eth1  # Your eth may differ
# dhclient eth1
# apt-get update
# apt-get upgrade

Add essential system components
# apt-get install rsyslog

Tuesday, November 29, 2011

Booting an old VIA EPIA-5000L motherboard

I purchased an old VIA fanless mini-ITX motherboard on eBay, including CPU and RAM and shipping, for a reasonable price ($43). I want to play with it and see what I can get it to do. Maybe build a cool case for it...

MB attached to ordinary ATX power supply, VGA monitor, and PS/2 Mouse.
Tiny black rectangle on the right is the on/off jumper.
Step 1: Hook it up

Happily, I have an old PS/2 keyboard, VGA monitor, and ATX power supply handy.
Hook them all up...and nothing.

Of course, the power switch.
Get the manual, read the manual, find the jumper, and use a spare jumper to connect them for a moment.

Hooray! Fans on the power supply start to spin! Beep! Splash appears on the monitor!

I made the following BIOS changes:
  • Always restart upon power loss (since I don't have a power switch!)
  • Enable fast startup (skip memtest, faster boot)
  • Skip splash (annoying)
  • Skip BIOS summary (annoying)
  • Change the boot device to USB-ZIP (not USB-FDD, essential for USB-boot later)


Step 2: Create a Debian Boot USB drive.

This is a pretty old motherboard, so the standard USB-HDD booting option is missing. That means Live-USB (hybrid USB/CD) .iso files won't work without some tweaking. The available USB options are USB-ZIP and USB-FDD. A quick web search turns up this page of instructions, but it doesn't work. Further digging reveals this page, a version of which does work.

  1. Select a USB Drive (small). Everything on it will be erased, so backup if needed.
  2. On a different (working) Debian or Ubuntu system, as root (use 'sudo su' to get a root prompt on Ubuntu). Not all commands will work with sudo alone.
  3. Plugin the USB drive. If your system automatically mounts it, then unmount (not eject) it.
  4. Use dmesg to find the USB drive's /dev/sd* node. For example, mine was sdz and sdz3.
  5. Format the USB drive to a bootable configuration. This will limit the accessible size to 250MB (the old ZIP-format maximum), so CD-sized live .isos won't work. See this page for mkdiskimage commands for other-size drives.
    mkdiskimage -4 /dev/sdz 0 64 32   # 1GB and below USB drives only
  6. Install the MBR:
    cat /usr/lib/syslinux/mbr.bin > /dev/sdz
  7. Get and install the boot image:
    wget -O /tmp/boot.img.gz http://ftp.debian.org/debian/dists/squeeze/main/installer-i386/current/images/hd-media/boot.img.gz
    zcat /tmp/boot.img.gz > /dev/sdz1
  8. Download the Live Session image. In this case, I used a Debian businesscard installer simply because it was a very small download:
    wget -O /tmp/debian-6.0.3-i386-businesscard.iso http://cdimage.debian.org/debian-cd/6.0.3/i386/iso-cd/debian-6.0.3-i386-businesscard.iso
    md5sums /tmp/debian-6.0.3-i386-businesscard.iso
    Compare the md5sum result to http://cdimage.debian.org/debian-cd/6.0.3/i386/iso-cd/MD5SUMS
  9. Mount the USB drive, and install the Live Session image:
    mkdir /tmp/usbmountpoint
    mount /dev/sdz3 /tmp/usbmountpoint
    cp /tmp/debian-6.0.3-i386-businesscard.iso /tmp/usbmountpoint/
    umount /tmp/usbmountpoint
  10. Check the resulting filesystem, and correct any errors (there may be a couple!)
    fsck.msdos -r /dev/sdz3
    My resulting filesystem is about 214MB, below the 250MB limit.
  11. Clean-up is optional, since all working files are in /tmp and will be deleted upon reboot anyway.
  12. Unplug the USB drive (it should already be unmounted)


Step 3: Boot Debian

The BIOS should be set to a startup device of USB-ZIP (step 1), and you should have a Debian USB drive (step 2). Put them together - try to boot the new motherboard from it. In my case, success!

I don't have a hard drive installed yet, so I'm not ready to actually install. But this was a successful power-on and boot.


UPDATE #1: For Xmas, one of the kids got a toy butterly-in-a-jar. It has a "Try Me" feature for in the store, a button that detached after opening the package. The button's connector looked just right to fit the power jumper, and indeed now I have a real power button for the motherboard. This turns out to be handy, because a stable system needs better power control than flipping the switch on the power supply...and my new silent power supply has no switch!

UPDATE #2: A chainloader can be used to bypass the USB-ZIP 250MB boot limit. I did a successful USB-ZIP boot to a complete Debian 6 system.