Basics of a quiet pc
  Quiet or Silent
  Boot Linux from CF
  Mini-Itx Comparison
  Diskless Windows
  Build a Media PC
  Silent PC Options
  Cubid 2699R Case
  Kiss dp-500
  Zalman Flower Cooler
  AcoustiPack Foam
  Build a PC Home Theater
  Build your own PC
  Upgrading and Repairing PCs
  Hardware Projects
  Privacy policy

Diskless Windows with PXE - Part 3

Now we have a working PXE system, and windows compressed, we can start on the disk image.

Build a new hard disk image

If you had a small enough hard disk, you could just use dd to copy the entire image onto linux for booting via PXE, but the fun (do I really mean fun?) part is being able to create disk images of any size, so you can match the size of your compressed windows file (drvspace.000)

In order to make bootable disk images, we need to copy a couple of sectors off of your existing windows harddrive. We only need to do this once, as from these two sectors we can build any size disk image.

First up, we need to get the windows harddrive into your linux box, so we can read bits off of it. Once in your linux box (I'll assume you've added it as the secondary master hdc) we need to make a note of some of its geometry settings. Run fdisk /dev/hdc and then press p to view the partition table. You should see your FAT16 partion there in all its glory. Make a note of the number of sectors (and bytes per sector).

The two bits we need off this disk, are the first 384 bytes of the disk, and the first 512 bytes of the first partion (were you've install windows)

dd if=/dev/hdc of=hd.384 bs=384 count=1
If you look at hd.384 in vi it should look a bit like
 offset    0  1  2  3   4  5  6  7   8  9  a  b   c  d  e  f  0123456789abcdef
00000000  fa e9 a2 00  56 51 53 88  d3 80 e2 8f  f6 c3 20 74  .VQS... t
00000010  31 bb aa 55  b4 41 cd 13  72 28 81 fb  55 aa 75 22  1UA.r(.Uu"
00000020  f6 c1 01 74  1d 5b 59 1e  66 6a 00 57  51 06 53 6a  .t.[
00000030  01 6a 10 89  e6 16 1f b8  00 42 cd 13  8d 64 10 1f  .j.....B..d..
00000040  eb 45 5b 59  53 52 57 51  06 b4 08 cd  13 07 72 39  E[YSRWQ....r9
00000050  51 c0 e9 06  86 e9 89 cf  59 c1 ea 08  92 40 83 e1  Q...Y..@.
00000060  3f f7 e1 96  58 5a 39 f2  73 23 f7 f6  39 f8 77 1d  ?.XZ9s#9w.
00000070  c0 e4 06 86  e0 92 f6 f1  fe c4 00 e2  89 d1 5a 5b  .....Z[
00000080  86 f0 b8 01  02 cd 13 eb  09 59 5f eb  02 b4 40 5a  .....Y_.@Z
00000090  5b f9 5e c3  5e ac 08 c0  74 09 b4 0e  bb 07 00 cd  [^^.t....
000000a0  10 eb f2 f4  eb fd 31 c0  8e d0 bc 00  7c fb fc 8e  .1.м.|.
000000b0  d8 8e c0 bf  00 06 89 e6  b9 00 01 f3  a5 ea c2 06  .......
000000c0  00 00 b8 00  12 b3 36 cd  10 be be 07  b9 04 00 84  ....6.....
000000d0  14 89 f5 78  3f 83 c6 10  e2 f5 e8 b7  ff 4e 6f 20  ..x?..No
000000e0  70 61 72 74  69 74 69 6f  6e 20 61 63  74 69 76 65  partition active
000000f0  0d 0a 00 84  14 79 1d e8  9a ff 49 6e  76 61 6c 69  .....y..Invali

Now to pull of the first 512 bytes of the first partition, we need to calculate where the first partition starts. If your hard drive has 63 sectors (with 512 bytes per sector) then under dos, the first partion starts 63 x 512 bytes in.

dd if=/dev/hdc of=hdp1.512 bs=512 skip=63 count=1
Which under vi should look a bit like
  offset    0  1  2  3   4  5  6  7   8  9  a  b   c  d  e  f  0123456789abcdef
00000000  eb 3c 90 4d  53 57 49 4e  34 2e 31 00  02 40 01 00  <.MSWIN4.1..@..
00000010  02 00 02 00  00 f8 fc 00  3f 00 40 00  3f 00 00 00  ......?.@.?...
00000020  41 e0 3e 00  80 00 29 cf  1b 32 45 20  20 20 20 20  A>...).2E
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...s3
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
While the disk is in the Linux box we may as well take this easy opportunity to copy all the files off. Make sure you get the hidden files as well (eg. io.sys, msdos.sys etc)

Now to create a new disk image. I usually size the disk image 5MB larger than the files it's going to take, so there is a little free space if needed. But if you are tight on memory, you may need to play with this.

Firstly create an empty file for the image. All of the following code assumes a 100MB disk which is is 512Bytes * 204800 blocks. The disk image geometry will be 100 cylinders, 64 heads, 32 sectors and 512 bytes per sector. This allows the cylinder count to match the size in Megabytes. If you are making a different size, then adjust accordingly.

dd if=/dev/zero of=hd.img bs=512 count=204800
Now mount the disk as a loop device
losetup /dev/loop0 hd.img
If you already have something loaded as loop0 you'll need to use a different loop device We need to create a partition table so run
fdisk /dev/loop0
Press x to go to the advanced menu, press c then 100 to set the cylinders. Then h and 64 for the heads, then s and 32 for the sectors. fdisk will probably then tell you its setting the sector offset for dos compatibility, which is what we want.

Now press r to return to the main menu, n to create a new partion. Create it as the first primary partition. Take the defaults offered, and fill the disk. Now press t and 6 to set its type id to 6 (FAT 16) and press a to make the partition active.

Now press w to write the partition to the file. fdisk will complain that it was unable to reread the disk, don't worry. restart fdisk and press p and you should see your lovely partition sitting there. double check the cylinders, heads and sectors for the disk are correct.

root@linuxbox:~# fdisk /dev/loop0

Command (m for help): p

Disk /dev/loop0: 64 heads, 32 sectors, 100 cylinders
Units = cylinders of 2048 * 512 bytes

      Device Boot    Start       End    Blocks   Id  System
/dev/loop0p1   *         1       100    102384    6  FAT16

Command (m for help):
Now we have a disk image with partition table, we don't need to make it ever again. All of the rest of the commands we need to finish off can be scripted as they are not interactive.

remember to unmount the loop device losetup -d /dev/loop0

We could just mount the new partion we have created, and copy the files on , but I've found linux dies if when you try to copy the 90mb drvspace.000 file on. Oops. Think there must be a bug there somewhere. So we need to create a stand-alone partition image, the same size as the one above, which we can copy files to, and then insert that image into the disk image, at the location of partition 1. See I said it was fun. Oh, and it gets better, just wait.

mkdosfs -F 16 -S 512 -R 1 -C hdp1.img 102384
When mkdosfs is creating large images it defaults to 32 sectors and 64 heads, which is why we used the same geometry for the disk image we fdisk'd. Now the partition is made, we don't ever need to re-make it if we just want to update the windows files in the image. Now mount the partition image, copy in the files, unmount it, and inject it into the disk image.
mount -o loop -t msdos hdp1.img /mnt/hd
rm /mnt/hd/*.*
cp win98/*.* /mnt/hd
umount /mnt/hd
dd if=hdp1.img of=hd.img conv=notrunc bs=512 count=204768 seek=32
Now, is when the real fun begins. In order to get this disk image to actually boot, its needs a disk boot sector and a bootable partition boot sector. But these sectors need to contain the geometry for the disk we are creating, not the disk they came from. Hence the following jiggery pokery.
# copy on the disk boot sector
dd if=hd.384 of=hd.img bs=1 count=384 conv=notrunc

# read the partion boot sector off the disk image
dd if=hd.img of=vdp1.old bs=512 skip=32 count=1

# make a copy of the real partition boot sector
cp hdp1.512

# read bytes 12 to 36 from old image bootsector to the new bootsector
dd if=vdp1.old conv=notrunc bs=1 skip=11 seek=11 count=25

# turn sectors into hex and escape the value to a file
echo -e -n "\x20"  > vdp1.fix

#  inject the value into the new boot sector
dd if=vdp1.fix conv=notrunc bs=1 count=1 seek=28

# inject the new boot sector to the start of the partion
dd of=hd.img conv=notrunc bs=512 seek=32 count=1
Ok has your head stopped spinning? so copy the image to the tftpboot directory
cp hd.img /tftpboot/win.img

If you want to know what you just did, visit Hale's Boot Sector Disassembly We should now be ready to boot windows. Set the pxe config to use the win.img file, and reboot your windows box. If everything goes according to plan, windows should load just fine.

If you want to save your diskimage from ram back to the linux box, so you can save your changes and make a new disk image, then close all your windows apps and drop into a dos command prompt. Change to the H drive, un-hide the drvspace.000 file, and copy it over the network to the linux server. The easiest way is to have samba installed on the linux server, and mount a drive from windows.

H:\>attrib -s -h -r DRVSPACE.000
H:\>copy DRVSPACE.000 \\linuxbox\root


If windows fails to start there are three main areas you may be having a problem.

Firstly does the disk image load completely. If not, then there could be timeout issues or, memory issues. Check your graphics card is not taking more memory than you expected, leaving you with insufficient.

Secondly does the disk image boot. If not, then check the steps when you created it. Retry the image one step at a time. mkdosfs can paste a message into the partition it creates, use it to check that the partition is even trying to load, before fixing its boot sector. Were the boot sectors you copied from the real disk ok? You may need to read Hale's guide and check your sectors by hand with vi

Thirdly windows tries to start but throws a wobbly. Go back to the windows hard disk, and tick all of the troubleshooting checkboxes. Also add the line bootmenu=1 to the bottom of your msdos.sys file, and try booting into safe mode.

Rinse and repeat.

If you are a boot sector guru and spot some error
with how I'm doing this, please let me know.

<< Part 2 | Part 3

© 2003-2010

Valid HTML 4.01! Valid CSS!