Logo

Wyse S50: MSDOS 

MSDOS

I've heard from two people who have spent some time and effort trying to run MSDOS on the Sx0. You can read about their efforts here. We have:

Acknowledgement

The information presented here came from Stefan in Romania. It outlines his struggle to install and run DOS 6.2 on a Wyse S50 and covers various patches he made to the S50 BIOS to achieve this.

All the files associated with this work can be downloaded from: https://mega.nz/folder/WdgXDLab#ppcn5d_TWSsuR34akuNKoQ

Adventures of reverse engineering the thin client WYSE Sx0 - S50

(English is not my native language so I might get some words misspelled in here).

DOS 6.2 running on a Wyse S50

Hi!. My name is Stefan and I'm from Romania. I'm a hardware guy for most of the time but I used to crack some software from time to time. I don't mean any harm to anybody, but I grew up in poverty and I had to do something to enjoy the software that I couldn't afford. I'm not actually a good cracker or hacker but what you see on the left image is the S50 booting MS-DOS 6.22 from the DOM and is displaying a "Summary Screen" that was hidden and disabled in BIOS. The FAN, over the CPU heatsink is added by myself too.

So... I've bought this thin client and I've wanted to install MS-DOS 6.22. Clearly it didn't work and this is how I've started to reverse this cute WYSE terminal. On the first hardware inspection I've found a small memory chip on the back of the PCB, an 8 pin SOIC EEPROM "93C46A" that is not bigger than 128 bytes. I've dumped the content of this chip using the CH341A (modified to read 93C chips) and all I've found was the serial number of the machine: 6IFDGB03427. (you'll find the contents of this chip in the "EEPROM_chip" folder).

Then I've start to read more, searched all the internet for documents that might help me understand this machine, and I've found some that I've put in the "\WYSE\Sx0-S50\Docs" folder. Docs about the CPU, the CS5536 Companion that is a Platform Controller HUB, and about the BIOS.

Long story short, all the system is controlled by this CS5536: when you power up the machine, this PCH is connecting the LPC BUS directly to the internal physical address BUS of the CPU core. The BIOS chip (SST49LF020A - LPC Flash) that is connected on the LPC bus is responding to addresses from FFFC:0000 to FFFF:FFFF. In this way, when the PCH releases the RESET signal line, the CPU will execute it's first code from FFFF:FFF0 like all the x86 CPU's do.

From now on I had to continue by reversing the actual BIOS boot block (physical memory from FFFF:0000 to FFFF:FFFF). 65,536 bytes of pure 16bit code.

DOS 6.2 running on a Wyse S50
I've tried dumping this directly from the machine (booted with DOS 6.22 from USB) but I know that some softwares use to patch themselves when they are running so I've build myself a SST49LF020A - Flash reader, eraser and writer using an Arduino Mega (clone from AliExpress). I've included the source code for this Flash programmer in the "\WYSE\Parallel flash programmer SST49LF020A" folder. It is a very slow programmer but it does the job. The Arduino PCB is patched to work only on 3.3v to be compatible with this Flash memory chip.

In this way I've dumped the entire BIOS flash chip. You can find this file in: "\WYSE\Sx0-S50\BIOS_image_from_the_chip\Full_BIOS_DUMP.BIN". This is the original BIOS found on this WYSE Sx0 - S50 machine. The FLASHROM.COM (Flash ROM Device Update Utility) does not support SST49LF020A chip - haven't tested but the chip is not listed in the supported chips.

David: I have a version of flashrom that works with the Wyse Sx0 and that runs on Tiny Core Linux. It is bootable from a USB drive. This runs with Tiny Core 12.0. You will need to replace the standard kernel with my special Sx0 Wyse Linux kernel and add the flashrom v1.2 binary.

To read: sudo ./flashrom -p internal:laptop=this_is_not_a_laptop -c SST49LF020A -r bios.img

The binary reports its status as UNTESTED for WRITE. I found that WRITE did work for me.

...back to Stefan...

After this was done, I've opened this dump with a hex editor and looked around for some obvious things. The BIOS boot block started with "$XPR" ascii code. From offset 30000h to 3FFFFh is the boot block.

BIOS dump

