/* hdtypes.c -- scan BIOS ROM for hard disk table containing cylinder, head, sector, write precompensation and land zone values. Table seems to be at 0xFE400 on most machines, FWIW. Some machines apparently start with a type 2 drive. hence the two signatures to search for. Must be root to open /dev/mem. Note that user type (type 47) values are hidden in CMOS RAM. Also type 15 will nearly always be unused, as type 15 is used as a flag in CMOS byte 0x12 to indicate drive type > 15 which is stored in CMOS 0x19 (and 0x1A for 2nd drive). BUGS: Guaranteed to not find anything on newer systems with a compressed ROM, or without a HD table whatsoever. HD tables are stone age, along with the MFM/RLL drives that they supported. Consider this a stone age program only useful on stone age (386/486) computers. Paul Gortmaker, 08/2000. This code is released under the GPL, blah blah blah... */ #define _GNU_SOURCE /* for memmem */ #include #include #include #include #include #include #include #include #define ROM_SIZE 0xffff #define ROM_OFFSET 0xF0000 #define NR_ENTRIES 47 int main(int argc, char **argv) { /* * Type 1 disk: 0x132 cyl (306), and 4 heads. * Type 2 disk: 0x267 cyl (615), and 4 heads. */ unsigned char type1sig[] = {0x32, 0x01, 0x04}; unsigned char type2sig[] = {0x67, 0x02, 0x04}; size_t sig_len = 3; int i, fd; void *bios_rom, *loc; char *file = "/dev/mem"; off_t offset = ROM_OFFSET; if (argc > 1) { file = argv[1]; offset = 0; } fd = open(file, O_RDONLY); if (fd == -1) { perror("open"); exit(-1); } bios_rom = mmap(0, ROM_SIZE, PROT_READ, MAP_SHARED, fd, offset); if ((long)bios_rom == -1) { perror("memmap"); exit(-1); } /* Check std location 1st before scanning whole ROM. */ loc = memmem(bios_rom+0xe400, ROM_SIZE-0xe400, type1sig, sig_len); if (loc == NULL) loc = memmem(bios_rom, ROM_SIZE, type1sig, sig_len); /* Still nothing? Hrrm. Try type 2... */ if (loc == NULL) { loc = memmem(bios_rom, ROM_SIZE, type2sig, sig_len); if (loc == NULL) { printf("Couldn't find type 1 or type 2 drive in BIOS ROM - giving up\n"); exit(-1); } } fprintf(stderr, "\nDisk table at %#x\n", ROM_OFFSET+loc-bios_rom-1); printf("\n\tType\tCyl.\tHead\tSect.\tWrite\tLand\n\t\t\t\t\tp-comp\tZone\n"); printf("\t--------------------------------------------\n"); for (i=0; i