VOGONS


First post, by EduBat

User metadata
Rank Member
Rank
Member

I looked around but could not find any practical way to get the BIOSes from my computers into files.
The programs I found were either too complicated (flashrom) or simple (romdumpr.)
The problem with flashrom is that it needs to be aware of the chipset and tries to get that by querying the PCI bus. A 486 computer without PCI will not work.
On the other hand, romdumpr just gets whatever is on the F000:000 segment at the time it runs. This presumes that the BIOS at the top of the 4Gbyte address space has a mirror image at that segment, which is not always correct. Most BIOSes run from the top of the 4Gb address space and then dynamically decompress themselves to RAM memory at F000:0000. (aka shadow ROM.)

Frustrated with this I decided to write my own generic BIOS dumper and the results are attached.
It should work on any computer with at least a 386 processor.
The only limitation is that it does not auto detect the BIOS size, which needs to be provided.
(Testing / comments are welcome.)
It runs on DOS (any version above 3) but should also work in FreeDOS (not tested,) in which case it can be placed on a Rufus formatted bootable memory stick and ran from there.

Reply 1 of 6, by zuldan

User metadata
Rank Oldbie
Rank
Oldbie
EduBat wrote on 2026-02-18, 19:52:
I looked around but could not find any practical way to get the BIOSes from my computers into files. The programs I found were e […]
Show full quote

I looked around but could not find any practical way to get the BIOSes from my computers into files.
The programs I found were either too complicated (flashrom) or simple (romdumpr.)
The problem with flashrom is that it needs to be aware of the chipset and tries to get that by querying the PCI bus. A 486 computer without PCI will not work.
On the other hand, romdumpr just gets whatever is on the F000:000 segment at the time it runs. This presumes that the BIOS at the top of the 4Gbyte address space has a mirror image at that segment, which is not always correct. Most BIOSes run from the top of the 4Gb address space and then dynamically decompress themselves to RAM memory at F000:0000. (aka shadow ROM.)

Frustrated with this I decided to write my own generic BIOS dumper and the results are attached.
It should work on any computer with at least a 386 processor.
The only limitation is that it does not auto detect the BIOS size, which needs to be provided.
(Testing / comments are welcome.)
It runs on DOS (any version above 3) but should also work in FreeDOS (not tested,) in which case it can be placed on a Rufus formatted bootable memory stick and ran from there.

Great little utility. Any chance there is an updated version with BIOS size detection?

Reply 2 of 6, by EduBat

User metadata
Rank Member
Rank
Member
zuldan wrote on 2026-04-25, 05:49:
EduBat wrote on 2026-02-18, 19:52:
I looked around but could not find any practical way to get the BIOSes from my computers into files. The programs I found were e […]
Show full quote

I looked around but could not find any practical way to get the BIOSes from my computers into files.
The programs I found were either too complicated (flashrom) or simple (romdumpr.)
The problem with flashrom is that it needs to be aware of the chipset and tries to get that by querying the PCI bus. A 486 computer without PCI will not work.
On the other hand, romdumpr just gets whatever is on the F000:000 segment at the time it runs. This presumes that the BIOS at the top of the 4Gbyte address space has a mirror image at that segment, which is not always correct. Most BIOSes run from the top of the 4Gb address space and then dynamically decompress themselves to RAM memory at F000:0000. (aka shadow ROM.)

Frustrated with this I decided to write my own generic BIOS dumper and the results are attached.
It should work on any computer with at least a 386 processor.
The only limitation is that it does not auto detect the BIOS size, which needs to be provided.
(Testing / comments are welcome.)
It runs on DOS (any version above 3) but should also work in FreeDOS (not tested,) in which case it can be placed on a Rufus formatted bootable memory stick and ran from there.

Great little utility. Any chance there is an updated version with BIOS size detection?

I tried, but I'm unable to come up with way to do it. When you try to read an area of the address space which has nothing assigned to it you get random data, which is indistinguishable from BIOS code, so I gave up for now.

Reply 3 of 6, by zuldan

User metadata
Rank Oldbie
Rank
Oldbie
EduBat wrote on 2026-04-26, 17:53:

I tried, but I'm unable to come up with way to do it. When you try to read an area of the address space which has nothing assigned to it you get random data, which is indistinguishable from BIOS code, so I gave up for now.

NSSI is able to do a BIOS dump without asking for the size. Not sure how it’s doing it.

https://www.navsoft.cz/products.htm

Reply 4 of 6, by zuldan

User metadata
Rank Oldbie
Rank
Oldbie

Maybe this will help

#include <stdio.h>
#include <dos.h>

#define BIOS_SEGMENT 0xF000

int main() {
unsigned char far *bios;
unsigned int size_blocks;
unsigned long size_bytes;

bios = (unsigned char far *)MK_FP(BIOS_SEGMENT, 0x0000);

/* Check signature */
if (bios[0] != 0x55 || bios[1] != 0xAA) {
printf("No valid BIOS signature found at F000:0000\n");
return 1;
}

size_blocks = bios[2]; // size in 512-byte units
size_bytes = (unsigned long)size_blocks * 512;

printf("Detected BIOS size: %lu bytes (%lu KB)\n",
size_bytes, size_bytes / 1024);

return 0;
}

