Installing the BeOS Under the QEMU PC Emulator

I install BeOS 5 Pro for Intel on my MacBook Pro by running it under an emulator.

Michael David Crawford
June 6, 2006

Copyright © 2006 Michael David Crawford.

Creative Commons License
This work is licensed under a Creative Commons Attribution-ShareAlike 2.5 License.

[Top]

I discuss installation of the BeOS in such detail here because QEMU does not yet support installation from the BeOS 5 Pro CD-ROM. After some experimentation, I found a workaround that works very well at getting it installed. However, while BeOS 5 Pro for Intel runs reliably, neither sound nor networking work yet. This makes it difficult to transfer files from the host computer, but there is a way. It's likely that now that I've found an installation procedure, the problems with sound and networking can be fixed.

The Problem: The BeOS CDROM Won't Boot

[Top]

There are two ways to boot from CDROM with QEMU: by using a real CDROM, or an image of one. QEMU provides an emulated CDROM drive for use by the emulated operating system.

When one tries to boot from the real BeOS 5 Pro CD, the kernel panics with the message:

PANIC: The boot loader was unable to find a BeOS volume to boot from.  
If you are trying to boot from the CD-ROM and find that you are unable 
to do so, press space during the boot sequence to enter the boot menu 
and select 'Boot from CD-ROM' as the boot volume.

BeOS on a MacBook Pro
BeOS on a MacBook Pro
(Click for full-size screen shot)

If you press space to enter the boot menu, you can select the CD-ROM but then you get the message "Please place the BeOS CD in the CD-ROM drive."

Now we try creating an image of the CD-ROM. In the Mac OS X Disk Utility, click on the icon of the CD-ROM, then select New -> Disk Image from BeOS Tools from the file menu. Select CD/DVD Master as the image format, with no encryption. Give the image a name like BeOS_Tools; Disk Utility appends the ".cdr" extension. Tell QEMU to use the image as the CD-ROM device, in Q, click the Edit PC icon, then on the Hardware icon, then select Choose Diskimage from the CD-ROM menu.

Again, you have to hold the space bar or the kernel panics. But when I do, the result is the same: "Please place the BeOS CD in the CD-ROM drive."

I think the problem is that the CD-ROM must not be fully emulated; the BeOS boot loader tries to access it in an unsupported way. Other operating systems must never have required whatever the BeOS is trying to do. I expect it won't be hard to fix, but until then...

The Workaround: Copy an Existing Installation

[Top]

After I searched for a solution on the Internet and found none, I had the following idea: install BeOS 5 Pro on a real PC, then copy its partition to a disk image file, then transfer that to my Mac and install it in Q.

There's a problem though: one can't just copy the BeOS partition, because the image will be missing the partition map that the boot loader requires. So what we do is create a blank file that's the size of a single IDE disk cylinder, append the BeOS partition, then use Linux' sfdisk partition table editor to add a partition map to our new image. Both sfdisk and fdisk will work with ordinary files, not just device files! We use sfdisk because it allows sector-level precision, so we can specify the BeOS partition's offset and size exactly as it was copied.

This requires Linux as well, but if you don't want to install Linux on your PC, you can boot from a Knoppix CD and save your image file on one of your other partitions.

But first, a...

Warning!

[Top]

Careless use of partition map tools like sfdisk and fdisk can destroy your data! Be Careful! You would do well to back up your data first.

However, because sfdisk accepts sector-level specifications, you can save your partition map in case it ever gets destroyed. Use this command:

# sfdisk -d /dev/hda > hda.txt

(Substitute the real device file of your drive for hda above). Save hda.txt to a floppy and put it in a safe place. Consider printing a hardcopy and taping it to your wall.

You only need to be root when copying the raw partition to your filesystem. All the other commands will work as a regular user, you don't need to be root.

The Procedure

[Top]

There's a caveat, though, in that the disk image file has to look like a real IDE disk drive to the BeOS boot loader. The geometries of IDE disk drives are specified by the numbers of sectors per track, heads per cylinder, and total number of cylinders. IDE disks use 512-byte sectors, so the size of a drive in bytes is:

