Preparing a Debian disk image for Bochs

From McGill University Physics Department Technical Services Wiki

Prepared a a directory using debootstrap which should contain all the files required to bootstrap a working system.

baal:/tmp/debianbochs# du -s root 
146668  root
Table of contents

Create a disk image

bximage is a tool in Bochs for creating virtual disk images.

baal:/tmp/debianbochs# bximage -hd -size=250 -mode=flat -q hda
========================================================================
                                bximage
                  Disk Image Creation Tool for Bochs
      $Id: bximage.c,v 1.25.2.1 2005/07/06 20:40:00 vruppert Exp $
========================================================================

I will create a 'flat' hard disk image with
  cyl=507
  heads=16
  sectors per track=63
  total sectors=511056
  total size=249.54 megabytes

Writing: [] Done.

I wrote 261660672 bytes to hda.

The following line should appear in your bochsrc:
  ata0-master: type=disk, path="hda", mode=flat, cylinders=507, heads=16, spt=63

Use Fdisk to partition image

baal:/tmp/debianbochs# fdisk hda
Device contains neither a valid DOS partition table, nor Sun, SGI or OSF disklabel
Building a new DOS disklabel. Changes will remain in memory only,
until you decide to write them. After that, of course, the previous
content won't be recoverable.

You must set cylinders.
You can do this from the extra functions menu.
Warning: invalid flag 0x0000 of partition table 4 will be corrected by w(rite)

Command (m for help): x

Expert command (m for help): c
Number of cylinders (1-1048576): 507

Expert command (m for help): h
Number of heads (1-256, default 255): 16

Expert command (m for help): s
Number of sectors (1-63, default 63): 63
Warning: setting sector offset for DOS compatiblity

Expert command (m for help): r

Command (m for help): n
Command action
   e   extended
   p   primary partition (1-4)
p
Partition number (1-4): 1
First cylinder (1-507, default 1): 
Using default value 1
Last cylinder or +size or +sizeM or +sizeK (1-507, default 507): +200M

Command (m for help): n
Command action
   e   extended
   p   primary partition (1-4)
p
Partition number (1-4): 2
First cylinder (390-507, default 390): 
Using default value 390
Last cylinder or +size or +sizeM or +sizeK (390-507, default 507): 
Using default value 507

Command (m for help): t
Partition number (1-4): 2
Hex code (type L to list codes): 82
Changed system type of partition 2 to 82 (Linux swap / Solaris)

Command (m for help): p

Disk hda: 0 MB, 0 bytes
16 heads, 63 sectors/track, 507 cylinders
Units = cylinders of 1008 * 512 = 516096 bytes

Device Boot      Start         End      Blocks   Id  System
  hda1               1         389      196024+  83  Linux
  hda2             390         507       59472   82  Linux swap / Solaris

Command (m for help): w
The partition table has been altered!

Calling ioctl() to re-read partition table.

WARNING: Re-reading the partition table failed with error 25: Inappropriate ioctl for device.
The kernel still uses the old table.
The new table will be used at the next reboot.
Syncing disks.

Extracting hda1

We can use sfdisk to extract the sector offsets in the image

baal:/tmp/debianbochs# sfdisk -C 507 -H 16 -S 63 -uS -l hda
Disk hda: cannot get geometry

Disk hda: 507 cylinders, 16 heads, 63 sectors/track
Units = sectors of 512 bytes, counting from 0

   Device Boot    Start       End   #sectors  Id  System
     hda1            63    392111     392049  83  Linux
     hda2        392112    511055     118944  82  Linux swap / Solaris
     hda3             0         -          0   0  Empty
     hda4             0         -          0   0  Empty

