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 10, 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 10, 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 10, 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 10, 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 10, 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 10, 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

Reply 7 of 10, by EduBat

User metadata
Rank Member
Rank
Member

Apparently the SMBIOS specification https://en.wikipedia.org/wiki/System_Management_BIOS defines a field in the BIOS structure that indicates the size of the BIOS itself. The main problem is that these specs only became a thing around 1999 or so. I'm not sure if there is interest in developing an automation that will only work on computers from this era onward or if it's ok to leave the program as is. Feedback and/or ideas are welcome.

The attachment Screenshot_2026-08-03_12-18-42.png is no longer available

Reply 8 of 10, by Tiido

User metadata
Rank l33t
Rank
l33t

Dumping the F0000...FFFFF range is fine for many 486 and older things but at some point during 486 era, the BIOSes started to decompress + shadow themselves and in the process what you read there will not match what is actually on the BIOS chip, and burning such an image on a BIOS chip will not work either. This is why FLASHROM and UNIFLASH are chipset aware, so that it can actually dump the actual chip rather than what is shadowed into memory.

T-04YBSC, a new YMF71x based sound card & Official VOGONS thread about it
Newly made 4MB 60ns 30pin SIMMs ~
mida sa loed ? nagunii aru ei saa 😜

Reply 9 of 10, by EduBat

User metadata
Rank Member
Rank
Member
Tiido wrote on Today, 14:12:

Dumping the F0000...FFFFF range is fine for many 486 and older things but at some point during 486 era, the BIOSes started to decompress + shadow themselves and in the process what you read there will not match what is actually on the BIOS chip, and burning such an image on a BIOS chip will not work either. This is why FLASHROM and UNIFLASH are chipset aware, so that it can actually dump the actual chip rather than what is shadowed into memory.

Correct. That is why my program gets the top "n" Kbytes from the 32 bit address space. (Where "n" is the input parameter to the program.)
So, as an example, instead of dumping the 000F0000...000FFFFF range, it gets the FFFF0000...FFFFFFFF range. (For a 64Kbyte chip.)
I understand my program may not work all the time, particularly on more modern computers with partitioned flash chips which need a program like FLASHROM or UNIFLASH, but it's a reasonable compromise.

Reply 10 of 10, by Harry Potter

User metadata
Rank Oldbie
Rank
Oldbie

Try scanning down from the top of memory until you get all 0's or 255's. That should be the beginning of the ROM.

Joseph Rose, a.k.a. Harry Potter
Working magic in the computer community