Part four - MS-DOS debugging

    After a week I’ve stared to reverse the MS-DOS boot process to find the bug that is keeping this WYSE tin client from booting DOS 6 from the DOM and is sitting there only with a blinking cursor.

    So I decided to build a new image, only with DOS 6 on it, extract the MBR from there and disassembly this code in IDA. 

The new DOS 6 image was booting well on Bochs virtual machine so I know that the image is good.


The MBR:

MBR structure


 On the left image you can see the MBR structure. From the 512 bytes that it has, 446 bytes are just code that is executed after the BIOS passes control to the MBR. The last 66 bytes represent the Partition Table and the Magic Word: 55AAh.

   MS-DOS 6 MBR code does not print anything on the screen by default, but it doesn’t mean that is not working on the WYSE machine. I have found that 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. This is not true till now, because the MBR is loading code from the DOM and is working well.

DOS 6 MBR and IDA disassembly can be found here.

    Something else is happening with DOS 6 that is not booting on this WYSE machine from the DOM. 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 by the BIOS 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 the DOM... problem might be in this ISRs... but now I’ll continue with DOS reverse.

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

    Then 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 hereI have started to reverse this with IDA and, this bootloader has a function for displaying errors too. Great! This way I had a tool for debugging the bootloader on the real machine. 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 to a data table: “floppy disk drive parameter table”). Some data and the pointer from the IVT are updated by this 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 address 0:500 in RAM
  • is searching for IO.SYS and MSDOS.SYS files in the FAT
  • it searches for the IO.SYS file on the DOM
  • is copying the first 3 sectors (512x3 = 1536 bytes) from the IO.SYS file to the 0:700 RAM address
  • is passing control to 0:700 address
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 address 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:


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

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

    Then 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 address 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 IO.SYS file 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 not a problem).

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


Second part of the IO.SYS:

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

Starting MS-DOS . . . function in IO.SYS

    At RAM address 70:0 (0:700) there 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 pieces of 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.

Load byte at address DS:SI into AL  to be printed -> Starting MS-DOS...

Data Segment register = 0473h

Source Index register = 0573h

Then I compute the text address:  473 x 10h = 4730 + 573F = 9E6F - 700(RAM offset) = 976F offset in IO.SYS second part // 70:976F (physical address in RAM).

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!

The final solution will be presented in the next post of this blog.

 Previous part            |           Last part

Comments

Popular posts from this blog

Part Two - BIOS ROMs of the WYSE Sx0 - S50

Adventures of reverse engineering the WYSE Sx0 – S50

Sound Blaster 16 emulation for DOS 6.22