So I stumbled onto LiteBSD while I was trying to see if I can cross compile 386BSD 0.0 from Windows (it compiles, but triple faults on boot.)

LiteBSD is a 4.4 BSD derived OS for PIC32MZ microcontrollers.

And to make things more fun, Serge Vakulenko has a Qemu fork that includes these simulators so you can run them on Linux and OS X.

So what about us poor Windows users?

Well a few tweeks, and only one annoying bug remains, but it’s easy enough to sidestep and it runs!


Even better, I got the console to kind of work, although you can still control+c it to kill Qemu.  I guess I could capture the signal being kind of UNIXy.

For some reason when opening the SD card image, it’s already open by the time pic32_sdcard_init is called.  Or so I suspect.  It gets the file handle of 3 which tells me that it shouldn’t be open.  So my fix is lame but it works.  Since something is holding the file that I can’t see, I launch Qemu like this:

qemu-system-mipsel.exe -machine pic32mz-wifire -nographic -serial vc -serial vc -serial vc -serial mon:stdio  -bios boot-wifire.hex -kernel vmunix.hex -hda litebsd.img

with the SD/HDA being litebsd.img but in pic32_sdcard_init I do this:


So you need a dummy file named litebsd.img (it’s just junk but it needs to exist), so whatever is blocking it will block it, then let pic32_sdcard_init open the file litebsd.img.SD which is the real file.

C:\litebsd>qemu-system-mipsel.exe -machine pic32mz-wifire -nographic -serial vc -serial vc -serial vc -serial mon:stdio -bios boot-wifire.hex -kernel vmunix.hex -hda litebsd.img
WARNING: Image format was not specified for ‘litebsd.img’ and probing guessed raw.
Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted.
Specify the ‘raw’ format explicitly to remove the restrictions.
Board: chipKIT WiFire
Processor: microAptivP
RAM size: 512 kbytes
Load file: ‘boot-wifire.hex’, 6916 bytes
Load file: ‘vmunix.hex’, 522408 bytes
sdcard: opened d->fd 3
Card0 image ‘litebsd.img’, 339969 kbytes
Copyright (c) 1982, 1986, 1989, 1991, 1993
The Regents of the University of California. All rights reserved.

4.4BSD-Lite build 13 compiled 2015-01-20
[email protected]:LiteBSD/sys/compile/WIFIRE.pic32
cpu: PIC32MZ2048ECG100 rev A4, 200 MHz
oscillator: system PLL div 1:6 mult x50
real mem = 512 kbytes
avail mem = 344 kbytes
using 18 buffers containing 73728 bytes of memory
spi1 at pins sdi=D14/sdo=C1/sck=D1
spi2 at pins sdi=F0/sdo=D11/sck=G6
spi3 at pins sdi=B10/sdo=C4/sck=B14
spi4 at pins sdi=F5/sdo=G0/sck=D10
uart1 at pins rx=F1/tx=D15, interrupts 112/113/114
uart4 at pins rx=F2/tx=F8, interrupts 170/171/172, console
sd0 at port spi3, pin cs=C3
sd0: type I, size 339968 kbytes, speed 12 Mbit/sec
sd0a: partition type b7, sector 2, size 204800 kbytes
sd0b: partition type b8, sector 409602, size 32768 kbytes
sd0c: partition type b7, sector 475138, size 102400 kbytes
bpf: sl0 attached
bpf: lo0 attached
WARNING: preposterous clock chip time — CHECK AND RESET THE DATE!

starting file system checks.
/dev/rsd0a: file system is clean; not checking
starting network
clearing /tmp
standard daemons: update.
Wed Dec 10 21:06:39 PST 2014

