Back when I started blogging, I started with a few quick things on the top of my head, that being Netware, SIMH, CP/M Zork, Xenix and of course Mach. Back in the shiny new world of 1999 we may have survived the Y2K apocalypses but the valley was firmly set in the mind of start-up fever that would lead to the looming .com crash but the menatlity of IPO & dump would remain to this very day.
The Utah projects around Mach were wound down with the OSKit being the next wave for pistachio, but that set the scene of more than average users now having ‘fast’ machines at their disposal and the ability to rifle though published source and roll their own. It was this environment of trying to make it in the full force of the post ‘year of the desktop’ Linux where xMach appeared, had some interest and quickly died. For the longest time I had thought all evidence of it had been eradicated as the domain had been excluded from wayback, and searching went nowhere. But one bored night I tried exploring sourceforge, a veteran of the pre .com bubble crash to see if it had anything, and yes it did!
Oh sure in retrospect it’s pretty obvious. All the cool kids had public repositories on the internet.. And then after the .com implosion so many took their CSV’s and went home. And so many of those just died in selfhosted, self imposed silence.
From what I remember one of the first goals was to time the source to make it easier to cross compile from either NetBSD or Linux, and utilize what was the double edged sword of Lites, the ability to run either 386BSD/NetBSD binaries or Linux binaries. And the Linux side was already incorporating shared libraries something that was desperately needed in 1993 for X11. But this was 2000! And of course the downfall of running Linux under xMach/Lites is that you will of course compare the performance, and Linux won hands down. Not to mention interest in improving and adding to Linux was in full mainstream support by 2000 so it made xMach feel all the more ancient.
But we didn’t come here for practicality!
Getting the source & tools
First off I’m going to use the cross tool chain for building OS Kit. i586-linux2.tar.gz (password and 404 apply) as I not only don’t feel like fighting why MIG doesn’t work in 64bit, and it’s just easier to enable 32bit usermode. Speaking of for Ubuntu 20.04.2:
dpkg --add-architecture i386 apt-get update apt-get install libc6:i386 libncurses5:i386 libstdc++6:i386 libc6-dev:i386 libfl-dev:i386 apt-get install sharutils gcc-multilib build-essential
And for people like me running on Windows 10, You absolutely MUST enable WSL v2. Without an actual kernel the multiarch simply doesn’t work. No doubt it has something to with actually running Linux vs emulating it. Probably mucking about with the LDT/GDT which you certainly cannot do as a process on Windows.
Next just add the old GCC 126.96.36.199 chain into your path:
Next up you’ll need the source, and being all new and trendy I put it over on GitHub. Clone the repo, and you are almost ready to start compiling!
As it turns out git didn’t preserve the executable scripts so you have to manually run this:
chmod +x kernel/c* chmod +x kernel/*sh chmod +x lites/conf* chmod +x lites/conf/*
You may have to pay attention to the build to make sure stuff doesn’t complain about ‘permission denied’
bash: ../kernel/configure: Permission denied
Basically if you see this, you didn’t do it right.
Building the xMach kernel
Make an object directory and run configure like this:
../kernel/configure --host=i586-linux --target=i586-linux --build=i586-linux --enable-elf --enable-libmach --enable-linuxdev --prefix=/usr/local/xmach;cp ../updated-conf/kernel/Makeconf .
For some reason configure never populates the compiler tools right, and I can either mess with autoconf (no thanks) or I can just include a known good file. It’s not hard to figure out, you can diff it if you want to, but it’s just set for a native 32bit build of MIG, and then using the cross tools to build the kernel.
type make, and wait 13 seconds, give or take…
i586-linux-ld -r -L/home/jsteve/src/xMach/kernel-build/lib -nostdlib \ -o bsdboot.o crt0.o about_to_die.o anno.o boot_info_dump.o boot_start.o cpu.o cpu_init.o cpu_tables_init.o cpu_tables_load.o crtn.o die.o do_boot.o exit.o gdt.o idt.o idt_inittab.o idt_irq_init.o main.o malloc.o panic.o phys_mem_add.o pic.o putchar.o puts.o real_tss.o real_tss_def.o rv86_real_int.o rv86_real_int_asm.o rv86_reflect_irq.o rv86_trap_handler.o serial.o trap_dump.o trap_dump_die.o trap_handler.o trap_return.o tss.o tss_dump.o -lmach_exec -lmach_c make: Leaving directory '/home/jsteve/src/xMach/kernel-build/boot/bsd' MACHBOOTDIR=
cd /home/jsteve/src/xMach/kernel-build/boot/bsd; pwd\ /home/jsteve/src/xMach/kernel-build/boot/bsd/mkbsdimage -o /home/jsteve/src/xMach/kernel-build/Mach /home/jsteve/src/xMach/kernel-build/kernel/kernel /home/jsteve/src/xMach/kernel-build/bootstrap/bootstrap real 0m13.135s user 0m12.060s sys 0m1.383s
I cannot stress just how incredibly fast this is. I’m pretty sure it literally took hours for this to run, assuming nothing went wrong, which it almost always did. As part of the fun, next do a ‘make install’
This is somewhat similar to the kernel build, however it is far more touchy. You absolutely MUST copy / fix the Makeconf file otherwise the build will be corrupted and the only way to fix is to remove the build directory and try again.
../lites/configure --host=i586-linux --target=i586-linux --build=i586-linux --enable-mach4 --prefix=/usr/local/xmach --with-mach4=../kernel;cp ../updated-conf/lites/conf/Makeconf conf
And once more again make the project and just wait a few seconds. BSD without the hardware support is pretty tiny
i586-linux-ld -o emulator.Lites.1.1.u3.out
./emulator_base-L/home/jsteve/src/xMach/lites-build/liblites -L/usr/local/xmach/lib -e __start ecrt0.o e_mig_support.o emul_generic.o error_codes.o emul_init.o emul_mapped.o emul_misc_asm.o e_bsd.o e_43ux.o bsd_1_user.o emul_mach_interface_user.o e_mach_msg_server.o e_stat.o e_bnr.o emul_exec.o signal_server.o e_uname.o e_mapped_time.o e_sysvipc.o e_linux.o e_sysv.o e_exception.o e_signal.o e_machinedep.o e_linux_trampoline.o e_linux_sysent.o e_isc4_sysent.o e_cmu_43ux_sysent.o e_lite_sysent.o emul_vector.o e_trampoline.o e_linux_getcwd.o -llites -lthreads -lmach_sa /usr/local/i586-linux2/lib/gcc-lib/i586-linux/188.8.131.52/libgcc.a && \ i586-linux-size emulator.Lites.1.1.u3.out && \ mv emulator.Lites.1.1.u3.out emulator.Lites.1.1.u3 text data bss dec hex filename 130195 16904 160 147259 23f3b emulator.Lites.1.1.u3.out make: Leaving directory '/home/jsteve/src/xMach/lites-build/emulator' make: Entering directory '/home/jsteve/src/xMach/lites-build/bin' make: Nothing to be done for 'all'. make: Leaving directory '/home/jsteve/src/xMach/lites-build/bin' real 0m6.423s user 0m6.006s sys 0m0.551s
Yes that’s six seconds. do a ‘make install’ and now your /usr/local/xmach directory is fully populated and ready to transport somewhere to do the ‘install’ and boot.
One thing to take notice of xMach over the standard last Mach4 is that the Linux boot options have been removed. There is all kinds of changes in 16bit assembly handling that need to be rewritten or fixed. I’m sure someone at some point has, but apparently it’s easier to go with the bsdboot and use either the machboot or GRUB (v1!) to get it going. Although Linux knows how to mount loop ‘diskfiles’ I don’t remember how to deal with partitions and BSD slices. So I did my typical trick of booting up an existing image, and using telnet/uucp to transfer xMach into an existing disk.
Booting however was a bit more fun, as the kernel is now compiled as a BSD ELF image and Grub 1.x won’t boot it. I used a ‘Super Grub2 disk hybrid‘ ISO image, and was able to just hit escape and type in:
kfreebsd (hd0,msdos2,bsd1)/Mach boot
Because of the massive drift in multiboot vs ‘BSD ELF’ the drive isn’t passed correctly so I have to manually tell it ‘/dev/hd0a/mach_servers’ and it’ll pick up Lites, and boot up!
And there we go, with my old Mach4/Lites image from 2009 with a ‘fresh’ cross compiled build from Windows 10 / Ubuntu 20.04
Where to go from here?
Realistically, nowhere. Seven years ago there was OpenMach, which seems to have done a few things, but even moving to a GAS from 2015 didn’t help me at all trying to build the 16bit stuff so the answer must lie in the past. Otherwise the fundamental problem as always is at best you will have a 4.4BSD system which again in 1992 would be awesome, but 2021? yeah it’s a curiosity at best.
Would qemu-user-static and binfmt-support work as replacement of true multiarch?
WSL2 would sound more easier, but in the long term WSL wins as doesn’t conflict with VMware and VBox native emulation kernel mode modules.
Thats a good point, and mostlikely would work. I do kind of miss running VMware in VMware. I had high hopes of the hypervisor platform thing being a platform that ‘we’ can all use to build accelerated i386 stuff. But I’ll be damned if I can find anything useful, not that I’d know what to do with it if I found it.