Bytes = 512 * Sectors * Heads * Cylinders

The disk image file must have an integer number of cylinders! My first attempt at an image file didn't, and the BeOS boot menu didn't show it. I think the boot loader tried to test the drive by seeking to the last cylinder, and when it got an error, it assumed the drive wasn't functioning. For that reason, we may also need to append some blank data to the end of the image so that the cylinder count is a whole number.

There's another problem: sfdisk gets the drive geometry from the Linux kernel, which reads it from the drive with an IDE command. But ordinary files don't have a geometry, so we have to give a geometry to ours in the way we create our partition map. The partition map identifies the geometry, so the BeOS will use what it finds. One can give the -S, -H or -C parameters to sfdisk to specify the number of sectors, heads and cylinders, but I found a bug in the version of sfdisk I used: sfdisk ignored my specifications, and built a partition map for 63 sectors and 63 heads. Thus I just had to use 63 * 63 = 3969 sectors per cylinder in my calculations.

After I worked out the procedure, I went through it all a second time while recording my terminal session so I can show it to you here. Hopefully that will make it all clear.

One other problem I found was that while I was able to get the video to work well for my first installation, which was a fresh install of BeOS 5 Pro, I couldn't get it to work for my second install of 5.0.1, which had been in use for some time. I think some preference is configured in my old installation which is screwing up my attempt to set the video mode. For this reason, I advise copying a fresh install of the BeOS rather than one you have been using on a real PC.

Here is a summary of the procedure:

  1. Install BeOS 5 Pro on a partition on a real PC
  2. Download a VESA video mode tool from BeBits to the BeOS volume
  3. Use dd to create an empty file one cylinder in size
  4. Use dd to copy the BeOS partition to a regular file
  5. Use cat with >> to append the BeOS image file to the first cylinder file
  6. If the final product is not a whole number of cylinders, use dd to create an empty file that makes up the difference
  7. Use cat with >> to append the tail file to the end of the image
  8. Create a text file that specifies the partition map to sfdisk
  9. Use sfdisk to write a partition map to the image file
  10. Copy the image file to the machine where it will be used with QEMU
  11. Download a BeOS boot floppy to the host PC
  12. Create a new guest PC with the BeOS image file and boot floppy image file
  13. Boot the BeOS then use the VESA video mode tool to set the video
  14. Reboot into a full color BeOS!

Got all that? I'll go through it step by step now, with a real working example. It's pretty complicated though; I suggest printing a hardcopy of this page and reading the whole thing through before commencing your installation.

Install BeOS on a Real PC

[Top]

First, use the BeOS 5 Pro installation CD to install the BeOS to a partition on a real PC. It doesn't have to be on the first drive. Set the partition's size to something that will fit reasonably well on the drive where QEMU will run. You can't make it smaller afterwards, but if you need more space, you can create a blank image file with QEMU and format it with the BeOS Drive Setup program.

Download a VESA Video Configuration Tool

[Top]

Before booting Linux, setup the BeOS network so you can download a VESA configuration tool from BeBits. There are two tools available: VESA Accepted and VESAme. VESA Accepted is more featureful, but VESAme is available in Dutch, German and Spanish in addition to English.

We need a video configuration tool because the BeOS doesn't support either of the available emulated video cards. However, the cards do support the industry-standard VESA 2 BIOS, as does the BeOS, so we will get full-color video and a choice of screen resolutions if we set the video mode. Without this, the BeOS only displays grayscale video and runs very slowly.

Be sure to download the VESA tool to your BeOS installation before you boot into Linux to copy your installation; because networking doesn't work yet in the BeOS, it would be very painful (though not impossible) to copy the VESA tool to the BeOS running under QEMU.

Use dd To Create an Empty File One Cylinder In Size

[Top]

Strictly speaking, the BeOS partition doesn't have to start on a cylinder boundary, but some software does care, so all the partition tools complain if a partition isn't cylinder-aligned.

As I said, no matter what I told it to do, the version of sfdisk I used created partition maps with a geometry of 63 sectors and 63 heads, so our first cylinder will have 63 * 63 = 3969 sectors. My BeOS boot drive is called "Darth", so that's what I'll name my image. We specify a blocksize of 512 to dd with the bs parameter:

