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

Notepad

Calculator

Write

Paintbrush

Sound Recorder

Calmira (replaces the default Program Manager)

Minesweeper

SkiFree

Tetris

LifeGenesis

JezzBall

Reversi

Visual Basic 3.0 (fully functional, because why not!)

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

Windows 3.1 Flash Edition (2.88M ED floppy disk image)

VGA Option ROM (because dumping this is a huge waste of time)

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

Comments: