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.

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

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.

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.

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

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:

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.

I’ve tried to build a cross compiler on MinGW32 before, and despite there being obvious steps on how to do it, I’ve never gotten it to work. Now I’ve built cross compilers before so it’s not like I don’t have any clue on what I’m doing, but the problem is that Windows isn’t UNIX, and I don’t want to use Cygwin.

So that enters another fun possibility known as the Canadian Cross, which is using a machine in the middle to build a compiler. As we all know, Linux is great for building and running GNU software, so a Linux machine to build my cross compiler would be the best. Now the whole point of this is that I wanted to build a MIPS program to run on Dynamips. And through a LOT of googling, I managed to find this program called CILO the cisco Linux loader. Now as far as I can tell the people trying to port Linux the the MIPS based cisco routers (3600 and 7200) never succeed, but they did manage to leave this bootloader behind. And compiling it was very tricky as they gave no hints on what to use. So with a lot of trial and error I found that binutils 2.18 is the minimal version that will work as the code depends on being able to do register aliasing which isn’t present in previous versions. Also according to this, they were using gcc 4.1.2 in their Linux port. So with some luck I did mange to get CILO to build with a cross compiler on Linux. Which was pretty awesome to see Dynamips run a C program!

But that doesn’t help me on the Windows side.

Now the first thing that I’d normally do is install the default MinGW cross tools, but because I need ancient binutils and GCC support as newer versions not only won’t work for what I want, but won’t build older versions I tried to keep things in step. This meant on Linux I first had to build a Linux to Windows cross compiler using binutils version 2.25.1 and GCC version 4.1.2 . Configuring and building binutils was a snap with:

I thought I could just use a new mingwrt and w32api but that proved disastrous as the newer libs gave me this fun error on trying to link a Win32 execuatable:

