From 4d022320084eabdc70607643dff9a1822ca92081 Mon Sep 17 00:00:00 2001 From: hpa Date: Fri, 14 Dec 2001 22:41:55 +0000 Subject: [PATCH] Be even more anal... --- memdisk/memdisk.asm | 112 +++++++++++++++++++++++++++++++++++++++++++--------- memdisk/setup.c | 66 ++++++++++++++++++++++++++++++- 2 files changed, 159 insertions(+), 19 deletions(-) diff --git a/memdisk/memdisk.asm b/memdisk/memdisk.asm index 9bc453d..610af31 100644 --- a/memdisk/memdisk.asm +++ b/memdisk/memdisk.asm @@ -17,6 +17,22 @@ ; ; **************************************************************************** +%define DEBUG_TRACERS ; Uncomment to get debugging tracers + +%ifdef DEBUG_TRACERS + +%macro TRACER 1 + call debug_tracer + db %1 +%endmacro + +%else ; DEBUG_TRACERS + +%macro TRACER 1 +%endmacro + +%endif ; DEBUG_TRACERS + org 0h %define SECTORSIZE_LG2 9 ; log2(sector size) @@ -64,6 +80,8 @@ Int13Start: pop dx js .nomatch ; If SF=0, we have a class match here jz .our_drive ; If ZF=1, we have an exact match + cmp ah,08h ; Is it Get Drive Parameters? + je .our_drive ; If so always handle for our own class cmp dl,[cs:DriveNo] jb .nomatch ; Drive < Our drive dec dl ; Drive > Our drive, adjust drive # @@ -85,9 +103,10 @@ Int13Start: mov ax,[SavedAX] pushad mov bp,sp ; Point BP to the entry stack frame + TRACER 'F' ; Note: AH == P_AH here cmp ah,Int13FuncsMax - jae Invalid + jae Invalid_jump xor al,al ; AL = 0 is standard entry condition mov di,ax shr di,7 ; Convert AH to an offset in DI @@ -96,6 +115,7 @@ Int13Start: Done: ; Standard routine for return mov P_AX,ax DoneWeird: + TRACER 'D' mov [LastStatus],ah and ah,ah @@ -112,6 +132,7 @@ DoneWeird: Reset: ; Reset affects multiple drives, so we need to pass it on + TRACER 'R' mov [LastStatus],al ; Clear the status (AL = 0) pop ax ; Drop return address popad ; Restore all registers @@ -121,9 +142,13 @@ Reset: and dl,80h ; Clear all but the type bit jmp far [cs:OldInt13] + Invalid: - mov ax,0100h ; Unsupported function - ret + pop dx ; Drop return address +Invalid_jump: + TRACER 'I' + mov ah,01h ; Unsupported function + jmp short Done GetDriveType: mov ah,[DriveNo] @@ -176,28 +201,61 @@ success: ret GetParms: - ; We need to get the "number of drives" from the BIOS - mov dl,P_DL - inc dl ; The drive whose number we're stealing - mov ah,08h - int 13h - inc dl ; Add ourselves to the count - mov P_DL,dl ; Drive count - mov P_DI,di ; Steal the diskette parameter table if applicable - mov ax,es + ; This gets invoked even for other drives, so that + ; we can modify the drive count on return + TRACER 'G' + mov dx,P_DX ; The drive whose number we're stealing + cmp dl,[DriveNo] + jb .belowdrive + ja .abovedrive + TRACER 'M' + mov dl,[DriveCnt] ; Cached data + mov P_DL,dl + test byte [DriveNo],80h + jnz .hd + mov di,[BPT] + mov P_DI,di + mov ax,[BPT+2] mov P_ES,ax mov bl,[DriveType] mov P_BL,bl +.hd: mov ax,[Cylinders] dec ax ; We report the highest #, not the count - or ah,[Sectors] xchg al,ah + shl al,6 + or al,[Sectors] mov P_CX,ax - mov al,[Heads] - dec al + mov ax,[Heads] + dec ax mov P_DH,al xor ax,ax ret + + ; If another disk, just mangle DL on return +.abovedrive: + TRACER 'A' + dec dl ; Adjust drive # to what the BIOS believes +.belowdrive: + TRACER 'B' + mov di,P_DI + mov ax,P_ES + mov es,ax + mov bx,P_BX + mov cx,P_CX + mov ax,P_AX + pushf + call far [OldInt13] + inc dl ; Add ourselves to the count + mov P_AX,ax + mov P_BX,bx + mov P_CX,cx + mov P_DX,dx + mov P_DI,di + mov cx,es + mov P_ES,cx + TRACER 'R' + ret ; Set up registers as for a "Read", and compares against disk size setup_regs: @@ -239,8 +297,8 @@ setup_regs: ret .overrun: pop ax ; Drop setup_regs return address - mov ax,0400h ; Sector not found - ret + mov ax,0200h ; Missing address mark + ret ; Return to Done int15_e820: cmp edx,534D4150h ; "SMAP" @@ -372,8 +430,23 @@ bcopy: pop eax ret +%ifdef DEBUG_TRACERS +debug_tracer: pushad + pushfd + mov bp,sp + mov bx,[bp+9*4] + mov al,[cs:bx] + inc word [bp+9*4] + mov ah,0Eh + mov bx,7 + int 10h + popfd + popad + ret +%endif + section .data - alignb 8 + alignb 2 Int13Funcs dw Reset ; 00h - RESET dw GetStatus ; 01h - GET STATUS dw Read ; 02h - READ @@ -434,6 +507,9 @@ OldDosMem dw 0 ; Old position of DOS mem end DriveNo db 0 ; Our drive number DriveType db 0 ; Our drive type (floppies) +DriveCnt db 0 ; Drive count (from the BIOS) + db 0 ; Pad +BPT dd 0 ; BIOS parameter table pointer (floppies) MyStack dw 0 ; Offset of stack diff --git a/memdisk/setup.c b/memdisk/setup.c index 530dc0c..eff2d47 100644 --- a/memdisk/setup.c +++ b/memdisk/setup.c @@ -45,10 +45,23 @@ struct patch_area { uint8_t driveno; uint8_t drivetype; + uint8_t drivecnt; + uint8_t _pad1; + + uint16_t bpt_offs, bpt_seg; uint16_t mystack; }; +/* The Disk Parameter Table is required on hard disks */ +struct dpt { + uint16_t max_cyl; /* Max cylinder */ + uint8_t max_head; /* Max head */ + uint8_t junk1[5]; /* Obsolete junk, leave at zero */ + uint8_t ctrl; /* Control byte */ + uint8_t junk2[7]; /* More obsolete junk */ +}; + /* This is the header in the boot sector/setup area */ struct setup_header { char cmdline[0x1f1]; @@ -183,8 +196,12 @@ rdz_32(uint32_t addr) /* Addresses in the zero page */ #define BIOS_INT13 (0x13*4) /* INT 13h vector */ -#define BIOS_INT15 (0x15*4) /* INT 13h vector */ +#define BIOS_INT15 (0x15*4) /* INT 15h vector */ +#define BIOS_INT41 (0x41*4) /* INT 41h vector */ +#define BIOS_INT46 (0x46*4) /* INT 46h vector */ #define BIOS_BASEMEM 0x413 /* Amount of DOS memory */ +#define BIOS_EQUIP 0x410 /* BIOS equipment list */ +#define BIOS_HD_COUNT 0x475 /* Number of hard drives present */ /* * Routine to seek for a command-line item and return a pointer @@ -514,6 +531,34 @@ uint32_t setup(void) "D" (0) : "esi", "edi", "ecx"); + /* Query drive parameters of this type */ + { + uint16_t bpt_es, bpt_di; + uint8_t cf, dl; + + asm volatile("pushw %%es ; " + "xorw %1,%1 ; " + "movw %1,%%es ; " + "movb $0x08,%%ah ; " + "int $0x13 ; " + "setc %2 ; " + "movw %%es,%0 ;" + "popw %%es" + : "=a" (bpt_es), "=D" (bpt_di), + "=c" (cf), "=d" (dl) + : "d" (geometry->driveno & 0x80) + : "esi", "ebx", "ebp"); + + if ( cf ) { + pptr->drivecnt = 1; + pptr->bpt_offs = pptr->bpt_seg = 0; + } else { + pptr->drivecnt = dl+1; + pptr->bpt_offs = bpt_di; + pptr->bpt_seg = bpt_es; + } + } + /* Install the interrupt handlers */ printf("old: int13 = %08x int15 = %08x\n", rdz_32(BIOS_INT13), rdz_32(BIOS_INT15)); @@ -524,6 +569,25 @@ uint32_t setup(void) printf("new: int13 = %08x int15 = %08x\n", rdz_32(BIOS_INT13), rdz_32(BIOS_INT15)); + /* Update various BIOS magic data areas (gotta love this shit) */ + + if ( geometry->driveno & 0x80 ) { + /* Update BIOS hard disk count */ + wrz_8(BIOS_HD_COUNT, rdz_8(BIOS_HD_COUNT)+1); + } else { + /* Update BIOS floppy disk count */ + uint16_t equip = rdz_16(BIOS_EQUIP); + if ( equip & 1 ) { + if ( (equip & (3 << 6)) != (3 << 6) ) { + equip += (1 << 6); + } + } else { + equip |= 1; + equip &= ~(3 << 6); + } + wrz_16(BIOS_EQUIP, equip); + } + /* Reboot into the new "disk" */ asm volatile("pushw %%es ; " "xorw %%cx,%%cx ; " -- 2.7.4