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?

** EDIT

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-12.5.i386.zip

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
./hello

Fun?!

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

Qemu 2.4.0.1 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!

asd

MIPS ARC

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.

Also DO NOT USE THE PCSPEAKER DEVICE.

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, mega-nerd.com

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

#!/bin/bash

# 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.
export PKG_CONFIG_PATH=$PKG_CONFIG_PATH_MINGW32MSVC

# Now just execute pkg-config with the given command line args.
pkg-config $@

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 hawk.ro,  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.

32bit / 64bit GDB collision

So I’m trying to force a break in a program to look at the call stack.  Normally pretty easy stuff as far as adding breakpoints or the random i=j/0 type thing to force a div0 exception etc.

But I’ve been going crazy with this fun error:

gdb: unknown target exception 0x4000001f at 0x453b1c

And I should have checked my path earlier, as even though I’m using the 32bit version of GCC, the TDM-GCC project bundles their 32bit GDB as gdb32.exe .  Ouch.  The other hint of course was in the banner:

GNU gdb (GDB) 7.9.1
Copyright (C) 2015 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type “show copying”
and “show warranty” for details.
This GDB was configured as “x86_64-w64-mingw32”.

Yeah, further oops, in actually paying attention to how it executes:

(gdb) r
Starting program: C:\temp\dynamips\dynamips.exe -P 1700 -s 0:0:gen_eth:”\Device\NPF_{2F7A0E3F-0908-4489-8117-475A6AD299A6}” C1700-Y-.BIN -j
[New Thread 2696.0x22b0]
warning: `C:\WINDOWS\SYSTEM32\ntdll.dll’: Shared library architecture i386:x86-64 is not compatible with target architecture i386.
warning: `C:\WINDOWS\system32\wow64.dll’: Shared library architecture i386:x86-64 is not compatible with target architecture i386.
warning: `C:\WINDOWS\system32\wow64win.dll’: Shared library architecture i386:x86-64 is not compatible with target architecture i386.
warning: Could not load shared library symbols for WOW64_IMAGE_SECTION.
Do you need “set solib-search-path” or “set sysroot”?
warning: Could not load shared library symbols for WOW64_IMAGE_SECTION.
Do you need “set solib-search-path” or “set sysroot”?
warning: Could not load shared library symbols for NOT_AN_IMAGE.
Do you need “set solib-search-path” or “set sysroot”?
warning: Could not load shared library symbols for NOT_AN_IMAGE.
Do you need “set solib-search-path” or “set sysroot”?
warning: `C:\WINDOWS\system32\wow64cpu.dll’: Shared library architecture i386:x86-64 is not compatible with target architecture i386.
[New Thread 2696.0xabc]

Great.

So it’s not some exciting bug, but rather the 64bit version of gdb can kick off a 32bit exe, but it’ll get lost inside.  The proper 32bit GDB looks like this:

C:\temp\dynamips>gdb32.exe dynamips.exe
GNU gdb (GDB) 7.9.1
Copyright (C) 2015 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type “show copying”
and “show warranty” for details.
This GDB was configured as “mingw32”.

And sure enough the call stack works fine.

Breakpoint 1, 0x00453b1c in mpc860_fec_set_nio ()
(gdb) bt
#0 0x00453b1c in mpc860_fec_set_nio ()
#1 0x004827e2 in dev_c1700_mb_eth_set_nio ()
#2 0x0044abdf in cisco_card_enable_all_nio ()
#3 0x0044b9df in vm_slot_enable_all_nio ()
#4 0x0044bb0e in vm_slot_init ()
#5 0x0044bb36 in vm_slot_init_all ()
#6 0x00481b5d in c1700_init_platform ()
#7 0x00481dc3 in c1700_init_instance ()
#8 0x004155b3 in vm_init_instance ()
#9 0x004125dc in main ()
(gdb)

Wasn’t that fun?!

My 80’s TV!

Speaking of retro!

totally!

totally!

It’s the best thing since GTA Vice City!

It’s kind of amazing there is that much uploaded to youtube these days.  I guess with enough archivists out there, you never have to leave those oh so innocent and simple decades.  Or at least the ‘music channels’ are the perfect thing to listen to, while reading olduse.net.

Anyone using truecrypt or any derivative work

will want to incorporate these patches on the Windows platform:

