Skip to content
Ryan Collins edited this page Mar 13, 2022 · 6 revisions

Welcome to the VM-OS wiki!

Approximate design of how this works/will work:

  1. Compile the linux kernel, with a specific set of build options. (optimised mostly for Qemu itself to start with for testing purposes)
  2. Find a simple bootloader, to handle booting (qemu testing doesn't need this, but real hardware will)
  3. A custom init script to: a. Set up DHCP (get an IP address, if there's a network) b. Set up IO devices (keyboard/mouse), if required. c. Start up Qemu with a configured VM image, which will run in foreground. d. Then loop until Qemu exits, and shutdown the machine (gracefully).

Why?

The goal is to be able to run, on new hardware, many old operating systems (just by providing a VM image).

The boot time should be fast: we don't need systemd just to run a VM (the VM itself should govern the startup time).

But really, why?

This is a learning experience about operating systems, Linux in general, and VMs.

Log of getting this built:

This section will be split/will be separated later into a write up. This contains various notes of issues/improvements throughout.

  1. Unable to mount root fs on unknown block

Unable to mount root fs

This confused me slightly: seems as though the root fs isn't set up properly/in the right format, but the question is: how to fix this?

https://unix.stackexchange.com/questions/67462/linux-kernel-is-not-finding-the-initrd-correctly

In general, while this might work, there's probably an easier way: create a GZIP file containing the file system structure.

To start with, lets go back to basics: use a prebuilt tool to do this. Also use a prebuild kernel (the one provided by Fedora).

I used https://github.com/venomlinux/mkinitramfs to build the initrd, and changed /init to be my own one. Did it work? Well, sort of....

It booted, found the root file system (so some progress) but couldn't run /init

  1. The importance of statically linking: Exit code -2: but what does this really mean? It means a file doesn't exist. However, /init does exist?

Running `gcc main.c -o init" builds a dynamic executable, which has a dynamic link on libc.

In fact, you can see this in action - compile it as such, and then run ldd init:

[ryan@lexo init]$ ldd init 
        linux-vdso.so.1 (0x00007fff019b1000)
        libc.so.6 => /lib64/libc.so.6 (0x00007f5f4fd3c000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f5f4ff61000)

This is dynamically linked, as the first file called is actually the linker (ld), which then links this file with other associated libraries.

As such, that exit code -2 actually means "the linker doesn't exist/one of the provided libraries doesn't exist", which is the case.

We can solve this by running gcc -static main.c -o init: compile this while including libc into the binary itself. At first, this failed because of a missing dependency. You need the static libc libraries installing, which on Fedora is easily fixed by running yum -y install glibc-static.

Then, success!

Screenshot from 2022-03-13 09-48-42

This isn't much, but shows it works.

  1. Adding Qemu to the mix Compiling Qemu using static libs seems tricky. As such, we can cheat and dynamically link everything.

ldd shows the associated linked libraries. We can write scripts to copy these linked libs from the host OS, to our custom OS.

We then copy the host qemu binaries and include them in the image.

Does it work? Not quite. system(...) in C runs some command using the root shell /bin/sh which doesn't exist. Adding in the host /bin/sh causes this to work properly and invoke Qemu.

We also need to include the bootloader rom images (from `usr/share/seabios) for this to work properly.

With this, and lots of trial and error later, we get something booting. Now for the image! I copied FreeDOS into the images/ folder and added an entry into main.c to boot QEMU into it using "-cdrom" and it worked:

Screenshot from 2022-03-13 20-58-58

What about Windows 98? This surely won't work? Well partly yes and no: it boots, and console based things work, but the UI portions don't (as expected).

Screenshot from 2022-03-13 21-03-35

It then boots into a completely blank screen when trying to load the UI (because we don't have VGA support).

Clone this wiki locally