I've exported this boot block at "\WYSE\Sx0-S50\BIOS_image_from_the_chip\1.Extracted_Boot_Block_16bit_region\Original\Extracted_Boot_Block_16bit_region.bin" and other memory blobs that started with "$IMG", "$BMP" and "$PAL". Then I've found this important info about the other blobs. They are compressed with an algorithm made by some "Jeremy Collake".

BIOS dump

The website doesn't exist anymore, but I've found a fork of his work on some website. You can find the source code and the windows executable in the "\WYSE\Tools\CALG1 Compression Library" folder. "jcalg1_test.exe" is a windows console tool that can be used to expand and compress this memory blobs that turned out to be: 10 option ROMs and one raw bitmap file and its video palette color.

VSA Init ROM - Virtual System Architecture is a piece of software that is hiding the real hardware from the OS and is emulating standard hardware like keyboard controller, IDE controller, CMOS and other hardware.

Geode Architecture
This emulation is made at the hardware level by setting some Model Specific Registers (MSRs) that control the GeodeLink Interface Units (GLIUs). This GLIUs can trap CPU access to some defined memory regions and run some ISRs from VSA software instead or route the access to some other device. VSA system is a TSR (Terminate and Stay Resident).

On the left you can see the real hardware architecture of a Geode CPU package. The physical address bus of the CPU core is directly connected to the GLIU_1.

All the 4Gb memory space that the CPU can access is provided and managed by the GLIU_1.

There are hundreds of MSRs inside this GLIUs that are programmed by the BIOS code for the system to act as you wish. Without VSA, MS-DOS will be unable to access a USB memory stick as a HDD, or read a USB keyboard buffer (MS-DOS doesn't have USB support but you can read and write data from or to a USB mem. stick). For more information about the VSA I have provided datasheets in the "\WYSE\Sx0-S50\Docs\Virtual System Architecture - VSA" folder, and source code of the VSA system that I hardly gathered from the internet.

JVGA BIOS - Version 5.30a - video BIOS subsystem software - not explored yet.

PXE ROM - Preboot Execution Environment PXE-2.0 + Realtek RTL8139 BIOS functions - not explored yet. This software is used to boot the thin client from a network.

UHCI ROM - this ROM provides Interrupt Service Routines (ISR) for USB HIDs like keyboard, mouse and ISR for USB Disks INT 13, etc.

GUI ROM - this is the graphic user interface of the BIOS. This ROM is loaded when you press "DEL" key at system startup. The code is obfuscated to discourage reverse engineering on this. They used the stack as general registers to compute things. Is not hard to reverse but it consumes a lot of time when you need to keep track of the stack.

I've tried to swap this ROM with another ROM made for other CS5536 system that had all the settings in the GUI but NVRAM tokens where not the same. Lots of token errors on this one:

BIOS dump

The new GUI after lots of errors looks like this:

BIOS menu

I had to revert this and stick with the original one. If anybody will like to trace this code and add features to the GUI it will be nice. There is an IDA Pro disassembly of the GUI started by me in the "\WYSE\Sx0-S50\BIOS_image_from_the_chip\2. Extracted_ROMs\Expanded" folder.

Some people might ask: "why not swap the entire BIOS if you have one alike" - this might end up in fire. GPIOs are defined in software: if they are Inputs or Outputs. If one BIOS sets one GPIO as output when it is needed to be an input.. then a lot of current might flow true that pin... so fire might happen).

Bitmap - this is the WYSE logo.

Xpress ROM - this, by the name, is an interesting ROM. Datasheets refer to Xpress ROM as the BIOS GUI but is not. This is just a "Summary Screen" that was disabled and I've managed to patch it to enable it to show at the system startup. By default if a boot device was detected, the "Summary Screen" was disabled. The extra delay before loading the OS is intentional, it can be adjusted by patching the ROM.

BIOS dump

Disk ROM - this ROM is overwriting the Disk ISRs with the right ones depending from where the system will be booted: DOM, USB, Flash. (need to study more, here might be where DOS hangs for DOM and not for USB).

XPACPI - ACPI functions

text data - unknown ROM

$PAL image video palettes - colors for the WYSE bitmap image

You can find all of this ROMs in the expanded and compressed form in the "\WYSE\Sx0-S50\BIOS_image_from_the_chip\2. Extracted_ROMs" folder.

SST49LF020A BIOS chip Memory Map

