home *** CD-ROM | disk | FTP | other *** search
- ;**************************************************************************
- ;* * * * 386 PROTECT info * * *
- ;**************************************************************************
-
- ;* * 386 Descriptor template
- DESC386 STRUC
- limDesc386 dw 0 ; limit bits (0..15)
- LO_apDesc386 dw 0 ; base bits (0..15)
- MID_apDesc386 db 0 ; base bits (16..23)
- accessDesc386 db 0 ; accessDesc386 byte
- granDesc386 db 0 ; granularity byte
- HI_apDesc386 db 0 ; base bits (24..31)
- DESC386 ENDS
-
- GDT386 STRUC
- limitGdt dw ?
- LO_apBaseGdt dw ?
- HI_apBaseGdt dw ?
- GDT386 ENDS
-
- Zero segment use32 at 0
- org 13*4
- Int13Vector label dword
- Zero ends
-
- ;MEM3_Code segment use16 para public 'CODE'
- ;MEM3_Code ends
-
- ;codeg group code, MEM3_Code
-
- ;MEM3_Code segment
- assume cs:code, ds:code, es:nothing
-
- MEM3_Start label byte ; Start of relocatable code
- ;MEM3_Data label byte ; Start of our data
-
- MEM3_Offset = offset code:MEM3_Data-offset code:MEM3_Start
-
- OurGDT equ byte ptr ($+MEM3_Offset) ; Simple GDT
- DESC386 <>
- descCS equ byte ptr ($+MEM3_Offset)
- DESC386 <0FFFFh,0,0,09Fh,0,0> ; Conforming CS
- descRealBig equ byte ptr ($+MEM3_Offset)
- DESC386 <0FFFFh,0,0,093h,0cfh,0> ; Page Granularity
- ; 4Gb Limit
- GDTLen EQU ($+MEM3_Offset-OurGDT)
-
- GDTPtr equ qword ptr ($+MEM3_Offset)
- GDT386 <GDTLen,0,0>
-
- OldInt13 equ dword ptr ($+MEM3_Offset)
- dd 0 ; Old contents of int 13 vector
-
- GDTMoveBlock equ byte ptr ($+MEM3_Offset)
- ; 386 Template OK for Move Block
- DESC386 <> ; Nul Descriptor
- DESC386 <> ; GDT Descriptor
- descSource equ byte ptr ($+MEM3_Offset)
- DESC386 <0FFFFh,0,0,93h,0,0> ; Source Segment Descriptor
- descDest equ byte ptr ($+MEM3_Offset)
- DESC386 <0FFFFh,0,0,93h,0,0> ; Destination Segment Descriptor
- DESC386 <> ; BIOS use
- DESC386 <> ; BIOS use
-
- ;*******************************************************************************
- ;
- ; MoveExtended386
- ; XMM Move Extended Memory Block for the 80386
- ;
- ; Entry:
- ; ES:BX Points to structure containing:
- ; bCount dd ? ; Length of block to move
- ; SourceHandle dw ? ; Handle for souce
- ; SourceOffset dd ? ; Offset into source
- ; DestHandle dw ? ; Handle for destination
- ; DestOffset dd ? ; Offset into destination
- ;
- ; Return:
- ; AX = 1 Success
- ; AX = 0 Failure
- ; Error code in BL
- ;
- ; Registers Destroyed:
- ; Flags
- ;
- ;-------------------------------------------------------------------------------
- MoveExtended386 proc near
-
- sti ; Be nice
- push bp ; Set up stack frame so we
- mov bp, sp ; can have local variables
- sub sp, 18
- Count = -4 ; Local DWORD for byte count
- Return = -6 ; Local WORD for return code
- SrcHandle = -8
- DstHandle = -10
- SrcLinear = -14
- DstLinear = -18
- push eax ; Save upper word of registers
- push ecx
- push esi
- push edi
- push bx
-
- xor ax, ax
- mov [bp.Return], ax ; Assume success
- mov [bp.SrcHandle], ax
- mov [bp.DstHandle], ax
- mov ecx, es:[si.bCount]
- mov [bp.Count], ecx
-
- shr dword ptr [bp.Count], 1 ; No odd byte counts
- jc MEM3_InvCount
- jz MEM3_Exit ; Exit immediately if zero
-
- lea bx, [si.SourceHandle] ; Normalize Source
- call GetLinear386 ; Linear address in edi
- jc MEM3_SrcError ; Have Dest Error Code
- xchg esi, edi ; Save source address in ESI
- mov [bp.SrcHandle], bx ; Save Handle for Unlock
-
- lea bx, [di.DestHandle]
- call GetLinear386 ; Normalize Destination
- jc MEM3_Error
- mov [bp.DstHandle], bx ; Save Handle for Unlock
-
- smsw ax
- shr ax, 1 ; Protected mode?
- jc MEM3_MoveBlock ; if so, use int 15h
- ; Must preserve DS
-
- call word ptr ControlJumpTable[5*2] ; Call LocalEnableA20()
- cmp ax, 1
- jne MEM3_Error
-
- xor cx, cx
- mov es, cx
- assume es:Zero
- mov ax, cs
- shl eax, 16
- mov ax, offset code:Int13Handler+MEM3_Offset
- cli
- push [OldInt13] ; For reentrancy
- xchg eax, [Int13Vector] ; Install our int 13 handler
- mov [OldInt13], eax
- sti
-
- push ds
- mov ds, cx
- assume ds:Zero
- mov ecx, [bp.Count]
- shr ecx, 1 ; Now DWORD count
- ; Odd word count in carry
- ; Now we have:
- ; ESI = 32 bit Source Linear Address
- ; EDI = 32 bit Destination Linear Address
- ; DS = ES = 0
- ; If the limit of DS or ES is still the Real Mode
- ; default of 64k and ESI or EDI is greater than 64k,
- ; these instructions will fault with an int 13.
- ; In this case, our int 13 handler will set up
- ; the descriptors to have 4Gb limits (real big mode)
- ; and will iret to the faulting instruction.
-
- ; The following persuades masm to output
- ; both a 66h and 67h prefix
- Fault0:
- rep movs dword ptr [esi], dword ptr [edi] ; DWORDS first
- ; THE NEXT INSTRUCTION MUST HAVE ADDRESS SIZE OVERRIDE
- db 67h ; CHIP BUG - DO NOT REMOVE
- nop ; CHIP BUG - DO NOT REMOVE
-
- rcl ecx, 1
- Fault1:
- rep movs word ptr [esi], word ptr [edi] ; Now the odd word
- ; THE NEXT INSTRUCTION MUST HAVE ADDRESS SIZE OVERRIDE
- db 67h ; CHIP BUG - DO NOT REMOVE
- nop ; CHIP BUG - DO NOT REMOVE
-
- pop ds
- assume ds:code
- pop eax ; saved [OldInt13]
- cli ; NECESSARY
- xchg eax, [OldInt13] ; OldInt13 potentially INVALID
- mov [Int13Vector], eax ; Deinstall our handler
- sti
-
- call word ptr ControlJumpTable[6*2] ; Call LocalDisableA20()
- cmp ax, 1
- jne short MEM3_Error
-
- MEM3_Exit:
- mov bx, [bp.SrcHandle] ; Unlock Handles if necessary
- or bx, bx
- jz short MEM3_NoSrcHandle
- dec [bx.cLock] ; Unlock Source
- MEM3_NoSrcHandle:
- mov bx, [bp.DstHandle]
- or bx, bx
- jz short MEM3_NoDstHandle
- dec [bx.cLock] ; Unlock Destination
- MEM3_NoDstHandle:
- pop bx ; Restore original registers
- pop edi
- pop esi
- pop ecx
- pop eax
- mov ax, 1
- cmp word ptr [bp.Return], 0
- je short MEM3_Success
- dec ax ; AX = 0 for error
- mov bl, byte ptr [bp.Return]
- MEM3_Success:
- mov sp, bp ; Unwind stack
- pop bp
- ret
-
- MEM3_InvCount:
- mov bl, ERR_LENINVALID
- jmp short MEM3_Error
- MEM3_SrcError:
- cmp bl, ERR_LENINVALID ; Invalid count
- je short MEM3_Error ; yes, no fiddle
- sub bl, 2 ; Convert to Source error code
- MEM3_Error:
- mov [bp.Return], bl
- jmp short MEM3_Exit
-
- ;*******************************************************************************
- ;
- ; GetLinear386
- ; Convert Handle and Offset (or 0 and SEG:OFFSET) into Linear address
- ; Locks Handle if necessary
- ; Nested with MoveExtended386 to access local variables
- ;
- ; Entry:
- ; ES:BX Points to structure containing:
- ; Handle dw
- ; Offset dd
- ; ECX Count of bytes to move
- ;
- ; Return:
- ; BX Handle of block (0 if conventional)
- ; EDI Linear address
- ; CARRY => Error
- ;
- ; Registers Destroyed:
- ; EAX
- ;
- ;-------------------------------------------------------------------------------
-
- GetLinear386 proc near
- cli ; NO INTERRUPTS
- mov edi, dword ptr es:[bx+2] ; Offset from start of handle
- mov bx, word ptr es:[bx] ; Handle in bx
- or bx, bx
- jz short GL3_Conventional
-
- cmp [bx.Flags], USEDFLAG ; Valid Handle?
- jne short GL3_InvHandle
-
- movzx eax, [bx.Len] ; Length of Block
- shl eax, 10 ; now in bytes
- sub eax, edi ; EAX = max possible count
- jb short GL3_InvOffset ; Base past end of block
- cmp eax, ecx
- jb short GL3_InvCount ; Count too big
-
- inc [bx.cLock] ; Lock Handle
- movzx eax, [bx.Base]
- shl eax, 10 ; Base byte address
- add edi, eax ; Linear address
-
- GL3_OKExit:
- clc
- sti
- ret
-
- GL3_Conventional:
- movzx eax, di ; Offset in EAX
- shr edi, 16
- shl edi, 4 ; Segment*16 in EDI
- add edi, eax ; Linear address in EDI
- mov eax, edi
- add eax, ecx
- cmp eax, 10FFF0h ; Max addressable inc. HMA
- jbe short GL3_OKExit
- GL3_InvCount:
- mov bl, ERR_LENINVALID
- jmp short GL3_Error
- GL3_InvHandle:
- mov bl, ERR_DHINVALID ; Dest handle invalid
- jmp short GL3_Error
- GL3_InvOffset:
- mov bl, ERR_DOINVALID ; Dest Offset invalid
- GL3_Error:
- stc
- sti
- ret
-
- GetLinear386 endp
-
- ;*******************************************************************************
- ;
- ; Int13Handler
- ; Handler for int 13 during our rep moves
- ; If it is a real interrupt, jump to the old handler
- ; If it is a fault, set Real Big Mode and return
- ;
- ; Entry:
- ;
- ; Return:
- ;
- ; Registers Destroyed:
- ; BX, DS, ES if fault from one of our instructions, otherwise
- ; NONE
- ;
- ;-------------------------------------------------------------------------------
-
- Int13Handler proc far
- assume cs:code, ds:nothing, es:nothing
- push bp
- mov bp, sp ; Base to look at faulting address
- push ax
-
- mov al, 0Bh ; Party on PIC to see if interrupt
- out 20h, al
- in al, 20h ; ISR
- test al, 20h ; IRQ5, int 13
- jnz short NotOurInt13
-
- mov ax, cs
- cmp [bp+4], ax ; Fault from our cs?
- jne short NotOurInt13 ; no, SOMETHING IS FUNNY!
- cmp word ptr [bp+2], offset code:Fault0+MEM3_Offset
- je short LoadDescriptorCache
- cmp word ptr [bp+2], offset code:Fault1+MEM3_Offset
- jne short NotOurInt13 ; Not one of our instructions ????
-
- LoadDescriptorCache:
- mov bx, descRealBig - OurGDT ; Special 4Gb selector
- lgdt qword ptr cs:[GDTPtr]
-
- mov eax, cr0
- or al,1
- mov cr0, eax ; Go into Protected Mode
- ; NOTE: NMIs will kill us!!!
-
- db 0eah ; jmp far flush_prot
- dw offset code:flush_prot+MEM3_Offset ; Clears the prefetch
- dw descCS - OurGDT
-
- flush_prot:
- mov es, bx ; Set up the segments we want
- mov ds, bx
-
- and al, 0FEh
- mov cr0, eax ; Return to Real Mode
-
- db 0EAH ; jmp far flush_real
- dw offset code:flush_real+MEM3_Offset
- patch3 equ word ptr ($+MEM3_Offset)
- dw 0
-
- flush_real:
- xor ax, ax
- mov ds, ax
- mov es, ax
-
- pop ax
- pop bp
- iret ; Back to faulting instruction
-
- NotOurInt13:
- pop ax
- pop bp
- jmp cs:[OldInt13]
-
- Int13Handler endp
-
- ;*******************************************************************************
- ;
- ; MEM3_MoveBlock
- ; Set up GDT and call int 15h Move Block
- ; Nested within MoveExtended386
- ; See 80286 programmer's reference manual for GDT entry format
- ; See Int 15h documentation for Move Block function
- ;
- ; Entry:
- ; [BP.Count] Word count for move
- ; ESI Linear address of the source
- ; EDI Linear address of the destination
- ;
- ; Interrupts are ON
- ;
- ; Return:
- ; CARRY => Error
- ; Error code in BL
- ;
- ; Registers Destroyed:
- ; Flags, EAX, ECX, ESI, EDI, ES
- ;
- ;-------------------------------------------------------------------------------
- MEM3_MoveBlock:
- assume ds:code
- mov [bp.SrcLinear], esi
- mov [bp.DstLinear], edi
- mov ax, ds
- mov es, ax
- assume es:code
-
- DMB_loop:
- mov ecx, 512 ; Do max of # words left or
- cmp ecx, [bp.Count] ; or max Move Block allows
- jbe short DMB0
- mov ecx, [bp.Count]
- DMB0:
- push ecx
- lea si, [GDTMoveBlock] ; Pointer to GDT for Block Move
-
- lea di, [descSource.LO_apDesc386] ; Source Descriptor
- mov eax, dword ptr [bp.SrcLinear]
-
- CLI ; No interrupts until int 15h
- ; Allows reentrancy
- stosw
- shr eax, 16
- stosb ; Source Descriptor done
-
- lea di, [descDest.LO_apDesc386] ; Destination Descriptor
- mov eax, dword ptr [bp.DstLinear]
- stosw
- shr eax, 16
- stosb ; Destination Descriptor done
-
- clc ; MUST DO THIS, int 15h doesn't bother
- mov ah, 87h ; Block Move - Assumes protect
- int 15h ; mode code will allow interrupts
-
- STI
- pop ecx
- jc short DMB_Error
-
- sub [bp.Count], ecx
- jz MEM3_Exit ; All done
- shl ecx, 1 ; Back to byte count
- add [bp.SrcLinear], ecx ; Update source for next chunk
- add [bp.DstLinear], ecx ; Update destination
- jmp short DMB_loop
-
- DMB_Error:
- xor bh, bh
- mov bl, al
- mov bl, cs:[Int15Err][bx] ; Pick up correct error code
- jmp MEM3_Error
-
- Int15Err equ byte ptr ($+MEM3_Offset)
- db 0, ERR_PARITY, ERR_LENINVALID, ERR_A20
-
- MoveExtended386 endp
-
- MEM3_End label byte ; End of relocatable code
-