Simons Blog | Newest post | About / Imprint

Going through by virtual attic: cos+

Posted on: 2021-03-13

Welcome back. If you haven't read the previous articles about my virtual attic I suggest starting out by reading about Ulsop and ILAS first. Getting fed up with the limits of DOS-based Realmode software I started multiple attempts to write a proper protected mode system. Unfortunately not all of them survived. My first attempt was based on 16 bit Protected mode because I wanted it to be able run on my old 286 PC. But that didn't get very far, I found some bootloader on the Internet which worked with FAT formatted floppy disks. The loader was able to load my OS kernel, which switched to protected mode, set up the GDT to access its code and data and print some stuff to the screen. I didn't get any further... With the next attempt I've given up on 16 bit CPUs and went 32 Bit, again with the same bootloader. I even managed to port some of ILAS' GUI over but never got any disk access to work - talking about priorities here ... sheesh .... I might have a floppy of this semi-functional system called COS(X) somewhere, but it's probably lost as well. But let's not cry over spilt milk, let's see what we have. And what we have is the successor, cos+.

The cos is for "Compact Operating System". Which it really is ... it's compact. So with cos+ I wanted to have the OS sort-of working before attempting a graphical interface, so most stuff is commandline based. It features a GUI - which crashes upon startup. (Widgets again based on ILAS). I might only have an older backup because I remember doing some GUI-stuff in cos+, but it could also be the emulation / virtualization software. Another one of my earlier priorities was porting a C compiler, so that's what I did. Actually, it just uses the GNU C compiler on Linux with a custom linker script and runtime init code - but that works very well.

Due to the nature of cos+ being a full OS, not just something that runs on DOS, it's not possible to run it on DOSBox anymore, but it needs a fully virtualized environment. For development I used bochs, but it will run on VirtualBox and qemu as well. If you still have an internal floppy drive you can also write it to a floppy disk and boot off your real PC. It's probably not even able to do any damage because I've never implemented any disk writing routines.... Maybe it will run off a USB disk, but I've never tried. Bochs however is very useful for development because if something goes wrong you get detailled information about where it crashed and why. It helped a lot to see register dumps in case of a triple fault instead of just having the thing reboot.

cos+ has a multiboot compliant kernel so it can be booted from GRUB. The nice thing about GRUB is that it allows for lots of configuration such as kernel parameters (which can even be altered before startup) and boot modules, which are just files grub will load into memory. cos+ just puts all modules it receives into a ramdisk. This helped a lot during the development of a filesystem driver - which I did before writing the driver for the floppy disk controller.

So after the kernel is loaded from GRUB, the system is already in 32 Bit protected mode. The entry point is in klib.asm which checkes for a valid multiboot signature, sets up a stack and passes control to kernel_main() in kernel.c It starts by setting up the GDT, memory management and various drivers. Then it rescues the multiboot information from its own memory manager - copying all the bits into properly allocated memory and initializes even more drivers. Then it parses the commandline to see if there are any filesystems to assign. cos+ uses a drive-based filesystem like DOS and Windows, not a single-root system like Linux, UNIX and ILAS. So drives are "assigned", not "mounted". But drive designations can be longer than one character - the idea was to eventually have system roots which are not just a:/ and c:/, but also roots like http:/. During boot COS+ assigns the following filesystems

Drive Content
dev: Device Filesystem (devfs)
sys: System filesystem, contains information about the system, drivers, irqs and processes
tmp: Temporary filesystem, backed by a ramdisk like Linux tmpfs
part: Partition management filesystem (see below)
a: FAT filesystem on first floppy drive
cfg: Maps to a:/cfg/ (specified by boot parameter)

After assigning all the filesystems it opens the console driver dev:/con, runs the process specified via the init= parameter or alternatively init.cxe or cmd.cxe from the main volume (a:). For now we just have a:/cmd.cxe which is, you guessed it, a simple command shell.

The system is quite limited however because cos+ uses segmented memory and no paging. This can be quite tricky to work with using GCC. Also I never got proper kernel/usermode separation to work, so all userspace processes just run in ring 0 and can bring down the entire system if something goes wrong. Which is does often ... Proper ring 3 support was planned but I never got around to implement it.

What really killed further cos+ development off was the many, many bugs it has and also lots of technical debt acquired to accomplish short-term goals. One of the biggest WTFs is probably that it has kernel managed string-lists (!) because I needed string lists for a program and there is no userspace memory management yet ...

Let's get to some of cos+ features and supported devices:

Any block device or block device can be assigned to a drive. So "dev:/fd0" gets assigned to drive "a". If you want a FAT disk image from drive c, named stuff.img mounted on the "stuff:/" drive you can call "assign fat stuff c:/stuff.img". The partition table driver can be sandwiched in between to access partitions. So you probably won't assign "dev:/bios-ata0" anywhere (since that's the whole disk), but for a FAT filesystem on your fist disk you can use "part:/01dev:/bios-ata0". Or if that same image file mentioned above has a partition table you could do "part:/01c:/stuff.img", no loop-devices needed. Minix uses subpartitions which COS+ also supports, eg. "part:/01part:/02dev:/bios-ata0"

The harddisk driver just uses the BIOS to access any kind of disk so it can be used with IDE and SATA disks and probably even USB as long as the BIOS can work with it. cos+ accomplishes this by switching to real mode, executing the BIOS call and switching back to protected mode. This means that all tasks are suspended while the disk access is going on. The BIOS trick is also used to easily switch video modes.

So, finally, let's fire it up and see what it does. This is output when booting cos+ in bochs:

  Booting 'COS+ System'

kernel (fd0)/boot/kernel.bin +MAPFS cfg a:/cfg/;
   [Multiboot-elf, <0x100000:0x16d3c:0x71b20>, shtab=0x189118, entry=0x1000b5]

----
COS+ V0.2 Operating system (C) Simon Laburda 2004, Loading....
Initializing memory-management:
  Base memory (636KB)
  Extended memory (31680KB)
cmdline: "(fd0)/boot/kernel.bin;+MAPFS cfg a:/cfg/; "
Available memory: 31706KB
sb16: No SoundBlaster card detected
Found SVGA V2 from Bochs VBE (C) 2002-2020 http://savannah.nongnu.org/projects/v
gabios/
PS/2-driver loaded: found regular PS/2-Mouse
Assigning FS: MAPFS cfg a:/cfg/
Loading libc.... done
Using init "a:/cmd.cxe"
[a:/] _

I pasted it as text because cos+ boots in text mode. There isn't really much more I can show for now. Even the very simple textmode based database tool I wrote for it crashes on startup. But I remember it working and actually being used. I'm currently porting over the build environment over to more modern Linux systems and try to get things working again. There won't be any new additions to the code or big changes in how the kernel works, just bugfixes. Unfortunately I can't upload the floopy image used for the above screenshot as it contains personal information. Once I get it running I'll post a tarball and freshly built floppy image.

Unlike ILAS however I don't think I will be continuing to work on this because of the technical debt and it not really having any use for anything ...