Next I will present the BIOS chip memory map. The hex values represent the offset address in the chip. All ROM images are compressed with "CALG1 Compression Library" and all have a header of 32 bytes where is described the location where every ROM needs to be extracted, the size of the ROM before was compressed, the size after compression + some checksum that is not used.

The data in the table is for the original BIOS. Patched ones are different.

Padding - header
+ all zeroes

0
ROM header
Compressed VSA Init ROM
9CC0
9CE0
ROM header
Compressed JVGA BIOS
1:D170
1:D190
ROM header
Compressed PXE ROM
2:1110
2:1130
ROM header
Compressed UHCI ROM
2:6F50
2:6F70
ROM header
Compressed GUI ROM
2:70D0
2:70F0
ROM header
Compressed Bitmap image
2:A410
2:A430
ROM header
Compressed Xpress ROM
2:B570
2:B590
ROM header
Compressed HID ROM
2:C250
2:C270
ROM header
Compressed Disk ROM
2:CE40
2:CE60
ROM header
Compressed XPACPI ROM
2:E540
2:E560
ROM header
Compressed some text ROM
2:EA20
2:EA40
Header
$PAL image video palettes
2:FBE0
2:FC00
Header
BootBlock
3:0000
3:0020
End of memory3:FFFF

I have patched the code for the 'ROM searching function' in the Boot block and all the ROMs headers because the BIOS procedure to find the ROMs was obfuscated and it was hard to swap ROMs in this way. Some strange computations have been used just to get the compressed ROM size + header. I just patched the ROMs headers with exact data and this function with a lot of NOPs for me to easily swap ROMs like the GUI ROM.

BIOS disassembly

This is all with the BIOS patching. There is still a lot of info in the "Docs" folder that I have not read yet. A step forward will be to completely reverse the GUI ROM, find what all the NVRAM tokens do to know what other settings can be made and added to the GUI without broking anything. More info about the BIOS structure can be found in the "Info.xlsx". I have written there the most important BIOS steps from the moment of the system power up to the moment of MS-DOS boot.

All of this reverse took me about 4 months and now when I'm writing this I might forgot to mention some things, but many details can be found in the IDA disassemble files. Just browse the folders. I have also made some small "info.txt" files to keep track of all the progress.

Second chapter: MS-DOS reverse

After a week I've stared to reverse the MS-DOS boot process to find the bug that is keeping it from booting.

I've started with the MBR block (512 bytes) from the DOS 7 working image - I wanted to learn about the boot process so I've started with this working image. (\WYSE\Sx0-S50\Crafted_128M_DOM_image_DOS_7\DOM_128M_DOS_7.1.img)

I've extracted this MBR from the DOS 7 image and reversed It with IDA. Something was wrong: Win98 MBR (DOS 7) was bad for my DOM: it was rewriting the MBR sector of the DOM every time the system was booted and I know that DOMs memory have a limited number of writes before they fail to work anymore - just like SSDs.

So I decided to build a new image, only with DOS 6 on it, to extract the MBR from there and replace this DOS 7 bad MBR with that one.

I have made a new folder for this new image: "\WYSE\Sx0-S50\Crafted_128M_DOM_image_MSDOS_6", then I've built and put a new image with MS-DOS 6.22 on this folder: "MS_DOS_6.22.img"

The new DOS 6 image was booting well on Bochs virtual machine and I've extracted the MBR from it and I have updated my working DOS 7 image with this MBR using a hex editor. WYSE booted well with this MBR too, so I think DOS 7 image is good for now.

Having this DOS 6 image I've started to reverse this one instead because this had a problem. So I've started patching things and testing on the WYSE terminal to see the result.

"F1 . . . DOS , Default: F1" text on the screen before boot it was from the win98 MBR. MS-DOS 6 MBR does not print anything, but it doesn't mean that is not working. It has a function to print an error if it encounters one.

This was good, because I have used this function as a debugging tool: patched the MBR so it will display the error text when I wanted - this way I knew that the code was running and it was not stuck there as many people say about this WYSE machines that the BIOS is disabling the DOM at some time after boot and this is why DOS 6 is not booting. It is not true till now, because the MBR is loading code from the DOM and is working well.

Something else is happening with DOS 6 that is not booting on this WYSE machine. It might be that INT13 from the BIOS it has its own CHS scheme for the DOM and some sectors will be mixed up next in the code.

