Friday 30 July 2010

LAP - Actual Build - Part 9a, What Went Wrong

As I have remarked a couple of times, the first build of this did not boot. As a result, I decided to use Grub 0.97 instead of 1.97. The failure may not have been the fault of Grub 1.97, and I am therefore going to repeat all the Grub 1.97 instructions here, as I may want to review this in the future to try to get it to work.

There are 3 reasons, to my mind, why a boot might fail. The first is the Grub bootloader. If this is configured incorrectly, then you do not pass go. The second is the Kernel. If you are trying to boot off a USB Key but you have not configured USB Storage support in the Kernel, it ain't going to work with even the best grub configuration. The third potential issue is if you haven't configured your /etc/fstab file to actually mount [/] properly.

When I tried to boot from the USB Key the boot process would continually fail, and complain that the 'root=' that I was trying to mount could not be found. No matter what combination of options I put into the grub configuration nothing seemed to work. Irritatingly, sometimes it failed saying sdb1 could not be found, and then listed the possible partitions -INCLUDING FUCKING sdb1. However, sometimes it did not. One of the things that really fucks me off is an intermittent problem, and here I had one. So I went looking for solutions. I went in the reverse order of the potential problems in the previous paragraph.

I had started with an fstab which used the UUID for the USB Key. That's the long-string-of-letters-and-numbers you find if you look in /dev/disk/by-uuid. However, due to the collossal fuckup that was trying to boot, I reverted to mounting the drive by reference to its label, which I called 'amiga', way back when I formatted it in the configuration stages. Why are either of these options not in the book? The book supposes that you are installing to a Harddisk drive. We are installing to a USB Key. As we have already seen if we shift from PC to PC the /dev/sd{a-d}1 changes. So, if we boot on a PC using an [fstab] file which just references the sdb1 location, for instance, then we'll be fucked if it is not exactly the same. One way we can avoid this is by referring to disks by their UUID number. This is the random string and is allocated at the time of (I think) formatting the disk. The UUID is built into the USB Key and will follow it from machine to machine, so referring to it directly is always going to work. That may, however, have contributed to the grand boot fuckup, as I shall now be calling it. So I switched the fstab to use the label instead. This did not immediately fix the problem, but it is now working and being a strong proponent of the 'if it ain't broke don't fix it' school, I am not fucking around with the fstab file now.

So I had tried fstab. My next move was to try the kernel. I actually went through:

<*> ATA/ATAPI/MFM/RLL support  --->
<*> Serial ATA (prod) and Parallel ATA (experimental) drivers  --->
Sonics Silicon Backplane  ---> (apart from debuggin)
USB

*** NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may ***                                                             
*** also be needed; see USB_STORAGE Help for more info ***
<*>   USB Mass Storage support

and activated every single option I could find. I then compiled what must have been a massive Kernel file. Did it work? Did it fuck.

I then tried to get to grips with the settings for Grub 1.97. Few of them made any sense to me. I couldn't work out what the 'search' line in the configuration file was supposed to do. It looked quite unlike anything in the 0.97 version of grub. I suspected that the problem was the reassignation of drive identities when booting from the USB Key. This is relatively easy to fix in grub 0.97, but most definitely NOT in 1.97. So I decided to use Grub 0.97. The only way I could think to do this (because there is no automatic package management in LFS) was to format the disk and start again. This took a few hours. They were not particularly happy hours. Especially when it changed precisely fuck all about the boot problem.

