1793605145

Reverse Engineering Old BIOS ROMs: What Nobody Tells You


There's a romantic idea that reverse engineering an old BIOS means sitting down with a hex dump, a cup of coffee and the patience of a monk. Half of that is true. The other half is spending three weeks convinced the ROM is corrupted when, in fact, the 8-euro programmer I bought was reading the bytes with the endianness swapped, or reading the chip badly because of a pin that wasn't seated properly in the clip. I start there because nobody talks about it. The problem is rarely in the code. It's in arriving at the code with the certainty that what you have is what was actually there. A twenty-something-year-old 27C256 EPROM loses bits. That's not forum legend. I once had a 386 board where two consecutive reads of the same chip gave different MD5s, and only on the third dump did I realize a single bit in the POST area was flipping depending on the temperature of the bench. I learned to read every chip at least five times, compare everything, and only then trust anything. It sounds like paranoia, but it saves you days chasing a bug that doesn't exist. Then comes the part people assume is the hard one: disassembly. And here I'm less kind to the state of the art than most. Ghidra is extraordinary work, and I use it, but its decompiler on 16-bit real-mode code, with segmentation, is of dubious use. It spits out pseudo-C full of pointers that mean nothing, because the segment context lives in registers the program keeps changing by hand. Honestly, for a 1990 BIOS I almost always end up with `ndisasm -b 16` or `objdump -D -b binary -m i8086`, with an editor open next to it, annotating by hand. Reading assembly without the crutch of a pretty decompilation teaches you more than any new tool. And now everyone wants to sell me the idea that a language model will explain the ROM for you. I've tried. It invents routine names with a confidence it hasn't earned, and when it's wrong, it's wrong convincingly, which is worse. The starting point, at least, is always the same, and it's elegant. On an x86, the processor wakes up and jumps to 0xFFFFFFF0, or, in the old modes, to F000:FFF0, which is only sixteen bytes before the end of the address space. Sixteen. Room for a `JMP FAR` and not much else. The ROM ends right there, with the build date in ASCII just after it, something like "03/14/94", and a model identification byte. Many people skip right past it. I went there first, always, because the date tells you which generation of code you're dealing with, and that changes how you think about everything else. (An aside, unrelated to anything: the first EPROM programmer I ever had was one of those machines with a UV lamp switch, and I ruined half a chip by leaving the window uncovered for an afternoon. I still have the scar, which is just a yellow stain on the glass.) Back to the code. What really eats time in an Award or AMI BIOS from the 486 era isn't the boot code, it's the fact that it's compressed. Award used LZH modules (the lh5 format, more or less what LHA did), and the boot block, decompressed, is just a tiny loader. If you open the ROM in an editor and see mostly noise, that's not obfuscation, it's compression. `cbrom` and MMTool solved this on the manufacturers' side, but finding versions that run without complaining is a hobby of its own. I once lost a night to an executable that would only start in pure DOS and not in the prompt of any VM, because it assumed certain interrupt timings. And then there's the checksum. The classic rule is simple: the sum of all the bytes in the ROM modulo 256 must be zero, and one byte is reserved just to make the math work. If you change an instruction and forget that byte, the machine loads the POST, prints a checksum error and stops. It has happened to me: I patched a boot message, broke the sum, and spent twenty minutes suspecting the patch when all I needed was to fix one byte. It sounds stupid. It is. On option ROMs, which I like more than any other part. Each one starts with 0x55 0xAA, followed by the size in 512-byte blocks, and an entry point three bytes further on. The BIOS walks the space between C0000 and E0000 in 2 KB steps looking for that signature, validates the sum and jumps in. A video card, a SCSI controller, a network card with remote boot, all of them depend on this small, fragile mechanism. It seems almost too simple to have survived twenty years of PCs, and yet it did. Now, an opinion that might cost me a few looks. I think nostalgia ruins a lot of the work done in this scene. I see preservation projects that treat every ROM as a sacred relic, publishing the dump with an epic text and no useful annotation. A dump without analysis is just a file. I'll take someone who documents what each INT 13h routine does over someone who writes a poem about the motherboard a thousand times over. But, contradicting myself already, I don't know if that's fair. Pure preservation, without analysis, has value because tomorrow someone with more patience will pick it up. That dump of an unknown 286 that nobody has looked at in fifteen years might be exactly what solves a compatibility mystery. I'm torn. Probably both sides are right, and I just have less patience for one of them. There's also the legal question, which everyone avoids and which isn't as gray as they claim. The reason compatible BIOSes exist is that in 1984 Phoenix made a clean-room reimplementation of IBM's BIOS, with one team reading the specification and another writing the code, never crossing paths. Compaq had done something similar shortly before. That created the clone industry. Reverse engineering for interoperability has a long history, and I find it irritating when someone treats the subject as if it were contraband. What keeps me awake, in the end, is something else: the knowledge is disappearing faster than the chips. The authors of the original comments, when there were any, retired or died. The manufacturers' tools live on disks nobody archived. And I still think the best you can do is take an old board, read the chip five times, and write down what you found, even if it's half wrong. I still think about that bit that flipped with the temperature.

(0) Comments

Welcome to Chat-to.dev, a space for both novice and experienced programmers to chat about programming and share code in their posts.

About | Privacy | Donate
[2026 © Chat-to.dev]