diff --git a/tests/absread/absread.c b/tests/absread/absread.c new file mode 100644 index 0000000..ec9ef0e --- /dev/null +++ b/tests/absread/absread.c @@ -0,0 +1,208 @@ +#include +#include +#include + +typedef unsigned long uint32_t; +typedef unsigned short uint16_t; +typedef unsigned char uint8_t; + +void die(char *msg) +{ + printf("%s\n", msg); + exit(1); +} + +/* Both traditional DOS and FAT32 DOS return this structure, but + FAT32 return a lot more data, so make sure we have plenty of space */ +struct deviceparams { + uint8_t specfunc; + uint8_t devtype; + uint16_t devattr; + uint16_t cylinders; + uint8_t mediatype; + uint16_t bytespersec; + uint8_t secperclust; + uint16_t ressectors; + uint8_t fats; + uint16_t rootdirents; + uint16_t sectors; + uint8_t media; + uint16_t fatsecs; + uint16_t secpertrack; + uint16_t heads; + uint32_t hiddensecs; + uint32_t hugesectors; + uint8_t lotsofpadding[224]; +}; + +void get_partition_offset(int drive) +{ + static struct deviceparams dp; + int err=0; + + printf("Getting drive info: int21h function 440Dh subfunction 0860h\n"); + + dp.specfunc = 1; /* Get current information */ + + __asm { + mov ax, 0x440d + mov bx, drive + mov cx, 0x0860 + mov dx, offset dp + int 0x21 + mov ax, 0 + adc ax, 0 + mov err, ax + } + + if (!err) + { + printf("Partition Offset = %02lXh [c=%02u,h=%02u,s=%2u]\n", dp.hiddensecs, dp.cylinders, dp.heads, dp.secpertrack); + printf("FAT32 version 4860h to compare\n"); + } + else + printf("Original version failed, checking FAT32 version using 4860h\n"); + + __asm { + mov ax, 0x440d + mov bx, drive + mov cx, 0x4860 + mov dx, offset dp + int 0x21 + mov ax, 0 + adc ax, 0 + mov err, ax + } + + if (!err) + { + printf("Partition Offset = %02lXh\n", dp.hiddensecs); + return; + } + else + printf("FAT32 version failed.\n"); +} + +struct rwblock { + uint8_t special; + uint16_t head; + uint16_t cylinder; + uint16_t firstsector; + uint16_t sectors; + uint16_t bufferoffset; + uint16_t bufferseg; +}; + +static struct rwblock mbr = { + .special = 0, + .head = 0, + .cylinder = 0, /* 5265, 3fh */ + .firstsector = 0, /* MS-DOS, unlike the BIOS, zero-base sectors */ + .sectors = 1, + .bufferoffset = 0, + .bufferseg = 0 +}; + + +void read_mbr(int drive, const void *buf) +{ + uint8_t err=0; + uint16_t ds_seg=0; + + //printf("read_mbr(%c:,%p)", 'a'+drive-1, buf); + + mbr.bufferoffset = (unsigned short)buf; + __asm { + push ds + pop ax + mov ds_seg, ax + } + mbr.bufferseg = ds_seg; + //printf("DS = %04Xh\n", ds_seg); + + __asm { + mov ax, 0x440d + mov bx, drive + mov cx, 0x0861 + mov dx, offset mbr + int 0x21 + mov ax, 0 + adc ax, 0 + mov err, al + } + + if (!err) { + //printf("Success reading MBR\n\n"); + return; + } + + __asm { + mov ax, 0x440d + mov bx, drive + mov cx, 0x4861 + mov dx, offset mbr + int 0x21 + mov ax, 0 + adc ax, 0 + mov err, al + } + + if (!err) { + //printf("Success reading FAT32 MBR\n\n"); + return; + } + + printf("mbr read error"); +} + +int main(int argc, char *argv[]) +{ + unsigned int c,h,s; + static uint8_t buf[1024]; + unsigned drive = (unsigned)(argv[1][0]); /* a=1,b=2,... */ + drive = drive-'a'+1; + printf("Query drive %c:\n", 'a'+drive-1); + + get_partition_offset(drive); + + read_mbr(drive, buf); + printf("MBR: %02Xh %02Xh %02Xh %02Xh %02Xh %02Xh %02Xh %02Xh\n", + ((const uint8_t *)buf)[0], + ((const uint8_t *)buf)[1], + ((const uint8_t *)buf)[2], + ((const uint8_t *)buf)[3], + ((const uint8_t *)buf)[4], + ((const uint8_t *)buf)[5], + ((const uint8_t *)buf)[6], + ((const uint8_t *)buf)[7]); + + printf("Finding drive\n"); + for (c = 1024; c <= 5265; c++) { + for (h = 0; h < 255; h++) + for (s = 0; s <= 63; s++) + { + mbr.cylinder = c; + mbr.head =h; + mbr.sectors=s; + read_mbr(drive, buf); + if (buf[0] != 0) { + printf("Found at %u,%u,%u\n", c,h,s); + + printf("MBR: %02Xh %02Xh %02Xh %02Xh %02Xh %02Xh %02Xh %02Xh\n", + ((const uint8_t *)buf)[0], + ((const uint8_t *)buf)[1], + ((const uint8_t *)buf)[2], + ((const uint8_t *)buf)[3], + ((const uint8_t *)buf)[4], + ((const uint8_t *)buf)[5], + ((const uint8_t *)buf)[6], + ((const uint8_t *)buf)[7]); + + exit(0); + } + } + printf("c=%u,", c); fflush(NULL); + } + + return 0; +} diff --git a/tests/absread/build.bat b/tests/absread/build.bat new file mode 100644 index 0000000..3c643e6 --- /dev/null +++ b/tests/absread/build.bat @@ -0,0 +1,2 @@ +@ECHO OFF +wcl -e3-we-wx-zq-os-s-zp1-mt-bt=DOS absread.c