The majority of motherboard manufactures still only allow you to update your BIOS either from within Windows, from a USB stick within the BIOS itself, or from a floppy with DOS. The first option doesn’t work with a linux box for obvious reasons. While the second option is nice for updating one box, it quickly becomes a hassle when you have an entire rack you need to update. And the third option is antiquated by any meaning of the word… or is it? While the days of floppies are long gone, the reign of the floppy image is still going strong in the world of PXE boot.

The biggest limitation of a floppy image is easily its size. 1.44MB is almost useless in today’s world of terabyte hard drives. Since BIOS images take up about 1MB, that leaves room for not much else. Meaning no scripting, no fancy menus, just the flasher program and your BIOS image. One of the most common methods around this limitation is to offsite your BIOS images to a samba share and instead use the 1.44MBs of space for network utilities. While this does work fine, it brings back bad memories of networking in DOS that I’d rather not experience again. Instead, I’ll walk you through how to expand a floppy image to whatever size is comfy for you, and most importantly, keep it bootable.

Things you will need:

  • A bootable floppy image (http://www.bootdisk.com/ has a bunch)
  • dd
  • mkfs.msdos
  • hexdump, for verification purposes
  • A PXELINUX PXE boot environment

1. Procure a bootable floppy image

Download your bootable floppy image and save it to a directory of your choosing. If your downloaded it from http://www.bootdisk.com/, chances are it’s saved as a Windows executable. Have no fear, just run unzip on it and it should extract the tasty image within:

david@bt:~$ wget http://www.dq.com.pl/pliki/boot%20disk/boot98c.exe
 --2011-08-06 16:52:31--  http://www.dq.com.pl/pliki/boot%20disk/boot98c.exe
 Resolving www.dq.com.pl... 85.128.137.63
 Connecting to www.dq.com.pl|85.128.137.63|:80... connected.
 HTTP request sent, awaiting response... 200 OK
 Length: 864362 (844K) [application/x-msdownload]
 Saving to: `boot98c.exe'
100%[======================================>] 864,362      529K/s   in 1.6s
2011-08-06 16:52:33 (529 KB/s) - `boot98c.exe' saved [864362/864362]
david@bt:~$ unzip boot98c.exe
 Archive:  boot98c.exe
 warning [boot98c.exe]:  105508 extra bytes at beginning or within zipfile
 (attempting to process anyway)
 file #1:  bad zipfile offset (local header sig):  211016
 (attempting to re-compensate)
 inflating: boot98c.IMA
 david@bt:~$ ls
 boot98c.exe  boot98c.IMA

2. Create a new floppy image with the size you want

Now that we have our donor bootable floppy image with its delicious boot code, we need to create an empty floppy image with the new size. First, figure out how much space you need. For this tutorial I’m going with 10MB. Convert that value to KB (you can do this from within bash by running “expr $((sizeinMB << 10))”), in my case that’s 10240. This is going to be the last argument we use in mkfs.msdos:

david@bt:~$ expr $((10 << 10))
10240
david@bt:~$ mkfs.msdos -I -v -C test.img 10240
mkfs.msdos 3.0.3 (18 May 2009)
test.img has 64 heads and 32 sectors per track,
logical sector size is 512,
using 0xf8 media descriptor, with 20480 sectors;
file system has 2 16-bit FATs and 4 sectors per cluster.
FAT size is 20 sectors, and provides 5101 clusters.
Root directory contains 512 slots.
Volume ID is df50ef01, no volume label.
david@bt:~$ du -h test.img
52K     test.img

You may notice that the file size is only 52K. This is normal. This command just created the filesystem’s metadata. You can still mount it and the OS will see it as 10MB of space. Take note of the sector size (512 in this example), amount of heads (64), and sectors per track (32). You will need these later to calculate the amount of cylinders.

3. Copy over boot information to new image

Let’s compare the boot sector from the bootable image to the one we just created:

david@bt:~$ hexdump -C -n 512 boot98c.IMA
00000000  eb 3c 90 2a 34 68 55 3c  49 48 43 00 02 01 01 00  |.<.*4hU<IHC.....|
00000010  02 e0 00 40 0b f0 09 00  12 00 02 00 00 00 00 00  |...@............|
00000020  40 0b 00 00 00 00 29 49  2d e1 18 42 4f 4f 54 39  |@.....)I-..BOOT9|
00000030  38 41 20 20 20 20 46 41  54 31 32 20 20 20 33 c9  |8A    FAT12   3.|
00000040  8e d1 bc fc 7b 16 07 bd  78 00 c5 76 00 1e 56 16  |....{...x..v..V.|
00000050  55 bf 22 05 89 7e 00 89  4e 02 b1 0b fc f3 a4 06  |U."..~..N.......|
00000060  1f bd 00 7c c6 45 fe 0f  38 4e 24 7d 20 8b c1 99  |...|.E..8N$} ...|
00000070  e8 7e 01 83 eb 3a 66 a1  1c 7c 66 3b 07 8a 57 fc  |.~...:f..|f;..W.|
00000080  75 06 80 ca 02 88 56 02  80 c3 10 73 ed 33 c9 fe  |u.....V....s.3..|
00000090  06 d8 7d 8a 46 10 98 f7  66 16 03 46 1c 13 56 1e  |..}.F...f..F..V.|
000000a0  03 46 0e 13 d1 8b 76 11  60 89 46 fc 89 56 fe b8  |.F....v.`.F..V..|
000000b0  20 00 f7 e6 8b 5e 0b 03  c3 48 f7 f3 01 46 fc 11  | ....^...H...F..|
000000c0  4e fe 61 bf 00 07 e8 28  01 72 3e 38 2d 74 17 60  |N.a....(.r>8-t.`|
000000d0  b1 0b be d8 7d f3 a6 61  74 3d 4e 74 09 83 c7 20  |....}..at=Nt... |
000000e0  3b fb 72 e7 eb dd fe 0e  d8 7d 7b a7 be 7f 7d ac  |;.r......}{...}.|
000000f0  98 03 f0 ac 98 40 74 0c  48 74 13 b4 0e bb 07 00  |.....@t.Ht......|
00000100  cd 10 eb ef be 82 7d eb  e6 be 80 7d eb e1 cd 16  |......}....}....|
00000110  5e 1f 66 8f 04 cd 19 be  81 7d 8b 7d 1a 8d 45 fe  |^.f......}.}..E.|
00000120  8a 4e 0d f7 e1 03 46 fc  13 56 fe b1 04 e8 c2 00  |.N....F..V......|
00000130  72 d7 ea 00 02 70 00 52  50 06 53 6a 01 6a 10 91  |r....p.RP.Sj.j..|
00000140  8b 46 18 a2 26 05 96 92  33 d2 f7 f6 91 f7 f6 42  |.F..&...3......B|
00000150  87 ca f7 76 1a 8a f2 8a  e8 c0 cc 02 0a cc b8 01  |...v............|
00000160  02 80 7e 02 0e 75 04 b4  42 8b f4 8a 56 24 cd 13  |..~..u..B...V$..|
00000170  61 61 72 0a 40 75 01 42  03 5e 0b 49 75 77 c3 03  |aar.@u.B.^.Iuw..|
00000180  18 01 27 0d 0a 49 6e 76  61 6c 69 64 20 73 79 73  |..'..Invalid sys|
00000190  74 65 6d 20 64 69 73 6b  ff 0d 0a 44 69 73 6b 20  |tem disk...Disk |
000001a0  49 2f 4f 20 65 72 72 6f  72 ff 0d 0a 52 65 70 6c  |I/O error...Repl|
000001b0  61 63 65 20 74 68 65 20  64 69 73 6b 2c 20 61 6e  |ace the disk, an|
000001c0  64 20 74 68 65 6e 20 70  72 65 73 73 20 61 6e 79  |d then press any|
000001d0  20 6b 65 79 0d 0a 00 00  49 4f 20 20 20 20 20 20  | key....IO      |
000001e0  53 59 53 4d 53 44 4f 53  20 20 20 53 59 53 7f 01  |SYSMSDOS   SYS..|
000001f0  00 41 bb 00 07 60 66 6a  00 e9 3b ff 00 00 55 aa  |.A...`fj..;...U.|
00000200
david@bt:~$ hexdump -C -n 512 test.img
00000000  eb 3c 90 6d 6b 64 6f 73  66 73 00 00 02 04 01 00  |.<.mkdosfs......|
00000010  02 00 02 00 50 f8 14 00  20 00 40 00 00 00 00 00  |....P... .@.....|
00000020  00 00 00 00 00 00 29 01  ef 50 df 20 20 20 20 20  |......)..P.     |
00000030  20 20 20 20 20 20 46 41  54 31 36 20 20 20 0e 1f  |      FAT16   ..|
00000040  be 5b 7c ac 22 c0 74 0b  56 b4 0e bb 07 00 cd 10  |.[|.".t.V.......|
00000050  5e eb f0 32 e4 cd 16 cd  19 eb fe 54 68 69 73 20  |^..2.......This |
00000060  69 73 20 6e 6f 74 20 61  20 62 6f 6f 74 61 62 6c  |is not a bootabl|
00000070  65 20 64 69 73 6b 2e 20  20 50 6c 65 61 73 65 20  |e disk.  Please |
00000080  69 6e 73 65 72 74 20 61  20 62 6f 6f 74 61 62 6c  |insert a bootabl|
00000090  65 20 66 6c 6f 70 70 79  20 61 6e 64 0d 0a 70 72  |e floppy and..pr|
000000a0  65 73 73 20 61 6e 79 20  6b 65 79 20 74 6f 20 74  |ess any key to t|
000000b0  72 79 20 61 67 61 69 6e  20 2e 2e 2e 20 0d 0a 00  |ry again ... ...|
000000c0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
000001f0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 55 aa  |..............U.|
00000200

For those who are interested, you can see what each offset means at Wikipedia.

As you can see, the disk we made is missing a bunch of information (the asterisk means bunches of zeros). We want to copy over all of the boot instructions, but we don’t want to overwrite the geometry information so we can retain our 10MB image. The jump instructions and the OEM data are located in the first 11 bytes (offset 00 to 0A in hexadecimal). We want to copy that from the bootable image to the new one. From offset 0B to offset 3E we have the geometry information, which we want to retain on the new image. From offset 3E to offset 200, we have the actual OS boot code. We obviously want to copy that over to the new image. To make all of these changes we bust out dd:

david@bt:~$ dd if=boot98c.IMA of=test.img bs=1 count=11 conv=notrunc
11+0 records in
11+0 records out
11 bytes (11 B) copied, 0.000163496 s, 67.3 kB/s
david@bt:~$ dd if=boot98c.IMA of=test.img bs=1 skip=62 seek=62 conv=notrunc count=450
450+0 records in
450+0 records out
450 bytes (450 B) copied, 0.0491807 s, 9.1 kB/s

The reason we only counted to 450 is because 512-62=450. Now let’s compare the two boot sectors:

david@bt:~$ hexdump -C -n 512 boot98c.IMA                                      
00000000  eb 3c 90 2a 34 68 55 3c  49 48 43 00 02 01 01 00  |.<.*4hU<IHC.....|
00000010  02 e0 00 40 0b f0 09 00  12 00 02 00 00 00 00 00  |...@............|
00000020  40 0b 00 00 00 00 29 49  2d e1 18 42 4f 4f 54 39  |@.....)I-..BOOT9|
00000030  38 41 20 20 20 20 46 41  54 31 32 20 20 20 33 c9  |8A    FAT12   3.|
00000040  8e d1 bc fc 7b 16 07 bd  78 00 c5 76 00 1e 56 16  |....{...x..v..V.|
00000050  55 bf 22 05 89 7e 00 89  4e 02 b1 0b fc f3 a4 06  |U."..~..N.......|
00000060  1f bd 00 7c c6 45 fe 0f  38 4e 24 7d 20 8b c1 99  |...|.E..8N$} ...|
00000070  e8 7e 01 83 eb 3a 66 a1  1c 7c 66 3b 07 8a 57 fc  |.~...:f..|f;..W.|
00000080  75 06 80 ca 02 88 56 02  80 c3 10 73 ed 33 c9 fe  |u.....V....s.3..|
00000090  06 d8 7d 8a 46 10 98 f7  66 16 03 46 1c 13 56 1e  |..}.F...f..F..V.|
000000a0  03 46 0e 13 d1 8b 76 11  60 89 46 fc 89 56 fe b8  |.F....v.`.F..V..|
000000b0  20 00 f7 e6 8b 5e 0b 03  c3 48 f7 f3 01 46 fc 11  | ....^...H...F..|
000000c0  4e fe 61 bf 00 07 e8 28  01 72 3e 38 2d 74 17 60  |N.a....(.r>8-t.`|
000000d0  b1 0b be d8 7d f3 a6 61  74 3d 4e 74 09 83 c7 20  |....}..at=Nt... |
000000e0  3b fb 72 e7 eb dd fe 0e  d8 7d 7b a7 be 7f 7d ac  |;.r......}{...}.|
000000f0  98 03 f0 ac 98 40 74 0c  48 74 13 b4 0e bb 07 00  |.....@t.Ht......|
00000100  cd 10 eb ef be 82 7d eb  e6 be 80 7d eb e1 cd 16  |......}....}....|
00000110  5e 1f 66 8f 04 cd 19 be  81 7d 8b 7d 1a 8d 45 fe  |^.f......}.}..E.|
00000120  8a 4e 0d f7 e1 03 46 fc  13 56 fe b1 04 e8 c2 00  |.N....F..V......|
00000130  72 d7 ea 00 02 70 00 52  50 06 53 6a 01 6a 10 91  |r....p.RP.Sj.j..|
00000140  8b 46 18 a2 26 05 96 92  33 d2 f7 f6 91 f7 f6 42  |.F..&...3......B|
00000150  87 ca f7 76 1a 8a f2 8a  e8 c0 cc 02 0a cc b8 01  |...v............|
00000160  02 80 7e 02 0e 75 04 b4  42 8b f4 8a 56 24 cd 13  |..~..u..B...V$..|
00000170  61 61 72 0a 40 75 01 42  03 5e 0b 49 75 77 c3 03  |aar.@u.B.^.Iuw..|
00000180  18 01 27 0d 0a 49 6e 76  61 6c 69 64 20 73 79 73  |..'..Invalid sys|
00000190  74 65 6d 20 64 69 73 6b  ff 0d 0a 44 69 73 6b 20  |tem disk...Disk |
000001a0  49 2f 4f 20 65 72 72 6f  72 ff 0d 0a 52 65 70 6c  |I/O error...Repl|
000001b0  61 63 65 20 74 68 65 20  64 69 73 6b 2c 20 61 6e  |ace the disk, an|
000001c0  64 20 74 68 65 6e 20 70  72 65 73 73 20 61 6e 79  |d then press any|
000001d0  20 6b 65 79 0d 0a 00 00  49 4f 20 20 20 20 20 20  | key....IO      |
000001e0  53 59 53 4d 53 44 4f 53  20 20 20 53 59 53 7f 01  |SYSMSDOS   SYS..|
000001f0  00 41 bb 00 07 60 66 6a  00 e9 3b ff 00 00 55 aa  |.A...`fj..;...U.|
00000200
david@bt:~$ hexdump -C -n 512 test.img                                         
00000000  eb 3c 90 2a 34 68 55 3c  49 48 43 00 02 04 01 00  |.<.*4hU<IHC.....|
00000010  02 00 02 00 50 f8 14 00  20 00 40 00 00 00 00 00  |....P... .@.....|
00000020  00 00 00 00 00 00 29 01  ef 50 df 20 20 20 20 20  |......)..P.     |
00000030  20 20 20 20 20 20 46 41  54 31 36 20 20 20 33 c9  |      FAT16   3.|
00000040  8e d1 bc fc 7b 16 07 bd  78 00 c5 76 00 1e 56 16  |....{...x..v..V.|
00000050  55 bf 22 05 89 7e 00 89  4e 02 b1 0b fc f3 a4 06  |U."..~..N.......|
00000060  1f bd 00 7c c6 45 fe 0f  38 4e 24 7d 20 8b c1 99  |...|.E..8N$} ...|
00000070  e8 7e 01 83 eb 3a 66 a1  1c 7c 66 3b 07 8a 57 fc  |.~...:f..|f;..W.|
00000080  75 06 80 ca 02 88 56 02  80 c3 10 73 ed 33 c9 fe  |u.....V....s.3..|
00000090  06 d8 7d 8a 46 10 98 f7  66 16 03 46 1c 13 56 1e  |..}.F...f..F..V.|
000000a0  03 46 0e 13 d1 8b 76 11  60 89 46 fc 89 56 fe b8  |.F....v.`.F..V..|
000000b0  20 00 f7 e6 8b 5e 0b 03  c3 48 f7 f3 01 46 fc 11  | ....^...H...F..|
000000c0  4e fe 61 bf 00 07 e8 28  01 72 3e 38 2d 74 17 60  |N.a....(.r>8-t.`|
000000d0  b1 0b be d8 7d f3 a6 61  74 3d 4e 74 09 83 c7 20  |....}..at=Nt... |
000000e0  3b fb 72 e7 eb dd fe 0e  d8 7d 7b a7 be 7f 7d ac  |;.r......}{...}.|
000000f0  98 03 f0 ac 98 40 74 0c  48 74 13 b4 0e bb 07 00  |.....@t.Ht......|
00000100  cd 10 eb ef be 82 7d eb  e6 be 80 7d eb e1 cd 16  |......}....}....|
00000110  5e 1f 66 8f 04 cd 19 be  81 7d 8b 7d 1a 8d 45 fe  |^.f......}.}..E.|
00000120  8a 4e 0d f7 e1 03 46 fc  13 56 fe b1 04 e8 c2 00  |.N....F..V......|
00000130  72 d7 ea 00 02 70 00 52  50 06 53 6a 01 6a 10 91  |r....p.RP.Sj.j..|
00000140  8b 46 18 a2 26 05 96 92  33 d2 f7 f6 91 f7 f6 42  |.F..&...3......B|
00000150  87 ca f7 76 1a 8a f2 8a  e8 c0 cc 02 0a cc b8 01  |...v............|
00000160  02 80 7e 02 0e 75 04 b4  42 8b f4 8a 56 24 cd 13  |..~..u..B...V$..|
00000170  61 61 72 0a 40 75 01 42  03 5e 0b 49 75 77 c3 03  |aar.@u.B.^.Iuw..|
00000180  18 01 27 0d 0a 49 6e 76  61 6c 69 64 20 73 79 73  |..'..Invalid sys|
00000190  74 65 6d 20 64 69 73 6b  ff 0d 0a 44 69 73 6b 20  |tem disk...Disk |
000001a0  49 2f 4f 20 65 72 72 6f  72 ff 0d 0a 52 65 70 6c  |I/O error...Repl|
000001b0  61 63 65 20 74 68 65 20  64 69 73 6b 2c 20 61 6e  |ace the disk, an|
000001c0  64 20 74 68 65 6e 20 70  72 65 73 73 20 61 6e 79  |d then press any|
000001d0  20 6b 65 79 0d 0a 00 00  49 4f 20 20 20 20 20 20  | key....IO      |
000001e0  53 59 53 4d 53 44 4f 53  20 20 20 53 59 53 7f 01  |SYSMSDOS   SYS..|
000001f0  00 41 bb 00 07 60 66 6a  00 e9 3b ff 00 00 55 aa  |.A...`fj..;...U.|
00000200

Much better.

4. Copy over OS files to new disk

Now that we have our shiny new bootable floppy, we can copying over the OS from the old floppy:

david@bt:~$ mktemp -d /tmp/old.XXXXXX
/tmp/old.rvviBJ
david@bt:~$ mktemp -d /tmp/new.XXXXXX
/tmp/new.NFM4WP
david@bt:~$ sudo mount -o loop test.img /tmp/new.NFM4WP/
david@bt:~$ sudo mount -o loop boot98c.IMA /tmp/old.rvviBJ/
david@bt:~$ sudo cp -r /tmp/old.rvviBJ/* /tmp/new.NFM4WP/
david@bt:~$ ls /tmp/new.NFM4WP/
attrib.exe    chkdsk.exe    edit.com    label.exe    scandisk.exe  xcopy32.mod
autoexec.bat  command.com   edit.hlp    mem.exe      scandisk.ini  xcopy.exe
cd1.sys       config.sys    fdisk.exe   move.exe     scanreg.exe
cd2.sys       deltree.exe   format.com  mscdex.exe   smartdrv.exe
cd3.sys       diskcopy.com  himem.sys   msdos.sys    sys.com
cd4.sys       drvspace.bin  io.sys      mtmcdai.sys  xcopy32.exe
david@bt:~$ df -h
Filesystem            Size  Used Avail Use% Mounted on
*
/dev/loop0             10M  1.4M  8.7M  14% /tmp/new.NFM4WP
/dev/loop1            1.4M  1.3M   97K  94% /tmp/old.rvviBJ
david@bt:~$ sudo umount /tmp/new.NFM4WP/
david@bt:~$ sudo umount /tmp/old.rvviBJ/

5. Final configurations for PXELINUX

Remember how I told you to jot down the sector size, number of heads, and sectors per track? Good, because we need it now. To ensure that PXELINUX is aware of the geometry, we need to provide it with the number of sectors per track, amount of heads, and the amount of cylinders the image has. To calculate the amount of cylinders we use the following equation:

Cylinders = TotalNumberOfSectors / NumberOfHeads / NumberOfSectorsPerTrack

Since the sector size is 512, we can take the filesystem size in KB from earlier and just double it for the total of 20480 sectors. We then divide that by 64 heads, then divide that by 32 sectors. Our number of cylinders should come out to 10. In your pxelinux config file you’ll want to put this information in like this:

label flash_bios
      kernel memdisk
      append initrd=test.img floppy c=10 s=32 h=64

And there you go, a 10MB bootable floppy image. Hooray!

There’s a neat script that can do all that we did in this article, available here. Have fun and happy hacking!

« »