bjarne:/home/mike/BeHack# dd if=/dev/zero of=Darth.img bs=512 count=3969
3969+0 records in
3969+0 records out
2032128 bytes (2.0 MB) copied, 0.04616 seconds, 44.0 MB/s

/dev/zero is a special file that always gives you zeroes no matter how much data you read from it. The command "man dd" will give you documentation on the dd command.

Use dd To Copy the BeOS To a Regular File

[Top]

This is the only step where you need to su to root; for safety, you should perform all the other steps as an ordinary user.

First, we need to make sure we know which partition has the BeOS on it. sfdisk -d will list the partition map. BeOS partitions have the partition id 0xEB, or "Be" backwards. In my case, my BeOS installation is on my second IDE drive, /dev/hdb:

mike@bjarne:~/BeHack$ su
Password:
bjarne:/home/mike/BeHack# sfdisk -d /dev/hdb > hdb.part
bjarne:/home/mike/BeHack# cat hdb.part
Warning: extended partition does not start at a cylinder boundary.
DOS and Linux will interpret the contents differently.
# partition table of /dev/hdb
unit: sectors

/dev/hdb1 : start=        1, size=  8032499, Id=eb, bootable
/dev/hdb2 : start=  8032500, size=  3213000, Id=eb
/dev/hdb3 : start= 11245500, size=  4819500, Id=b7
/dev/hdb4 : start= 16065000, size= 62091225, Id= 5
/dev/hdb5 : start= 16065063, size=  3212937, Id=b8
/dev/hdb6 : start= 19278063, size=  3212937, Id=82
/dev/hdb7 : start= 22491063, size= 12851937, Id= 7
/dev/hdb8 : start= 35343063, size= 20884437, Id= 7
/dev/hdb9 : start= 56227563, size=  9638937, Id=b7
/dev/hdb10: start= 65866563, size= 12289662, Id= 7

You can see I have two BeOS partitions: /dev/hdb1 and /dev/hdb2. I'll be copying the second one for this article. Note that sfdisk -d reports partition figures in precise units of sectors, and in an easily machine-parsed format that can be read back by sfdisk for creating partition tables. In a little while, we'll create a similarly formatted partition specification for our image.

Now we copy the image file to a regular file with dd. The dd man page says that one can give the oflag=append parameter to append the output to an existing file, but when I tried to append to my first cylinder file, dd clobbered it, so instead we'll copy to a second file, then use cat to append it. Unfortunately this means creating two copies of the partition, which can take up quite a lot of space.

bjarne:/home/mike/BeHack# dd if=/dev/hdb2 of=hdb2.img bs=512
3213000+0 records in
3213000+0 records out
1645056000 bytes (1.6 GB) copied, 142.748 seconds, 11.5 MB/s

Use cat with >> to Append the BeOS Image File to the First Cylinder File

[Top]

Redirecting a command's standard output with two greater than signs - ">>" - appends the output to any existing file. Be careful not to just use one greater than sign - ">" - or you'll clobber the file you're trying to append to and have to start over again.

mike@bjarne:~/BeHack$ cat hdb2.img >> Darth.img
mike@bjarne:~/BeHack$ ls -l
total 3219096
-rw-r--r-- 1 mike mike 1647088128 2006-06-06 04:08 Darth.img
-rw-r--r-- 1 root root 1645056000 2006-06-06 04:06 hdb2.img
-rw-r--r-- 1 root root        687 2006-06-06 03:40 hdb.part

Use dd to Create a File That Makes Up a Whole Number of Cylinders

[Top]

Chances are the image file you just created does not make up an integer number of cylinders. If you try to use it, the BeOS boot loader will reject it, and the drive won't be visible in the boot menu. To fix that, we calculate how many sectors are needed to make up the difference and create an empty file of that size.

Note the size of Darth.img in the ls -l listing above: 1647088128 bytes. We first calculate how many cylinders it is. sfdisk wants us to use a cylinder size of 63 sectors * 63 heads = 3969 sectors. Each sector has 512 bytes, so we have:

