• Please review our updated Terms and Rules here

Need clarification on typical BIOS segments

Trixter

Veteran Member
Joined
Aug 31, 2006
Messages
7,478
Location
Chicagoland, Illinois, USA
(I wasn't sure if this was more a programmer question or a hardware question, so I posted this in the forum with the most number of BIOS Version sticky posts :)

In trying to come up with a simple way to fingerprint a machine for my benchmark-in-progress, I came across the idea to do a quick CRC of the BIOS. For speed, it's a 16-bit CRC of the BIOS. (That CRC is stored as a quick way to identify two identical class machines, as well as help generate a unique ID for the record.) However, I was trying so hard to not leave any old machine behind that, keeping the 5150 at the front of my mind, I wrote code to calculate a CRC for the entire 64K F000:0000 segment. But looking at some BIOS listings for some clone BIOSes tonight, they all have an ORG of C000.

Did I make a mistake? Should I only "guarantee" myself that the BIOS starts at F000:C000? Or is the entire 64K F000 segment the right choice? I don't want to be reading random bytes/holes/adapter roms by mistake...
 
IBM 5150: F6000 to FFFFF

IBM 5160 - first BIOS: F6000 to FFFFF
IBM 5160 - second and third BIOS: F0000 to FFFFF

IBM 5170: F0000 to FFFFF
 
Much obliged, but is there any way to actually detect the starting location? I looked at F000:6000 of various ROMs and don't see a 55AAh header:

E9 8F 7E E8 A7 6B CB E8 02 65 CB C1 00 00 00 00


E9 8F 7E E8 A7 6B CB E8 02 65 CB 5D E8 C7 2F 74

etc.
 
The 55AAh header is only a requirement for a BIOS extension ROM, not the main BIOS ROM itself.

Crud. So how do I detect the true starting address of the ROM in any PC or clone? (Or is that not possible because the ROM starts with arbitrary code and no signature/header/magic cookie?)
 
Crud. So how do I detect the true starting address of the ROM in any PC or clone? (Or is that not possible because the ROM starts with arbitrary code and no signature/header/magic cookie?)
At FFFF0 is a jump to the startup code in the ROM, but that code isn't guaranteed to be a the beginning of the ROM. In some cases though, it could give you a clue.

A lot of early clones probably copied the BIOS date of an IBM BIOS release, for compatibility reasons.
So perhaps look at the BIOS date.
If the date matches one of the three 5150 BIOS releases, assume that you have an IBM 5150 or 5150 clone with a ROM start address of F6000.
If the date matches the first 5160 BIOS release, assume you have an IBM 5160 or 5160 clone with a ROM start address of F6000.
If the date matches a later 5160 BIOS release, assume you have an IBM 5160 or 5160 clone with a ROM start address of F0000.
If the date matches one of the three 5170 BIOS releases, assume that you have an IBM 5170 or 5150 clone with a ROM start address of F0000.
Of course, there's the worry of what to do if there is no date match.

A different approach would be to CRC only from F6000 to FFFFF, on every machine.
 
Unless I'm mistaken; some clones (like the Compaq portable) may only contain a BIOS from FE000 to FFFFF. IBM systems have BASIC at F6000 to FDFFF, which is somewhat of a "supplementary" program to the BIOS, but you could still call it a part of the BIOS.

As mentioned, early IBM XTs have nothing but 8K mirrors before F6000, while later IBM XTs have additional BIOS code from F0000 to F5FFF. IBM PC's have nothing in the mentioned range, so any reads from this memory should yield unpredictable data.
 
I would think you could write an exception routine. If it's there obviously you can go with IBM CRC validation, otherwise if no IBM rom then try offset c000. The 55AA ending was just to show that it was valid bootable code (MBR) from what I recall. But yeah troublesome if there's any other writable memory or roms assigned in that range that could change the CRC.
 
I don't know if there's any dependable way to do this. At least one PC compatible-ish system requires that the PC-compatible BIOS be loaded off the boot disk (i.e. there's very little in ROM).

FE000 FFFF is probably safe. Beyond that, there's no standard set of locations. Unfortunately, among various vendors, I'm not certain that this is enough, as later BIOSes use the FE000 area as a place to keep "standard" locations and jump off to lower memory to actually do functions. So one Phoenix BIOS may look very much like another in these locations.
 
If it's only for identification purposes, you can do a checksum starting from the address stored at FFFF1 (FFFF:0001) to the end of the ROM (F000:FFFF). Or even use just the last 16 bytes of the ROM (F000:FFF0-F000:FFFF) as a fingerprint. It contains the reset address and the bios release date, so this data will be different for different BIOS vendors, and hopefully it will be changing even when a BIOS of a given vendor is rebuilt.
 
I don't think that will be unique enough, Sergey. What Jim wants to do, if I read him correctly, is tie a given checksum to a specific system type. In my experience, the date tends not to be all that unique (just think of all of the XT clone BIOSes. Some different vendors of that time even shared the same BIOS!.
 
I don't think that will be unique enough, Sergey. What Jim wants to do, if I read him correctly, is tie a given checksum to a specific system type. In my experience, the date tends not to be all that unique (just think of all of the XT clone BIOSes. Some different vendors of that time even shared the same BIOS!.
In this case the rest of the BIOS might not be unique as well :)
 
If it's only for identification purposes, you can do a checksum starting from the address stored at FFFF1 (FFFF:0001) to the end of the ROM (F000:FFFF). Or even use just the last 16 bytes of the ROM (F000:FFF0-F000:FFFF) as a fingerprint. It contains the reset address and the bios release date, so this data will be different for different BIOS vendors, and hopefully it will be changing even when a BIOS of a given vendor is rebuilt.

Aha, now we're getting somewhere. I had considered using the last 16 bytes verbatim, but that didn't feel right for some reason. If I do that, I may call it something else, like a "BIOS fingerprint".

The FFFF1 address is intriquing -- what is that location officially supposed to be? (looks at a few BIOS listings...) Oh, that's the jump to the "reboot"/start of diagnostics routine? Good thinking! I like that idea, and I will probably use that. That seems to be about as foolproof as I can do across all machines.

Chuck: Good point about multiple machines using the same BIOS, however I really am just trying to "fingerprint" the BIOS and not the machine itself. Trying to fingerprint the entire system would be much more difficult, I think; I'd have to start with the BIOS and then start enumerating every piece of hardware in the system, from the easy (RAM, CPU model, CPU speed) to the difficult (peripheral cards, pretty much the entire BIOS data area, etc.). And if I got to that point, I doubt I would be able to come up with something that would return consistent results anyway since one flipped bit would mean 99.999998% identical machines would not register as identical. Fingerprinting the system is not a major function of the benchmark I'm working on, and neither is the BIOS CRC -- it's just an extra to satisfy the curious. Like, "oh hey, those two machines have the same BIOS".

Thanks for the suggestions!
 
Last edited:
...Good point about multiple machines using the same BIOS, however I really am just trying to "fingerprint" the BIOS and not the machine itself. Trying to fingerprint the entire system would be much more difficult, I think; I'd have to start with the BIOS and then start enumerating every piece of hardware in the system, from the easy (RAM, CPU model, CPU speed) to the difficult (peripheral cards, pretty much the entire BIOS data area, etc.). And if I got to that point, I doubt I would be able to come up with something that would return consistent results anyway since one flipped bit would mean 99.999998% identical machines would not register as identical. Fingerprinting the system is not a major function of the benchmark I'm working on, and neither is the BIOS CRC -- it's just an extra to satisfy the curious. Like, "oh hey, those two machines have the same BIOS"!...

Exactly, the "machine fingerprint" would be the same (for example) for some IBM XTs, Portable PCs, and 3270 PCs...

They all used the XT motherboard, but were in a different case housing or had additional adapters...

Were it as easy as microchannel, where the planar had an almost unique ID (the duplicates can be determined), and adapters/features only need a little code to query...
 
For future reference, here's the code derived from the above conversation. And, based on the above conversation, it should be reliable across all machines.

Code:
Function CalcBIOSCRC16:word;
var
  BIOSInitVector:pointer ABSOLUTE $FFFF:0001;
begin
  CalcBIOSCRC16:=CRC16Buf(BIOSInitVector,$ffff-word(BIOSinitVector),0); {buf, len, seed}
end;

The CRC16 is the same one used by Forsberg for xmodem, and is an assembly-optimized version of this.
 
For future reference, here's the code derived from the above conversation. And, based on the above conversation, it should be reliable across all machines.

Code:
Function CalcBIOSCRC16:word;
var
  BIOSInitVector:pointer ABSOLUTE $FFFF:0001;
begin
  CalcBIOSCRC16:=CRC16Buf(BIOSInitVector,$ffff-word(BIOSinitVector),0); {buf, len, seed}
end;

The CRC16 is the same one used by Forsberg for xmodem, and is an assembly-optimized version of this.

While we're discussing BIOSes (and I got here from a Google search for "Compaq Portable I" "bios rom"), how did this routine work out for you? I imagine it should work fine. The reboot vector will almost always point to the same location (0xf000:0xe05b). I'm not sure if a completely unmodified ERSO BIOS actually exists... from analysis I've done, at least the string table at 0xf000:0x0000 and 0xf000:0x0500 will differ based on computer manufacturer. But Chuck is the resident ERSO expert, and I only compared 4 ERSO clones lol.
 
Back
Top