-
Notifications
You must be signed in to change notification settings - Fork 0
Using PC XT ROM BASIC to host XTIDE BIOS
Using PC XT ROM BASIC to host XTIDE BIOS (the hard way)
- Introduction
- Hardware used
- Booting Cassette BASIC from the emulator
- Reverse engineering Juko XT BIOS
- Burn patched BIOS and XTIDE
- Test patched BIOS and XTIDE in real hardware
Original IBM PC 5150 included a built-in version of BASIC interpreter, also referred to as Cassette BASIC, as part of the 40 KB total ROM. This version of BASIC was 32KB, and it was installed in a second ROM socket:
The BIOS will try to boot to Cassette BASIC if it cannot find a disk that it can boot from. It will accomplish this using INT 18h, that will transfers control to physical addresses F600:0. This is mentioned in the "IBM Technical Reference":
The idea is use ROM BASIC as a host for our XTIDE BIOS without using any extra ISA card.
But there is a problem with this: original XT BIOS will not try to look for Option ROMs above 0xF400 address space; and the solution is simple, you can use a modern XT BIOS like Super PC/Turbo XT Bios or GlaBIOS, that support booting from ROM BASIC.
However, I'll take a different, and much more fun, approach by reverse engineering the original Turbo XT BIOS and extend the memory search range for Option ROMs.
- JUKO XT Motherboard
- NEC V20 CPU (D70108C-8)
- Winbond W83757F Multi I/O ISA card
- 27c256 32KB ROM (INTEL D27256)
- Raspberry Pi
- USB to Serial TTL
- TTL to RS232 adapter
- TL866 EPROM programmer
PCem includes a Generic XT
implementation at ./roms/genxt
. I'll use this to create a new machine:
You will need to place basic rom into ./roms/genxt
folder. The name of the file should be ibm-basic-1.10.rom
and it should be 32KB size.
Boot screen should look like this:
And if you press a key, you should see Basic interpreter:
That's a good start, as it means that PCem is successfully loading ROM BASIC for this Generic XT Clone PC.
Now copy XTIDE image to ./roms/genxt/
and replace ibm-basic-1.10.rom
And after reboot, and press some key, you will get a blank screen. This is because this generic BIOS cannot boot from ROM BASIC.
Let's try to replace the pcxt.rom
with GlaBIOS ROM
After reboot:
Now that we know that we can boot XTIDE from BASIC ROM, let's try to use the original Juko XT BIOS. Replace the pcxt.rom
again, but this time with Juko XT ROM. Reboot, and as expected XTIDE was not loaded:
Next step will be to disassemble Juko BIOS ROM image.
If we check IBM PC XT Technical Reference, we can find the routine that checks for Optional ROMs:
The BIOS checks if the ROM starts with 0xAA55
magic word, and it will search from 0xC800
till 0xF600
.
With that information we can define a strategy for reversing Juko BIOS:
- disassemble BIOS
- search for
AA55
word - identify routine that checks end of memory block
- patch upper limit so that it can reach
0xFE00
(that should cover0xF600
and above).
To disassemble the BIOS you can use NASM:
ndisasm -b 16 -o 0 juko_baby_xt_bxm_12.bin > juko.asm
And search for magic word:
cat juko.asm | grep aa55 -A 10 -B 10
First match is the one we are looking for. The routine checks for ROM starting with magic word 0xaa55
, from 0xC800
and 0xF400
.
To achieve our goal we just need to change 0xF400
to 0xFE00
.
Now, you can open the image in your hex editor and look for the byte sequence 81FB00F4
:
And we can replace 0xF4
with 0xFE
:
If you want to do this from the shell instead, you can use dd
:
printf '\xFE' | \
dd \
conv=notrunc \
of=juko_baby_xt_bxm_12_patched.bin \
bs=1 \
seek=$((0x3fe))
Great. Now let's boot the machine and see what we get:
A black screen of course. This is because the BIOS has a checksum, and we have changed one byte, and this will generate a different sum.
Going back to "IBM Technical Reference", we can see the checksum routine:
This is quite straightforward, it is an 8bit sum of each byte within 8K ROM; and the sum must be zero. Last byte of the ROM is used to adjust the checksum, so what we can do is set that last byte to 0x00
:
and calculate the 8bit sum using a simple python script:
import sys
if len(sys.argv) < 2:
print("Usage: python calculate_checksum.py filename.rom")
sys.exit(1)
filename = sys.argv[1]
with open(filename, "rb") as f:
rom_data = bytearray(f.read())
rom_checksum = sum(rom_data[0:]) & 0xFF
print(f"Checksum: {rom_checksum:02x}")
Running the script will return this value:
$ python checksum.py ~/juko/pcxt.rom
Checksum: ff
And to calculate the value needed to get zero we can do:
0x100 - 0xFF = 0x01
So, we need to set last byte to 0x01
:
We save the file and restart the machine:
And it worked. XTIDE BIOS was loaded from ROM BASIC!
Next step would be to burn the new BIOS to a 32KB EPROM.
We are ready to burn the patched BIOS image. This procedure should be straightforward, just take the 27c64
chip, erase it using UV, and burn the new image to it.
For the XTIDE there is one thing to take into account though: Juko XT board expects a 27c256
ROM (32KB). If you use a smaller one like 27c64
or 27c128
you might encounter unexpected behaviour because of pin 27:
So, if you are planning to use 27c64
or 27c128
make sure to disconnect pin 27 and pull it to high.
For 27c256
just burn the 8K image and fill the rest with zeros.
Remove any ISA with boot ROM and insert 27c256
ROM into Cassette BASIC ROM socket along with 27c64
BIOS ROM. The machine should boot into XTIDE, and you can use debug
DOS tool to check that the code is in the expected memory address:
I didn't expect to see this. XTIDE code is located at 0xF800
and not in 0xF600
as it should be. But then I realized that this is due to ROM shadowing.