https://github.com/veracrypt/VeraCrypt/commit/9b24da3398581da1fa66c6b8f682bbcfa7ded4fd

https://github.com/veracrypt/VeraCrypt/commit/b7f9df6e4f09ba342fdbbadc63af5062cc57eaf2

So yeah, apparently you can get full admin rights through the driver. oops.

InfoTaskForce running on PowerPC (Dynamips)

choices..

choices..

Well considering what a hit it was, the last time I did this, I thought I’d give it another go!

And after a bit of fighting, I got it to run!

Now what were the obstacles?  Well for starters not having a full libc certainly hurts things.  Things like a malloc.  And without getting fancy with the memory map I did the lamest cheat ever, which is a 1MB static array I just handed out with a fake malloc (no free, I didn’t bother to track chunks), and you know it works enough.

Also I need to read files, and I need to look more into the hardware to see how to do that.  There seems to be plenty of hooks for NVRAM, but the ROMMON substitute doesn’t seem to support them.  Also there is no ROMMON hook for reading from the console!  The MIPS cilo is more ROMMON dependent, while the PowerPC c1700 talks to the uart directly so this is a PowerPC thing for right now.

I also learned something exciting about ld, which is how it can absorb binary images into objects, that you can link and access directly into your program!  No more having to convert it to hex, make these insane headders that CPP may or may not bomb over.  No you can make them objects right away!

ppc-elf-ld -r -b binary -o planetfa.o planetfa.dat

In this example I read the file planetfa.dat as BINARY, and encapsulate it in an object file called planetfa.o . It’ll now have a symbol name of _binary_planetfa_dat_start for where the image begins, _binary_planetfa_dat_size will tell me how big it is in memory, and _binary_planetfa_dat_end will mark the end of this ‘file’ in memory.

Now in the old days when it was a file I could access it like this:

fread ((char *)ptr,block_size,(int)num_blocks,game_file);

But that won’t work.  So now instead of calling fopen/fclose (which don’t exist in CILO), I set a counter to what my current offset is, change the ‘fseek’ to just set the global counter to where it should be, and when I fread I just memcpy:

memcpy(ptr,_binary_planetfa_dat_start+fseekp,num_blocks*block_size);
fseekp=fseekp+(num_blocks*block_size);

I suppose I could just have wrapped the f* calls into some emulation library but I don’t need to get all that crazy sophisticated.

C:\temp\dynamips>dynamips.exe -P 1700 -X -r 4 ciscoload.bin
Cisco Router Simulation Platform (version 0.2.15-experimental(merge uppc smips)Build-3-x86/MinGW stable)
Copyright (c) 2005-2011 Christophe Fillot.
Build date: Sep 19 2015 19:33:12

Local UUID: 0450c178-6480-11e5-a559-019031cf957a

Pcap version [WinPcap version 4.1.3 (packet.dll version 4.1.0.2980), based on libpcap version 1.0 branch 1_0_rel0b (20091008)]
Unsure if this file (c1700_i0_rommon_vars) needs to be in binary mode
Virtual RAM size set to 4 MB.
IOS image file: ciscoload.bin

ILT: loaded table “mips64j” from cache.
ILT: loaded table “mips64e” from cache.
ILT: loaded table “ppc32j” from cache.
ILT: loaded table “ppc32e” from cache.
vtty_term_init
CPU0: carved JIT exec zone of 64 Mb into 2048 pages of 32 Kb.
C1700 instance ‘default’ (id 0):
VM Status : 0
RAM size : 4 Mb
NVRAM size : 32 Kb
IOS image : ciscoload.bin

Loading BAT registers
Loading ELF file ‘ciscoload.bin’…
ELF entry point: 0x8000d9c8

C1700 ‘default’: starting simulation (CPU0 IA=0xfff00100), JIT enabled.
ROMMON emulation microcode.

Launching IOS image at 0x8000d9c8…
CILO
CiscoLoader (CILO) – Linux bootloader for Cisco Routers
Available RAM: 4096 kB
Available commands:
queen
hanoi
horse
fib
planetfall
halt

Enter filename to boot:
malloc 64512 offset is 0 offset is now 64522
malloc 38912 offset is 64522 offset is now 103444
PLANETFALL
Infocom interactive fiction – a science fiction story
Copyright (c) 1983 by Infocom, Inc. All rights reserved.
PLANETFALL is a trademark of Infocom, Inc.
Release 37 / Serial number 851003

