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.
- Set up a workplace
- Grab something to work with
- Dig into the disk (any of boot.img, bootnet.img, drivers.ing, etc…)
- Grab a copy of the initrd and uncompress it
- Dig into the initrd
- What is important in the initrd
- Dig into the modules.cgz file
- 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:
- 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:
- 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.
- Modifying pcitable
- Repacking modules.cgz
- Repacking initrd.img
- Repacking the Disk
- 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:
- Notes on initrd
mkdir /tmp/unpack cd /tmp/unpack |
cp /mnt/cdrom/images/boot.img . |
mkdir disk.dir mount boot.img disk.dir -o loop |
cp disk.dir/initrd.img initrd.img.gz gunzip initrd.img.gz |
mkdir initrd.dir mount initrd.img initrd.dir -o loop |
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.
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 |
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.
sym53c8xx
scsi
"Symbios 53C896"
Sample: usb-storage: usbcore scsi_mod usb-ohci: usbcore usb-uhci: usbcore vfat: fat
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″/
cd /tmp/unpack/modules find . -type f | cpio -o -H crc | gzip -n9 >../modules.cgz mv ../modules.cgz . |
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 |
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 |
find 2.4.7-10BOOT/ | grep -v "BOOT/$" | cpio -o -H crc >modules.cpio gzip -9 -n modules.cpio gzip -9 -n initrd.img |
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