Virtual OS development

A cookbook of OS development using Virtual PC on Windows

(C) 2010 A. Tarpai (tarpai76 at gmail)

 

Download

I enclose all the files (except executables) here. Good luck!

 

 

Virtual OS development

Boot kernel.bin in VPC from virtual floppy

About

Virtual machines

Virtual floppy driver

Ken Katofs VFD 2.1

Making the boot floppy

Writing assembly boot block code

Creating the image file

Open the image file in VFD 2.1

Making kernel.bin

main.c

startup.asm

DJGPP: a gcc and tools port to DOS

Putting it all together

Required pre-install

Step by step

Run another cycle: change main.c

Download

Whatfs next?

Serial I/O with the box

HW Virtual Serial Port by www.HW-group.com

Seting up HW VSP 2.5.10

Troubleshootig Hyper Terminal (HT) with HW VSP

VPC and serial ports

COM1 port settings in our OS

Summary

Cookbook

All together

 

 

 

Boot kernel.bin in VPC from virtual floppy

About

This is a start package if somebody wants to get into os/hardware/game/embedded-development on a bare PC.

 

This is a description about how I used M$ Virtual PC on XP for os development exercises! :) The goal was to set up and configure a development environment using free products, and making it pure virtual, so one doesn't need 2 machines for os dev. It will emulate all hardware devices in software. Also for starting to develop a 32-bit kernel in C using gcc...

 

This is how far this exercise goes: boot and write an "A" with 32-bit C-code in VPC:

 

main()

{

 *(char*)0xb8000='A';

}

 

 

 

Virtual machines

M$ Virtual PC (VPC) is a free virtual machine software, an application that simulates/emulates a whole PC in a window. It can boot from both physical (eg. floppy) or virtual devices (a disk image file: .vhd for hard disk and .vfd for floppy disk*).

 

There are many other free virtual machine (VM) software products: VirtualBox, Bochs, VMware.. I tried a few of them, and ended up using VPC. First, it was very simple to download, install and set up on XP. Second, and the main reason, the graphics hardware it emulates: there is an S3 Trio64 inside and I've been hacking S3 Trio64V+ chips before, learned much about it, knew the register set as I was interested in 2D-accelerated SVGA graphics on real hardware. VPC actually emulates this chip very well on the register level (there are of course differences).

 

These are the setting of our very plain os dev virtual machine, which boots from floppy and emulates COM1 only:

 

 

 

* It's possible to attach a floppy image file directly to VPC, but only by editing the .vmc file. When eg. the image file, floppy.vfd,  is in the same directory:

<floppy id="0">

               <pathname>

                   <absolute type="string" />

                   <relative type="string">floppy.vfd</relative>

               </pathname>

</floppy>

This works fine when the content of the image is manipulated only by VPC.. but here we want to copy a new kernel.bin to the disk each time. So.. we need a tool anyway that can use a floppy image file.. such as VFD 2.1.. but then why not simply mount as A:?

Virtual floppy driver

Boot the PC from floppy requires the least effort to program and this is important in the beginning. Of course VPC can access physical drives but using a virtual floppy drive in software with image files is much-much faster. What we need is a free virtual floppy drive software (which mounts A:), and make this boot disk image.

 

Ken Kato's VFD 2.1

A nice and free floppy drive virtualization tool I used. It can mount an image file as A: that VPC can boot from.

 

Making the boot floppy

The following is to make a floppy image file, but the process is essentially the same for a real boot floppy disk too.

 

Writing assembly boot block code

Booting from floppy is the easiest. BIOS loads the 512 byte boot sector from floppy to address 0000:7C00 and starts executing the code in 16-bit real mode. I don't know more details here, x86 assembly, floppy controller programming, etc. so the code is based on J. Fine's floppy boot sector code - many thanks for that! The code loads a binary file from floppy using BIOS calls to a given address in memory. Enough to start a 32-bit kernel! :) We need:

 

  1. bootblk.asm source code
  2. an assembler: nasm.exe

 

nasm -oboot.blk bootblk.asm

 

This will produce an 512 byte size 16-bit binary x86 code, which has to be copied on the floppy image into the first sector.. and here comes PARTCOPY from J. Fine again, but first lets make the floppy image file itself.

 

Creating the image file

First of all we need a file of the size exactly 1 474 560 bytes (1,44 MB), because the floppy has

  1. 2 sides
  2. 80 tracks
  3. 18 sector per track
  4. 512 bytes per sector

and 2 x 80 x 18 x 512 = 1474560.

 

On ms dos creatfil.exe can be used (part of Windows 2000 Resource kit) from the command prompt:

 

        creatfil.exe floppy.img 1440

 

Open the image file in VFD 2.1

Start vfdwin.exe to open the image file and mount as drive A:

 

 

It can be done from the command prompt too - see later.

 

Making kernel.bin

This file will be the 32-bit binary file, which will be loaded from disk by the boot sector code at absolute linear address 0x100000 (1M). The goal is to write it in C. Note, that the running environment is very primitive, basically nothing. I don't even know yet where the stack is..

main.c

For now the C kernel is 1 line and puts an "A" on the screen. It could be named anything actually, because there is no run-time or loader or such. No argv/argc parameters either! The startup code simply calls _main().

startup.asm

Startup.asm is a one-line assembly module that makes a jump to the externaly defined symbol _main. It exists only because I cannot rely a C compiler to place code at a certain address, and kernel.bin should start at a fix adress.

 

DJGPP: a gcc and tools port to DOS

 

