How to Modify Red Hat Boot Disks and Driver Disks


I don’t have time to fix the documentation that follows, so here’s a short rendition from memory of how you go about merging drivers from drvnet.img into boot.img. Again, this is from memory, so just use your best judgement. I will accept any corrections to it.

# Let’s make a working directory for us

mkdir /tmp/workspace

# Now let’s grab the bits we wish to merge with boot.img

cd /tmp/workspace
cp -a /mnt/cdrom/images/drvnet.img .
mkdir drvnet.img.dir
mount drvnet.img drvnet.img.dir -o loop,ro
mkdir stufftoadd
cd drvnet.img.dir
cp -a modules.cgz pcitable modinfo modules.dep ../stufftoadd
(Note that modinfo might be listed with some other name mod-info or modules.info)
cd ../stufftoadd
mkdir modules
cd modules
zcat ../modules.cgz | cpio -idvm
umount drvnet.img.dir
rmdir drvnet.img.dir
rm drvnet.img

# Now let’s start working with boot.img

cd /tmp/workspace
cp -a /mnt/cdrom/images/boot.img .
mkdir boot.img.dir
mount boot.img boot.img.dir -o loop,rw
cp -a boot.img.dir/initrd.img .
mv initrd.img initrd.img.gz
gunzip initrd.img.gz
mkdir initrd.img.dir
mount initrd.img initrd.img.dir -o loop,rw
mkdir modifiedstuff
cd initrd.img.dir/modules
cp -a modules.cgz pcitable modinfo modules.dep ../../modifiedstuff
(Note that modinfo might be listed with some other name mod-info or modules.info)
cd /tmp/workspace/modifiedstuff
mkdir modules
cd modules
zcat ../modules.cgz | cpio -idvm
cd /tmp/workspace

Now select your drivers from /tmp/workspace/stufftoadd/modules and add them to /tmp/workspace/modifiedstuff/modules.
When ready to repack modules.cgz, then use:

cd /tmp/workspace/modifiedstuff/modules
find . -type f | cpio -o -H crc | gzip -n9 >../modules.cgz

Also edit the other 3 files in /tmp/workspace/modifiedstuff: pcitable, mod-info, and modules.dep.

pcitable is responsible for autoloading of the drivers
Please don’t allow duplicate lines for any given “vendor id” and “device id” combination.
Some devices have more than one driver so choose only 1 driver.

mod-info provides text information to the user during installation about a given driver.

modules.dep, if your driver requires other modules to be loaded first then this file will cause them to load.

Once you have modified these 4 files to your satisfaction (modules.cgz, modules.dep, modinfo, pcitable) then compare the sizes with those in /tmp/workspace/initrd.img.dir/modules/. When working with these floppy images space is very tight. You may be able to get these 4 files into initrd.img; however, the initrd.img may not fit back on boot.img. Remember to make space in modules.cgz by deleting out drivers you know that you will not be using. I usually try remove the same amount that I add. Of course you don’t need to worry with space if you’re doing a pxe install.

After you are happy with the sizes then lets repack (stop if you get an error, fix it, then proceed):

cd /tmp/workspace/modifiedstuff
cp -a modules.cgz pcitable modules.dep modinfo /tmp/initrd.img.dir/modules
(Note that modinfo might be listed with some other name mod-info or modules.info)
dd if=/dev/zero of=/tmp/initrd.img.dir/zero >/dev/null 2>&1
rm /tmp/initrd.img.dir/zero
cd /tmp/workspace
umount initrd.img.dir
rmdir initrd.img.dir
gzip -n9 initrd.img
mv initrd.img.gz initrd.img
mv initrd.img boot.img.dir
umount boot.img.dir
rmdir boot.img.dir

If no errors then your boot.img should now be populated with the drivers you put in.


