312 lines
11 KiB
NASM
312 lines
11 KiB
NASM
;;******************************************************************************
|
|
;;* Copyright (c) 1983-2020, Insyde Software Corporation. All Rights Reserved.
|
|
;;*
|
|
;;* You may not reproduce, distribute, publish, display, perform, modify, adapt,
|
|
;;* transmit, broadcast, present, recite, release, license or otherwise exploit
|
|
;;* any part of this publication in any form, by any means, without the prior
|
|
;;* written permission of Insyde Software Corporation.
|
|
;;*
|
|
;;******************************************************************************
|
|
;;
|
|
;; Abstract:
|
|
;;
|
|
|
|
.MODEL small
|
|
.586p
|
|
.code
|
|
|
|
INCLUDE Int15Rom.EQU
|
|
|
|
CodeStart:
|
|
ORG 0
|
|
db 55h, 0AAh
|
|
CodeSize db ((((offset CodeEnd) - (offset CodeStart)) / 512) + 1)
|
|
ORG 3
|
|
jmp HookInt15
|
|
|
|
OldINT15SegOff dw ?, ?
|
|
INT15SmiPort dw ?
|
|
INT15SmiData dw ?
|
|
INT15FnEntry dw ?
|
|
MaxINT15FnCount dw ?
|
|
CpuRegisters dw ?
|
|
;Initialize INT15 option rom
|
|
; Input Registers:
|
|
; Regs.X.AX = COMMON_INT15_SMI;
|
|
; Regs.X.CX = MAX_OEM_INT15_FN_COUNT;
|
|
; Regs.X.DX = SW_SMI_PORT;
|
|
; Regs.X.DS = FunctionListSegment;
|
|
; Regs.X.ES = CpuRegistersSegment;
|
|
HookInt15:
|
|
cli
|
|
push eax
|
|
push ebx
|
|
push ecx
|
|
push edx
|
|
; OEM INT15 data initialize
|
|
mov cs:[INT15SmiPort], ax
|
|
mov cs:[INT15SmiData], dx
|
|
mov cs:[MaxINT15FnCount], cx
|
|
|
|
mov ax, ds
|
|
mov cs:[INT15FnEntry], ax
|
|
|
|
mov ax, es
|
|
mov cs:[CpuRegisters], ax
|
|
|
|
; Hook INT15
|
|
push cs
|
|
pop dx
|
|
shl edx, 16
|
|
push offset INT15CallBack
|
|
pop dx
|
|
mov eax, 15h
|
|
call ChangeInterruptTable
|
|
mov dword ptr cs:OldINT15SegOff, eax
|
|
|
|
pop edx
|
|
pop ecx
|
|
pop ebx
|
|
pop eax
|
|
sti
|
|
retf
|
|
|
|
; Oem Int15 call back function
|
|
INT15CallBack:
|
|
pushfd
|
|
call CompareInt15FunList
|
|
jc OriginalInt15Vector
|
|
popfd
|
|
call SaveCpuRegisters
|
|
call CheckCpuMode
|
|
jc EXIT_INT15
|
|
call TriggerSmi
|
|
call RestoreCpuRegisters
|
|
EXIT_INT15:
|
|
retf 2
|
|
|
|
OriginalInt15Vector:
|
|
popfd
|
|
jmp dword ptr cs:[OldINT15SegOff]
|
|
|
|
;****************************************************************************
|
|
;* CheckCpuMode *
|
|
;* *
|
|
;* PURPOSE: Check Cpu Mode *
|
|
;* DESCRIPTION: *
|
|
;* USES: *
|
|
;* PASSED: InSmmFlag *
|
|
;* SPECIAL: NOTHING. *
|
|
;* RETURNS: CY: If InSmmFlag = 055aah ,it means the caller in smm mode *
|
|
;* set InSmmFlag = 0aa55h and return *
|
|
;* NC: Caller in normal Cpu mode, do smi *
|
|
;****************************************************************************
|
|
CheckCpuMode PROC NEAR
|
|
push es
|
|
push ax
|
|
mov ax, cs:[CpuRegisters]
|
|
mov es, ax
|
|
cmp es:INT15_PRIVATE_INFO.InSmmFlag, 55aah
|
|
jne Normal_mode
|
|
mov es:INT15_PRIVATE_INFO.InSmmFlag, 0aa55h
|
|
stc
|
|
jmp Smm_mode
|
|
Normal_mode:
|
|
clc
|
|
Smm_mode:
|
|
pop ax
|
|
pop es
|
|
ret
|
|
CheckCpuMode ENDP
|
|
|
|
;****************************************************************************
|
|
;* CompareInt15FunList *
|
|
;* *
|
|
;* PURPOSE: Save CpuRegisters to CpuRegs *
|
|
;* DESCRIPTION: *
|
|
;* USES: *
|
|
;* PASSED: AX - Interrupt service number *
|
|
;* EDX - New Interrupt Segment:Offset *
|
|
;* SPECIAL: NOTHING. *
|
|
;* RETURNS: EAX - Original Interrupt Segment:offset *
|
|
;****************************************************************************
|
|
CompareInt15FunList PROC NEAR
|
|
pushad
|
|
push ds
|
|
|
|
mov cx, cs:[MaxINT15FnCount]
|
|
push cs:[INT15FnEntry]
|
|
pop ds
|
|
xor si, si
|
|
|
|
SearchNextInt15Fun:
|
|
cmp word ptr ds:[si], 0
|
|
je NoMergeFun
|
|
cmp ax, word ptr ds:[si]
|
|
je FindMergeInt15Fun
|
|
add si, 2
|
|
loop SearchNextInt15Fun
|
|
|
|
NoMergeFun:
|
|
stc
|
|
jmp Compare_Exit
|
|
|
|
FindMergeInt15Fun:
|
|
clc
|
|
|
|
Compare_Exit:
|
|
pop ds
|
|
popad
|
|
ret
|
|
CompareInt15FunList ENDP
|
|
|
|
;****************************************************************************
|
|
;* TriggerSmi *
|
|
;* *
|
|
;* PURPOSE: Save CpuRegisters to CpuRegs *
|
|
;* DESCRIPTION: *
|
|
;* USES: *
|
|
;* PASSED: AX - Interrupt service number *
|
|
;* EDX - New Interrupt Segment:Offset *
|
|
;* SPECIAL: NOTHING. *
|
|
;* RETURNS: EAX - Original Interrupt Segment:offset *
|
|
;****************************************************************************
|
|
TriggerSmi PROC NEAR
|
|
push dx
|
|
push ax
|
|
|
|
mov ax, cs:[INT15SmiPort]
|
|
mov dx, cs:[INT15SmiData]
|
|
|
|
out dx, al
|
|
out 0edh, al ;IO dummy for Smi trigger synchronous
|
|
|
|
pop ax
|
|
pop dx
|
|
ret
|
|
TriggerSmi ENDP
|
|
|
|
;****************************************************************************
|
|
;* SaveCpuRegisters *
|
|
;* *
|
|
;* PURPOSE: Save CpuRegisters to CpuRegs *
|
|
;* DESCRIPTION: *
|
|
;* USES: *
|
|
;* PASSED: All Cpu Registers *
|
|
;* SPECIAL: NOTHING. *
|
|
;* RETURNS: None *
|
|
;****************************************************************************
|
|
SaveCpuRegisters PROC NEAR
|
|
push es
|
|
push cs:[CpuRegisters]
|
|
pop es
|
|
|
|
mov es:EFI_DWORD_REGS.RegEAX, eax
|
|
mov es:EFI_DWORD_REGS.RegEBX, ebx
|
|
mov es:EFI_DWORD_REGS.RegECX, ecx
|
|
mov es:EFI_DWORD_REGS.RegEDX, edx
|
|
mov es:EFI_DWORD_REGS.RegESI, esi
|
|
mov es:EFI_DWORD_REGS.RegEDI, edi
|
|
|
|
pushfd
|
|
pop es:EFI_DWORD_REGS.RegEFlags
|
|
|
|
push cs
|
|
pop es:EFI_DWORD_REGS.RegCS
|
|
push ss
|
|
pop es:EFI_DWORD_REGS.RegSS
|
|
push ds
|
|
pop es:EFI_DWORD_REGS.RegDS
|
|
push fs
|
|
pop es:EFI_DWORD_REGS.RegFS
|
|
push gs
|
|
pop es:EFI_DWORD_REGS.RegGS
|
|
push ebp
|
|
pop es:EFI_DWORD_REGS.RegEBP
|
|
push esp
|
|
pop es:EFI_DWORD_REGS.RegESP
|
|
pop es
|
|
|
|
push ds
|
|
push cs:[CpuRegisters]
|
|
pop ds
|
|
push es
|
|
pop ds:EFI_DWORD_REGS.RegES
|
|
pop ds
|
|
|
|
ret
|
|
SaveCpuRegisters ENDP
|
|
|
|
;****************************************************************************
|
|
;* RestoreCpuRegisters *
|
|
;* *
|
|
;* PURPOSE: Restore CpuRegisters from CpuRegs *
|
|
;* DESCRIPTION: *
|
|
;* USES: *
|
|
;* PASSED: ES:SI - Point to CpuRegs *
|
|
;* SPECIAL: NOTHING. *
|
|
;* RETURNS: All Cpu registers *
|
|
;****************************************************************************
|
|
RestoreCpuRegisters PROC NEAR
|
|
|
|
push cs:[CpuRegisters]
|
|
pop es
|
|
|
|
mov eax, es:EFI_DWORD_REGS.RegEAX
|
|
mov ebx, es:EFI_DWORD_REGS.RegEBX
|
|
mov ecx, es:EFI_DWORD_REGS.RegECX
|
|
mov edx, es:EFI_DWORD_REGS.RegEDX
|
|
mov esi, es:EFI_DWORD_REGS.RegESI
|
|
mov edi, es:EFI_DWORD_REGS.RegEDI
|
|
|
|
push es:EFI_DWORD_REGS.RegSS
|
|
pop ss
|
|
push es:EFI_DWORD_REGS.RegDS
|
|
pop ds
|
|
push es:EFI_DWORD_REGS.RegFS
|
|
pop fs
|
|
push es:EFI_DWORD_REGS.RegGS
|
|
pop gs
|
|
push es:EFI_DWORD_REGS.RegEBP
|
|
pop ebp
|
|
push es:EFI_DWORD_REGS.RegEFlags
|
|
popfd
|
|
;
|
|
; Can't restore CS and ESP
|
|
;
|
|
; push (EFI_DWORD_REGS PTR es:[si]).RegCS
|
|
; pop cs
|
|
; push es:EFI_DWORD_REGS.RegESP
|
|
; pop esp
|
|
push es:EFI_DWORD_REGS.RegES
|
|
pop es
|
|
|
|
ret
|
|
RestoreCpuRegisters ENDP
|
|
|
|
;****************************************************************************
|
|
;* ChangeInterruptTable *
|
|
;* *
|
|
;* PURPOSE: Change Interrupt table *
|
|
;* DESCRIPTION: *
|
|
;* USES: *
|
|
;* PASSED: AX - Interrupt service number *
|
|
;* EDX - New Interrupt Segment:Offset *
|
|
;* SPECIAL: NOTHING. *
|
|
;* RETURNS: EAX - Original Interrupt Segment:offset *
|
|
;****************************************************************************
|
|
ChangeInterruptTable PROC NEAR
|
|
push es
|
|
push 0
|
|
pop es
|
|
shl eax, 2
|
|
push dword ptr es:[eax]
|
|
mov dword ptr es:[eax], edx
|
|
pop eax
|
|
pop es
|
|
ret
|
|
ChangeInterruptTable ENDP
|
|
|
|
CodeEnd:
|
|
END
|