Reply 5 of 6, by zuldan

User metadata
Rank Oldbie
Rank
Oldbie

If you wanted to get more than just the motherboard BIOS

- Scan the upper memory area (0xC0000–0xF0000)
- Detect all option ROMs (video BIOS, network boot ROMs, etc.)
- Detect the system BIOS
- Validate each ROM via checksum
- Dump each ROM to its own file

#include <stdio.h>
#include <dos.h>

#define START_SEG 0xC000
#define END_SEG 0xF000
#define STEP 0x80 /* 2 KB steps (0x80 paragraphs) */

unsigned char far *make_ptr(unsigned int seg) {
return (unsigned char far *)MK_FP(seg, 0x0000);
}

int check_signature(unsigned char far *ptr) {
return (ptr[0] == 0x55 && ptr[1] == 0xAA);
}

int checksum_valid(unsigned char far *ptr, unsigned long size) {
unsigned long i;
unsigned char sum = 0;

for (i = 0; i < size; i++) {
sum += ptr[i];
}

return (sum == 0);
}

void dump_rom(unsigned char far *ptr, unsigned long size, int index) {
char filename[20];
FILE *fp;
unsigned long i;

sprintf(filename, "rom%d.bin", index);

fp = fopen(filename, "wb");
if (!fp) {
printf("Error creating %s\n", filename);
return;
}

for (i = 0; i < size; i++) {
fputc(ptr[i], fp);
}

fclose(fp);

printf(" Dumped to %s\n", filename);
}

int main() {
unsigned int seg;
int rom_index = 0;

printf("Scanning for ROMs...\n");

for (seg = START_SEG; seg <= END_SEG; seg += STEP) {
unsigned char far *ptr = make_ptr(seg);

if (check_signature(ptr)) {
unsigned int size_blocks = ptr[2];
unsigned long size = (unsigned long)size_blocks * 512;
Show last 20 lines

printf("\nROM found at %04X:0000\n", seg);
printf(" Size: %lu bytes (%lu KB)\n", size, size / 1024);

if (checksum_valid(ptr, size)) {
printf(" Checksum: VALID\n");
} else {
printf(" Checksum: INVALID\n");
}

dump_rom(ptr, size, rom_index++);

/* Skip ahead to avoid re-detecting same ROM */
seg += (size / 16) - STEP;
}
}

printf("\nScan complete. %d ROM(s) found.\n", rom_index);
return 0;
}

- Starts at 0xC0000 (where VGA BIOS usually lives)
- Moves in 2 KB increments (standard ROM alignment)
- Looks for the 0x55AA signature
- Reads the size byte
- Verifies checksum (sum of all bytes = 0)
- Dumps each ROM as:
rom0.bin
rom1.bin
etc.

Reply 6 of 6, by EduBat

User metadata
Rank Member
Rank
Member

All processors from the 386 and above start running code 16 bytes below the 4GBytes address so the chipsets need to map the EEPROM(s)/FLASH containing the BIOS to the space just below the 4Gbytes.
Some older chipsets also mirror the last 64Kbytes (or 128Kbytes) before the top of the 4Gbytes onto the last 64Kbytes (or 128Kbytes) of the first megabyte of address space.

What almost all BIOSes do is decompress code&data from the EEPROM/Flash to the RAM at the end of the first 1Megabyte. What we have here is already the result of this decompression stage. They can also decompress "option ROMs" onto the RAM at the space between C000:0000 and E000:0000 if needed.

Programs like romdumpr and NSSI only extract and save these 64Kbytes (or 128Kbytes) "System BIOSes" and "Option ROMS" onto files as we can see in the code you posted. The reason for this is that they are real mode programs running in pure DOS.

BIOSDUMP is a protected mode program running with the 32 bit DPMI DOS extender provided with DJGPP. It is able to see the whole 32bit address space and is able to get the BIOS at the top of the 4Gbytes and save it. It gets the code before any decompression takes place and is exactly what you would get if you took the chip out of the motherboard and read it on an hardware programmer.

Relatively modern BIOSes can be quite big. As examples my Gigabyte GA-7N400 Pro has a BIOS of 512Kbytes and my asus P5Q has a BIOS of 1Mbyte.
On the GA-7N400 Pro depending on whether you want to use the RAID controller or not or the SATA controller or not the BIOS will decompress the respective "option ROMs" to RAM or not.

BIOSDUMP can work on all computers that can run DOS, from a 386SX up to whatever modern computer that still has "legacy BIOS" support (a.k.a. CSM)
I have no way of knowing, a priori, if a computer has a 64K,....512K,.....1M,.....12M....etc BIOS and so far have not been able to find any way to guess it.

Example "modern" PC memory map:

The attachment Screenshot_2026-04-28_17-22-21.png is no longer available

This free book provides a lot more details:
https://github.com/pinczakko/BIOS-Disassembly … jutsu-Uncovered