Another routine day of drudgery aboard the Stellar Patrol Ship Feinstein. This
morning’s assignment for a certain lowly Ensign Seventh Class: scrubbing the
filthy metal deck at the port end of Level Nine. With your Patrol-issue
self-contained multi-purpose all-weather scrub brush you shine the floor with a
diligence born of the knowledge that at any moment dreaded Ensign First Class
Blather, the bane of your shipboard existence, could appear.

Deck Nine
This is a featureless corridor similar to every other corridor on the ship. It
curves away to starboard, and a gangway leads up. To port is the entrance to
one of the ship’s primary escape pods. The pod bulkhead is closed.

Deck Nine Score: 0/4451
PLANETFALL
Infocom interactive fiction – a science fiction story
Copyright (c) 1983 by Infocom, Inc. All rights reserved.
PLANETFALL is a trademark of Infocom, Inc.
Release 37 / Serial number 851003

Deck Nine Score: 0/4451
>

For anyone crazy enough, you can find my MinGW Dynamips on sourceforge, cross compilers for PowerPC, and the branch of the firmware source that includes InfoTaskForce, and the binary image.

While I don’t want to write an OS for this, it is almost tempting.  Or go the other route, and add in some non router based hardware… Like audio hardware, or a framebuffer.

Does anyone have a 1700 to test to see if any of this works?  Or a 7200?! 😀

Continuing with a PowerPC ELF compiler for Windows

Continuing on from yesterdays adventure I built the PowerPC compiler to support the Cisco 1700 (and maybe the 7200 NPE-G2?).

Much to my surprise, this one works too!

Loading ELF file ‘../ciscoload.bin’…
ELF entry point: 0x8000cba0

C1700 ‘default’: starting simulation (CPU0 IA=0xfff00100), JIT enabled.
ROMMON emulation microcode.

Launching IOS image at 0x8000cba0…
CIL
Error: Unable to find any valid flash! Aborting load.

Awesome!

Building this was a lot more fun.  I thought I could sidestep building a Linux to PowerPC ELF cross compiler, but as it turns out, to bootstrap libgcc, you really need a compiler that can do this.  But with the steps basically down, it was trivial to whip up.

Although I did keep on hitting this error with the Win32 tools that “-mstrict-align” is not supported, while trying to build the startup and libgcc sources using the MinGW targeted compiler through wine.  But once I had a native Linux to PowerPC toolchain in place, not only could I build the Windows based compiler, but I can also use the flag -mstrict-align on Windows without it complaining.  So lesson learned, have a cross compiler built to the final target to make life easier when building a Canadian cross.

As always, building the binutils package was a snap, just run:

./configure --host=i686-mingw32 --target=ppc-elf -prefix=/ppc

and I had my assembler/linker/librarian in no time.

Because of the aforementioned -mstrict-align issue, I got more creative with the parameters for GCC.

./configure --target=ppc-elf --prefix=/ppc --disable-nls --disable-werror --disable-libssp --without-headers --disable-threads --build=i486-linux-gnu --host=i686-mingw32

But with the Linux to PowerPC cross compiler in place, I was able to quickly generate a working toolchain.

I copied in CILO, and added in a build batch file to manually build it, and updated the test directory to run it.

So for those who are interested here is my toolchains:

And a mirror on sourceforge of my cross toolchains, PowerPC and MIPS.

As a minor addendum, The 1700 can run stuff that is far more complicated than the MIPS.  I’m not sure why I get so many TLB violations for doing something more complicated but I (poorly) ported aclock to run on the cisco 1700!

Aclock on the cisco 1700 via Dynamips
Aclock on the cisco 1700 via Dynamips

The Dynamips ROMMON emulator doesn’t provide the keyboard input function call so it can’t read from the keyboard.  Also it can’t read the clock, so I have it running 250,000 dhrystones between clock ticks.  Although I think that is far too many, maybe 125,000 would be more like it but it runs on the PowerPC.  While on the MIPS I get nothing but this:

*** TLB (Load/Fetch) Exception ***
PC = 0x80008964, Cause = 0x00008008, Status Reg = 0x00408103

Oh well.  Maybe it’s a stack problem I guess I’ll have to break down and do a memory map and write a malloc if I want to go down this road.  Although back in 1999 this would be incredible but today I don’t think anyone would run anything but IOS on their cisco hardware.