However, I now at least had a simple grub file to work with. The first thing I could fix was the [root (hdX,X) line. I knew that using the same [hdX] as the Key was using during the install was a bad idea, because it would be reassigned on boot. I changed this to [root (hd0,0)], and this let me at least start the boot. I then got the same error messages as before. I thought that the [kernel=] line may have had a problem with finding the USB Key because of the stupid messages like 'sdb1 cannot be found, try sdb1 instead'. Fucking ridiculous. I thought if I set it find the disk by UUID or Label instead it might fix this. It turns out that you can't do that without configuring an [init]ial [r]am[d]isk. That does not sound like fun, so I turned to the Kernel Documentation instead to try and find an alternative. In there I came across the [rootdelay] option. This tells the Kernel to wait for a specified number of seconds before trying to boot. In particular it lets us wait for the USB Keys to show up. 10 seconds seems to work fine. Once I had put this setting in the grub.lst file, it ACTUALLY FUCKING BOOTED LINUX!

POSSIBLY if hd0,0 and rootdelay=10 AND fstab had been correct it may have worked with grub 1.97. Maybe. So, in case I want to revert to grub 1.97 at some point in the future, I am going to repeat its install commands here. Firstly you need to install the package - run these commands from the /sources directory.

tar -xzvf archive/grub-1.97.2.tar.gz
cd grub-1.97.2
mkdir build 
cd build 
../configure --prefix=/usr --sysconfdir=/etc --disable-grub-emu --disable-grub-emu-usb --disable-grub-fstest --disable-efiemu 

The [sysconfdir] presumably tells the install where to put the configuration files for grub.  According to the book, the [disable] options block program features that we have no need for in LFS.  Fair enough.

make -j2
make install
cd ../..
rm -rvf grub-1.97.2

There is much more to do to install Grub to the boot sector of the disk in question. 

First we setup a [device.map] file, which will be no fucking use once we reboot from the USB Key:

grub-mkdevicemap --device-map=device.map

Let's have a look at the contents:

cat device.map

I got:

(hd0) /dev/sda 
(hd1) /dev/sdb 
(hd2) /dev/sdc

[sda] is the harddisk in my laptop. [sdb] is the USB Key which the LiveCD is running from. [sdc] is the USB Key which has Linux From Scratch installed on it. To install the operative files for grub (as opposed to installing the package which we did earlier) I ran this command:

grub-install --grub-setup=/bin/true /dev/sdc

The [grub-setup=/bin/true] option makes sure that the actual MBR remains untouched for the time being. We can now automatically make the configuration file for grub:

grub-mkconfig -o /boot/grub/grub.cfg

This produced these messages:

Generating grub.cfg ... 
Found linux image: /boot/vmlinux-2.6.32.8-lfs-6.6 
done

I then ran the following command to install Grub to the MBR of the USB Key:

grub-setup /dev/sdc 

And that should be that. Only it won't be. We'll have to change the grub.cfg and probably device.map to reflect the reality of what will happen when the USB Key is the boot device.  And I am bollocksed if I am going to work out how to do that when 0.97 just bloody works.

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

Wednesday 28 July 2010

LAP - Actual Build - Part 8, Stripping Scripts

This is less exciting than the title may have lead you to believe.

From the book, "[i]f the intended user is not a programmer and does not plan to do any debugging on the system software".  Hmm.  Cough, cough.  OOOOOOH FUCK, YES THAT'S ME.

To make sure that we are clear to strip the files we need to exit the chroot:

logout

Now, when I wanted to exit the chroot environment to either mount the sources directory or download nano, I just automatically ran 'exit'.  Apparently, however, the flavour of the day is 'logout'...  Followed straight away by chrooting back in:

sudo chroot "/media/lfs" /tools/bin/env -i HOME=/root TERM="$TERM" PS1='\u:\w\$ ' PATH=/bin:/usr/bin:/sbin:/usr/sbin CORES_TO_USE=-j2 /tools/bin/bash --login 

What we omit this time around is the [/tools/bin] bit of the PATH, because of course it is no longer needed, and the [+h] option to the [bash] shell option.  For some reason though, we are still running the Toolchain [bash] instead of the newly built one.

/tools/bin/find /{,usr/}{bin,lib,sbin} -type f -exec /tools/bin/strip --strip-debug '{}' ';'

This command uses the Toolchain [find] command to apply the command [strip] with option [strip-debug] to every [f] regular file type in the directories specified.

If, for any reason we need to exit the Chroot, then instead of running the command set out in Part 1, we need to run the following command instead:

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

The next thing we need to do is install the LFS scripts that the SysVInit programs are going to use to get everything up and running on boot.  First change into the correct directory, if not already there:

cd /tmp
tar -xjvf /sources/lfs-bootscripts-20100124.tar.bz2
cd lfs-bootscripts-20100124
make install

This installs a lot of scripts, perhaps the most important is the 'rc' script that we saw referenced as a command in the SysVInit configuration file.  What you basically end up with is a directory in /etc called rc.d.  It is common in Linux from configuration files to get so unwieldy that they effectively end up as directories of individual configuration files.  When that happens you tend to append '.d' to the end of the original filename to signify that it is now a directory.

That directory contains a further directory called init.d, in which there are the scripts we have just installed which run the various boot commands.  The rc.d directory also contains other folders rc{0-6}.d  which contain symbolic links to the scripts in init.d.  The way these scripts are named are important.  They start with an 'S' if they start a script and 'K' of they stop a script.  That is followed by a number which denotes the order the scripts in the folder are run.

cd ..
rm -rvf lfs-bootscripts-20100124

Next we setup the clock configuration file.  The UTC=1 means that we are one hour ahead of UTC.  You can find the appropriate number for you by running:

hwclock --localtime --show

If that time is an hour behind your watch then UTC=1, as it does for me.  If it is 7 hours ahead then presumably your number is UTC=-7.  Check out a LFS hint explaining all this here.

cat > /etc/sysconfig/clock << "EOF"
# Begin /etc/sysconfig/clock
UTC=1
# Set this to any options you might need to give to hwclock,
# such as machine hardware clock type for Alphas.
CLOCKPARAMS=
# End /etc/sysconfig/clock
EOF

The next file configures various settings for the console.  I am selecting only the [uk] [KEYMAP].  I am keeping the [FONT] command in, but because I have no idea what it does I am commenting [#] it out.

cat > /etc/sysconfig/console << "EOF"
# Begin /etc/sysconfig/console
KEYMAP="uk"
#FONT="lat1-16 -m 8859-1"
# End /etc/sysconfig/console
EOF

Next the "The inputrc file handles keyboard mapping for specific situations."  Which is pretty damn vague.  I think it sets up how the text input to the command line is actually handled.

cat > /etc/inputrc << "EOF"
# Begin /etc/inputrc
# Modified by Chris Lynn 

# Allow the command prompt to wrap to the next line
set horizontal-scroll-mode Off

# Enable 8bit input
set meta-flag On
set input-meta On

# Turns off 8th bit stripping
set convert-meta Off

# Keep the 8th bit for display
set output-meta On

# none, visible or audible
set bell-style none

# All of the following map the escape sequence of the value
# contained in the 1st argument to the readline specific functions
"\eOd": backward-word
"\eOc": forward-word

# for linux console
"\e[1~": beginning-of-line
"\e[4~": end-of-line
"\e[5~": beginning-of-history
"\e[6~": end-of-history
"\e[3~": delete-char
"\e[2~": quoted-insert

# for xterm
"\eOH": beginning-of-line
"\eOF": end-of-line

# for Konsole
"\e[H": beginning-of-line
"\e[F": end-of-line

# End /etc/inputrc
EOF

We are now going to skip ahead to the BLFS book, and will install their [/etc/profile] scripts. Instead of having a very basic profile file, that file will scan the [/etc/profile.d] directory and will run all scripts in it.

cat > /etc/profile << "EOF"
# Begin /etc/profile
# Written for Beyond Linux From Scratch
# by James Robertson <jameswrobertson@earthlink.net>
# modifications by Dagmar d'Surreal <rivyqntzne@pbzpnfg.arg>

# System wide environment variables and startup programs.

# System wide aliases and functions should go in /etc/bashrc.  Personal
# environment variables and startup programs should go into
# ~/.bash_profile.  Personal aliases and functions should go into
# ~/.bashrc.

# Functions to help us manage paths.  Second argument is the name of the
# path variable to be modified (default: PATH)
pathremove () {
        local IFS=':'
        local NEWPATH
        local DIR
        local PATHVARIABLE=${2:-PATH}
        for DIR in ${!PATHVARIABLE} ; do
                if [ "$DIR" != "$1" ] ; then
                  NEWPATH=${NEWPATH:+$NEWPATH:}$DIR
                fi
        done
        export $PATHVARIABLE="$NEWPATH"
}

pathprepend () {
        pathremove $1 $2
        local PATHVARIABLE=${2:-PATH}
        export $PATHVARIABLE="$1${!PATHVARIABLE:+:${!PATHVARIABLE}}"
}

pathappend () {
        pathremove $1 $2
        local PATHVARIABLE=${2:-PATH}
        export $PATHVARIABLE="${!PATHVARIABLE:+${!PATHVARIABLE}:}$1"
}


# Set the initial path
export PATH=/bin:/usr/bin

if [ $EUID -eq 0 ] ; then
        pathappend /sbin:/usr/sbin
        unset HISTFILE
fi

# Setup some environment variables.
export HISTSIZE=1000
export HISTIGNORE="&:[bf]g:exit"

# Setup a red prompt for root and a green one for users.
NORMAL="\[\e[0m\]"
RED="\[\e[1;31m\]"
GREEN="\[\e[1;32m\]"
if [[ $EUID == 0 ]] ; then
  PS1="$RED\u [ $NORMAL\w$RED ]# $NORMAL"
else
  PS1="$GREEN\u [ $NORMAL\w$GREEN ]\$ $NORMAL"
fi

for script in /etc/profile.d/*.sh ; do
        if [ -r $script ] ; then
                . $script
        fi
done

# Now to clean up
unset pathremove pathprepend pathappend
# End /etc/profile
EOF

Now we make a directory to stick all the little scripts in:
install --directory --mode=0755 --owner=root --group=root /etc/profile.d

And now for the little scripts themselves. The first configures coloured directories when we are [ls]ing around the file system.
cat > /etc/profile.d/dircolors.sh << "EOF"
# Setup for /bin/ls to support color, the alias is in /etc/bashrc.
if [ -f "/etc/dircolors" ] ; then
        eval $(dircolors -b /etc/dircolors)

        if [ -f "$HOME/.dircolors" ] ; then
                eval $(dircolors -b $HOME/.dircolors)
        fi
fi
alias ls='ls --color=auto'
EOF

This next one sets up the paths. Note that at the end of it the path [.] for our current folder is commented out. Uncommenting makes the current directory part of the path. This is described as a security risk though, so we'll leave it commented out just now.
cat > /etc/profile.d/extrapaths.sh << "EOF"
if [ -d /usr/local/lib/pkgconfig ] ; then
        pathappend /usr/local/lib/pkgconfig PKG_CONFIG_PATH
fi
if [ -d /usr/local/bin ]; then
        pathprepend /usr/local/bin
fi
if [ -d /usr/local/sbin -a $EUID -eq 0 ]; then
        pathprepend /usr/local/sbin
fi

if [ -d ~/bin ]; then
        pathprepend ~/bin
fi
#if [ $EUID -gt 99 ]; then
#        pathappend .
#fi
EOF

Don't really know what this does, don't really care:
cat > /etc/profile.d/readline.sh << "EOF"
# Setup the INPUTRC environment variable.
if [ -z "$INPUTRC" -a ! -f "$HOME/.inputrc" ] ; then
        INPUTRC=/etc/inputrc
fi
export INPUTRC
EOF

This next one affects what permissions bullshit is set on new files and folders created.
cat > /etc/profile.d/umask.sh << "EOF"
# By default we want the umask to get set.
if [ "$(id -gn)" = "$(id -un)" -a $EUID -gt 99 ] ; then
  umask 002
else
  umask 022
fi
EOF

We also need to add the X folders to the path - if it is installed.
cat > /etc/profile.d/X.sh << "EOF"
if [ -x /usr/X11R6/bin/X ]; then
        pathappend /usr/X11R6/bin
fi
if [ -d /usr/X11R6/lib/pkgconfig ] ; then
        pathappend /usr/X11R6/lib/pkgconfig PKG_CONFIG_PATH
fi
EOF

And, some localisation crap:
cat > /etc/profile.d/i18n.sh << "EOF"
# Set up i18n variables
export LANG=en_GB.ISO-8859-1
EOF

We also want to setup our prompt:
cat > /etc/bashrc << "EOF"
# Begin /etc/bashrc
# Written for Beyond Linux From Scratch
# by James Robertson <jameswrobertson@earthlink.net>
# updated by Bruce Dubbs <bdubbs@linuxfromscratch.org>

# System wide aliases and functions.

# System wide environment variables and startup programs should go into
# /etc/profile.  Personal environment variables and startup programs
# should go into ~/.bash_profile.  Personal aliases and functions should
# go into ~/.bashrc

# Provides a colored /bin/ls command.  Used in conjunction with code in
# /etc/profile.

alias ls='ls --color=auto'

# Provides prompt for non-login shells, specifically shells started
# in the X environment. [Review the LFS archive thread titled
# PS1 Environment Variable for a great case study behind this script
# addendum.]

NORMAL="\[\e[0m\]"
RED="\[\e[1;31m\]"
GREEN="\[\e[1;32m\]"
if [[ $EUID == 0 ]] ; then
  PS1="$RED\u [ $NORMAL\w$RED ]# $NORMAL"
else
  PS1="$GREEN\u [ $NORMAL\w$GREEN ]\$ $NORMAL"
fi

# End /etc/bashrc
EOF

We also want to set our variable to use multicores when compiling packages. We may want to add other custom variables in the future, so lets name the file something sensible:
cat > /etc/profile.d/custom_variables.sh << "EOF"
# Set up a variable to let us use multicores when compiling
CORES_TO_USE=-j2
EOF

Finally we want to generate a file for the directory colours, not sure why.
dircolors -p > /etc/dircolors

We set the hostname by sending the contents of the following file:

echo "HOSTNAME=amiga" > /etc/sysconfig/network

I am not going to be configuring a network card using scripts.  Instead I am going to use the dhcpcd program (ah, fuck gotta download that as well now) to grab all the network settings from my router.  I still need a hosts file, but we can make it basic:

cat > /etc/hosts << "EOF"
# Begin /etc/hosts (no network card version)
127.0.0.1 amiga.localdomain amiga localhost
# End /etc/hosts (no network card version)
EOF

I am going to replace our earlier resolv.conf with the following entirely commented out version.  The actual DNS services will be handled by my router.

cat > /etc/resolv.conf << "EOF"
# Begin /etc/resolv.conf
#domain 
#nameserver 
#nameserver 
# End /etc/resolv.conf
EOF

And that should complete the configuration scripts.

To summarise, now we have changed our chroot command, the list of commands to get into the chroot from a cold boot LiveCD is as follows:

umount -v /media/amiga
sudo mkdir /media/lfs
sudo mount -v -t ext3 /dev/disk/by-label/amiga /media/lfs
sudo mount -v --bind /dev /media/lfs/dev
sudo mount -vt devpts devpts /media/lfs/dev/pts
sudo mount -vt tmpfs shm /media/lfs/dev/shm
sudo mount -vt proc proc /media/lfs/proc
sudo mount -vt sysfs sysfs /media/lfs/sys
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

From this point on, you should not use the Ramdisk. We will need to keep some source files around - especially the kernel source. Also we will be downloading more source code directly to the Amiga Key. We therefore now need the /sources/ directory to be persistent. So, from now on do not go into /tmp to make your packages; go to /sources instead. I have therefore NOT included the /tmp --bind command in the above list.

Now, onto matters of boot.

Tuesday 27 July 2010

LAP - Actual Build - Part 7, A-Z

We are now moving on to build the remaining packages in roughly alphabetical order.  This suggests to me that either all the dependancy issues have been resolved, or it is a MASSIVE coincidence that the order for the build of all these packages just happens to be alphabetical.

First up is  new package, autoconf.  Like the next package, automake, these are both needed for automatic routines in (re)building software from source code.
tar -xjvf /sources/autoconf-2.65.tar.bz2
cd autoconf-2.65
./configure --prefix=/usr
make $CORES_TO_USE
make $CORES_TO_USE check

## ------------- ## 
## Test results. ## 
## ------------- ## 

414 tests behaved as expected. 
25 tests were skipped.

This one took over 10 minutes on my Quad Core, but it was reduced to under 9 minutes with the ramdisk approach.

make install
cd ..
rm -rvf autoconf-2.65

tar -xjvf /sources/automake-1.11.1.tar.bz2
cd automake-1.11.1
./configure --prefix=/usr --docdir=/usr/share/doc/automake-1.11.1
make $CORES_TO_USE
make $CORES_TO_USE check

===================================== 
1 of 672 tests failed 
(63 tests were not run) 
See tests/test-suite.log 
Please report to bug-automake@gnu.org 
===================================== 

Oh dear.  This is the first unexpected failure that I have come across.  I spent a bit of time looking into this.  The whole report in the test suit about the failure looks like this:

FAIL: acloca22.test (exit: 1)
=============================

/sources/automake-1.11.1/tests:/bin:/usr/bin:/sbin:/usr/sbin:/tools/bin
=== Running test ./acloca22.test
++ pwd
/sources/automake-1.11.1/tests/acloca22.dir
+ set -e
+ cat
+ cat
+ cat
+ cat
+ aclocal-1.11 -Werror -I .
+ automake-1.11 --foreign -Werror -Wall
+ autoconf
+ ./configure
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking for a thread-safe mkdir -p... /bin/mkdir -p
checking for gawk... gawk
checking whether make sets $(MAKE)... yes
configure: creating ./config.status
config.status: creating Makefile
+ make
make: Nothing to be done for `all'.
+ grep GREPFOO Makefile
GREPFOO = 
+ grep GREPBAR Makefile
+ sed s/FOO/BAR/
+ mv -f t configure.in
+ rm -f foo.m4
+ make
CDPATH="${ZSH_VERSION+.}:" && cd . && /bin/sh /sources/automake-1.11.1/tests/acloca22.dir/missing --run aclocal-1.11 -I .
 cd . && /bin/sh /sources/automake-1.11.1/tests/acloca22.dir/missing --run automake-1.11 --foreign
CDPATH="${ZSH_VERSION+.}:" && cd . && /bin/sh /sources/automake-1.11.1/tests/acloca22.dir/missing --run autoconf
make: Nothing to be done for `all'.
+ grep GREPFOO Makefile
GREPFOO = 
+ Exit 1
+ set +e
+ exit 1
+ exit 1
+ exit_status=1
+ set +e
+ cd /sources/automake-1.11.1/tests
+ case $exit_status,$keep_testdirs in
+ test 0 '!=' 0
+ echo 'acloca22: exit 1'
acloca22: exit 1
+ exit 1

I have concluded precisely jack shit from that.  I then googled for 'FAIL: acloca22.test'.  I found some other people on the LFS Mailing list referring to this.  I also, critically found the official build logs for LFS 6.6 here [http://www.linuxfromscratch.org/lfs/build-logs/6.6/core2duo/test-logs/095-automake] which includes another acloca??.test failure.  I have resolved to carry on regardless, and I will see what happens.  It would be spiffing if the book could flag up that this is a problem, like with GCC and its muddy flaps.

make install
cd ..
rm -rvf automake-1.11.1

Next we need bzip2 again:

tar -xzvf /sources/bzip2-1.0.5.tar.gz
cd bzip2-1.0.5

We want to install the documentation for this (no really we do) and this is best achieved by applying a patch with a really simple output:
patch -Np1 -i /sources/bzip2-1.0.5-install_docs-1.patch

patching file Makefile 

sed -i 's@\(ln -s -f \)$(PREFIX)/bin/@\1@' Makefile

A, sed my old friend.  Still as completely fucking impenetrable as ever eh?  The books tells us that “The […] command ensures installation of symbolic links are relative”.  Riiiight.  Again, I know what every word in that sentence means individually but put them together and snorkel my plunge aardvark if I coin my plain!

make -f Makefile-libbz2_so

This is on about dynamic libraries again.  Apparently if the normal Makefile (some sort of script apparently) is used then you don't get the lovely dynamic libraries that are all the rage these days.
make clean

Bit odd that we are doing a make clean at this stage.  Must make sense to someone.

make $CORES_TO_USE
make PREFIX=/usr install

Finally we need to rearrange some of the installed files again:
cp -v bzip2-shared /bin/bzip2 
cp -av libbz2.so* /lib 
ln -sv ../../lib/libbz2.so.1.0 /usr/lib/libbz2.so 
rm -v /usr/bin/{bunzip2,bzcat,bzip2} 
ln -sv bzip2 /bin/bunzip2 
ln -sv bzip2 /bin/bzcat 
cd ..
rm -rvf bzip2-1.0.5

Diffutils was also in the Toolchain.

tar -xzvf /sources/diffutils-2.8.1.tar.gz
cd diffutils-2.8.1

We need another patch to correct a localisation issue.  This has something to do with treating white spaces according to their current locale; which frankly sounds a bit racist to me.
patch -Np1 -i /sources/diffutils-2.8.1-i18n-1.patch

patching file src/diff.c 
Hunk #1 succeeded at 273 (offset -2 lines). 
patching file src/diff.h 
Hunk #1 succeeded at 25 with fuzz 2 (offset 2 lines). 
Hunk #2 succeeded at 362 (offset -1 lines). 
patching file src/io.c 
Hunk #1 succeeded at 25 (offset -1 lines). 
Hunk #2 succeeded at 213 (offset -1 lines). 
Hunk #3 succeeded at 261 (offset -1 lines). 
patching file src/side.c 
Hunk #1 succeeded at 74 with fuzz 1 (offset 1 line). 
Hunk #2 succeeded at 197 (offset 1 line). 
patching file src/util.c 
Hunk #1 succeeded at 312 (offset -9 lines). 
Hunk #2 succeeded at 441 (offset -9 lines). 
touch man/diff.1

Now there is definitely something wrong with [touch man].  Surely.  This step is supposed to correct an error by making the [diff.1] file look as if it has been accessed more recently that is actually the case.  That must be sort sort of bizarre fucking bug to trip up the software based on that issue.

./configure --prefix=/usr
make $CORES_TO_USE
make install
cd ..
rm -rvf diffutils-2.8.1

Gawk is a little out of alphabetical order for some reason.  Again this was in the Toolchain.

tar -xjvf /sources/gawk-3.1.7.tar.bz2
cd gawk-3.1.7
./configure --prefix=/usr --libexecdir=/usr/lib
make $CORES_TO_USE
make $CORES_TO_USE check

This time, happily the result was:
ALL TESTS PASSED

I guess I was right about the locale thingy screwing up the test in the Toolchain build.

make install
mkdir -v /usr/share/doc/gawk-3.1.7
cp    -v doc/{awkforai.txt,*.{eps,pdf,jpg}} /usr/share/doc/gawk-3.1.7

I am going to stop commenting on these commands now - they essentially just manually install the documentation that comes with the package.  They all look a little different, but if you spot a reference to a [doc] directory, that is what it is about.

cd ..
rm -rvf gawk-3.1.7

Another refugee from the Toolchain stumbles across for the final installation, in the form of Findutils.

tar -xzvf /sources/findutils-4.4.2.tar.gz
cd findutils-4.4.2
./configure --prefix=/usr --libexecdir=/usr/lib/findutils --localstatedir=/var/lib/locate

The [localstatedir] option tells the software where to put its [locate] database file.  To be FHS compliant it needs to be in [/var/lib].  I have little concept of exactly what the database is actually used for, but at least I know where it is.
make $CORES_TO_USE
make $CORES_TO_USE check

Running /sources/findutils-4.4.2/xargs/testsuite/xargs.gnu/P3-n1-IARG.exp ... 
FAIL: P3-n1-IARG, wrong stdout output: xargs.out /sources/findutils-4.4.2/xargs/testsuite/xargs.gnu/P3-n1-IARG.xo differ: char 7, line 2 
child process exited abnormally 
[…]
# of expected passes        95 
# of unexpected failures    1 
xargs (GNU findutils) 4.4.2 
make[3]: *** [check-DEJAGNU] Error 1 
make[3]: Leaving directory `/sources/findutils-4.4.2/xargs/testsuite' 
make[2]: *** [check-am] Error 2 
make[2]: Leaving directory `/sources/findutils-4.4.2/xargs/testsuite' 
make[1]: *** [check-recursive] Error 1 
make[1]: Leaving directory `/sources/findutils-4.4.2/xargs' 
make: *** [check-recursive] Error 1 

Cock.  This error is not replicated in the LFS 6.6 log files.  Buggeration.  On a total whim, I re-ran the test with no [j2] multicore enabled.  The failure went away.  Just to test I then re-ran it with the multicore enabled again.  The failure is still gone!  Three cheers for inconsistency and a lack of logic!
make install

Again, we may need the program on boot and if /usr is not mounted it has to be in [/bin].
mv -v /usr/bin/find /bin 
sed -i 's/find:=${BINDIR}/find:=\/bin/' /usr/bin/updatedb

Accordingly to the book that [sed] command is necessary because “[t]he updatedb script also needs to be modified to correct an explicit path ”.  Explicit paths are my favourite kind.  Far better than those coy paths that leave it all up to the imagination.  Sorry, mind wandered there, tends to do that when I am faced with neuron paralyzingly confusing tosh masquerading as a command and the reason for it.
cd ..
rm -rvf findutils-4.4.2

Flex is apparently used for making other programs that see patterns in text.
tar -xjvf /sources/flex-2.5.35.tar.bz2
cd flex-2.5.35

We need to fix a bug in the software by applying a patch:
patch -Np1 -i /sources/flex-2.5.35-gcc44-1.patch
patching file skel.c

./configure --prefix=/usr
make $CORES_TO_USE
make $CORES_TO_USE check

Tests succeeded: 46 
Tests FAILED: 0
On a subsequent build I did get an error:

Results:
Tests succeeded: 45
Tests FAILED: 1
make[4]: *** [check-local] Error 1
make[4]: Leaving directory `/sources/flex-2.5.35/tests'
make[3]: *** [check-am] Error 2
make[3]: Leaving directory `/sources/flex-2.5.35/tests'
make[2]: *** [check-recursive] Error 1
make[2]: Leaving directory `/sources/flex-2.5.35/tests'
make[1]: *** [check-recursive] Error 1
make[1]: Leaving directory `/sources/flex-2.5.35'
make: *** [check] Error 2

The error was with [test-bison-nr]. As with another package, I re-ran the tests without the Multi Core option, and it worked fine.

make install

Flex is a update of a program called lex.  To ensure backwards compatibility we need to make a symbolic link for the library file:
ln -sv libfl.a /usr/lib/libl.a

We also need to make a 'lex' program.  This is not as simple as linking the flex program.  Flex itself has a compatibility mode which makes it work like the old lex program.  So what we do is write a short script called 'lex' which runs flex in the lex compatibility mode.
cat > /usr/bin/lex << "EOF" 
#!/bin/sh
# Begin /usr/bin/lex
exec /usr/bin/flex -l "$@"
# End /usr/bin/lex
EOF
chmod -v 755 /usr/bin/lex

We have not seen the cat ... EOF command for a while, but it works in exactly the same way.  The lines in that file that begin with '#' are treated as comments and have no effect.  So the only line that does anything is the [exec ...] line.

mkdir -v /usr/share/doc/flex-2.5.35
cp    -v doc/flex.pdf /usr/share/doc/flex-2.5.35 
cd ..
rm -rvf flex-2.5.35

Gettext again:

tar -xzvf /sources/gettext-0.17.tar.gz
cd gettext-0.17

The patch here fixes a permissions bug, and therefore automatically gets the thumbs up from me.
patch -Np1 -i /sources/gettext-0.17-upstream_fixes-2.patch

patching file gettext-tools/misc/autopoint.in 
patching file gettext-tools/src/write-catalog.c

./configure --prefix=/usr --docdir=/usr/share/doc/gettext-0.17 
make $CORES_TO_USE
make $CORES_TO_USE check

=================== 
All 30 tests passed 
===================

Excellent.

make install
cd ..
rm -rvf gettext-0.17

Now we have the Kid Frighteningly named Groff.  Following from the last two, this one also is involved in processing text files.

tar -xzvf /sources/groff-1.20.1.tar.gz
cd groff-1.20.1
PAGE=A4 ./configure --prefix=/usr

I've selected A4 here because I am not a burger munching gun enthusiast.  If I was I would have gone for letter.  Even if I got this wrong I could change the setting later in the /etc/papersize file.

make $CORES_TO_USE
make docdir=/usr/share/doc/groff-1.20.1 install

Again, we need some symbolic links for compatibility:

ln -sv eqn /usr/bin/geqn
ln -sv tbl /usr/bin/gtbl
cd ..
rm -rvf groff-1.20.1

The next package, for a change, is not involved in processing fucking text files.  It's an old favourite Gzip, from the Toolchain. Now, the eagle-eyed amongst you may have noticed that the book installs Grub 1.97 at this point. I am not going to. I will go into the problems in more detail elsewhere, but for now, I am going to use Grub 0.97 instead, and we will install and configure that later.

tar -xzvf /sources/gzip-1.4.tar.gz
cd gzip-1.4
./configure --prefix=/usr --bindir=/bin
make $CORES_TO_USE
make $CORES_TO_USE check

================== 
All 5 tests passed 
================== 

make install

This time we actually move some files OUT of the /bin folder and into /usr/bin, because we know we will not need them before /usr is available if on a separate partition.

mv -v /bin/{gzexe,uncompress,zcmp,zdiff,zegrep} /usr/bin
mv -v /bin/{zfgrep,zforce,zgrep,zless,zmore,znew} /usr/bin
cd ..
rm -rvf gzip-1.4

IP Route contains a bunch of network utils.  It does not contain stuff that I usually use, but is presumably necessary for other programs.

tar -xjvf /sources/iproute2-2.6.31.tar.bz2
cd iproute2-2.6.31

Part of the package would require something to do with Berkeley DB, which I presume to be a Database made at the Berkeley University.  We are not going to bother with it, and we don't care about that particular part of this package, so we stop it installing by, yes, a sed command:
sed -i '/^TARGETS/s@arpd@@g' misc/Makefile

make $CORES_TO_USE DESTDIR=

This is the make command, and it defaults to /usr so we do not need to add anything to the [DESTDIR=] option.

make $CORES_TO_USE DESTDIR= SBINDIR=/sbin MANDIR=/usr/share/man DOCDIR=/usr/share/doc/iproute2-2.6.31 install

The make ... install contains some options that we would usually see applied to the configure script.  You'll note we have not run one, so we shouldn't grumble that we have to apply them to the make ... install

cd ..
rm -rvf iproute2-2.6.31

The kbd package, a development only surprising to those astonished at the sun's continual rising, relates to the keyboard.  It has programs to do stuff like handle the LEDs and change keyboard maps.

tar -xzvf /sources/kbd-1.15.1.tar.gz
cd kbd-1.15.1

This package does not come with a configure script.  If only we have some sort of utility to create a configure script...  Oh, yes - remember autoconf:

autoreconf

The backspace/delete keys have odd behaviour unless patched, so lets patch.
patch -Np1 -i /sources/kbd-1.15.1-backspace-1.patch

patching file data/keymaps/i386/dvorak/dvorak-l.map 
patching file data/keymaps/i386/dvorak/dvorak-r.map 
patching file data/keymaps/i386/fgGIod/tr_f-latin5.map 
patching file data/keymaps/i386/qwerty/lt.l4.map 
patching file data/keymaps/i386/qwerty/lt.map 
patching file data/keymaps/i386/qwerty/no-latin1.map 
patching file data/keymaps/i386/qwerty/ru1.map 
patching file data/keymaps/i386/qwerty/ru2.map 
patching file data/keymaps/i386/qwerty/ru-cp1251.map 
patching file data/keymaps/i386/qwerty/ru-ms.map 
patching file data/keymaps/i386/qwerty/ru_win.map 
patching file data/keymaps/i386/qwerty/se-ir209.map 
patching file data/keymaps/i386/qwerty/se-lat6.map 
patching file data/keymaps/i386/qwerty/tr_q-latin5.map 
patching file data/keymaps/i386/qwerty/ua.map 
patching file data/keymaps/i386/qwerty/ua-utf.map 
patching file data/keymaps/i386/qwerty/ua-utf-ws.map 
patching file data/keymaps/i386/qwerty/ua-ws.map 
./configure --prefix=/usr --datadir=/lib/kbd

As is becoming predictable, the data directory for kbd is normally under /usr, so we need to change that in case /usr is not available at boot time.

make $CORES_TO_USE
make install

Again, because the /usr [blah blah blah blah blah] move these files:
mv -v /usr/bin/{kbd_mode,loadkeys,openvt,setfont} /bin
mkdir -v /usr/share/doc/kbd-1.15.1
cp -R -v doc/* /usr/share/doc/kbd-1.15.1
cd ..
rm -rvf kbd-1.15.1

Less is a text file viewer.  If you run a command like man bollocks_utility and the resulting text output is too big for one screen, then you would pipe the output to less, 'man bollocks_utility | less'.  Or you can just run 'less [filename]' and it will let you see the contents.
tar -xzvf /sources/less-436.tar.gz
cd less-436
./configure --prefix=/usr --sysconfdir=/etc
make $CORES_TO_USE
make install
cd ..
rm -rvf less-436

It's make's time in the final build.
tar -xjvf /sources/make-3.81.tar.bz2
cd make-3.81

This patch is described as an upstream patch, which means that the changes it makes will eventually find their way into the next version of the package.
patch -Np1 -i /sources/make-3.81-upstream_fixes-1.patch

patching file job.c 
patching file main.c 
patching file make.h
./configure --prefix=/usr
make $CORES_TO_USE
make $CORES_TO_USE check
351 Tests in 96 Categories Complete ... No Failures :-) 

make install
cd ..
rm -rvf make-3.81

We need the next package to install the manual software.  This lets you run the command 'man [name of program]' and it should bring up the manual pages for the program.
tar -xzvf /sources/man-db-2.5.6.tar.gz
cd man-db-2.5.6
./configure --prefix=/usr --libexecdir=/usr/lib --sysconfdir=/etc --disable-setuid --with-browser=/usr/bin/lynx --with-vgrind=/usr/bin/vgrind --with-grap=/usr/bin/grap

According to the book the [disable-setuid] option "disables making the man program setuid to user man."  What.  The.  Fuck.  Does.  That.  Mean.  ?  Is it actually using the word 'setuid' as a verb?  Because that is the only way it makes grammatical sense.  I mean it still makes no fucking sense sense, but at least it holds together grammatically if you make that assumption.

[with-browser=/usr/bin/lynx] sets the default web browser to lynx.  This is a text only web browser that I have fond memories of using in the early 1990's.  I don't think it has kept up to date with the latest fashions in web page design though.  It is also not installed as as part of LFS, but I may have to explore installing it when I have finished LFS.  If only because the only other web browser that I will be installing is Aweb - the Amiga browser!

The vgrind and grap programs are also not installed.  They are apparently connected to the Groff program, and I cannot be bothered to work out what they actually do, as I have no intention of installing them.
make $CORES_TO_USE
make $CORES_TO_USE check
=================== 
All 11 tests passed 
===================

make install
cd ..
rm -rvf man-db-2.5.6

Modules are a little bit odd.  To the best of my guesses, what happens is that some hardware drivers are built into the Kernel itself, and some are left to be loaded or unloaded as the mood takes the users of the system.  Stuff that can be loaded or unloaded is know as a kernel module and the following package contains tools to manage them.

tar -xjvf /sources/module-init-tools-3.11.1.tar.bz2
cd module-init-tools-3.11.1

Now, strangely at this stage the book gets what I can only describe as bitchy.  And I quote:

The testsuite of this package is geared towards the needs of its Maintainer. The command make check builds a specially wrapped version of modprobe which is useless for normal operation.

Useless, I tell you.  Geared towards the needs of its Maintainer!  Really?  Want to elaborate, or did he just steal someone's signature file and not give proper attribution?  Anyway, giving a nod to the Maintainer lets run this testsuite anyway.

./configure
make check

Right enough actually, we are definitely in the realm of screeds and screeds of crap rather than simple messages and smiley faces.

./tests/runtests

The most relevant message I got was:
configure: WARNING: docbook2man not found

Hmmm.  Maybe the bitchiness was justified after all.
make clean
./configure --prefix=/ --enable-zlib-dynamic --mandir=/usr/share/man

Oh fuck a duck, we are asking for a Dynamic Zlib.  Is that not an Eastern European rapper?
make $CORES_TO_USE
make INSTALL=install install

Nice to see someone has worked out how to get stating the fucking obvious into command line operations.  When I look at that though, I cannot help but read it as INSTALL=install (on steroids).  If you are reading on in the hope that that complete bollocks is going to get a meaningful explanation, stop now.
cd ..
rm -rvf module-init-tools-3.11.1

tar -xjvf /sources/patch-2.6.1.tar.bz2
cd patch-2.6.1

One of the tests for patch requires the program 'ed', which we have not installed.  We can change this by, and the irony is not lost on me, patching.
patch -Np1 -i /sources/patch-2.6.1-test_fix-1.patch

patching file tests/crlf-handling 

./configure --prefix=/usr
make $CORES_TO_USE

Aaaaaaaaah:

/sources/patch-2.6.1/src/patch.c:1542: warning: the use of `mktemp' is dangerous, better use `mkstemp' 

Aaaaaa---oh, we have seen and ignored that before haven't we?

make $CORES_TO_USE check

25 tests (25 passed, 0 failed) 
All tests succeeded!

Good.

make install
cd ..
rm -rvf patch-2.6.1

Psmisc is like the second half of the Procps package.  It contains more utilities dealing with information about running processes.
tar -xzvf /sources/psmisc-22.10.tar.gz
cd psmisc-22.10
./configure --prefix=/usr
make $CORES_TO_USE
make install

There is some stuff in the book about a program called pidof.  This is not normally installed, and this is not normally a problem, unless we are not going to install something called sysvinit.  We are going to install sysvinit so we can ign...................zzzzzzz.............zzzz.....wat....snurfle...

cd ..
rm -rvf psmisc-22.10

The shadow program is the one that properly handles passwords.  It also has a cool name.
tar -xjvf /sources/shadow-4.1.4.2.tar.bz2
cd shadow-4.1.4.2

Coreutils has already installed a good program called 'groups', so we do not want shadow to overwrite that.  Sed comes to out rescue.  Yeah for sed!  Wait, what?

sed -i 's/groups$(EXEEXT) //' src/Makefile.in
find man -name Makefile.in -exec sed -i 's/groups\.1 / /' {} \;

Also we need to disable the Korean and Chinese man pages because the man program is racist, or something true but less inflammatory.

sed -i -e 's/ ko//' -e 's/ zh_CN zh_TW//' man/Makefile.in

As this program encrypts passwords, we need to select and encyption mechanism.  The default 'crypt' is not good enough for various technical reasons, so we want to use MD5.  Was that not a robot on Star Wars?  Also we need to account for a change in the recommended location for the 'mail' directory.  Which we will not be using.

sed -i -e 's@#ENCRYPT_METHOD DES@ENCRYPT_METHOD MD5@' -e 's@/var/spool/mail@/var/mail@' etc/login.defs
./configure --sysconfdir=/etc
make $CORES_TO_USE
make install

One, by now routine, program replacement:

mv -v /usr/bin/passwd /bin

Lets also, for the sake of argument assume that we want to actually implement the password security.  We need to run:

pwconv
grpconv

When, or rather if, we add a normal user to the system, we will use the new 'useradd' program that has just been installed.  It will make a mailbox for that new user.  We will most likely not want that to happen, so:
sed -i 's/yes/no/' /etc/default/useradd

The last stage of the shadow install is to finally set our root password for the system we are building on the USB Key.

passwd root

To avoid forgetting it, I am going with 'root' as a reflection of the 'lfs' password I used earlier.  If I do get all this up and running, and security for my Amiga on a USB Key becomes an issue, I will be sure to change it.

cd ..
rm -rvf shadow-4.1.4.2

The kernel spits out messages about the operation of your system on a regular basis – and especially when something odd happens.  The following package contains software to trap these messages and store them in log files.

tar -xzvf /sources/sysklogd-1.5.tar.gz
cd sysklogd-1.5
make $CORES_TO_USE
make BINDIR=/sbin install

We also need to set up the configuration file for the software using the familiar [cat] command:

cat > /etc/syslog.conf << "EOF"
# Begin /etc/syslog.conf
auth,authpriv.* -/var/log/auth.log
*.*;auth,authpriv.none -/var/log/sys.log
daemon.* -/var/log/daemon.log
kern.* -/var/log/kern.log
mail.* -/var/log/mail.log
user.* -/var/log/user.log
*.emerg *
# End /etc/syslog.conf
EOF

The format of the file tells the programs how to deal with certain types of kernel messages.  For example, any messages detected as type [mail] are logged in the [/var/log/mail.log] file.

cd ..
rm -rvf sysklogd-1.5

The next package sounds similar, but that is only because it is adjacent in the alphabet.  The SysVInit package contains software which controls how the System boots up and shuts down.  This is not the old autoexec.bat or config.sys from the old DOS days, but instead is software which controls the boot process itself.  LFS uses a run levels system.  The idea is that there are several levels of computer 'awakeness' and certain software is configure to run at certain runlevels.  So, for instance, you would have your low level stuff like logging scripts (in the last package) on a fairly low runlevel, whereas something more glitzy like a graphical interface would be in a higher runlevel.  It works in reverse at shutdown time.  The higher runlevel software is closed down first, and then these programs descend through the runlevels until the machine is halted.
tar -xzvf /sources/sysvinit-2.86.tar.gz
cd sysvinit-2.86

We first need to make a message make more sense by changing it using … sed.

sed -i 's@Sending processes@& configured via /etc/inittab@g' src/init.c

We have also already installed the 'wall' program which is also included in this package.  We suppress its installation as follows:

sed -i -e 's/utmpdump wall/utmpdump/' -e 's/mountpoint.1 wall.1/mountpoint.1/' src/Makefile
make $CORES_TO_USE -C src

The [C] command just changes to the [src] directory before running the command.  Sounds to me like the same as running [cd src & make $CORES_TO_USE] but hey ho,
make -C src install

The configuration file for SysVInit is one of the most complicated we have seen so far:

cat > /etc/inittab << "EOF"
# Begin /etc/inittab
id:3:initdefault:
si::sysinit:/etc/rc.d/init.d/rc sysinit
l0:0:wait:/etc/rc.d/init.d/rc 0
l1:S1:wait:/etc/rc.d/init.d/rc 1
l2:2:wait:/etc/rc.d/init.d/rc 2
l3:3:wait:/etc/rc.d/init.d/rc 3
l4:4:wait:/etc/rc.d/init.d/rc 4
l5:5:wait:/etc/rc.d/init.d/rc 5
l6:6:wait:/etc/rc.d/init.d/rc 6
ca:12345:ctrlaltdel:/sbin/shutdown -t1 -a -r now
su:S016:once:/sbin/sulogin
1:2345:respawn:/sbin/agetty tty1 9600
2:2345:respawn:/sbin/agetty tty2 9600
3:2345:respawn:/sbin/agetty tty3 9600
4:2345:respawn:/sbin/agetty tty4 9600
5:2345:respawn:/sbin/agetty tty5 9600
6:2345:respawn:/sbin/agetty tty6 9600
# End /etc/inittab
EOF

OK, lets have a go at picking that apart.  Any line starting with '#' is a comment only, and is ignored.  The [id] line tells the system the default runlevel to use.  We should see this increasing when we install 'X'.  The line [si] I think just tells the system to run this package.  Then you have a list of 0-6 runlevels and the command to run at each runlevel.  The command is [rc] with an option [0-6].  What happens then is, I think, that the [rc] command runs all the scripts it finds in differently numbered folders.  These particular scripts are set up later in the installation.  Some programs which are installed will put their own scripts into these folders so they auto run on boot.  I will have to give some consideration to doing this with the Amiga software.

The [ca] line sets up what happens when you hold down CTRL, ALT and DELETE.  The next line says what happens when the root user logs in.  The last six lines of the file set up the six terminals that you can switch between using CTRL + ALT + F1-6 when the system boots.

Well, that sounded good.  Could be a complete load of shite though.  There is a man page [http://www.netadmintools.com/html/5inittab.man.html] with some more information.

cd ..
rm -rvf sysvinit-2.86

It's tar's turn to be reinstalled in final form.

tar -xjvf /sources/tar-1.22.tar.bz2
cd tar-1.22
./configure --prefix=/usr --bindir=/bin --libexecdir=/usr/sbin
make $CORES_TO_USE
make $CORES_TO_USE check
## ------------- ## 
## Test results. ## 
## ------------- ## 

69 tests were successful. 
8 tests were skipped. 
make install
cd ..
rm -rvf tar-1.22

Texinfo again.
tar -xzvf /sources/texinfo-4.13a.tar.gz
cd texinfo-4.13
./configure --prefix=/usr
make $CORES_TO_USE
make $CORES_TO_USE check

I take back the charitable comments I made about the error reports in the Toolchain build.  On reviewing the reports this time around, it is the screeds and screeds of crap type of report but with the following types of messages liberally strewn throughout the aforementioned screeds and screeds of crap:

================== 
All [x] tests passed 
================== 

Can I bothered scanning through all the screeds and screeds of crap looking for these messages to make sure everything is OK?  No Mr Texinfo maintainer, I fucking can't.  Sort this bullshit out.

make install

According to the book, we can install "the components belonging in a TeX installation", if we want to.  I have no idea whatsoever that this means.  Erring on the side of safety, lets just install it anyway.

make TEXMF=/usr/share/texmf install-tex
cd ..
rm -rvf texinfo-4.13

As we saw way back when setting up the directory structure and mounting the virtual file systems, we need some software to manage the hardware devices attached to the system.  The package for this is 'udev'.

tar -xjvf /sources/udev-151.tar.bz2
cd udev-151

Firstly, we need to some special LFS configuration files to configure udev:
tar -xvf /sources/udev-config-20100128.tar.bz2

We need to create some particular files and directories that udev cannot create for itself.  This is very similar to what we did when we were setting up for the Chroot:

install -dv /lib/{firmware,udev/devices/{pts,shm}}
mknod -m0666 /lib/udev/devices/null c 1 3
ln -sv /proc/self/fd /lib/udev/devices/fd
ln -sv /proc/self/fd/0 /lib/udev/devices/stdin
ln -sv /proc/self/fd/1 /lib/udev/devices/stdout
ln -sv /proc/self/fd/2 /lib/udev/devices/stderr
ln -sv /proc/kcore /lib/udev/devices/core
./configure --prefix=/usr --sysconfdir=/etc --sbindir=/sbin --with-rootlibdir=/lib --libexecdir=/lib/udev --docdir=/usr/share/doc/udev-151 --disable-extras --disable-introspection

The [with-rootlibdir=/lib] option sets where the library is to be installed instead of /usr because /usr may not be avail..............zzzzzzzzzzzzzzzzzzz.  The [libexecdir=/lib/udev] option sets the directory to use to install the configuration files.  The [disable-extras] and [disable-introspection] stop particular parts of udev being installed which are not necessary for LFS, and which would require other packages to be installed.
make $CORES_TO_USE
make install

The following commands install particular support for RAID [http://en.wikipedia.org/wiki/RAID], "device-mapper" (wtf?), hand held devices, and ISDN.  The latter two have a distinct 1990's whiff about them I have to say.
install -m644 -v rules/packages/64-*.rules /lib/udev/rules.d/
install -m644 -v rules/packages/40-pilot-links.rules /lib/udev/rules.d/
install -m644 -v rules/packages/40-isdn.rules /lib/udev/rules.d/

Then we need to install the special LFS config files that we unpacked earlier.

cd udev-config-20100128
make install
make install-doc
cd ../..
rm -rvf udev-151

At this point if we were following the instructions, we would install the vim text editor.  I have tried to use vim in the past, and ... fuck that shit.  I am going for 'nano' instead.  I have already managed to build that successfully, simply as an example.  Lets do it. 

So lets just 'wget' the nano...  Oh bollocks, we don't have wget installed.  Right.  Hmm.  OK, lets try this:
exit

This quits the Chroot environment, and our LiveCD image
cd /media/lfs/sources
sudo wget http://www.nano-editor.org/dist/v2.1/nano-2.1.10.tar.gz

Then we go back into the Chroot:

sudo chroot "/media/lfs" /tools/bin/env -i HOME=/root TERM="$TERM" PS1='\u:\w\$ ' PATH=/bin:/usr/bin:/sbin:/usr/sbin:/tools/bin CORES_TO_USE=-j2 /tools/bin/bash --login +h
cd /tmp

We should now have the nano source code /sources in this folder.  What we might want to do is download this right at the beginning, which would save a hop, skip and a jump to download it at this stage.
tar -xzvf /sources/nano-2.1.10.tar.gz
cd nano-2.1.10
./configure --prefix=/usr --sysconfdir=/etc/nano --enable-color --enable-multibuffer --enable-nanorc

The [enable-color] command ... oh fuck off and work it out yourself.  [disable-multibuffer] disables multiple file buffers.  Not entirely sure what that means.  The [enable-nanorc] allows nano to be configured using .nanorc files in each users home directory.  We will setup a system wide nanorc file in the /etc/nano directory below.

In a spectacular turn of events, and completely unlike my attempts elsewhere in my blog, I id not get screeds and screeds of error messages.  Splendid.

make $CORES_TO_USE

Still no massive fuckups!

make install
install -v -m644 -D doc/nanorc.sample /etc/nano/nanorc.sample
install -v -m755 -d /usr/share/doc/nano-2.1.10
install -v -m644 doc/{,man/,texinfo/}*.html /usr/share/doc/nano-2.1.10

The helpfully named nanorc.sample file can be perused at your leisure if you are particularly interested in how text based text editors present themselves.  Let me know how that goes from you if you can tear yourself away from your album you sick philatelist.  For the rest of us, we would install a global configuration file as follows:

cat > /etc/nano/nanorc << "EOF"
set autoindent
set const
set fill 72
set historylog
set multibuffer
unset nohelp
set regexp
set smooth
set suspend
EOF

Brilliantly, BLFS recommends the option 'set nohelp'.  Hmm.  Text based text editor.  Complicated key sequences for commands.  Unintuitive interface.  'nohelp'?  hahahahahahahaha, fuck that.  That's why I have gone for 'unset nohelp' as a double negative opposite to the suggestion.

cd ..
rm -rvf nano-2.1.10

And, that, as they say, is that for the main software build.