Notice that hda1 starts at sector 63, the partition table / [Master Boot Record (http://en.wikipedia.org/wiki/Master_boot_record)] resides in sector 0, this leaves sectors 1 through 62 unused. I suspect this can be blamed on Microsoft. We can extract the three components using dd.

baal:/tmp/debianbochs# dd bs=512 count=63 if=hda of=hda0
63+0 records in
63+0 records out
32256 bytes transferred in 0.000416 seconds (77542254 bytes/sec)
baal:/tmp/debianbochs# dd bs=512 skip=63 count=392049 if=hda of=hda1
392049+0 records in
392049+0 records out
200729088 bytes transferred in 3.148529 seconds (63753292 bytes/sec)
baal:/tmp/debianbochs# dd bs=512 skip=392112 count=118944 if=hda of=hda2
118944+0 records in
118944+0 records out
60899328 bytes transferred in 0.513578 seconds (118578539 bytes/sec)
baal:/tmp/debianbochs# ls -l hda*
-rw-r--r--  1 root root 261660672 Jul 19 17:20 hda
-rw-r--r--  1 root root     32256 Jul 19 17:48 hda0
-rw-r--r--  1 root root 200729088 Jul 19 17:49 hda1
-rw-r--r--  1 root root  60899328 Jul 19 17:49 hda2

These components can be reassembled using cat

baal:/tmp/debianbochs# cat hda{0,1,2} > test
baal:/tmp/debianbochs# cmp -l hda test
baal:/tmp/debianbochs# rm test

Format hda1

baal:/tmp/debianbochs# mke2fs hda1
mke2fs 1.37 (21-Mar-2005)
hda1 is not a block special device.
Proceed anyway? (y,n) y
Filesystem label=
OS type: Linux
Block size=1024 (log=0)
Fragment size=1024 (log=0)
49152 inodes, 196024 blocks
9801 blocks (5.00%) reserved for the super user
First data block=1
24 block groups
8192 blocks per group, 8192 fragments per group
2048 inodes per group
Superblock backups stored on blocks: 
        8193, 24577, 40961, 57345, 73729

Writing inode tables: done                            
Writing superblocks and filesystem accounting information: done

This filesystem will be automatically checked every 22 mounts or
180 days, whichever comes first.  Use tune2fs -c or -i to override.

Copy kernel and GRUB into the root tree

baal:/tmp/debianbochs# cp /usr/src/Bochs/linux-2.4.31/System.map root/boot/
baal:/tmp/debianbochs# mkdir root/boot/grub
baal:/tmp/debianbochs# cp /lib/grub/i386-pc/stage[12] root/boot/grub/
baal:/tmp/debianbochs# ed root/boot/grub/menu.lst
root/boot/grub/menu.lst: No such file or directory
a
title Linux
        kernel /boot/bzImage root=/dev/hda1
.
w
49
q

Copy the tree into the image

baal:/tmp/debianbochs# mkdir -p mnt
baal:/tmp/debianbochs# mount -o loop hda1 mnt
baal:/tmp/debianbochs# tar cf - -C root . | tar xf - -C mnt
baal:/tmp/debianbochs# umount mnt

Reassemble the image

baal:/tmp/debianbochs# cat hda{0,1,2} > hda 

Make a GRUB floppy

baal:/tmp/debianbochs# cat /lib/grub/i386-pc/stage[12] > floppy.img   

Edit bochsrc

config_interface: textconfig
display_library: x
romimage: file=$BXSHARE/BIOS-bochs-latest, address=0xf0000
megs: 32
vgaromimage: file=$BXSHARE/VGABIOS-lgpl-latest

floppya: 1_44=floppy.img, status=inserted

ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14
ata0-master: type=disk, path="hda", mode=flat, cylinders=507, heads=16, spt=63

boot: floppy

Install GRUB in MBR using Bochs

    GNU GRUB  version 0.95  (639K lower / 31744K upper memory)

 [ Minimal BASH-like line editing is supported.  For the first word, TAB
   lists possible command completions.  Anywhere else TAB lists the possible
   completions of a device/filename. ]

grub> root (hd0,0)
 Filesystem type is ext2fs, partition type 0x83

grub> setup (hd0)
 Checking if "/boot/grub/stage1" exists... yes
 Checking if "/boot/grub/stage2" exists... yes
 Checking if "/boot/grub/e2fs_stage1_5" exists... no
 Running "install /boot/grub/stage1 (hd0) /boot/grub/stage2 p /boot/grub/menu.l
st "... succeeded
Done.

grub>

Boot from hard disk in Bochs

Updated bochsrc

config_interface: textconfig
display_library: x
romimage: file=$BXSHARE/BIOS-bochs-latest, address=0xf0000
megs: 32
vgaromimage: file=$BXSHARE/VGABIOS-lgpl-latest

floppya: 1_44=floppy.img, status=inserted

ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14
ata0-master: type=disk, path="hda", mode=flat, cylinders=507, heads=16, spt=63

boot: disk

Everything works perfectly!