Cylinders = 1647088128 / ( 63 * 63 * 512 ) = 810.523... Cylinders

We don't worry about the size of the fractional part. Unless it divides into an even number of cylinders, we need to round up (that is, take the ceiling) to find the final size for our image. In my case, it's 811 cylinders.

Now we calculate the size of our tail file. Don't try to calculate using the result you just got; you might lose precision in your calculation. Instead calculate the number of bytes in an 811 cylinder drive image:

Bytes = 811 Cylinders * 63 Sectors * 63 Heads * 512 bytes = 1648055808 Bytes

Now subtract the present size of our image to get the tail file size in bytes:

Tail Size = 1648055808 Bytes - 1647088128 Bytes = 967680 Bytes

The tail file should be an integer number of sectors. Calculate how many by dividing by 512:

Tail Sectors = 96780 Bytes / 512 Bytes/Sector = 1890 Sectors

If it doesn't divide evenly, that is if this last calculation had a fractional part, then you've made a mistake and should re-do your calculations more carefully.

Now we use dd to create a tail file with the calculated number of sectors:

mike@bjarne:~/BeHack$ dd if=/dev/zero of=tail.dat bs=512 count=1890
1890+0 records in
1890+0 records out
967680 bytes (968 kB) copied, 0.022061 seconds, 43.9 MB/s

Use cat with >> to Append the Tail File to the End of the Image

[Top]

Again, be careful to use two greater than signs and not just one, or you'll clobber your image file and have to start over:

mike@bjarne:~/BeHack$ cat tail.dat >> Darth.img
mike@bjarne:~/BeHack$ ls -l
total 1611964
-rw-r--r-- 1 mike mike 1648055808 2006-06-06 04:10 Darth.img
-rw-r--r-- 1 root root        687 2006-06-06 03:40 hdb.part
-rw-r--r-- 1 mike mike     967680 2006-06-06 04:01 tail.dat

Note that the size of my image file is now the size my calculation above said it needed to be, that is, 1648055808 Bytes. Just to make sure, I'll divide it by the number of bytes in a cylinder:

1648055808 Bytes / ( 63 Sectors * 63 Heads * 512 Bytes ) = 811 Cylinders

Again, what's important is for the number of cylinders to be a whole number.

Create a Text File that Specifies the Partition Map to sfdisk

[Top]

sfdisk can be used in an automated way to create a partition map from a specification given in a text file; sfdisk -d prints out an existing partition table in the format needed for this.

In the section where we copied the BeOS partition to a regular file, we used sfdisk to save our drive's partition map in a file called hdb.part. Here's it is again:

mike@bjarne:~/BeHack$ cat hdb.part
/dev/hdb1 : start=        1, size=  8032499, Id=eb, bootable
/dev/hdb2 : start=  8032500, size=  3213000, Id=eb

Note the size of the second partition, the one we copied: 3213000 Sectors. Our first-cylinder file was 63 Sectors * 63 Heads = 3960 Sectors, so we need to create a text file that specifies the start of our single partition at 3960 Sectors, with a size of 3213000 Sectors. Here it is:

mike@bjarne:~/BeHack$ cat Darth.part
# partition table of Darth.img
unit: sectors

Darth.img1: start=        3969, size=  3213000, Id=eb, bootable

For your partition specification file, you can just copy the above text starting with the word "unit" (don't copy the cat command!) and substitute the size I give in boldface with the actual size of your BeOS partition.

Use sfdisk to Write a Partition Map to the Image File

[Top]

Here's where you don't want to be root, and to be sure you're writing to your image file and not to your real hard drive. sfdisk will create a partition map given the above file on the standard input, but it complains because the first sector of the image doesn't already contain a boot sector. We need to give the full path to sfdisk because /sbin is not in the PATH for ordinary users:

mike@bjarne:~/BeHack$ /sbin/sfdisk Darth.img < Darth.part
Warning: Darth.img is not a block device
Disk Darth.img: cannot get geometry

Disk Darth.img: 0 cylinders, 0 heads, 0 sectors/track

sfdisk: ERROR: sector 0 does not have an msdos signature
 Darth.img: unrecognized partition
Old situation:
No partitions found
Warning: given size (3213000) exceeds max allowable size (0)

sfdisk: bad input

Fortunately, sfdisk offers the --force option to do it anyway. Just to make sure, we use the -H and -S parameters to specify the number of heads and sectors, because it can't get them from the kernel:

mike@bjarne:~/BeHack$ /sbin/sfdisk --force -H 63 -S 63 Darth.img < Darth.part
Warning: Darth.img is not a block device
Disk Darth.img: cannot get geometry

Disk Darth.img: 0 cylinders, 63 heads, 63 sectors/track

sfdisk: ERROR: sector 0 does not have an msdos signature
 Darth.img: unrecognized partition
Old situation:
No partitions found
Warning: given size (3213000) exceeds max allowable size (0)
New situation:
Warning: The partition table looks like it was made
  for C/H/S=*/33/63 (instead of 0/63/63).
For this listing I'll assume that geometry.
Units = sectors of 512 bytes, counting from 0

   Device Boot    Start       End   #sectors  Id  System
Darth.img1   *      3969   3216968    3213000  eb  BeOS fs
                start: (c,h,s) expected (1,30,1) found (1,0,1)
                end: (c,h,s) expected (1023,32,63) found (810,32,63)
Darth.img2             0         -          0   0  Empty
Darth.img3             0         -          0   0  Empty
Darth.img4             0         -          0   0  Empty
Warning: partition 1 extends past end of disk
Successfully wrote the new partition table

Re-reading the partition table ...
BLKRRPART: Inappropriate ioctl for device

If you created or changed a DOS partition, /dev/foo7, say, then use dd(1)
to zero the first 512 bytes:  dd if=/dev/zero of=/dev/foo7 bs=512 count=1
(See fdisk(8).)

Note the warning that the partition map was created for 33 heads instead of the 63 specified. If this is really the case, then the partition map causes our image file to no longer have a whole number of cylinders. Fortunately this turned out to be spurious; it seems that IBM PC-architecture partitioning is a black art.

Copy the Image File to the Machine Where it will be Used with QEMU

[Top]

In my case, I'm running QEMU under the Q front-end on an Intel OS X MacBook Pro. I transferred the file with ftp running in the OS X Terminal program. This can take quite a while if the image file is big. Take a break while it transfers, you need it!

Download a BeOS Boot Floppy to the Host Computer

[Top]

You need a boot floppy because sfdisk doesn't place a boot loader in the first sector of the image when it created the partition map. You can download a BeOS boot floppy image from the Zelect.org Zeta/BeOS/Haiku Software Repository.

Alternatively, you can boot your PC back into the BeOS and give the following command:

$ makebootfloppy -cd -preserve

A boot floppy image file called boot.img will be placed in the /tmp directory. makebootfloppy will complain if it doesn't find a floppy in the floppy drive, but it still seems to create the image OK. After creating the image, ftp it to your QEMU host computer.

Create a New Guest PC with the BeOS Image File and Boot Floppy Image File

For now I just have the procedure for configuring Q on Mac OS X; I'll get back to you on Linux and Windows after I've had a chance to try out their QEMU ports.

In Q, click the "+" icon in the Q Control window to create a new Guest PC:

Create a new guest PC in Q

In the window that appears, click the Hardware icon, and set the Floppy and Hard Disk menus to the two image files. Set the Boot From menu to floppy:

Options for BeOS hardware in Q

Either of the video card options seems to work equally well once the VESA settings are configured. I didn't have any luck with the network or sound, but you're welcome to try. Click the Update PC button to save your settings.

Drum roll, please...

Boot the BeOS

[Top]

Click on the item for your new Guest PC in the Q Control window to select it, then click the triangle icon to boot. Hopefully the BeOS boot loader will appear; as soon as it does, press and hold your space bar to enter the boot menu - I found that I had to select the boot drive or the loader would panic.

In the boot menu, use the arrow keys to select "Select new boot volume" and press return. Hopefully you will see your BeOS boot drive listed, with kernel_intel on the right. If it doesn't appear, there is some kind of error in the partition geometry or the size of your image file - were your sector and cylinder calculations correct?

If you see your drive, use the arrow keys to select it, then press return. In the next screen, select "continue booting", and press return. Hopefully what you see next will look something like this:

BeOS boot loader

Set Your VESA 2 Video Mode

The BeOS doesn't recognize either of the available emulated video cards, so the desktop will (hopefully) appear in a grayscale safe video mode. The BeOS will run very slowly, with the pointer lagging behind your mouse movements, because video accelleration isn't enabled. You need to use one of the VESA video mode tools we previously downloaded to set the video mode. After rebooting, you should get full color and faster performance:

The BeOS doesn't recognize the QEMU emulated video card

The BeOS does support the VESA 2 video bios, and will work correctly if we set the video mode manually. Here I set it with Vesa Accepted:

Setting the VESA 2 video mode

If you forgot to download a VESA tool to your BeOS volume, you can set it manually by creating a simple configuration file as follows:

$ cat /boot/home/settings/kernel/drivers/vesa
mode 1024 768 16

If you set your resolution to the same as that of your host computer, then give the -full-screen parameter to QEMU in your Guest PC's Advanced settings, you can run full-screen. However, this didn't work on my MacBook Pro as its 1400 by 900 screen is not one of the resolutions supported by QEMU's emulated video cards.

If you hope and pray and cross your fingers, maybe when you reboot, your screen might look something like mine does here (click for a full-size screen shot):

BeOS on a MacBook Pro

You'll find it runs much faster with the video mode set. I get about three frames per second in GL Teapot on a 1.83 GHz MacBook Pro. My MacBook has a dual-core Intel processor, but QEMU does not yet take advantage of multiple CPUs despite the fact that it can emulate them.

Now go have a cup of tea and relax.

Where to Go from Here

[Top]

While I don't get any crashes from the BeOS running under the emulator, it's not very usable with neither sound nor the network able to work. The emulated ethernet card is detected, and if I configure it and restart networking, no error is reported. But any attempt to connect is met with the message "socket: name not found".

I expect that now that installation is possible at all, and with the BeOS running mostly reliably, it should be straightforward to find the problems and fix them in the emulator.

Faster video performance and therefore faster overall emulation could be enabled by writing a BeOS driver for QEMU's emulated Cirrus Logic GD5446 PCI video card. Lots of people have written BeOS video drivers so I expect this won't be hard.

Without networking, it's very painful to transfer files to and from the host computer. It is possible though - I learned the hard way that I needed a VESA mode tool, and figured out how to transfer files after getting my installation running under Q. What I did was create a second image file that I formatted and mounted under my QEMU Linux installation, copied the VESA tool to it, then dismounted the filesystem and mounted it under the BeOS. One cannot yet go directly from MacOS X, as it won't format raw image files, and Q doesn't support OS X .dmg disk images. I'll discuss this in more detail in my next revision to this article.

It's easy to see how the procedure I outlined could work for most operating systems, not just the BeOS. It could be useful for safely testing configuration changes before committing to them on a real computer, or for debugging arcane problems by reverse-engineering them with the emulator under a debugger.

It's also easy to see how this error-prone procedure could be automated. A Perl or Python script could do it under Linux; a program written in C could do it under any operating system.

I won't be doing that myself though because I need to devote my attention to developing Ogg Frog; I worked out this procedure because it will be helpful to Ogg Frog's development to be able to test builds for all my target platforms from my one laptop.

I expect I will do some hacking on QEMU though, to add some basic support for SCSI. I plan to add enough of an emulation of the SCSI Common Access method to rip and burn CDs from emulated systems.

That's all for now, but in coming days I will discuss other operating systems and other emulators.

Ciao! -- Mike

[Top]

What the Bold Print Giveth, the Fine Print Taketh Away

Copyright © 2006 Michael D. Crawford.

Ogg Frog, Rippit, Rippit the Ogg Frog, the Frog logo and the Circle Flowers logo are trademarks of Michael D. Crawford. All other trademarks are the property of their respective owners.

So there.