Used to compile and link the kernel parts in C. It worked really well for me for osdev for both C and C++. Download, make dir, unpack, ... follow the readme-s. I use simply gcc -c main.c to make an object file for the ld linker, which makes kernel.bin. Using gcc and co. is a much bigger discussion anyway...

 

 

Putting it all together

=> create a bootable floppy image that will load the 32-bit binary file "kernel.bin" from disk to address 0x100000 (1M), that writes "A" on the screen and halts.

 

Required pre-install

 

  1. creatfil.exe
  2. partcopy.exe
  3. vfdwin.exe
  4. nasm.exe
  5. djgpp: gcc C-compiler for dos
  6. source files:
  1. bootblk.asm
  2. startup.asm
  3. main.c

 

Step by step

 

  1. creatfil floppy.img 1440
  2. start vfd
  3. open floppy.img in vfd as a:
  4. format a:
  5. close and save floppy.img
  6. run bootblk.bat, which
  7. nasm -oboot.blk bootblk.asm
  8. PARTCOPY boot.blk 0 3 floppy.img 0
  9. PARTCOPY boot.blk 3E 1C2 floppy.img 3E
  10. open floppy.img in vfd again
  11. assemble startup.asm
  12. compile main.c
  13. link startup.o and main.o to binary kernel.bin
  14. copy kernel.bin to disk a:
  15. boot VPC..

 

Here is the image file zipped for simplicity [...].

 

On success VPC will boot from this image and put an "A" on the screen!! Then we are happy :))

 

Run another cycle: change main.c

Next time after writing more C code into main.c, we just make the new kernel.bin, copy to disk and boot VPC again. Splendid! :) The batch file kernel.bat that does exactly this. Of course later on other object files (assembly, C, C++ even mixed) can be linked into the binary, thus building up our own system.

 

 

 

 

What's next?

Well, the whole PC is yours in 32-bit C.. so.. it depends.

 

My next step was to get I/O through the serial port and start reading/writing some pc hardware, and prepare the (software) multitask kernel. Then graphics! :))

 

Most people start extensive programming of the Intel CPU by setting up paging, segments, TSS, 64-bit modes, multicores.. many things I have very little idea about. My personal interest was more general but consequent in one thing: Intel-independent. I had some design idea of a multitask system with GUI and not cpu, disks, consoles, vga, bios or vesa bios. Sorry.

 

 


Serial I/O with the box

 

The purpose is to set up VPC for floppy boot and serial I/O communication, both virtual, emulated in software. This chapter is about virtual serial I/O. Why? Because this is the easiest programmed I/O on the PC in the os - and also tastes old-skool using terminals ;) !

 

HW Virtual Serial Port by www.HW-group.com

There are lots of virtual serial port emulation software, but this worked for me, so I could communicate with the OS in the virtual machine using Hyper Terminal on Windows. HW VSP is free and can connect a virtual serial port to a TCP/IP port. Virtual PC connects to this virtual serial port, while Hyper Terminal to the TCP/IP port. Works like a charm! :)

 

Seting up HW VSP 2.5.10

This will create and connect COM5 with port 22222 on the localhost (127.0.0.1):

 

 

 

Troubleshootig Hyper Terminal (HT) with HW VSP

 

  1. run (and configure) HW VSP to connect eg. COM5 to TCP port 22222 (as above)
  2. run 2 instances of HT
  3. with one connect to COM5
  4. with the other one connect to TCP port 22222
  5. typing in one of the windows and text should appear in the other one:

 

 

 

VPC and serial ports

From the inside, the guest os, everything is normal and standard. I will find a working COM1 port at I/O port 3F8. This is of course emulated and where it goes is set up during virtual machine setup. It can map to one of the physical COM ports or any virtual COM ports of the host. The goal is to connect VPC with HT. HW VSP can create a virtual COM port, lets say COM5, and this is the host COM port VPC's COM1 port should be mapped to (see the settings above).

 

COM1 port settings in our OS

I prefer serial I/O communication for early osdev, not IBM PC-specific character screens and ps/2-keyboard drivers at this stage. It takes anyway only a few lines of C code to set up the PCfs serial COM port for I/O, eg. 9600 8-N-1 (9600 baud speed, 8 bit per byte, no parity, 1 stop bit):

 

  outb(COM1+3, 0x80);       // set DLAB

  outb(COM1+0, 1);          // baudrate LO

  outb(COM1+1, 0x0C);       // HI (0c => 9600 baud)

  outb(COM1+3, 0x03);       // clear DLAB & set 8-N-1

 

That is perfectly enough for character I/O: on the other side we only need a standard terminal program, which connects to the other SER/COM port. Also a matter of taste, but I simply used XP's included Hyper Terminal for that.

 

 

Summary

Cookbook

 

  1. nasm
  2. gcc
  3. VPC (virtual machine)
  4. VFD (virtual floppy drive)
  5. VSD (virtual serial port)

 

  1. gcc compiles and ld links everything to a binary file, spirit.rom
  2. written to A: (virtual floppy drive)
  3. VPC boots from A:, the virtual floppy drive
  4. VPC's COM1 is mapped to hostsfs virtual COM5, that the os uses for I/O
  5. VSD is set up to create a virtual COM5 port and connect it to TCP port 22222
  6. Hyper Terminal connects to TCP port 22222

 

All together

 

 

This is a cookbook on the screen and some other info a Windows host. I have good experience with it, developing on a virtual machine (= an application running on a host) saves a lot of time and much easier: we have to deal with one particular hardware only. It also emulates a PC very well in hardware.  

 

 

And this is how far I got: hi-res true-color graphics, widgets, mouse/keyboard, re-entrant image decoders (here gif), software multitask kernel, messages, lots of lots of goodies :))