Thursday 29 July 2010

LAP - Actual Build - Part 9, Making it Boot

We now need to actually make our USB Key bootable.  The first step in that is to create the configuration file which tells the system what filesystems are connected.
cat > /etc/fstab << "EOF"
# Begin /etc/fstab
# file system  mount-point type   options        dump fsck
#                                                     order
/dev/disk/by-label/amiga     /           ext3  defaults,barrier=1       1    1
#/dev/disk/by/uuid/????     none        swap   pri=1          0    0
proc           /proc       proc   defaults       0    0
sysfs          /sys        sysfs  defaults       0    0
devpts         /dev/pts    devpts gid=4,mode=620 0    0
tmpfs          /dev/shm    tmpfs  defaults       0    0
# End /etc/fstab
EOF

The file contains filesystem objects on the left handside, then where they are mounted in the filesystem in the next column.  The third column has the type of the filesystem that you are mounting.  The rest of the settings depend on the particular mount, and are not worth going into here.

I mount the USB Key by reference to its label which I set way back in the configuration phase.  That way I do not have to rewrite the [fstab] file every time I move the USB Key between filesystems.  We already know about proc, sysfs, devpts and tmpfs.  These are all the filesystems we had to mount to use the chroot.  I am not going to bother with swap, it does not make sense on a USB Key, so I have [#] commented that line out.  I am leaving the information in the file, though, just in case.

The next stage is to, finally, actually compile our Kernel. I've gone through this process a couple of times and it is mind numbingly complex. The menu system for setting all the kernel options is, and I am being charitable here, obtuse. There appears to be absolutely no rhyme nor reason to the ordering of menu entries or indeed the whole menu structure.

It strikes me strongly as a historical bodge job. Each time someone has a bright idea to modify the kernel, another option goes into the menu structure. It is just added in wherever the author fancies. Multiply this by several hundred times and you get some idea of how unstructured the whole thing is. Frankly, a LOT of work could be done to make this system more intuitive.

And I don't mean that the names of the vast majority of various menu entries are bizarre. I mean there is a certain stupidity in having a menu right on the opening screen for "File systems", a separate opening screen menu for "Block Layers" (which are the storage devices that are going to get the fucking file systems) AND THEN a menu under the Device Drivers menu for "Block Devices". There is a separate Device Driver menu for PATA, SCSI and SATA drivers. Waaaaaay down the list is an entry for USB Support and waaaaaaaay down the sub-menu is finally the entry for USB Mass Storage support. All of this stuff relates to storage devices. Why the fuck is it spread all over the place?

Here's a suggestion. Menu entry: "Storage". All the storage shit in there. You want to change something to do with Storage? You go to the Storage menu. You could also just DUPLICATE the entry for USB Mass Storage in the Menu entry: "USB Shit". There is no reason why you need to only have one of each item.

Don't get me started on the fucking network nonsense. Opening screen menu called "Networking Support" and then a separate Device Driver section for "Network device support". Confused yet?

What they also need is some kind of indication about the fuck up potential of each of the settings. As it is, when you start up the editor you get a whole load of default settings. You have no idea which ones can go and which have to stay. Now, what I would like to see is the menu not only structured by hardware function, but also by complexity. So, something like a beginner gets all the default stuff and then a quiz about what graphics card, sound card, network card and hard disk type he has. A more intermediate user is let into all the multiple choice settings, but the real confusing stuff is hidden away. Stuff like CPU settings and I2C and debugging crap.

Frankly this menu system requires someone to take the interface design equivalent to a blowtorch to it. Anyway, it is all we've got. What I would absolutely recommend, when you get stuck, and you will, is that you go and read Linux Kernel in a Nutshell, specifically chapters 4 (which explains how you use the menu configuration program), 7 (which explains how you go about working out what kernel settings you need for your machine) and 8 (which sets out some common configuration groups for stuff like USB Storage support). The book is excellent, and available under the Creative Commons licence. It is not entirely up to date (it is for kernel 2.6.18 and we are using 2.6.32) but it is a brilliant primer.

OK, lets get on with this bollocks. Here is what I did, and it seems to work. It is probably quite bloated though, and an after-project job will be to trim this down to get rid of the stuff I do not need.

cd /sources
tar -jxvf /sources/linux-2.6.32.8.tar.bz2
cd linux-2.6.32.8
make mrproper
make LANG=en_GB.utf8 LC_ALL= menuconfig

I am then faced with the following menu of options.

                         General setup  --->                                                                     
                        [*] Enable loadable module support  --->                                                    
                        -*- Enable the block layer  --->                                                           
                            Processor type and features  --->                                                       
                            Power management and ACPI options  --->                                                 
                            Bus options (PCI etc.)  --->                                                            
                            Executable file formats / Emulations  --->                                              
                        [*] Networking support  --->                                                                
                            Device Drivers  --->                                                                   
                            Firmware Drivers  --->                                                                  
                            File systems  --->                                                                     
                            Kernel hacking  --->                                                                    
                            Security options  --->                                                                  
                        -*- Cryptographic API  --->                                                                 
                        [*] Virtualization  --->                                                                   

The first thing you want to do is to go into filesystems and make sure that EXT2-EXT4 is all supported in the kernel.  Select the following options:

                      <*> Second extended fs support                                                              
                      [*]   Ext2 extended attributes                                                              
                      [*]     Ext2 POSIX Access Control Lists                                                     
                      [*]     Ext2 Security Labels                                                                
                      [ ]   Ext2 execute in place support                                                         
                      <*> Ext3 journalling file system support                                                    
                      [ ]   Default to 'data=ordered' in ext3                                                     
                      [*]   Ext3 extended attributes                                                              
                      [*]     Ext3 POSIX Access Control Lists                                                     
                      [*]     Ext3 Security Labels                                                                
                      <*> The Extended 4 (ext4) filesystem                                                        
                      [*]   Ext4 extended attributes (NEW)                                                        
                      [*]     Ext4 POSIX Access Control Lists                                                     
                      [*]     Ext4 Security Labels 

If using EXT4 then make sure that the following is set:

                      [*]   Support for large (2TB+) block devices and files (NEW)

You also need to install your sound drivers.  You find these as follows:

 Device Drivers  --->
<*> Sound card support  --->
<*>   Advanced Linux Sound Architecture  --->
[*]   PCI sound devices  --->

If, of course you are using a PCI based soundcard.  I select the following to fit with my various machines:

<*>   Emu10k1 (SB Live!, Audigy, E-mu APS)
<*>   Intel HD Audio  --->
<*>   Intel/SiS/nVidia/AMD/ALi AC97 Controller

I have a couple of nVidia motherboards, and need support for their onboard controllers:

 Device Drivers  --->
<*> Serial ATA (prod) and Parallel ATA (experimental) drivers  --->
<*>     NVIDIA SATA support 

To get high resolution (!) text screens on boot I made sure these settings were activated:

Device Drivers  --->
Graphics support  --->
<*> /dev/agpgart (AGP Support)  --->
<*>   Intel 440LX/BX/GX, I8xx and E7x05 chipset support

Device Drivers  --->
Graphics support  --->
<*> Direct Rendering Manager (XFree86 4.1.0 and higher DRI support)  --->
<*>   Intel 830M, 845G, 852GM, 855GM, 865G (i915 driver)  --->                              
                             i915 driver

I actually came back and changed this setting during a later build. X was complaining that it could not find 'i915'. I have to say, it did not seem to make any difference whatsoever to the system, but I don't like errors. I changed this to build this as a module. This lets you also choose the i830 driver as a module as well. This way the system can choose whatever it likes. X stopped complaining once I did this. Still made no change to the performance.

Device Drivers  --->
Graphics support  --->
-*- Support for frame buffer devices  --->
<*>   Userspace VESA VGA graphics support                                                   
                     [*]   VESA VGA graphics support 

I did NOT enable the nvidia framebuffer driver. Also, do NOT set the -> Device Drivers -> Graphics -> Console display driver support -> Framebuffer Console support to install as a module. It will give you a blank screen.

To ensure that wireless networking was going to work I set the following options:

Device Drivers  --->
[*] Network device support  --->
[*]   Wireless LAN (NEW)  --->
[*]   Wireless LAN (IEEE 802.11)  --->
<m>   Broadcom 43xx wireless support (mac80211 stack)

Note, I have set that to [M] for module.  This means I can load or unload it depending on the machine I am running the USB Key from.  You would want to look through the rest of that menu to find out if there are any other wireless drivers you want to install. After I finished the build, I went back and rebuilt the kernel with the Atheros driver selected as a module. This allowed me to get my PCI Express Abit Airpace card to work. No firmware needed.

Device Drivers  --->
[*] Network device support  --->
-*-   PHY Device support and infrastructure  --->
<m>   Drivers for Broadcom PHYs

[*] Networking support  --->
<*>   RF switch subsystem support  --->

I turned this RF option off in a later build and it made no difference. Best to remove unnecessary crap thinks I.

[*] Networking support  --->
[*]   Wireless  ---> 
[*]   Old wireless static regulatory definitions
[*]   Wireless extensions
[*]     Wireless extensions sysfs files
<m>   Common routines for IEEE802.11 drivers
<*>   Generic IEEE 802.11 Networking Stack (mac80211)
[*]   Enable LED triggers

To help with USB I set the following:

Device Drivers  --->
[*] USB support  --->
<*>   Support for Host-side USB
The trackpad on my laptop can be erratically detected so I am going to build the 'mouse' driver as a module:

Device Drivers  --->
Input device support  --->
[*]   Mice  --->
<m>   PS/2 mouse

Once I set all that I went to

Save an Alternate Configuration File

and made sure that my changes were saved.  I then selected:

< Exit >

and it dropped me back to the prompt.  From there I ran the by now customary:

make $CORES_TO_USE

The build messages ended with:

Root device is (8, 33) 
Setup is 12156 bytes (padded to 12288 bytes). 
System is 4189 kB 
CRC 25b759c7 
Kernel: arch/x86/boot/bzImage is ready  (#1) 

The build itself took 28m50s on my celeron laptop.  I also need to run a separate command to compile the drivers I specified as [M]odules.

make modules_install

Then we copy the files we just made to the /boot directory:

cp -v arch/x86/boot/bzImage /boot/vmlinux-2.6.32.8-lfs-6.6
cp -v System.map /boot/System.map-2.6.32.8
cp -v .config /boot/config-2.6.32.8

We can also install the documentation:

install -d /usr/share/doc/linux-2.6.32.8
cp -r Documentation/* /usr/share/doc/linux-2.6.32.8

We also want to convert all the files in this directory to root ownership to protect them in the future:

chown -R 0:0

This returned the following helpful message:

chown: missing operand after `0:0' 
Try `chown --help' for more information.

Ah. Perhaps we need the '.' to tell it we are referring to the current directory.

chown -R 0:0 .

Seems to have worked.  To ensure that any USB drivers start up in the right order, we install the following modprobe configuration file:

install -v -m755 -d /etc/modprobe.d
cat > /etc/modprobe.d/usb.conf << "EOF"
# Begin /etc/modprobe.d/usb.conf

install ohci_hcd /sbin/modprobe ehci_hcd ; /sbin/modprobe -i ohci_hcd ; true
install uhci_hcd /sbin/modprobe ehci_hcd ; /sbin/modprobe -i uhci_hcd ; true

# End /etc/modprobe.d/usb.conf
EOF

Next, according to the LFS6.6 instructions is the configuration of Grub 1.97.  For reasons I will go into in full in due course, I am using Grub 0.97 instead.

Grub 0.97, or legacy grub, is an older version of grub than is used in the LFS 6.6 book.  I am going to use it instead of Grub 1.97, for reasons I go into in more detail elsewhere.  As 0.97 is not in the large .tar file I downloaded, the first thing I will have to do is download the 0.97 version.  As with nano, this means exiting the chroot to get internet access back.

exit
cd /media/lfs/sources
sudo wget ftp://alpha.gnu.org/gnu/grub/grub-0.97.tar.gz
sudo wget http://www.linuxfromscratch.org/patches/lfs/6.5/grub-0.97-disk_geometry-1.patch
sudo wget http://www.linuxfromscratch.org/patches/lfs/6.5/grub-0.97-256byte_inode-1.patch
sudo chroot "/media/lfs" /usr/bin/env -i HOME=/root TERM="$TERM" PS1='\u:\w\$ ' PATH=/bin:/usr/bin:/sbin:/usr/sbin CORES_TO_USE=-j2 /bin/bash --login
cd /sources

tar -xzvf grub-0.97.tar.gz
cd grub-0.97
patch -Np1 -i /sources/grub-0.97-disk_geometry-1.patch

Disk Geometry sounds a bit scary, but actually this just makes grub more compatible with some newer SATA drives, and makes it better are detecting drives in general.  Brings it up to date in other words.  The second patch make grub compatible with ext2 systems which use 256 byte inodes.  No word on how it works with 128 bit earnodes.

patch -Np1 -i /sources/grub-0.97-256byte_inode-1.patch
./configure --prefix=/usr
make CFLAGS="-march=i486 -mtune=native -Os"
make check

==================
All 1 tests passed
==================

make install

We need to make a directory in the boot folder to contain all the [grub] files.  Some systems will have the /boot folder contained in its own partition, and it is therefore important to have all the relevant files in one place:

mkdir -v /boot/grub

What we then do is copy some … important files that do … something … important to the new directory:

cp -v /usr/lib/grub/i386-pc/stage{1,2} /boot/grub
cp -v /usr/lib/grub/i386-pc/e2fs_stage1_5 /boot/grub

What I am going to do next is create a script to use to configure grub.  I am doing this so I do not have to use the grub interactive system, but can simply automate it instead.

cat > /etc/grub.conf << "EOF"
root (hd1,0)
setup (hd1)
quit
EOF

In the script, we first tell grub that our root partition is [hd1,0].  In the language of grub this means /dev/sdb1.  Why does grub have to be different?  Well it just does, but I am not going to rant about this too much, because I understand it is much better in the latest versions of grub, which I am stubbornly refusing to use.  I did once get caught out with this, I had done a bit of disk swapping and my Amiga Key was [sdd1]. However there was NO [sdc1] on the system, so I had to point grub at [hd2] instead of [hd3]. The next command tells grub to install itself to the MBR of [hd1] or [sdb].  It then quits.  Obviously, if the Amiga Key has a different designation (sdc) for instance, you would replace hd1 (hd2 for sdc). To find the correct drive, you can run grub, and use the command [geometry (hdX)] where X is where you think you should install grub. The response will tell you the device name so you can double check. We then have to run the script:

grub --batch < /etc/grub.conf

The [<] in this scenario reverses the direction of the file that follows, so the [grub] program when used with the [batch] option looks for input which is then supplied by the [<].

Next we will create the configuration file for Grub which actually sets up what happens when grub tries to boot. When you first do this you probably want the timeout to be, say, 30 seconds. However, once it is up and running you can change it to, say, 1 second.

cat > /boot/grub/menu.lst << "EOF"
# Begin /boot/grub/menu.lst
# By default boot the first menu entry.
default 0
# Allow 30 seconds before booting the default.
timeout 30
# Use prettier colors.
color green/black light-green/black
# The first entry is for LFS.
title LFS 6.6
root (hd0,0)
kernel /boot/vmlinux-2.6.32.8-lfs-6.6 root=/dev/sdd1 vga=773 rootdelay=10
EOF

Right, first of all you will have noted that we are using [hd0,0] here, not the [hd3,0] from earlier.  Why?  Well my best guess is that when we actually boot from the device it becomes the first drive, at least as far as grub is concerned.

The [kernel] line tells grub what kernel file to load and where to find it.  The file referred to was created when we built our kernel, and we copied it to that directory.  We next set the partition that contains the root drive.  This is the tricky bit.  This will vary from machine to machine, and even on the same machine, depending on how the machine dishes out the names at boot.  We cannot use [label] or [uuid] settings here.  Potentially we could if we used an [init]ial [r]am [d]isk, or we upgraded Grub, but I'm not exploring that for now.  The bottom line is that if I get a boot error when I move to a new machine, I can just edit the grub commands on boot, and then re-write the menu.lst file.  Editing the grub commands on boot is EASY, we just hit 'e' when selecting the entry and we can change whatever we want.

[vga=773] tells the kernel to use a graphical mode of 1024x768.  771 is 800x600.  [rootdelay=10] is most likely to be the solution to my grand boot fuckup.  The kernel doesn't always, and hardly never, detects USB devices before it decides to try to boot from them.  This is monumentally stupid, and is partially corrected by this command.  It tells the kernel to wait 10 seconds to let and USB devices get configure before trying to boot.  This prevents the system shitting itself when it can't find the disk you have told it exists.

Adding another boot option is really easy. You just copy the [title], [root] and [kernel] lines and give them alternative options. You will want to do this if you regularly move the Amiga Key between machines, as hitting 'e' and manually editing the lines is going to get very boring after a while.

mkdir -v /etc/grub

We then just make a symbolic link, the need for which escapes me at present.

ln -sv /boot/grub/menu.lst /etc/grub
cd ..
rm -rf grub-0.97

Then you just reboot into a functional system.  Maybe!

You will probably want to rebuild your kernel at some stage, and if so the commands are as follows (assuming you are in either chroot or running on metal).  This will start you with a clean default kernel build.  If that does not work for you, then you should omit the [make mrproper] line, and it should load your last settings.

cd /sources/linux-2.6.32.8
make mrproper
make LANG=en_GB.utf8 LC_ALL= menuconfig
make $CORES_TO_USE
make modules_install
cp -v /boot/vmlinux-2.6.32.8-lfs-6.6 /boot/vmlinux-2.6.32.8-lfs-6.6.backup
cp -v /boot/System.map-2.6.32.8 /boot/System.map-2.6.32.8.backup
cp -v /boot/config-2.6.32.8 /boot/config-2.6.32.8.backup
cp -v arch/x86/boot/bzImage /boot/vmlinux-2.6.32.8-lfs-6.6
cp -v System.map /boot/System.map-2.6.32.8
cp -v .config /boot/config-2.6.32.8

No comments:

Post a Comment