BTW: BIOS has two separate ISRs for INT13: one is for USB Disk and the other for DOM Disk. The INT13 ISR is updated at system power up with one of this two versions depending if a USB Disk is present or not.

I have not reversed this two INT13 ISRs yet, but I will... because DOS6 is booting on the WYSE from USB and not from DOM... problem might be in this ISRs... but now I'll continue with DOS reverse.

The MBR: When the system powers up, the BIOS loads the MBR at address 0:7C00.

The DOS 6 MBR starts by copying itself from 0:7C00 to 0:600 address in RAM and continues execution from 0:61D. It tests the DOM partitions to see if the disk is bootable, then it loads the MS-DOS bootloader (512 bytes) from the DOM offset 0x4000 to RAM at address 0:7C00 overwriting the first copy of the MBR and is passing the execution to the bootloader.

MBR has passed the test here: It was able to access the DOM and read data from it. (this was tested by me on the real machine with the error function as a debug tool)

The bootloader:

Seeing that the MBR is working fine, the next step was to extract the bootloader to the "\WYSE\Sx0-S50\Crafted_128M_DOM_image_MSDOS_6\2.Bootloader\Bootloader.bin". I have started to reverse this with IDA too. (IDA disassembly with lots of comments can be found for all of this pieces of code in the folders that I've made).

This bootloader has a function for displaying errors too. Great! This way I had a tool for debugging the bootloader too. I can patch the code anywhere I need to see if the code is working.

By placing a jump instruction in the code to this Error function, burning the image back to the DOM, booting the WYSE from the DOM I can tell if the code I'm debugging is working or not. If the error message was displayed I knew that the code is working and the problem is not there.

This bootloader is starting by relocating interrupt 1E (1E pointer from the IVT is not actually an ISR for an interrupt, is a pointer for a data table: "floppy disk drive parameter table"). Some data and the pointer from the IVT are updated by the bootloader. This might be a cause too for the DOS 6 not booting, because the BIOS is not providing such a table, relocated data is just some code from the BIOS - is garbage, but for now this table is not used by anything, it just sits there in the RAM.

Then the bootloader is:

  • updating the BIOS Parameter Block (DISK parameters like CHS - more details in Bootloader.bin.idb),
  • is searching for the FAT (File Allocation Table),
  • is copying the FAT to 0:500,
  • is searching for IO.SYS and MSDOS.SYS files in the FAT,
  • it searches for the IO.SYS file on the DOM and
  • is copying the first 3 sectors (512x3 = 1536 bytes) from the IO.SYS file to the 0:700 address on the RAM and
  • is passing control to 0:700 address.

BIOS INT13 might ignore the "BIOS Parameter Block" from the bootloader, and it might provide another CHS scheme. For example the DOS 6 image is formatted with 8 Heads, BIOS might provide 16 Heads for the DOM. Either way the first sectors on the disk will be accessed in the same way until BIOS responds to a Head 0 read command with a Head 9 read, mixing everything up.

It might be a good idea to inject some MBR code that can print the BIOS CHS scheme. It is done by INT13 function 08h - Get Drive Parameters. It will be helpful but I don't have time now for this. I know how to disassembly code but is hard for me to write code in assembler.

For now the Bootloader has passed the test too: It was able to access the DOM and read data from it. (this was tested by me on the real machine with the error function as a debug tool).

The IO.SYS:

The IO.SYS file is made from two executable pieces of code. The first part, the MSLOAD (Microsoft loader) is in RAM now at 0:700 and is executing. I have traced all of this, the code is working fine till now. My debug tool... this Error function is displaying an error on the screen when I want it to:

BIOS details

Now this error: "Non-System disk or disk error..." is from the IO.SYS file. I have patched the MSLOAD inside the IO.SYS... so now I know that the code from the MSLOAD is working. Exactly the code from 9F44:043C physical address, 9:F87C linear address. (MSLOAD relocates itself from 0:700 to 9:F440).

This MSLOAD is starting by relocating the BIOS Parameter Block (Disk data) to itself - it has some empty bytes from 0:703 to 0:837 just for this data.

It asks the BIOS for the amount of base memory available in the system (< 640 KB). Last kilobyte from the top of the memory is used by the EBDA (Extended BIOS Data Area) from address 9:FC00 to A:0000 so MSLOAD is copying itself from 0:700 to 9:4400 in RAM and is not overwriting the EBDA and continues execution from 9F44:0238 physical // 9:F678 linear.

At this address I've patched the code to jump to the error that you see above, so, code at 9F44:0238 is working.

Then the MSLOAD is loading the second part of the IO.SYS file, from offset: 5A6h till the end of the file to RAM at address 0:700. Code loaded from DOM is actually a few bytes longer but this is due to the loading function.

This is where the INT13 BIOS might be misplaced some sectors...

Second part of the IO.SYS file:

From the moment I've opened this code in IDA I've known that here is the clue for the problem of the DOS 6 not booting on the Wyse machine.

In the first few instructions this code must print "Starting MS-DOS..." and, on the real machine nothing is happening. Code from this RAM address 0:700++ have been executed successfully before, and nothing else was loaded to stop this from working. DOS kernel have not been loaded yet and still no message is printed on the WYSE machine.

It is clearly that the MSLOAD had loaded other sectors from the DOM to this RAM address and this is because of the BIOS INT13 ISR. The INT 13 is addressing the DOM in a different way than the DOS6 thinks it does.

IO.SYS detail

At RAM address 70:0 (0:700) is a jump to 70:17FB. Here some data is backed up from AX and BX then DS is loaded with 0473 and SI with 573F. This two CPU registers point to the "Starting MS-DOS..." text that need to be displayed, like my "Error function" did when I have debugged the MSLOAD and other code. INT 10 have been working good till now so there is no reason why this text will not be displayed. The only reason is the INT13 BIOS ISR that has is own "Cylinder Header Sector" translation scheme.

Now, to fix this, all I have to do is to find out what is the BIOS CHS scheme for the DOM and format the image by that scheme, or patch the INT13 ISR in the BIOS to be compatible with my image. Hurray!

Another day had passed and I've remembered that I have BIOS dumps of other machines like this WYSE. In the folder "\WYSE\Other_systems_with_GX_500_and_CS5536\EPX-GX500_BIOS\Original BIOS 2007\Extracted_ROMs_Compressed" I have a DiskROM image for a known system EPX-GX500 that is made to work with DOS 6.

So the easiest way to make this WYSE boot DOS 6 was to swap this DiskROM in the BIOS.

This will replace the INT 13 ISR with a good working one. I have done just that.

Hurray !!! the WYSE booted into DOS 6.22.

Now for someone to make this WYSE work like this, it needs to find a way to burn this BIOS "\WYSE\Sx0-S50\BIOS_image_from_the_chip\Patch\Patch_DISK_ROM\ Original+Xpress_Patch+New_PAL+DiskROM.bin" to the BIOS chip, either by using my Arduino programmer, or by the mean of some software.

SST had provided a driver written in C in 2006 for writing this chip from the DOS. I have found it by the way of the "Time Machine" on the SST website in 2006. The file is "\WYSE\Sx0-S50\Docs\SST49LF020A_BIOS_chip_driver.txt" for whoever wants to compile this. There was a compiled version at that time on the SST website, but the "Time Machine" didn't get that.

And you need to use an adapter like this: to burn the "D:\WYSE\Sx0-S50\Crafted_128M_DOM_image_MSDOS_6\ MS_DOS_6.22.img" to a 128Mb DOM.

The interface on the image can be found on AliExpress by the name of "USB to SATA-IDE" and the adapter for the DOM can be found on Ali by the name of "44 pin 2.5 IDE male to male adapter".

You can use the provided: "WYSE\Tools\ HDDRawCopy1.20Portable.exe" software for this task.

There are other software and documents in the package I've provided. I will let everyone explore those because it was a really long journey for me and I can't explain everything here.

If you want to transfer files from USB to the DOM just make a USB with MS-DOS 6.22 image on it, put whatever files you want in this USB drive and boot from USB. DOM will be mounted as "D" drive. You can transfer files from the USB to the DOM now.

Hope this will help you fix your WYSE machine.

This information is free for use and distribution by anyone!

All the files associated with this work can be downloaded from: https://mega.nz/folder/WdgXDLab#ppcn5d_TWSsuR34akuNKoQ

 


Any comments? email me. Added August 2024