undefined reference to `___chkstk_ms’

And googling that around the consensus is that your binutils, and gcc is too old, and upgrade, granpa! But I want old software so I naturally have to just use older versions, and for gcc 4.1.2 I wanted:

mingwrt-3.18-mingw32-dev.tar.gz

w32api-3.15-1.mingw32-dev.tar.lzma

Now I could build and link and test my Linux to Windows toolchain!

Now for the crazy part.

First I need a binutils, so I configured binutils 2.18 like this:

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

And sure enough with a little prodding I had a MIPS assembler/linker/librarian and all that fun stuff!

The fun part of course is that during the build, gcc will want to run the cross compiler and dump it’s host machine bit types by running ‘xgcc -dumpspecs’. Well thankfully via wine, Linux can run Win32 execuatables so I saved myself a few minutes by not having to copy over the partial compiler, and run the command, and transfer the results back.

So with a bit more hand holding on the build I finally got it to finish compiling by linking /bin/true to fix-headers . What a mission. Now I excitedly transfered my build to my Windows host, and setup some environment variables and built the hello world cisco application, and, it worked! (well crashes the same way as the pre-built one, but it does say:

It may not look like much, but It is running the program! Dynamips is missing a bunch of hardware, like flash. Or I found out the ability to read from the console using the promlib. But it can print to it at least.

So for those who want to give it a try, here is my MIPS-ELF tool-chain for Win32, that includes the cisco loader!

The second virtualization contest is now on! Similar to the previous one, the winner receives $100 via Paypal and the submission is posted on this blog! Hopefully this one will be little bit more challenging. 🙂

The progress so far: A few years ago I came in to possession of a set of floppy disks pictured here:

Thanks to Al Kossow from bitsavers.org the floppy disk content has been recovered. Michal Necasek of OS/2 museum successfully converted them in to an usable format and made some modifications to get them to boot on VirtualBox:

Couple of years later, thanks to Andrew Gong, a WYSE Unix tape has been found on eBay:

More recently Al Kossow was able to read the tape in to an image, which now I have uploaded to my web server: wyseunix321a.zip

The next step is yours! Install the whole system on to a hypervisor of your choice, document the process and supply a vanilla boot image or VM.

The winner shall be the person who will first post a comment declaring success including a screenshot and can further prove it by emailing emailing me the submission shortly after. If the comment gets blocked by spam filter, don’t worry the original submission time will of course count. Oh and almost forgot: I also need aclock binary for it, however if there is no compiler and the standard SysV binary works fine, you are exempt from the requirement.

The catch? Looks like floppy disk trouble. The boot disk is fine after it has been fixed up by Michal. The Base floppy looks like has same content as boot. Copy Tools is very small. Looks like it may be truncated. Hopefully not, but if yes I count on your creativity. Remember that Dell Unix is an exactly save release of SystemV/386 and did not have or needed copy tools to install.

Good Luck!

Update: Looks like the contest has been won by Mihai! Congratulations!

So over in my work on porting Dynamips to MinGW, I’ve created a version of SLiRP that sends and receives data over UDP. In retrospect, something I should have done a long time ago, as it makes troubleshooting it easier as now if it were to crash it’s a stand alone program, so it won’t crash the emulator.

The good news is that I’ve been able to copy files into the virtual router using HTTP. I’ve even been able to access my OS/2 machine over FTP and load a file!

Part of the ‘trick’ is that you should set your time out to be as long as possible to send a million packets. I just set the maximum values.

line con 0

exec-timeout 35791 23
stopbits 1

line aux 0

stopbits 1

line vty 0 4

exec-timeout 35791 0
timeout login response 300
password cisco
login

!
end

In addition, a 7200 with idle performs MUCH better than a 1700 without idle. There is something up with ptask, and only dispatching packets every so often. I’m guessing it’s done that way for a reason.

Also one other cool IOS trick I learned today is that you can redirect to a file resource! Say you want that ‘show tech-support’ as a file on the disk? No problem!

show tech-support | redirect disk0:tech.txt

And of course the newer versions of IOS have a ‘do’ command that you can run from config mode to execute user commands.

This will listen on port 20001, and send traffic to 127.0.0.1 on port 20000. Easy right?

Manually interfacing from the hypervisor can be the ‘fun’ part. I haven’t tested with any of the tools, as I don’t know if they will let you leave something ‘listening’ that isn’t connected. For my tests I end up building something with their UI, then loading up my hypervisor that logs, and seeing what it is actually doing so I can inject stuff like this:

This creates a udp nio, and attaches it onto the virtual etherswitch S1, and puts it on VLAN 1. As you can see it listens on UDP port 20000, which is where slirp_rdr is setup to send it’s data to, and it’ll send to 20001 where slirp_rdr is listening.

I’ve hard coded port 42323 to telnet into 10.0.2.15. As always SLiRP is hard coded to have the following ip address schema:

Gateway 10.0.2.2
DNS 10.0.2.3
Netmask 255.255.255.0

Be sure to set your router to 10.0.2.15/24 for this to work, and add 10.0.2.2 as your default gateway.

The ONLY address that will respond to ping is 10.0.2.2 . This is just the way SLiRP is. HTTP and TCP based stuff works best, things like PPTP will not. It’s really hit and miss, but the cool thing is that it doesn’t require any device drivers, it’s all user mode code!

The following is a guest post / wrap-up of the Q2DOS adventure by [HCI]Mara’akate.
In the last update sezero and I([HCI]Mara’akate) tied up most loose ends with regards to Q2DOS. Specifically: adding in DXE support for mods and cleaning up some code from the early efforts. During this time, a forum user by the name of ggorts (strogg spelled backwards!) mentioned the possibility of using an old Mesa version with 3DFX support in DOS. I worked on separating the ref_soft from being statically linked into a DXE form and sezero cleaned up any potential problems there.

I mentioned the possibility of attempting the Mesa port to sezero and he thought it was probably a wasted effort and thought making a ref_glide depending only on glide3x.dxe would be a better way to go with less overhead. I started some initial work on it but quickly abandoned this side-project as I have no real glide (or even OpenGL) knowledge and didn’t have enough time on my hands to play around with it.

Around this time, we also separated the GameSpy browser code into a separate DXE for potential legal issues. The GameSpy code was publicly released, but never officially GPL’d. Using this method, other port authors could link against a gamespy.dll to add in the browser capabilities that connect to my GameSpy master server emulator (see QDOS branch for source code to that particular project).

Ggorts also came up with some code for us to be able to finally use the banked modes and Mode-X 320×240. Though 320×240 Mode-X seems to have some issues with certain emulator configurations, for the most part it works OK. This also helped us to get some ASM rendering code in from Q1 and help clean up the original mess that was the SVGA driver; a lot of unused code from Q1 was removed and sezero found a clever way to send the video modes list between the game binary and renderer DXE.

In any event, one night I figured I’d take a stab at trying to get Mesa working in Q2DOS. Checking out the Mesa3d FTP and researching the various changelogs it appears as if Mesa 5 series was the last true effort with Mesa 6.4.x series being the last maintained version with 3DFX specific code. I got everything to compile but ran into hard-lock issues no matter what I attempted. During this time, ggorts found out some various small, but now obvious issues. Including increasing the stack size to 1MB and he hard-coded the ref_gl to only work in 640×480. It took a lot of pleading but eventually he released his source with a static compile for Voodoo 1 cards only as he was testing this on emulators like DOSBox with glide support and PCem dev branch.

I worked on cleaning up the source and he produced some glide3x libraries for me for Voodoo 2 and Voodoo 5 as these were the only cards I personally owned. Imagine my surprise as I first loaded it up and it actually worked! And it was smooth with no rendering issues!

At this point, sezero became involved and worked very hard to clean up the Mesa compile issues, including various scary warnings and helped to update us to the final glide3x commit pushed to the development branch and Mesa v6.4.3 which was an unreleased maintenance update for Mesa v6.4.2.

It was a long journey to get the code all working together just right, and a big thanks goes out to the early Mesa crew including Brian Paul, Daniel Borca, and “KoolSmoky” and the mysterious ggorts fellow who pushed hard for this feature.

To recap, Q2DOS from the last time we talked now has:

3DFX Rendering with Mesa v6.4.3 for all Voodoo cards.

Separated renderer so it is no longer statically linked.

GameSpy is now a DXE.

WAV streaming, which is practically free as opposed to the OGG format.

We are about at the end of our Q2DOS journey. A few odds and ends with Mesa and Voodoo 5 SLI issues remain (though nothing too show stopping) and there’s a small wishlist of some unnecessary features but it’s come a long way from the initial null driver effort!

*Neozeed

I have to say it is simply incredible to see how Q2DOS went from a very primitive ‘wow it works’ port to a full featured port. Simply amazing!

I just saw mention of my Snoopy on Fortran over on hawk.ro. He’s in the process of formatting it to run on a REAL VAX. So this will have to do for the placeholder when he shows us what it looks like on paper!