Windows 3.1 Flash Edition

Recently, a friend of mine paid me a visit with a few of his ThinkPads. Over a course of a weekend, I've prepared a SPI flasher based on flashrom and a Raspberry Pi and flashed a few ThinkPads. Besides my rage that was mostly a result of badly written libreboot and coreboot docs (things are hard to find, a ton of the info is outdated, etc), I came up with an idea for corebooting my own X200.

(totally unncessary) SeaBIOS hacking

Because the standard coreboot payload with SeaBIOS only occupies only about 1MB out of the full 8 on the ROM, I thought about embedding a full OS on the remaining 7 megs. It turns out that SeaBIOS has partial support for booting from flash - it sets up a virtual floppy drive with your floppy of choice loaded from floppyimg/<name>.lzma, but this gives us at best 2.88MB (standard ED floppy disk size, exactly 2x as large as a popular 1.44M), and I wanted more.

To use the whole area, I've tried modifying a few bits of SeaBIOS source code. I've mostly looked at the part used for handling the floppy itself..

// from src/hw/floppy.c struct floppyinfo_s FloppyInfo[] VARFSEG = { // Unknown { {0, 0, 0}, 0x00, 0x00}, // 1 - 360KB, 5.25" - 2 heads, 40 tracks, 9 sectors { {2, 40, 9}, FLOPPY_SIZE_525, FLOPPY_RATE_300K}, // 2 - 1.2MB, 5.25" - 2 heads, 80 tracks, 15 sectors { {2, 80, 15}, FLOPPY_SIZE_525, FLOPPY_RATE_500K}, // 3 - 720KB, 3.5" - 2 heads, 80 tracks, 9 sectors { {2, 80, 9}, FLOPPY_SIZE_350, FLOPPY_RATE_250K}, // 4 - 1.44MB, 3.5" - 2 heads, 80 tracks, 18 sectors { {2, 80, 18}, FLOPPY_SIZE_350, FLOPPY_RATE_500K}, // 5 - 2.88MB, 3.5" - 2 heads, 80 tracks, 36 sectors { {2, 80, 36}, FLOPPY_SIZE_350, FLOPPY_RATE_1M}, // 6 - 160k, 5.25" - 1 heads, 40 tracks, 8 sectors { {1, 40, 8}, FLOPPY_SIZE_525, FLOPPY_RATE_250K}, // 7 - 180k, 5.25" - 1 heads, 40 tracks, 9 sectors { {1, 40, 9}, FLOPPY_SIZE_525, FLOPPY_RATE_300K}, // 8 - 320k, 5.25" - 2 heads, 40 tracks, 8 sectors { {2, 40, 8}, FLOPPY_SIZE_525, FLOPPY_RATE_250K}, }

As we can see, this struct is used to determine floppy size. By modifying the amount of sectors I should be able to load bigger floppy images. I've tried changing the fifth case to 2 heads, 80 tracks and 72 sectors... But it resulted in an I/O Error.

The logical explanation as to why is that so is rather complicated. It's either that SeaBIOS can't allocate a proper amount of memory for the disk and it stops half-way, or it's about how the floppy controller talks with the hardware. After reading about how floppy systems are complicated on oswiki and fiddling with the code a bit more, I gave upon the idea about filling the whole ROM. Now, 2.88MB was the target.

Even more problems..?

After deciding upon the 2.88MB barrier, I tried booting windows from a flash drive, just as a test to see if everything worked. Well.. It turns out that libgfxinit isn't 100% VESA compliant and some older operating systems might crap out trying to init the display - all I could get was a black screen after typing `win` at the prompt. The fix was to embed a proprietary VGA Option ROM inside the coreboot image, which was hard only because no one dumped it before.