The following is in a bit of a mess so don’t rely on the following too much for detailed instructions. Basically the only thing messed up is which directories I say I’m working with. So the content is good, just don’t create a script out of it line for line.

  1. Set up a workplace
  2. 
    mkdir /tmp/unpack
    cd /tmp/unpack
    
  3. Grab something to work with
  4. 
    cp /mnt/cdrom/images/boot.img .
    
  5. Dig into the disk (any of boot.img, bootnet.img, drivers.ing, etc…)
  6. 
    mkdir disk.dir
    mount boot.img disk.dir -o loop
    
  7. Grab a copy of the initrd and uncompress it
  8. 
    cp disk.dir/initrd.img initrd.img.gz
    gunzip initrd.img.gz
    
  9. Dig into the initrd
  10. 
    mkdir initrd.dir
    mount initrd.img initrd.dir -o loop
    
  11. What is important in the initrd
  12. Initrd calls /linuxrc which then loads drivers from the modules.cgz file which resides in the /modules directory (in the same initrd file). If all you are doing is adding in modules for different hardware into one of the default Red Hat boot disks, then you only need to modify the files that exist in the /modules directory. Files of interest in the /modules directory are module-info, modules.dep, pcitable, and modules.cgz.

  13. Dig into the modules.cgz file
  14. 
    mkdir /tmp/unpack/modules
    cd /tmp/unpack/modules
    zcat /tmp/unpack/initrd.dir/modules/modules.cgz | cpio -idvm
    mkdir /tmp/unpack/work
    cd /tmp/unpack/initrd.dir/modules
    cp -a * /tmp/unpack/work
    cd /tmp/unpack
    
  15. Modifying modules.cgz
    • Add and subtract modules to and from modules.cgz as necessary.
    • You may grab modules from one of the other boot disks available (boot.img, bootnet.img, drivers.img, drvblock.img, drvnet.img, etc).
    • Remember to keep track of how much space you are using inside modules.cgz, or your initrd may not fit back on the boot disk.
    • If the module you need is not present on one of these disk images then you will need to build the module. Building the module is easy
      • Use my kernel page (Compiling linux kernel) as a guide. Here is a summary:
      • 
        cd /usr/src/linux-2.4.7-10
        make mrproper
        make clean
        cp configs/kernel-source-2.4.7-i386-BOOT.config .config
        

        Use the kernel-source-2.4.x-i386-BOOT.config as a starting guideline.

        
        vi Makefile
        

        Change the extraversion line to read -10BOOT for RH72 (RH72 uses a 2.4.7-10 kernel)

        
        make xconfig
        

        Use “make xconfig” to make sure that your driver is turned on as a module, then save and exit.

        
        make dep modules modules_install
        

        You should end up with the 2.4.7-10BOOT modules residing in /lib/modules/2.4.7-10BOOT. If you get any errors don’t worry, just check if your module has been created yet or not

        
        find . -name sim710
        

        If you have a “.o” file for your driver, then you’re done. Take that .o file with you back to your /tmp/unpack/modules/2.4.7-10BOOT directory.

  16. Modifying module-info
    • (Step 7 copied the “to be modified” copy of this into /tmp/unpack/work)
    • Follow the same format that exists in module-info
    • First see if there is an existing entry you can copy over from where you are getting the driver (such as from a different boot disk or from one of the drivers disks)
    • Second, see if you have an entry in your systems /boot/module-info that you can use
    • Otherwise create your own multi-line entry, such as:

    • sym53c8xx
      scsi
      "Symbios 53C896"

  17. Modifying modules.dep
    • (Step 7 copied the “to be modified” copy of this into /tmp/unpack/work)
    • Look in modules.dep (or dep-info) to see if your module depends on other modules. If your module isn’t listed in modules.dep (or if modules.dep is empty) then your module has no dependancies.
    • Follow the existing format in the file.
    • First, try to get a copy from where you got the driver (such as a boot disk or drivers disk).
    • Second, if you made your own driver then check in your systems /lib/modules/2.4.7-10/modules.dep. Please note that you should convert the format if you use information from your systems modules.dep – specifically your system will have a full path listed, please strip off this full path and only leave the drivername – further please remove all “.o” extensions.
    • Sample:
      
      usb-storage: usbcore scsi_mod
      usb-ohci: usbcore
      usb-uhci: usbcore
      vfat: fat
      
  18. Modifying pcitable
  19. Automatic loading of drivers is provided by pcitable. You will need a pcitable if you want kickstart to be fully automatic. If you don’t use “pcitable” then the driver will not automatically load and you will have to pick it from a list of drivers.
    This file is a tab separated list of vendor id, device id, driver module, and description.
    A vendor id mearly identifies the vendor. For example 0x8086 represents Intel and 0x0e11 represents Compaq.
    A vendor id and device id pair represents a specific pci device that a manufacturer makes.
    A device id identifies a particular device that a manufacturer makes. A device id is useless without the corresponding vendor id.
    A pci device should have only 1 entry in pcitable. There should not be multiple lines for a given pci device (vendor id and device id pair).
    Sometimes there are two or more drivers that will work for a particular pci device (vendor id and device id). For example certain network cards are supported by both tg3 and bcm5700.

    After adding in more lines to this file, remember to delete out any duplicate lines. Sort may help you out here. Uniq will probably not help, especially if you have 2 entries with different drivers for a single device.

    You can get a copy of pcitable from many places. Usually the best place is where you copied the driver from.

    You can also maintain a “master” pcitable which you keep up to date with all new hardware entries you require. This one “master” pcitable should work for most all versions of Red Hat Linux (and Fedora) versions that support pcitable. Basically try grabbing the latest pcitable available you can find.

    If pcitable isn’t working for you then most likely your tabs have been converted to spaces, go look again. Copy/paste generally converts tabs to spaces. I suggest the following method which uses “cat” to copy entries from one pcitable to another:

    In this example our main pcitable to update is located here:

    initrd.img.dir/modules/pcitable

    and we will be copying entries from the following pcitable:

    driverdisk/pcitable

    First we get only the driver we’re interested in, let’s grab the tg3 entries:

    cat driverdisk/pcitable | grep ‘”tg3″‘

    Now that output looks good, let’s append that to our main pcitable. Please be careful and use the DOUBLE greater than sign and not the single. Single overwrites and double will append to.:

    cat driverdisk/pcitable | grep ‘”tg3″‘ >> initrd.img.dir/modules/pcitable

    Remember to make sure you don’t have duplicate lines elsewhere in the pcitable file. Also take into consideration that the pci device might be in there but be using a different driver. You could try editing your main pcitable in vi and use:

    :%!sort

    Remember that :q! is the safe way out of vi if you mess things up.

    Another way of checking is (not tested but non-destructive):

    cat initrd.img.dir/modules/pcitable | awk ‘{print $1 $2}’ | wc -l
    cat initrd.img.dir/modules/pcitable | awk ‘{print $1 $2}’ | sed -e ‘s/ //g’ -e ‘s/\t//g’ | sort | uniq | wc -l

    The two lines should return the same answer. If the 2nd line is less than the first then you still have duplicate entries.

    Also you can change which driver gets loaded by changing the item in quotes. For example if you want to use the bcm5700 driver instead of the tg3 driver, then change “tg3” to be “bcm5700”. Then the bcm5700 driver will be automatically loaded (assuming the driver .o file is present).

    A substitute command in vi can be done as follows to change over from one driver to another:

    :%s/”tg3″/”bcm5700″/

  20. Repacking modules.cgz
  21. 
    cd /tmp/unpack/modules
    find . -type f | cpio -o -H crc | gzip -n9 >../modules.cgz
    mv ../modules.cgz .
    
  22. Repacking initrd.img
  23. Before moving modules.cgz back into the initrd, make sure that it is the same size or smaller than the original one.

    
    cd /tmp/unpack
    ls -ltr initrd.dir/modules/modules.cgz modules.cgz
    

    If the new modules.cgz is bigger than the original modules.cgz, then you will most likely get the modules.cgz back into the initrd.img; however, the initrd.img, will then probably be too big for the boot floppy. Consider throwing drivers you don’t need out of modules.cgz such as SCSI or Network Cards you don’t have or don’t plan on using. Even though there is plenty of space available in the initrd.img, there is only so much space available in the boot disk – and gzip is expecting much of the initrd.img file to be blank.

    Do the same kind of check on any of the other files you modified, such as modules.cgz, modules.dep, module-info, and pcitable, etc.

    
    cd /tmp/unpack
    for X in modules.dep, modules.cgz, module-info, pcitable; do \
    ls -ltr modules/$X initrd.dir/modules/$X; done
    

    Once you have compared the sizes of the various files then place them back into the initrd.dir.

    
    cd /tmp/unpack
    mv modules/modules.cgz initrd.dir/modules/modules.cgz
    mv modules/modules.dep initrd.dir/modules/modules.dep
    mv modules/module-info initrd.dir/modules/module-info
    mv modules/pcitable initrd.dir/modules/pcitable
    

    We need to blank out the unused portions of initrd – this is needed so gzip doesn’t try to compress data that we have already deleted out.

    
    cd /tmp/unpack
    dd if=/dev/zero of=initrd.dir/zero
    rm initrd.dir/zero
    
    Something similar to the following is expected:
    dd: writing to `initrd-everything/zero': No space left on device
    7479+0 records in
    7478+0 records out
    
    

    Unmount initrd.dir

    (This action finishes writing any cached information out to initrd.img, then it disconnects initrd.img from the initrd.dir directory. This behavior is just the same as working with a floppy under Linux – mount the floppy, work with it, unmount it – unmounting the floppy finishes writing any leftover information to the floppy, then returns to the prompt).

    
    cd /tmp/unpack
    umount initrd.dir
    

    Now gzip up initrd.img

    Note: The “file” utility can tell you if a file is compressed or not.

    
    cd /tmp/unpack
    gzip -9 -n initrd.img
    mv initrd.img.gz initrd.img
    
  24. Repacking the Disk
  25. Before moving the initrd.img back into the disk image, make sure that it is the same size or smaller than the original one.

    
    cd /tmp/unpack
    ls -ltr initrd.img disk.dir/initrd.img
    

    If you need more space in the disk image, you are able to remove all the disk.dir/*.msg files, but that is just about all the extra space you can get.

    Place the initrd.img back into the disk image

    
    cd /tmp/unpack
    mv initrd.img disk.dir/initrd.img
    

    Unmount the disk image – see note above on unmounting initrd.img for an understanding of why it is necessary to unmount the disk image.

    
    cd /tmp/unpack
    umount disk.dir
    
  26. Troubleshooting steps if initrd.img no longer fits on the boot disk
    • Try unpacking the initrd.gz, moving out your modules/* files, blanking the empty space with “dd if=/dev/zero of=initrd.dir/zero; rm initrd.dir/zero”, then move your modules back into your initrd.dir, then repack initrd. Try putting it back onto your boot disk.
    • Thin out unneeded drivers from modules.cgz.
    • Make sure you are using maximum compression and leaving out unnecessary details:
    • 
      find 2.4.7-10BOOT/ | grep -v "BOOT/$" | cpio -o -H crc >modules.cpio
      gzip -9 -n modules.cpio
      gzip -9 -n initrd.img
      
  27. Notes on initrd
  28. Important parts of an initrd are as follows:
    
    When initrd boots, it immediately runs /linuxrc
    
    SCSI modules are located in the /lib directory
    
    bin
     insmod
     sash
    dev
     console (5,1)
     null (1,3)
     ram (1,1)
     systty (4,0)
     tty1 (4,1)
     tty2 (4,2)
     tty3 (4,3)
     tty4 (4,4)
    etc
    lib
     ncr53c8xx.o
    linuxrc
    loopfs
    
    
    Contents of linuxrc
    
    #!/bin/sash aliasall echo "Loading ncr53c8xx module" insmod /lib/ncr53c8xx.o
    pcitable contains information similar to "lspci" and "lspci -n"

Here’s a script that I have and use to pull apart the bootnet.img floppy in the current directory. Once I modify the contents as I see fit (usually importing some driver from one of the other floppies into here) then I call the repack-bootnet.sh script which repacks everything for me. The repacking one probably can use some help in error recovery, but it works as is for now — just be careful about stuffing it too full.


/scripts/unpack-bootnet.sh

#!/bin/sh
if [ ! -f bootnet.img ]; then
        echo unable to find bootnet.img in current directory, exiting...
        exit
fi
mkdir bootnet.img.dir
mount bootnet.img bootnet.img.dir -o loop
cp -a bootnet.img.dir/initrd.img initrd.img.gz
gunzip initrd.img.gz
mkdir initrd.img.dir
mount initrd.img initrd.img.dir -o loop
mkdir modules.cgz.dir
zcat initrd.img.dir/modules/modules.cgz | (cd modules.cgz.dir && cpio -idvm)

/scripts/repack-bootnet.sh

#!/bin/sh
if [ ! -d modules.cgz.dir ]; then
        echo "Sorry, I don't understand how to reapck this..."
        exit
fi
SUCCESS=true

# Let's repack the modules
echo +++Repacking modules
(cd modules.cgz.dir && find . | grep -v "BOOT/$" | cpio -o -H crc | gzip -n -9 ) >modules.cgz
mv modules.cgz initrd.img.dir/modules/modules.cgz
RESULT=$?
if [ $RESULT -ne 0 ]; then
        SUCCESS=false
        echo No room left to place modules.cgz in initrd.img
        exit
fi

# Lets handle initrd
echo +++Repacking initrd
dd if=/dev/zero of=initrd.img.dir/zero.tmp bs=1440k count=8 >/dev/null 2>&1
if [ $? -eq 1 ]; then
        :
else
        echo unknown error writing zero file to initrd.img.dir
        exit
fi
rm -rf initrd.img.dir/zero.tmp
umount initrd.img.dir
echo +++Checking initrd.img for errors
e2fsck -f initrd.img
RESULT=$?
if [ $RESULT -ne 0 ]; then
        SUCCESS=false
        echo initrd.img had errors
        exit
fi
gzip -n -9 initrd.img
mv initrd.img.gz bootnet.img.dir/initrd.img
RESULT=$?
if [ $RESULT -ne 0 ]; then
        SUCCESS=false
        echo No room left to place initrd.img in bootnet.img
        gunzip initrd.img.gz
        mount initrd.img initrd.img.dir -o loop
        exit
fi


# Cleanup
if [ $SUCCESS == true ]; then
        echo +++Cleanup
        rm -rf modules.cgz.dir

        rmdir initrd.img.dir

        umount bootnet.img.dir
        rmdir bootnet.img.dir
fi


Here’s some work on automating the process of pulling a driver out of drvnet.img and placing it into bootnet.img:

Making sure we have only 1 entry to check:
MYMODULE=bcm5700
MYMODULE_COUNT=`cat mod/modinfo | grep $MYMODULE | sed -e 's,^\t.*$,,' | grep -v "^ *$" | wc -l`
if ($MYMODULE_COUNT > 1 -o $MYMODULE_COUNT < 1); then exit

cat mod/modinfo | awk -v MYVAR=$MYMODULE '
BEGIN {PRINT="OFF"}
{
if(PRINT=="ON")
   {
   if(/^\t/)
      {
      print
      }
   else
      {
      PRINT="OFF"
      }
   }
}
{
if(PRINT!="ON")
   {
   if($0 ~ MYVAR)
      {
      PRINT="ON"; print
      }
   }
}'
Just run all the above awk line together on one line; I seperated it
here for readability.

Ok, here's an update, a short little script that somewhat reliably
reads out of modinfo and complains if the user isn't specific enough
about which module to grab

if [ -z $1 ]; then
        echo Hey, tell me which module you want to import.
        exit
fi
MYMODULE=$1
MYMODULE_COUNT=`cat mod/modinfo | grep $MYMODULE | sed -e 's,^\t.*$,,' | grep -v "^ *$" | wc -l`
if [ $MYMODULE_COUNT -ne 1 ]; then
echo
cat mod/modinfo | grep $MYMODULE | sed -e 's,^\t.*$,,' | grep -v "^ *$"
echo
        echo No, not today, I am confused, please choose only one
        exit
fi
cat mod/modinfo | awk -v MYVAR=$MYMODULE 'BEGIN {PRINT="OFF"} {if(PRINT=="ON"){if(/^\t/){print}else{PRINT="OFF"}}} {if(PRINT!="ON"){if($0 ~ MYVAR) {PRINT="ON"; print}}}'


What’s left to do is:
work with modinfo — mostly done
work with pcitable — should be easy as pie (cat pcitable | grep -i $MYMODULE — needs a little work especially for tg3/bcm5700)
work with modules.dep — shouldn’t be a challenge (cat modules.dep | grep $MYMODULE)
work with modules.cgz — (zcat modules.cgz | cpio -idvm)
automate the unpacking of drvnet.img
get size of new module to be inserted
remove out enough stuff from bootnet.img to compensate for
new driver / interracting with user to choose which to delete


#!/bin/sh
# Inspect each of the boot disks or driver disks and
# tell me what modules are inside.
FILELIST="`file * | grep "Linux rev 1.0 ext2 filesystem data" | sed -e 's,:.*$,,'`"
FILELIST="$FILELIST `file * | grep "x86 boot sector, system SYSLINUX, FAT (12 bit)" | sed -e 's,:.*$,,'`"
for X in `echo $FILELIST | sed -e 's, ,\n,g' | sort`; do
echo
echo -----------
echo $X
echo -----------
mkdir tmp 2>/dev/null
mount $X tmp -o loop
INITRD=""
INITRD=`find tmp | grep initrd`
if [ -n "$INITRD" ]; then
        cp -a $INITRD .
        INITRD=`basename $INITRD`
        mv $INITRD ${INITRD}.gz
        gunzip ${INITRD}.gz
        mkdir initrd.dir
        mount $INITRD initrd.dir -o loop
        MODULES=""
        MODULES=`find initrd.dir | grep modules.cgz`
        if [ -n "$MODULES" ]; then
                mkdir modules.dir
                (cd modules.dir && zcat ../$MODULES | cpio -idvm 2>&1)
                rm -rf modules.dir
        fi
        umount initrd.dir
        rmdir initrd.dir
        rm -rf $INITRD
else
        MODULES=""
        MODULES=`find tmp | grep modules.cgz`
        if [ -n "$MODULES" ]; then
                mkdir modules.dir
                (cd modules.dir && zcat ../$MODULES | cpio -idvm 2>&1)
                rm -rf modules.dir
        fi
fi
umount tmp
rmdir tmp
done

Need more information? I found this cool link:
http://sysadmin.cs.caltech.edu/docs/help/Linux/1722_boot_floppy

If any of this information is unclear or needs changing, please comment below.

Also see
objcopy.html

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.