diff options
Diffstat (limited to 'contrib/syslinux-4.02/memdisk/memdisk.inc')
-rw-r--r-- | contrib/syslinux-4.02/memdisk/memdisk.inc | 1189 |
1 files changed, 1189 insertions, 0 deletions
diff --git a/contrib/syslinux-4.02/memdisk/memdisk.inc b/contrib/syslinux-4.02/memdisk/memdisk.inc new file mode 100644 index 0000000..91040ba --- /dev/null +++ b/contrib/syslinux-4.02/memdisk/memdisk.inc @@ -0,0 +1,1189 @@ +; -*- fundamental -*- (asm-mode sucks) +; **************************************************************************** +; +; memdisk.inc +; +; A program to emulate an INT 13h disk BIOS from a "disk" in extended +; memory. +; +; Copyright 2001-2009 H. Peter Anvin - All Rights Reserved +; Copyright 2009 Intel Corporation; author: H. Peter Anvin +; Portions copyright 2009 Shao Miller [El Torito code, mBFT, safe hook] +; +; This program is free software; you can redistribute it and/or modify +; it under the terms of the GNU General Public License as published by +; the Free Software Foundation, Inc., 53 Temple Place Ste 330, +; Boston MA 02111-1307, USA; either version 2 of the License, or +; (at your option) any later version; incorporated herein by reference. +; +; **************************************************************************** + +%include "../version.gen" + +; %define DEBUG_TRACERS ; Uncomment to get debugging tracers + +%ifdef DEBUG_TRACERS + +%macro TRACER 1 + call debug_tracer + db %1 +%endmacro +%macro WRITEHEX2 0-1 al +%ifnidni %1,al + push ax + mov al,%1 + call writehex2 + pop ax +%else + call writehex2 +%endif +%endmacro +%macro WRITEHEX4 0-1 ax +%ifnidni %1,ax + push ax + mov ax,%1 + call writehex4 + pop ax +%else + call writehex4 +%endif +%endmacro +%macro WRITEHEX8 0-1 eax +%ifnidni %1,eax + push eax + mov eax,%1 + call writehex8 + pop eax +%else + call writehex8 +%endif +%endmacro + +%else ; DEBUG_TRACERS + +%macro TRACER 1 +%endmacro +%macro WRITEHEX2 0-1 +%endmacro +%macro WRITEHEX4 0-1 +%endmacro +%macro WRITEHEX8 0-1 +%endmacro + +%endif ; DEBUG_TRACERS + +; Flags we test our configuration against +%define CONFIG_READONLY 0x01 +%define CONFIG_RAW 0x02 +%define CONFIG_SAFEINT 0x04 +%define CONFIG_BIGRAW 0x08 ; MUST be 8! + + org 0h + +%define SECTORSIZE (1 << SECTORSIZE_LG2) + + ; Parameter registers definition; this is the definition + ; of the stack frame. +%define P_DS word [bp+34] +%define P_ES word [bp+32] +%define P_EAX dword [bp+28] +%define P_HAX word [bp+30] +%define P_AX word [bp+28] +%define P_AL byte [bp+28] +%define P_AH byte [bp+29] +%define P_ECX dword [bp+24] +%define P_HCX word [bp+26] +%define P_CX word [bp+24] +%define P_CL byte [bp+24] +%define P_CH byte [bp+25] +%define P_EDX dword [bp+20] +%define P_HDX word [bp+22] +%define P_DX word [bp+20] +%define P_DL byte [bp+20] +%define P_DH byte [bp+21] +%define P_EBX dword [bp+16] +%define P_HBX word [bp+18] +%define P_HBXL byte [bp+18] +%define P_BX word [bp+16] +%define P_BL byte [bp+16] +%define P_BH byte [bp+17] +%define P_EBP dword [bp+8] +%define P_BP word [bp+8] +%define P_ESI dword [bp+4] +%define P_SI word [bp+4] +%define P_EDI dword [bp] +%define P_DI word [bp] + + section .text + ; These pointers are used by the installer and + ; must be first in the binary +Pointers: dw Int13Start + dw Int15Start + dw MemDisk_Info ; Portions are patched by installer + dw TotalSize + dw IretPtr + +IretPtr equ Int13Start.iret +Int13Start: + jmp strict near .SafeHookEnd ; 3-byte jump + db '$INT13SF' ; Signature for "safe hook" + db 'MEMDISK ' ; Vendor ID + dd 0 ; SEG:OFF of previous INT 13h hook + ; Must be filled in by installer + dd 0 ; "Safe hook" flags +; ---- "Safe hook" structure ends here --- + +; This next field should be guaranteed at this position after the +; "safe hook" structure. This allows for a MEMDISK OS driver to +; immediately find out the particular parameters using the mBFT +; and MDI structures. This binary will have the offset to the mBFT +; in this field to begin with, so the installer knows where the mBFT +; is. This is akin to the "Pointers" section above. The installer +; will refill this field with the physical address of the mBFT for +; future consumers, such as OS drivers. + dd mBFT ; Offset from hook to the mBFT + +.SafeHookEnd: + cmp word [cs:Recursive],0 + jne recursive + + ; Swap stack + mov [cs:Stack],esp + mov [cs:Stack+4],ss + mov [cs:SavedAX],ax + mov ax,cs + mov ss,ax + mov sp,[cs:MyStack] + +%if ELTORITO + cmp word [cs:SavedAX],4a00h ; El Torito function? + jae our_drive ; We grab it +%endif + ; See if DL points to our class of device (FD, HD) + push dx + push dx + xor dl,[cs:DriveNo] + pop dx + js .nomatch ; If SF=0, we have a class match here + ; 0x00 the sign bit for FD + ; 0x80 the sign bit for HD + jz our_drive ; If ZF=1, we have an exact match + cmp dl,[cs:DriveNo] + jb .nomatch ; Drive < Our drive + cmp dl,[cs:DriveShiftLimit] + jae .nomatch ; Drive > The maximum drive + ; number that we will shift for. + ; This leaves any higher-up BIOS + ; drives alone, such as an optical + ; disc drive 0xA0 or 0xE0 + dec dl ; Drive > Our drive, adjust drive # +.nomatch: + TRACER '!' + WRITEHEX2 dl + TRACER ',' + mov ax,[cs:SavedAX] + WRITEHEX4 + inc word [cs:Recursive] + pushf + call far [cs:OldInt13] + pushf + dec word [cs:Recursive] + push bp + mov bp,sp + cmp byte [cs:SavedAX+1],08h ; Get drive params function? + je .norestoredl ; DL = number of drives + cmp byte [cs:SavedAX+1],15h ; Get disk type function? + jne .restoredl + test byte [bp+4],80h ; Hard disk? + jnz .norestoredl ; CX:DX = size of device +.restoredl: + mov dl,[bp+4] +.norestoredl: + push ax + push ebx + push ds + mov ax,[bp+2] ; Flags + lds ebx,[cs:Stack] + mov [bx+4],al ; Arithmetic flags + pop ds + pop ebx + pop ax + pop bp + lss esp,[cs:Stack] +.iret: iret + +recursive: + TRACER '@' +jmp_oldint13: + jmp far [cs:OldInt13] + +our_drive: + ; Set up standard entry frame + push ds + push es + mov ds,ax + mov es,ax + mov ax,[SavedAX] + pushad + mov bp,sp ; Point BP to the entry stack frame + TRACER 'F' + WRITEHEX4 + ; Note: AX == P_AX here + cmp ah,Int13FuncsCnt-1 + ja Invalid_jump +%if ELTORITO + mov al,[CD_PKT.type] ; Check if we are in + cmp al,0 ; El Torito no emulation mode + ja .emulation ; No. We support the function + cmp ah,3fh ; Yes. We must not support functions + jbe Invalid_jump ; 0 through 3Fh. Check and decide +.emulation: +%endif + xor al,al ; AL = 0 is standard entry condition + mov di,ax + shr di,7 ; Convert AH to an offset in DI + call [Int13Funcs+di] + +Done: ; Standard routine for return + mov P_AX,ax +DoneWeird: + TRACER 'D' + xor bx,bx + mov es,bx + mov bx,[StatusPtr] + mov [es:bx],ah ; Save status + and ah,ah + + lds ebx,[Stack] + ; This sets the low byte (the arithmetic flags) of the + ; FLAGS on stack to either 00h (no flags) or 01h (CF) + ; depending on if AH was zero or not. + setnz [bx+4] ; Set CF iff error + popad + pop es + pop ds + lss esp,[cs:Stack] + iret + +Reset: + ; Reset affects multiple drives, so we need to pass it on + TRACER 'R' + xor ax,ax ; Bottom of memory + mov es,ax + test dl,dl ; Always pass it on if we are + ; resetting HD + js .hard_disk ; Bit 7 set + ; Some BIOSes get very unhappy if we pass a reset floppy + ; command to them and don't actually have any floppies. + ; This is a bug, but we have to deal with it nontheless. + ; Therefore, if we are the *ONLY* floppy drive, and the + ; user didn't request HD reset, then just drop the command. + ; BIOS equipment byte, top two bits + 1 == total # of floppies + test byte [es:0x410],0C0h + jz success + jmp .pass_on ; ... otherwise pass it to the BIOS +.hard_disk: + ; ... same thing for hard disks, sigh ... + cmp byte [es:0x475],1 ; BIOS variable for number of hard + ; disks + jbe success + +.pass_on: + pop ax ; Drop return address + popad ; Restore all registers + pop es + pop ds + lss esp,[cs:Stack] ; Restore the stack + and dl,80h ; Clear all but the type bit + jmp jmp_oldint13 + + +Invalid: + pop dx ; Drop return address +Invalid_jump: + TRACER 'I' + mov ah,01h ; Unsupported function + jmp short Done + +GetDriveType: + test byte [DriveNo],80h + mov bl,02h ; Type 02h = floppy with changeline + jz .floppy + ; Hard disks only! DO NOT set CX:DX for floppies... + ; it apparently causes Win98SE DOS to go into an loop + ; resetting the drive over and over. Sigh. + inc bx ; Type = 03h + mov dx,[DiskSize] ; Return the disk size in sectors + mov P_DX,dx + mov cx,[DiskSize+2] + mov P_CX,cx +.floppy: + mov P_AH,bl ; 02h floppy, 03h hard disk + pop ax ; Drop return address + xor ax,ax ; Success... + jmp DoneWeird ; But don't stick it into P_AX + +GetStatus: + xor ax,ax + mov es,ax + mov bx,[StatusPtr] + mov ah,[bx] ; Copy last status + ret + +ReadMult: + TRACER 'm' +Read: + TRACER 'R' + call setup_regs +do_copy: + TRACER '<' + call bcopy + TRACER '>' + movzx ax,P_AL ; AH = 0, AL = transfer count + ret + +WriteMult: + TRACER 'M' +Write: + TRACER 'W' + test byte [ConfigFlags],CONFIG_READONLY + jnz .readonly + call setup_regs + xchg esi,edi ; Opposite direction of a Read! + jmp short do_copy +.readonly: mov ah,03h ; Write protected medium + ret + + ; Verify integrity; just bounds-check +Seek: +Verify: + call setup_regs ; Returns error if appropriate + ; And fall through to success + +CheckIfReady: ; These are always-successful noop functions +Recalibrate: +InitWithParms: +DetectChange: +EDDDetectChange: +EDDLock: +SetMode: +success: + xor ax,ax ; Always successful + ret + +GetParms: + TRACER 'G' + mov dl,[DriveCnt] ; Cached data + mov P_DL,dl + test byte [DriveNo],80h + jnz .hd + mov P_DI,DPT + mov P_ES,cs + mov bl,[DriveType] + mov P_BL,bl +.hd: + mov ax,[Cylinders] + dec ax ; We report the highest #, not the count + xchg al,ah + shl al,6 + or al,[Sectors] + mov P_CX,ax + mov ax,[Heads] + dec ax + mov P_DH,al + + ; + ; Is this MEMDISK installation check? + ; + cmp P_HAX,'ME' + jne .notic + cmp P_HCX,'MD' + jne .notic + cmp P_HDX,'IS' + jne .notic + cmp P_HBX,'K?' + jne .notic + + ; MEMDISK installation check... + mov P_HAX,'!M' + mov P_HCX,'EM' + mov P_HDX,'DI' + mov P_HBX,'SK' + mov P_ES,cs + mov P_DI,MemDisk_Info + +.notic: + xor ax,ax + ret +; +; EDD functions -- only if enabled +; +%if EDD +EDDPresence: + TRACER 'E' + TRACER 'c' + + cmp P_BX,55AAh + jne Invalid + mov P_BX,0AA55h ; EDD signature + mov P_AX,03000h ; EDD 3.0 + mov P_CX,0007h ; Bit 0 - Fixed disk access subset + ; Bit 1 - Locking and ejecting subset + ; Bit 2 - EDD subset + pop ax ; Drop return address + xor ax,ax ; Success + jmp DoneWeird ; Success, but AH != 0, sigh... + +EDDRead: + TRACER 'E' + TRACER 'r' + + call edd_setup_regs + call bcopy + xor ax,ax + ret + +EDDWrite: + TRACER 'E' + TRACER 'w' + + call edd_setup_regs + xchg esi,edi ; Opposite direction of a Read! + call bcopy + xor ax,ax + ret + +EDDVerify: +EDDSeek: + call edd_setup_regs ; Just bounds checking + xor ax,ax + ret + +EDDGetParms: + TRACER 'E' + TRACER 'p' + + mov es,P_DS + mov di,P_SI + mov si,EDD_DPT + + lodsw ; Length of our DPT + mov cx,[es:di] + cmp cx,26 ; Minimum size + jb .overrun + + cmp cx,ax + jb .oksize + mov cx,ax + +.oksize: + mov ax,cx + stosw + dec cx + dec cx + rep movsb + + xor ax,ax + ret + +.overrun: + mov ax,0100h + ret +%endif ; EDD + + ; Set up registers as for a "Read", and compares against disk + ; size. + ; WARNING: This fails immediately, even if we can transfer some + ; sectors. This isn't really the correct behaviour. +setup_regs: + + ; Convert a CHS address in P_CX/P_DH into an LBA in eax + ; CH = cyl[7:0] + ; CL[0:5] = sector (1-based) CL[7:6] = cyl[9:8] + ; DH = head + movzx ecx,P_CX + movzx ebx,cl ; Sector number + and bl,3Fh + dec ebx ; Sector number is 1-based + cmp bx,[Sectors] + jae .overrun + movzx edi,P_DH ; Head number + movzx eax,word [Heads] + cmp di,ax + jae .overrun + shr cl,6 + xchg cl,ch ; Now (E)CX <- cylinder number + mul ecx ; eax <- Heads*cyl# (edx <- 0) + add eax,edi + mul dword [Sectors] + add eax,ebx + ; Now eax = LBA, edx = 0 + + ; + ; setup_regs continues... + ; + ; Note: edi[31:16] and ecx[31:16] = 0 already + mov di,P_BX ; Get linear address of target buffer + mov cx,P_ES + shl ecx,4 + add edi,ecx ; EDI = address to fetch to + movzx ecx,P_AL ; Sector count + mov esi,eax + add eax,ecx ; LBA of final sector + 1 + shl esi,SECTORSIZE_LG2 ; LBA -> byte offset + add esi,[DiskBuf] ; Get address in high memory + cmp eax,[DiskSize] ; Check the high mark against limit + ja .overrun + shl ecx,SECTORSIZE_LG2-2 ; Convert count to dwords + ret + +.overrun: pop ax ; Drop setup_regs return address + mov ax,0200h ; Missing address mark + ret ; Return to Done + + ; Set up registers as for an EDD Read, and compares against disk size. +%if EDD +edd_setup_regs: + push es + mov si,P_SI ; DS:SI -> DAPA + mov es,P_DS + + mov dx,[es:si] + cmp dx,16 + jb .baddapa + + cmp dword [es:si+4],-1 + je .linear_address + + movzx ebx,word [es:si+4] ; Offset + movzx edi,word [es:si+6] ; Segment + shl edi,4 + add ebx,edi + jmp .got_address + +.linear_address: + cmp dx,24 ; Must be large enough to hold + ; linear address + jb .baddapa + + cmp dword [es:si+20],0 ; > 4 GB addresses not supported + mov ax,0900h ; "Data boundary error" - bogus, but + ; no really better code available + jne .error + + mov ebx,[es:si+16] + +.got_address: + cmp dword [es:si+12],0 ; LBA too large? + jne .overrun + + movzx ecx, word [es:si+2] ; Sectors to transfer + mov esi,[es:si+8] ; Starting sector + mov eax,esi + add eax,ecx + jc .overrun + cmp eax,[DiskSize] + ja .overrun + + shl ecx,SECTORSIZE_LG2-2 ; Convert to dwords + shl esi,SECTORSIZE_LG2 ; Convert to an offset + add esi,[DiskBuf] + mov edi,ebx + pop es + ret + +.baddapa: + mov ax,0100h ; Invalid command + pop es + pop ax ; Drop setup_regs return address + ret + +.overrun: + mov ax,0200h ; "Address mark not found" = + ; LBA beyond end of disk +.error: + and word [es:si+2],0 ; No sectors transferred + pop es + pop ax + ret + +EDDEject: + mov ax,0B200h ; Volume Not Removable + ret +%if ELTORITO +ElToritoTerminate: + TRACER 'T' + mov ax,[cs:SavedAX] + cmp al,1 ; We only support query, not terminate + jne ElToritoErr ; Fail + cmp dl,7fh ; Terminate all? + je .doit + cmp dl,[cs:DriveNo] ; Terminate our drive? + je .doit + jmp ElToritoErr ; Fail +.doit: mov es,P_DS ; Caller's DS:SI pointed to packet + mov di,P_SI ; We'll use ES:DI + mov si,CD_PKT.size ; First byte is packet size + xor cx,0 ; Empty our count + ;mov cl,[ds:si] ; We'll copy that many bytes + mov cl,13h + rep movsb ; Copy until CX is zero + mov ax,0 ; Success + ret +ElToritoEmulate: +ElToritoBoot: +ElToritoCatalog: +ElToritoErr: + TRACER '!' + mov ax,100h ; Invalid parameter + ret +%endif ; ELTORITO +%endif ; EDD + +; +; INT 15h intercept routines +; +int15_e820: + cmp edx,534D4150h ; "SMAP" + jne oldint15 + cmp ecx,20 ; Need 20 bytes + jb err86 + push ds + push cs + pop ds + push edx ; "SMAP" + and ebx,ebx + jne .renew + mov ebx,E820Table +.renew: + add bx,12 ; Advance to next + mov eax,[bx-4] ; Type + and eax,eax ; Null type? + jz .renew ; If so advance to next + mov [es:di+16],eax + mov eax,[bx-12] ; Start addr (low) + mov edx,[bx-8] ; Start addr (high) + mov [es:di],eax + mov [es:di+4],edx + mov eax,[bx] ; End addr (low) + mov edx,[bx+4] ; End addr (high) + sub eax,[bx-12] ; Derive the length + sbb edx,[bx-8] + mov [es:di+8],eax ; Length (low) + mov [es:di+12],edx ; Length (high) + cmp dword [bx+8],-1 ; Type of next = end? + jne .notdone + xor ebx,ebx ; Done with table +.notdone: + pop eax ; "SMAP" + mov edx,eax ; Some systems expect eax = edx = SMAP + mov ecx,20 ; Bytes loaded + pop ds +int15_success: + mov byte [bp+6], 02h ; Clear CF + pop bp + iret + +err86: + mov byte [bp+6], 03h ; Set CF + mov ah,86h + pop bp + iret + +Int15Start: + push bp + mov bp,sp + cmp ax,0E820h + je near int15_e820 + cmp ax,0E801h + je int15_e801 + cmp ax,0E881h + je int15_e881 + cmp ah,88h + je int15_88 +oldint15: pop bp + jmp far [cs:OldInt15] + +int15_e801: ; Get mem size for > 64 MB config + mov ax,[cs:Mem1MB] + mov cx,ax + mov bx,[cs:Mem16MB] + mov dx,bx + jmp short int15_success + +int15_e881: ; Get mem size for > 64 MB config + ; 32-bit code + mov eax,[cs:Mem1MB] + mov ecx,eax + mov ebx,[cs:Mem16MB] + mov edx,ebx + jmp short int15_success + +int15_88: ; Get extended mem size + mov ax,[cs:MemInt1588] + jmp short int15_success + +; +; Routine to copy in/out of high memory +; esi = linear source address +; edi = linear target address +; ecx = 32-bit word count +; +; Assumes cs = ds = es +; +bcopy: + push eax + push ebx + push edx + push ebp + + mov bx, real_int15_stub + + test byte [ConfigFlags], CONFIG_RAW|CONFIG_SAFEINT + jz .anymode ; Always do the real INT 15h + + smsw ax ; Unprivileged! + test al,01h + jnz .protmode ; Protmode -> do real INT 15h + +.realmode: + ; Raw or Safeint mode, and we're in real mode... + + test byte [ConfigFlags], CONFIG_SAFEINT + jnz .fakeint15 + +.raw: + TRACER 'r' + ; We're in real mode, do it outselves + + pushfd ; <A> + push ds ; <B> + push es ; <C> + + cli + cld + + xor ebx,ebx + mov bx,cs + shl ebx,4 + lea edx,[Shaker+ebx] + mov [Shaker+2],edx + + ; Test to see if A20 is enabled or not + xor ax,ax + mov ds,ax + dec ax + mov es,ax + + mov ax,[0] + mov bx,ax + xor bx,[es:10h] + not ax + mov [0],ax + mov dx,ax + xor dx,[es:10h] + not ax + mov [0],ax + + or dx,bx + push dx ; <D> Save A20 status + jnz .skip_a20e + + mov ax,2401h ; Enable A20 + int 15h +.skip_a20e: + mov dl,[ConfigFlags] + and dx,CONFIG_BIGRAW + add dx,8 + ; DX = 16 for BIGRAW, 8 for RAW + ; 8 is selector for a 64K flat segment, + ; 16 is selector for a 4GB flat segment. + + lgdt [cs:Shaker] + mov eax,cr0 + or al,01h + mov cr0,eax + + mov bx,16 ; Large flat segment + mov ds,bx + mov es,bx + + a32 rep movsd + + ; DX has the appropriate value to put in + ; the registers on return + mov ds,dx + mov es,dx + + and al,~01h + mov cr0,eax + + pop dx ; <D> A20 status + pop es ; <C> + pop ds ; <B> + + and dx,dx + jnz .skip_a20d + mov ax,2400h ; Disable A20 + int 15h +.skip_a20d: + popfd ; <A> + jmp .done + +.fakeint15: + ; We're in real mode with CONFIG_SAFEINT, invoke the + ; original INT 15h vector. We used to test for the + ; INT 15h vector being unchanged here, but that is + ; *us*; however, the test was wrong for years (always + ; negative) so instead of fixing the test do what we + ; tested and don't bother probing. + mov bx, fake_int15_stub + +.protmode: + TRACER 'p' +.anymode: + +.copy_loop: + push esi + push edi + push ecx + cmp ecx,4000h + jna .safe_size + mov ecx,4000h +.safe_size: + push ecx ; Transfer size this cycle + mov eax, esi + mov [Mover_src1], si + shr eax, 16 + mov [Mover_src1+2], al + mov [Mover_src2], ah + mov eax, edi + mov [Mover_dst1], di + shr eax, 16 + mov [Mover_dst1+2], al + mov [Mover_dst2], ah + mov si,Mover + mov ah, 87h + shl cx,1 ; Convert to 16-bit words + call bx ; INT 15h stub + pop eax ; Transfer size this cycle + pop ecx + pop edi + pop esi + jc .error + lea esi,[esi+4*eax] + lea edi,[edi+4*eax] + sub ecx, eax + jnz .copy_loop + ; CF = 0 +.error: +.done: + pop ebp + pop edx + pop ebx + pop eax + ret + +real_int15_stub: + int 15h + cli ; Some BIOSes enable interrupts on INT 15h + ret + +fake_int15_stub: + pushf + call far [OldInt15] + cli + 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 + +writehex2: pushad + pushfd + mov cx,2 + ror eax,4 + jmp writehex_common +writehex4: pushad + pushfd + mov cx,4 + ror eax,12 + jmp writehex_common +writehex8: pushad + pushfd + mov cx,8 + ror eax,28 +writehex_common: +.loop: push cx + push eax + and al,0Fh + cmp al,10 + jb .isdec + add al,'a'-'0'-10 +.isdec: add al,'0' + mov ah,0Eh + mov bx,7 + int 10h + pop eax + rol eax,4 + pop cx + loop .loop + popfd + popad + ret +%endif + + section .data align=16 + alignb 2 +Int13Funcs dw Reset ; 00h - RESET + dw GetStatus ; 01h - GET STATUS + dw Read ; 02h - READ + dw Write ; 03h - WRITE + dw Verify ; 04h - VERIFY + dw Invalid ; 05h - FORMAT TRACK + dw Invalid ; 06h - FORMAT TRACK AND SET BAD FLAGS + dw Invalid ; 07h - FORMAT DRIVE AT TRACK + dw GetParms ; 08h - GET PARAMETERS + dw InitWithParms ; 09h - INITIALIZE CONTROLLER WITH + ; DRIVE PARAMETERS + dw Invalid ; 0Ah + dw Invalid ; 0Bh + dw Seek ; 0Ch - SEEK TO CYLINDER + dw Reset ; 0Dh - RESET HARD DISKS + dw Invalid ; 0Eh + dw Invalid ; 0Fh + dw CheckIfReady ; 10h - CHECK IF READY + dw Recalibrate ; 11h - RECALIBRATE + dw Invalid ; 12h + dw Invalid ; 13h + dw Invalid ; 14h + dw GetDriveType ; 15h - GET DRIVE TYPE + dw DetectChange ; 16h - DETECT DRIVE CHANGE +%if EDD + dw Invalid ; 17h + dw Invalid ; 18h + dw Invalid ; 19h + dw Invalid ; 1Ah + dw Invalid ; 1Bh + dw Invalid ; 1Ch + dw Invalid ; 1Dh + dw Invalid ; 1Eh + dw Invalid ; 1Fh + dw Invalid ; 20h + dw ReadMult ; 21h - READ MULTIPLE + dw WriteMult ; 22h - WRITE MULTIPLE + dw SetMode ; 23h - SET CONTROLLER FEATURES + dw SetMode ; 24h - SET MULTIPLE MODE + dw Invalid ; 25h - IDENTIFY DRIVE + dw Invalid ; 26h + dw Invalid ; 27h + dw Invalid ; 28h + dw Invalid ; 29h + dw Invalid ; 2Ah + dw Invalid ; 2Bh + dw Invalid ; 2Ch + dw Invalid ; 2Dh + dw Invalid ; 2Eh + dw Invalid ; 2Fh + dw Invalid ; 30h + dw Invalid ; 31h + dw Invalid ; 32h + dw Invalid ; 33h + dw Invalid ; 34h + dw Invalid ; 35h + dw Invalid ; 36h + dw Invalid ; 37h + dw Invalid ; 38h + dw Invalid ; 39h + dw Invalid ; 3Ah + dw Invalid ; 3Bh + dw Invalid ; 3Ch + dw Invalid ; 3Dh + dw Invalid ; 3Eh + dw Invalid ; 3Fh + dw Invalid ; 40h + dw EDDPresence ; 41h - EDD PRESENCE DETECT + dw EDDRead ; 42h - EDD READ + dw EDDWrite ; 43h - EDD WRITE + dw EDDVerify ; 44h - EDD VERIFY + dw EDDLock ; 45h - EDD LOCK/UNLOCK MEDIA + dw EDDEject ; 46h - EDD EJECT + dw EDDSeek ; 47h - EDD SEEK + dw EDDGetParms ; 48h - EDD GET PARAMETERS + dw EDDDetectChange ; 49h - EDD MEDIA CHANGE STATUS +%if ELTORITO ; EDD El Torito Functions + ; ELTORITO _must_ also have EDD + dw ElToritoEmulate ; 4Ah - Initiate Disk Emulation + dw ElToritoTerminate ; 4Bh - Terminate Disk Emulation + dw ElToritoBoot ; 4Ch - Initiate Disk Emu. and Reboot + dw ElToritoCatalog ; 4Dh - Return Boot Catalog +%endif ; ELTORITO +%endif ; EDD + +Int13FuncsEnd equ $ +Int13FuncsCnt equ (Int13FuncsEnd-Int13Funcs) >> 1 + + + alignb 8, db 0 +Shaker dw ShakerEnd-$-1 ; Descriptor table limit + dd 0 ; Pointer to self + dw 0 + +Shaker_RMDS: dd 0x0000ffff ; 64K data segment + dd 0x00009300 + +Shaker_DS: dd 0x0000ffff ; 4GB data segment + dd 0x008f9300 + +ShakerEnd equ $ + + alignb 8, db 0 + +Mover dd 0, 0, 0, 0 ; Must be zero + dw 0ffffh ; 64 K segment size +Mover_src1: db 0, 0, 0 ; Low 24 bits of source addy + db 93h ; Access rights + db 00h ; Extended access rights +Mover_src2: db 0 ; High 8 bits of source addy + dw 0ffffh ; 64 K segment size +Mover_dst1: db 0, 0, 0 ; Low 24 bits of target addy + db 93h ; Access rights + db 00h ; Extended access rights +Mover_dst2: db 0 ; High 8 bits of source addy +Mover_dummy2: dd 0, 0, 0, 0 ; More space for the BIOS + + alignb 16, db 0 +mBFT: +; Fields common to all ACPI tables + dd ' ' ; ACPI signature ("mBFT") + ; This is filled-in by the installer + ; to avoid an accidentally valid mBFT + dd mBFT_Len ; ACPI table length + db 1 ; ACPI revision + db 0 ; ACPI table checksum + db 'MEMDSK' ; ACPI OEM ID + db 'Syslinux' ; ACPI OEM table ID + dd 0 ; ACPI OEM revision + dd 0 ; ACPI ASL compiler vendor ID + dd 0 ; ACPI ASL compiler revision +; The next field is mBFT-specific and filled-in by the installer + dd 0 ; "Safe hook" physical address + +; Note that the above ends on a DWORD boundary. +; The MDI has always started at such a boundary. +; Portions of the MDI are patched by the installer +MemDisk_Info equ $ ; Pointed to by installation check +MDI_Bytes dw MDI_Len ; Total bytes in MDI structure +MDI_Version db VERSION_MINOR, VERSION_MAJOR ; MEMDISK version + +DiskBuf dd 0 ; Linear address of high memory disk +DiskSize dd 0 ; Size of disk in blocks +CommandLine dw 0, 0 ; Far pointer to saved command line + +OldInt13 dd 0 ; INT 13h in chain +OldInt15 dd 0 ; INT 15h in chain + +OldDosMem dw 0 ; Old position of DOS mem end +BootLoaderID db 0 ; Boot loader ID from header + db 0 ; pad + +DPT_ptr dw 0 ; If nonzero, pointer to DPT + ; Original DPT pointer follows + +MDI_Len equ $-MemDisk_Info +mBFT_Len equ $-mBFT ; mBFT includes the MDI + +; ---- MDI structure ends here --- +DriveShiftLimit db 0ffh ; Installer will probe for + ; a range of contiguous drives. + ; Any BIOS drives above this region + ; shall not be impacted by our + ; shifting behaviour + db 0 ; pad to a DWORD + dw 0 ; pad to a QWORD +MemInt1588 dw 0 ; 1MB-65MB memory amount (1K) + +Cylinders dw 0 ; Cylinder count +Heads dw 0 ; Head count +Sectors dd 0 ; Sector count (zero-extended) + +Mem1MB dd 0 ; 1MB-16MB memory amount (1K) +Mem16MB dd 0 ; 16MB-4G memory amount (64K) + +DriveNo db 0 ; Our drive number +DriveType db 0 ; Our drive type (floppies) +DriveCnt db 0 ; Drive count (from the BIOS) + +ConfigFlags db 0 ; Bit 0 - readonly + +MyStack dw 0 ; Offset of stack +StatusPtr dw 0 ; Where to save status (zeroseg ptr) + +DPT times 16 db 0 ; BIOS parameter table pointer (floppies) +OldInt1E dd 0 ; Previous INT 1E pointer (DPT) + +%if EDD +EDD_DPT: +.length dw 30 +.info dw 0029h + ; Bit 0 - DMA boundaries handled transparently + ; Bit 3 - Device supports write verify + ; Bit 5 - Media is lockable +.cylinders dd 0 ; Filled in by installer +.heads dd 0 ; Filled in by installer +.sectors dd 0 ; Filled in by installer +.totalsize dd 0, 0 ; Filled in by installer +.bytespersec dw SECTORSIZE +.eddtable dw -1, -1 ; Invalid DPTE pointer +.dpikey dw 0BEDDh ; Device Path Info magic +.dpilen db 2ch ; DPI len +.res1 db 0 ; Reserved +.res2 dw 0 ; Reserved +.bustype dd 'MEM ' ; Host bus type (4 bytes, space padded) +.inttype dd 'MEMORY ' ; Interface type (8 bytes, spc. padded) +.intpath dd 0, 0 ; Interface path +.devpath dd 0, 0, 0, 0 ; Device path +.res3 db 0 ; Reserved +.chksum db 0 ; DPI checksum + +%if ELTORITO +; El Torito CD Specification Packet - mostly filled in by installer +CD_PKT: +.size db 13h ; Packet size (19 bytes) +.type db 0 ; Boot media type (flags) +.driveno db 0E0h ; INT 13h drive number +.controller db 0 ; Controller index +.start dd 0 ; Starting LBA of image +.devno dw 0 ; Device number +.user_buf dw 0 ; User buffer segment +.load_seg dw 0 ; Load segment +.sect_count dw 0 ; Emulated sectors to load +.geom1 db 0 ; Cylinders bits 0 thru 7 +.geom2 db 0 ; Sects/track 0 thru 5, cyls 8, 9 +.geom3 db 0 ; Heads +%endif ; ELTORITO + +%endif ; EDD + +; End patch area + + alignb 4, db 0 +Stack dd 0 ; Saved SS:ESP on invocation + dw 0 +SavedAX dw 0 ; AX saved on invocation +Recursive dw 0 ; Recursion counter + + alignb 4, db 0 ; We *MUST* end on a dword boundary + +E820Table equ $ ; The installer loads the E820 table here +TotalSize equ $ ; End pointer |