4.4BSD-Lite ( (tty4)


So there it is!  As always, you can do the whole telnet console, on port 2023 like the SPARC with:

qemu-system-mipsel.exe -machine pic32mz-wifire -nographic -serial vc -serial vc -serial vc -serial mon:telnet:,server,wait  -bios boot-wifire.hex -kernel vmunix.hex

In this case, I prefer to use the ‘wait’ portion of the server, so I can watch it boot.  Maybe I’m just weird.  But this way you can control+c to your hearts content.

As always, you can download my image here.

Also for those who like graphical serial connections (???) you can launch it like this:

qemu-system-mipsel.exe -machine pic32mz-wifire  -serial vc -serial vc -serial vc -serial vc  -bios boot-wifire.hex -kernel vmunix.hex -sd litebsd.img

And use control+alt and hunt around for s3, and you’ll have your console….. That you can’t paste into.

**EDIT I found out I forgot to link this with static libgcc so there were missing DLL’s.  sorry, I’ve re-linked and now it’ll just work out of the box (tested with clearing my path on Windows 10).  Next I need to add curses support.

WYSE Unix Virtualized

(this is a guest post from Tenox)


WYSE Unix Virtualization Challenge has been officially won by Mihai Gaitos of He received $100 prize via PayPal. Congratulations!

WYSE Unix has now been virtualized and can run in Qemu via Curses mode, or modified Bochs due to character map issues and vanilla VirtualBox!

wyse_on_bochswyse_on_vboxMihai has posted some gory details of the installation challenges on his website.

Ready to run image with modified Bochs binary for Linux is available here.
VirtualBox OVA file available here.

For hard core fanatics, the system comes with SLIP/slattach so you should be able to network it much like Dell Unix.

Special thanks to:
Andrew Gong for finding a tape image on eBay
Al Kossow of for recovering the tape image
Michal Necasek for patching up the original floppy disk image


More on adding disks to Solaris

So a while back, I built some stuff for Solaris on QEMU, and stuck it in a virtual disk.  Great.  Now the fun is years later trying to use it for yet another project.

By default Solaris doesn’t magically build out the dev tree so adding a disk won’t make it magically appear in the dev tree.  Add the ‘-r’ flag when booting, and it’ll do that.  I still like the verbose boot, so from the prom it’s ‘boot disk0 -rv’

Type help for more information
ok boot disk0 -rv
Boot device: /iommu/sbus/[email protected],8400000/[email protected],8800000/[email protected],0 File and args: -rv

And away we go!

while the kernel boots I can see it see’s my second disk

sd0 at esp0: target 0 lun 0
sd0 is /[email protected],10000000/[email protected],10001000/[email protected],8400000/[email protected],8800000/[email protected],0
<Qemu2GB cyl 4090 alt 2 hd 16 sec 63>
sd1 at esp0: target 1 lun 0
sd1 is /[email protected],10000000/[email protected],10001000/[email protected],8400000/[email protected],8800000/[email protected],0
<Qemu2GB cyl 4090 alt 2 hd 16 sec 63>
sd2 at esp0: target 2 lun 0
sd2 is /[email protected],10000000/[email protected],10001000/[email protected],8400000/[email protected],8800000/[email protected],0
<Qemu2GB cyl 4090 alt 2 hd 16 sec 63>

And once it starts user processes it’ll add in the device files

Configuring the /dev directory
Configuring the /dev directory (compatibility devices)

Which is great.  But how to view the disklabel?

prtvtoc can tell us, remember that s2 is the ‘whole disk’ on SYSV.

# prtvtoc /dev/rdsk/c0t2d0s2
* /dev/rdsk/c0t2d0s2 partition map
* Dimensions:
* 512 bytes/sector
* 63 sectors/track
* 16 tracks/cylinder
* 1008 sectors/cylinder
* 4092 cylinders
* 4090 accessible cylinders
* Flags:
* 1: unmountable
* 10: read-only
* First Sector Last
* Partition Tag Flags Sector Count Sector Mount Directory
0 2 00 0 132048 132047
1 3 01 132048 263088 395135
2 5 01 0 4122720 4122719
6 4 00 395136 3727584 4122719

So we have a 0, the 1 is ‘swap’, 2 is he whole disk, and a 6.

Running fsck can reveal that 0 is a real filesystem:

# fsck /dev/rdsk/c0t2d0s0
** /dev/rdsk/c0t2d0s0
** Last Mounted on /mnt
** Phase 1 – Check Blocks and Sizes
** Phase 2 – Check Pathnames
** Phase 3 – Check Connectivity
** Phase 4 – Check Reference Counts
** Phase 5 – Check Cyl groups
4 files, 32504 used, 29111 free (15 frags, 3637 blocks, 0.0% fragmentation)

while 6 is not.

# fsck /dev/rdsk/c0t2d0s6
** /dev/rdsk/c0t2d0s6
eg. fsck [-F ufs] -o b=# [special …]
where # is the alternate super block. SEE fsck_ufs(1M).

Sadly none of the stuff in there is ‘ready to run’ but rather built in it’s source directory.

And I wanted to make a 2GB /usr/local on another disk, so I copied my disk template file, (can use the OS, or the gnu-utils) and run format on the disk.

It was a matter of clearing out partitions, and making ONE BIG partition 0.

# format /dev/rdsk/c0t1d0s2
selecting /dev/rdsk/c0t1d0s2: data
[disk formatted]
Warning: Current Disk has mounted partitions.

disk – select a disk
type – select (define) a disk type
partition – select (define) a partition table
current – describe the current disk
format – format and analyze the disk
repair – repair a defective sector
label – write label to the disk
analyze – surface analysis
defect – defect list management
backup – search for backup labels
verify – read and display labels
save – save new disk/partition definitions
inquiry – show vendor, product and revision
volname – set 8-character volume name
format> partition

0 – change `0′ partition
1 – change `1′ partition
2 – change `2′ partition
3 – change `3′ partition
4 – change `4′ partition
5 – change `5′ partition
6 – change `6′ partition
7 – change `7′ partition
select – select a predefined table
modify – modify a predefined partition table
name – name the current table
print – display the current table
label – write partition map and label to the disk
partition> print
Volume: data
Current partition table (original):
Total disk cylinders available: 4090 + 2 (reserved cylinders)

Part Tag Flag Cylinders Size Blocks
0 alternates wm 0 – 4069 1.96GB (4070/0/0)
1 unassigned wu 0 0 (0/0/0)
2 backup wu 0 – 4089 1.97GB (4090/0/0)
3 unassigned wm 0 0 (0/0/0)
4 unassigned wm 0 0 (0/0/0)
5 unassigned wm 0 0 (0/0/0)
6 unassigned wm 0 0 (0/0/0)
7 unassigned wm 0 0 (0/0/0)

Good fun.  As always don’t forget how to mount the CD-ROM under Qemu, and add packages as needed.

I still think the quickest, and easiest way to power ‘off’ the VM is the poweroff command.

# poweroff
Apr 18 20:26:33 qemu24 poweroff: poweroffed by root
Apr 18 20:26:35 qemu24 syslogd: going down on signal 15
syncing file systems… done

Brutal, quick, and efficient.

Building Linux 0.11 on Windows 10

No really, it compiles! on Windows!
No really, it compiles! on Windows!

So continuing with the fun from yesterday, where I had managed to get gcc 1.40 running on Windows with MinGW, it was time to try to take the final leap and build Linux.

There wasn’t too much to massage on Linux, mostly Makefiles for the various tool name differences, and how to handle keyboard.S as the default setup for NTFS is case insensitivity.  While I did get some old version of as16 and ld16 to build, I’m not sure if they are working correctly.  Or it could be the ‘build’ tool.  The downside is that the final ‘Image’ file produced doesn’t work (I should add that all issues have since been fixed, and it is now possible to cross compile a running kernel from Windows, and boot it with Qemu).

But copying the ‘system’ file that is compiled on Windows, to a Linux VM, and having it do the boot setup does work!

And it boots!
And it boots!

Very cool to say the least!

I almost wonder if MSVC 1.0 could build any of this.  Then it could be possible to bootstrap Linux from Windows NT 3.1 … Although Windows 10 is good enough for me, right now.

And I got the DJGPP 1.0 gcc driver to work (soft of)!

C:\aoutgcc\test>gcc -v hello.c -o hello -I ../include-0.12 -L../lib
gcc version 1.40
cpp -v -I ../include-0.12 -undef -D__GNUC__ -Dunix -Di386 -D__unix__ -D__i386__ hello.c C:/Users/neozeed/AppData/Local/Temp/cca0_388.cpp
GNU CPP version 1.40
cc1 C:/Users/neozeed/AppData/Local/Temp/cca0_388.cpp -quiet -dumpbase hello.c -version -o C:/Users/neozeed/AppData/Local/Temp/cca0_388.s
GNU C version 1.40 (80386, BSD syntax) compiled by GNU C version 5.1.0.
default target switches: -m80387
a386 -o hello.o C:/Users/neozeed/AppData/Local/Temp/cca0_388.s
ld -o hello c:/aoutgcc/lib/crt0.o -L../lib hello.o c:/aoutgcc/lib/gnulib -lc c:/aoutgcc/lib/gnulib

Sorry that doesn’t format so well on a blog.  But now I only have to force the include path, and the lib directory. At this point I’d call it ‘good enough’

I uploaded the archive MinGW-aout-linux-011.7z.  If you want to compile Linux, you’ll need a MSYS from MinGW.  Otherwise, this is only interesting to people who run Windows and want to play with Linux 0.11.  I also included the Linux VM, and binaries for the tools.  It’s not even 7MB.  How is that for crazy small?



I got it all working now that I found all the portions to set to output as O_BINARY/wb that are needed on a Win32 host, so using MinGW I can build the as86/ld86/binutils/gcc and Linux 0.11!

My updated post is here.

Also I put all the source onto git, along with binaries up on sourceforge.  It’s worth mentioning that since I wrote this article, I have gotten quite a number of older versions of Linux to build, along with simple kernel debugging with GDB.  Kernels include:

Download Ancient Linux on Windows

Download Ancient Linux on Windows


Craziest cross compile yet!

Windows 10 to target Linux 0.11!

It works!
It works!

Sadly that ancient line program only runs ELF binaries, so that won’t work to test.

As I mentioned gcc doesn’t work. I need to tear more into DJGPP
to see how they did it or just use it’s gcc driver to run this.

In the test directory I’ve mimic’d what a Linux 0.11 install does when compiling
a single file into an exe.

simply run:

c_ hello

and it’ll compile hello.c into hello.

C:\aoutgcc>..\bin\cpp -v -I../include-0.12 -undef -D__GNUC__ -Dunix -Di386 -Dlinux -D__unix__ -D__i386__ -D__linux__ hello.c C:\Users\neozeed\AppData\Local\Temp\001.cpp
GNU CPP version 1.40

C:\aoutgcc>..\bin\cc1 C:\Users\neozeed\AppData\Local\Temp\001.cpp -quiet -dumpbase hello.c -version -o C:\Users\neozeed\AppData\Local\Temp\001.s
GNU C version 1.40 (80386, BSD syntax) compiled by GNU C version 5.1.0.
default target switches: -m80387

C:\aoutgcc>..\bin\a386 -o hello.o C:\Users\neozeed\AppData\Local\Temp\001.s

C:\aoutgcc>..\bin\ld -o hello ../lib/crt0.o hello.o ../lib/libc.a

Wasn’t that fun?

The ‘best’ way I can think of to test is to tar the exe like this:

C:\aoutgcc>..\bin\tar.exe hello.tar hello

And then run it with the Linux 0.11 on Qemu which can be found here:

qemu -L pc-bios -hda linux-0.11-devel-060625.qcow2 -no-reboot -m 16 -k en-us -fda hello.tar

Then once Linux boots, do this:

tar -xvf /dev/fd0
chmod +x hello


For anyone who wants to play at home, here is the complete sources, and binaries.

Qemu binaries for Windows

So here is my cross compiled Qemu binaries for Windows.

I added in my Control+Alt+d ‘fix’ to be a Control+Alt+Delete that anyone who runs Windows NT or MS-DOS will no doubt love.  The kbd_put_keycode function had been removed, so I also put that back in.

I also undid the weird scaling thing that has been around since version 1.1.  And I tried my best to merge in some NE2000 fixes.

Solaris 9
Solaris 9

I threw a Solaris 9 ISO at it, and it booted up to the text installer!


The MIPS ARC firmware however always bombs out on reset with an Interrupt Controller Error.

I tried the ‘doom’ test, and installing DooM 1.1 took FOREVER.  Writing to the disk is slow. Incredibly slow. I guess forcing the write thru cache is mandatory?

-drive file=bla.disk,if=ide,index=0,media=disk,cache=writethrough

I haven’t tested.


I nearly went deaf.  It doesn’t work properly, but rather loops so that one beep turns into a hurricane of beeps.

I’ve included the needed DLL’s, and compiled everything I could statically.  I guess I could have fought more but I have other things to do.

So the ‘cut down’ version which is i386/x86_64 only is HERE.

Those who want to try out the various RISC processors download the ‘full’ package HERE.

Building MinGW32 Qemu on Linux (or anything else I guess)

So as always it’s the glibc2 wars.  And as part of the fun you need pkg-config.  And since it has to run, you’ll end up with the native version.

Luckily I found this site,

So you can create a i586-mingw32msvc-pkg-config file.  Just in case it get's lost here it is:


# This file has no copyright assigned and is placed in the Public Domain.
# No warranty is given.

# When using the mingw32msvc cross compiler tools, the native Linux
# pkg-config executable works fine as long as the default PKG_CONFIG_LIBDIR
# is overridden.
export PKG_CONFIG_LIBDIR=/usr/i586-mingw32msvc/lib/pkgconfig

# Also want to override the standard user defined PKG_CONFIG_PATH with
# a mingw32msvc specific one.

# Now just execute pkg-config with the given command line args.
pkg-config [email protected]

Fun as always, right?

And as always Qemu can be configured with:

configure --cross-prefix=i586-mingw32msvc-

When cross compiling.

VAX Snoopy!

Hey Snoopy!
Hey Snoopy!

Following up on Adventures with Snoopy, Mihai has delivered!  Snoopy printed out from a VAX onto a real 9 pin printer, onto paper!

Just the way we used to do things a million years ago!

Be sure to check out the whole thing on,  complete with pictures, and source material!  Totally check it out, for that real programmer’s vibe!

And for those who have no idea, here is where it all started.