alder_lake_bios/Insyde/InsydeModulePkg/Csm/BiosThunk/Int15ServiceSmm/Int15Rom/Int15Rom.asm

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