Option ROMs should reside inside the original proprietary BIOS images. I've had a few dumps of lenovo BIOSes, but couldn't get anything out of them with tools like bios_extract or UEFITool. As it turns out, the X200 ROM is the "new" ROM variant (which is kinda weird considering that I've unpacked a T420 ROM before without a problem). The fix was to use some phoenix-proprietary tools, which I can't find now. You can download the VGA Option ROM here.

Choosing the software

The whole pack consists of a few of my favourite programs and games, notably..

Conway's game of life is coooool To achieve the glorious 256 colors and 1024x768 (partially seen in the screenshot above), I've had to use a modified SVGA driver. There are two patching programs for the standard SVGA256.DRV - one supposedly for VirtualBox, another one for VMWare. The VMWare one turned out to also work with my X200.

To have an acceptably working system, I also needed audio. Because the Conexant audio device doesn't have drivers for any system older than XP nor does it have a Sound Blaster compatibility mode, I was forced to use a generic PC Speaker driver. It's terrible, but it allows me to hear anything. It works on a principle of using very frequent interrupts to create some crude-sounding audio.

Besides graphics and audio, a fully-working OS should be able to transfer data. This was achieved via a DOS USB driver (if the device got hotplugged, R:\WINDOWS\USB\USB.BAT is your friend), or via SeaBIOS mounting it as the C: drive. Unfortunately, Windows doesn't properly interface with the drive and all files have to be transferred by saving them into RAMDisk, quitting Windows and copying them in DOS.

Click for a weeb version..

Compression time!

At the beginning, I thought about using PKUNZIP as a decompressor and RAMDRIVE.SYS as a ramdisk driver. When the project was half-way done, my archive got around the 2.6MB level, at which point it no longer fit on the floppy (there was around 150K of files that couldn't be compressed, like IO.SYS, MSDOS.SYS and COMMAND.COM). My fix was to use ZIP as an archiver (no compression) and XZ as a compressor. This way, I was able to fit around 7MB of data (!) on a 2.88MB floppy. As a fun fact, by compressing the XZ binary (that weighs an enormous 300KB!) with ZIP, I've saved another 150KB!

The testing process looked more or less like this, assuming that the floppy image has already existed..

$ cd win3_build $ zip -0 -r ../win3_build.zip * $ cd .. $ xz -e win3_build.zip # win3_build.zip -> win3_build.xz $ sudo mount win3.img /mnt/wrk $ cp win3_build.xz /mnt/wrk/win3.xz $ sudo umount /mnt/wrk

I didn't use `xz -9` mostly because it needed a ton of RAM and it just couldn't be properly unpacked under DOS. The `-e` switch is the "extreme" compression option which only takes a bit longer to compress and leaves no memory impact.

Download

As a bonus, here's my project directory after a week of work :P


Support me on ko-fi!

Comments:

nerd at 09.04.2019, 19:50:29

this is pretty cool, I'm glad that I'm not alone at doing strange things with old hardware, just to see if it can be done.

IDK at 17.12.2021, 22:20:01

Im confused , where can get these stuff in internet instead of these disks ?!

Zoo at 13.07.2022, 19:46:44

Is this Windows 3.1 or Windows 9x? The first screenshot has the Win3x min/max buttons but the second screenshot clearly has a Recycle Bin which was new in Win9x. What is this?

oscareczek at 13.07.2022, 19:59:38

This is Windows 3.1 with Calmira installed, which is a replacement shell resembling the 95 one.

FreeFull at 13.07.2022, 20:00:04

The recycle bin is added by Calmira, which also in general makes Win3x look and behave a bit more like Win9x

flyingfishfinger at 13.07.2022, 21:27:10

Very cool! I did this with TinyCore Linux on my X210. It included drivers for everything including WiFi and a basic GUI - but I first expanded the RAM chip to 16MB. FWIW I first started with the floppy images and also failed to make it larger. But then, coreboot can directly load a Linux kernel, so that was the easier way in the end...

Anonymous Coward at 13.07.2022, 23:54:15

Have you tried compressing the executables with UPX? Might help squeezing in some KB more :-)

balgaa at 14.07.2022, 00:56:30

Can you make Windows for Workgroup 3.11 with networking?

abd at 14.07.2022, 03:29:41

looks pretty cool, i'll show my buddies.

Nick at 14.07.2022, 04:02:11

This is good

InuYasha at 14.07.2022, 17:32:18

Came here for "Macromedia Flash" Edition. But was not disappointed. :)

oscareczek at 15.07.2022, 20:27:39

@Anonymous Coward this actually will make it worse since UPX is a significantly worse compressing algorithm than XZ and double compression is worse most of the time anyway. @balgaa technically Ethernet should be possible with some DOS driver, WLAN is out of the question.

leeloo at 20.07.2022, 07:49:18

Maybe you could try upgrade this setup to win95? I recall an old screenshot of win95 installed unpacked at 8mb used

By commenting, you agree for the session cookie to be stored on your device ;p