int.c
来自「Next BIOS Source code : Extensible Firmw」· C语言 代码 · 共 859 行 · 第 1/2 页
C
859 行
/*++
Copyright (c) 1999 - 2002 Intel Corporation. All rights reserved
This software and associated documentation (if any) is furnished
under a license and may only be used or copied in accordance
with the terms of the license. Except as permitted by such
license, no part of this software or documentation may be
reproduced, stored in a retrieval system, or transmitted in any
form or by any means without the express written consent of
Intel Corporation.
Module Name:
init.c
Abstract:
Main entry point on EFI 32-bit emulation environment. This envirnment layers
on top of the of a legacy BIOS
Revision History
--*/
#include "efi.h"
#include "efilib.h"
#include "Int86.h"
#include "PlIntCtrl.h"
#include "PlTpl.h"
//
// Interesting CR0 flags
//
#define CR0_PE 0x00000001
//
// Processor structres are packed
//
#pragma pack (1)
//
// Define what a processor GDT looks like
//
typedef struct {
UINT32 LimitLo : 16;
UINT32 BaseLo : 16;
UINT32 BaseMid : 8;
UINT32 Type : 4;
UINT32 System : 1;
UINT32 Dpl : 2;
UINT32 Present : 1;
UINT32 LimitHi : 4;
UINT32 Software : 1;
UINT32 Reserved : 1;
UINT32 DefaultSize : 1;
UINT32 Granularity : 1;
UINT32 BaseHi : 8;
} GDT ;
//
// Define what a processor descriptor looks like
//
typedef struct {
UINT16 Limit;
UINT32 Base;
} DESCRIPTOR;
#pragma pack ()
//
// Low stub lay out
//
#define LOW_STACK_SIZE (8*1024) // 8k?
typedef struct {
//
// Space for the code
//
CHAR8 Code[4096]; // ?
//
// Data for the code (cs releative)
//
DESCRIPTOR GdtDesc; // Protected mode GDT
DESCRIPTOR IdtDesc; // Protected mode IDT
UINT32 FlatSs;
UINT32 FlatEsp;
UINT32 LowCodeSelector; // Low code selector in GDT
UINT32 LowDataSelector; // Low data selector in GDT
UINT32 LowStack;
DESCRIPTOR RealModeIdtDesc;
//
// A low memory stack
//
CHAR8 Stack[LOW_STACK_SIZE];
} LOW_MEMORY_THUNK;
//
// Globals
//
LOW_MEMORY_THUNK *IntThunk;
STATIC BOOLEAN BiosIntCallerInitialized = FALSE;
//
//
//
BOOLEAN
Int86 (
IN UINT8 BiosInt,
IN IA32_RegisterSet_t *Regs
)
// returns carry flag
{
UINTN Status;
UINT16 *S16;
BOOLEAN SavedInterruptState;
Regs->x.Flags.Reserved1 = 1;
Regs->x.Flags.Reserved2 = 0;
Regs->x.Flags.Reserved3 = 0;
Regs->x.Flags.Reserved4 = 0;
Regs->x.Flags.IOPL = 3;
Regs->x.Flags.NT = 0;
Regs->x.Flags.IF = 1;
Regs->x.Flags.TF = 0;
S16 = (UINT16 *) (IntThunk->Stack + LOW_STACK_SIZE);
//
// Copy regs to low memory stack
//
S16 -= sizeof(IA32_RegisterSet_t) / sizeof(UINT16);
CopyMem (S16, Regs, sizeof(IA32_RegisterSet_t));
//
// Provide low stack esp
//
IntThunk->LowStack = ((UINT32) S16) - ((UINT32) IntThunk);
SavedInterruptState = PlSetInterruptState(FALSE); // insure interrupts are turned off
PlSetupInterruptControllerMask(INT_CTRLR_BIOSMODE); // Save/Setup interrupt controller mask
//
// Call the real mode int thunk code
//
_asm {
movzx ecx, BiosInt
mov edx, 0
mov eax, IntThunk
call eax
mov Status, eax
}
PlSetupInterruptControllerMask(INT_CTRLR_EFIMODE); // Save/Setup interrupt controller mask
PlSetInterruptState(SavedInterruptState); // Restore interrupt flag
PlGenerateIrq (0);
//
// Return the resulting registers
//
CopyMem (Regs, S16, sizeof(IA32_RegisterSet_t));
return Regs->x.Flags.CF ? TRUE : FALSE;
}
BOOLEAN
FarCall86 (
IN UINT16 Segment,
IN UINT16 Offset,
IN IA32_RegisterSet_t *Regs,
IN VOID *Stack,
IN UINTN StackSize
)
// returns carry flag
{
UINT32 CallAddress;
UINTN Status;
UINT16 *S16;
BOOLEAN SavedInterruptState;
CallAddress = (Segment<<16) | Offset;
Regs->x.Flags.Reserved1 = 1;
Regs->x.Flags.Reserved2 = 0;
Regs->x.Flags.Reserved3 = 0;
Regs->x.Flags.Reserved4 = 0;
Regs->x.Flags.IOPL = 3;
Regs->x.Flags.NT = 0;
Regs->x.Flags.IF = 1;
Regs->x.Flags.TF = 0;
S16 = (UINT16 *) (IntThunk->Stack + LOW_STACK_SIZE);
if (Stack!=NULL && StackSize!=0) {
//
// Copy Stack to low memory stack
//
S16 -= StackSize / sizeof(UINT16);
CopyMem (S16, Stack, StackSize);
}
//
// Copy regs to low memory stack
//
S16 -= sizeof(IA32_RegisterSet_t) / sizeof(UINT16);
CopyMem (S16, Regs, sizeof(IA32_RegisterSet_t));
//
// Provide low stack esp
//
IntThunk->LowStack = ((UINT32) S16) - ((UINT32) IntThunk);
SavedInterruptState = PlSetInterruptState(FALSE);
PlSetupInterruptControllerMask(INT_CTRLR_BIOSMODE); // Save/Setup interrupt controller
//
// Call the real mode int thunk code
//
_asm {
mov ecx, 0
mov edx, CallAddress
mov eax, IntThunk
call eax
mov Status, eax
}
PlSetupInterruptControllerMask(INT_CTRLR_EFIMODE);
PlSetInterruptState(SavedInterruptState);
PlGenerateIrq (0);
//
// Return the resulting registers
//
CopyMem (Regs, S16, sizeof(IA32_RegisterSet_t));
S16 += sizeof(IA32_RegisterSet_t) / sizeof(UINT16);
if (Stack!=NULL && StackSize!=0) {
//
// Copy low memory stack to Stack
//
CopyMem (Stack, S16, StackSize);
S16 += StackSize / sizeof(UINT16);
}
return Regs->x.Flags.CF ? TRUE : FALSE;
}
VOID
RealModeTemplate (
OUT UINT32 *LowCodeStart,
OUT UINT32 *LowCodeEnd
)
{
_asm {
mov eax, LowCodeStart
mov ecx, offset LCS0
mov [eax], ecx
mov eax, LowCodeEnd
mov ecx, offset LCS99
mov [eax], ecx
; patch in the far jump to 16bit protected mode
mov eax, offset LCSP3
mov ecx, offset LCS1
sub ecx, offset LCS0
mov [eax], ecx
mov ecx, IntThunk
mov ecx, LOW_MEMORY_THUNK [ecx].LowCodeSelector
mov [eax+4], cx
; patch in the far jump to real-mode
mov eax, offset LCSP4
mov ecx, offset LCS40
sub ecx, offset LCS0
mov [eax], cx
mov edx, IntThunk
shr edx, 4
mov [eax+2], dx
; patch in the real-mode ss
mov word ptr [LCSP5], dx
; patch in the far jump back to flat mode
mov eax, offset LCSP1
mov ecx, offset LCS90
mov [eax], ecx
mov cx, cs
mov [eax+4], cx
; path in flat ds value for restore
mov ax, ds
mov word ptr [LCSP2], ax
; patch in GdtDesc
mov ecx, IntThunk
mov ax, LOW_MEMORY_THUNK [ecx].GdtDesc
mov word ptr [LGDT0], ax
mov ax, LOW_MEMORY_THUNK [ecx+2].GdtDesc
mov word ptr [LGDT1], ax
mov ax, LOW_MEMORY_THUNK [ecx+4].GdtDesc
mov word ptr [LGDT2], ax
}
// always return
if (*LowCodeStart) {
return ;
}
//
// real mode int thunk code
//
_asm {
LCS0:
;
; Save protected mode registers
; CL = BiosInt to invoke
;
pushfd ; Save flags
cli
push edi ; Save C regs
push esi
push ebp
push edx
push ebx
mov esi, IntThunk ; esi = IntThunk
;
; Save flat 32bit stack location
;
mov LOW_MEMORY_THUNK [esi].FlatEsp, esp
;
; Patch in BiosInt value into low memory thunk
;
cmp edx,0
jne PatchFarCall
mov eax, esi
add eax, offset LCSP6
sub eax, offset LCS0
mov [eax-1], 0xcd ; INT inst
mov [eax], cl ; INT #
mov [eax+1], 0x90 ; NOP
mov [eax+2], 0x90 ; NOP
mov [eax+3], 0x90 ; NOP
jmp PatchComplete
PatchFarCall:
mov eax, esi
add eax, offset LCSP6
sub eax, offset LCS0
mov [eax-1], 0x9a ; CALL inst
mov [eax], edx ; Fill in SEG:OFF
PatchComplete:
;
; Set idt for real mode IVT
;
lidt fword ptr LOW_MEMORY_THUNK [esi].RealModeIdtDesc
;
; Load real-mode style selectors limits
;
mov eax, LOW_MEMORY_THUNK [esi].LowDataSelector
mov ebx, LOW_MEMORY_THUNK [esi].LowStack
mov gs, ax
mov fs, ax
mov es, ax
mov ds, ax
mov ss, ax
mov esp, ebx
_emit 0xEA ; jmp far 16:32
LCSP3: _emit 0x00 ; offset
_emit 0x00 ; (LCS1)
_emit 0x00
_emit 0x00
_emit 0x00 ; selector
_emit 0x00 ; (16bit CS)
LCS1:
;
; We are now in 16bit protcted mode, on the low memory
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?