int.c
来自「Next BIOS Source code : Extensible Firmw」· C语言 代码 · 共 859 行 · 第 1/2 页
C
859 行
;
;
; Turn protected mode off
;
_emit 0x66
mov eax, cr0
_emit 0x66
and eax, not CR0_PE
_emit 0x66
mov cr0, eax
_emit 0xEA ; jmp far 16:16
LCSP4: _emit 0x00 ; offset
_emit 0x00 ; (LCS40)
_emit 0x00 ; segment
_emit 0x00 ; (realmode cs)
LCS40:
;
; We are now in real mode
; Fix SS
;
_emit 0xb8 ; mov ax,
LCSP5: _emit 0x00 ; (readmode ss)
_emit 0x00
_emit 0x8e ; mov ss, ax
_emit 0xd0
sti
;
; Load regs with callers request
; NOTE1: that this pop sequence matches the
; IA32_RegisterSet_t structure.
; NOTE2: the follow instructions are really executed
; as 16 bit instructions as we are in real mode
;
pop eax
pop ebx
pop ecx
pop edx
pop esi
pop edi
popfd
pop es
pop ebp ; throw away cs
pop ebp ; throw away ss
pop ds
pop ebp
_emit 0xcd ; issue NT or a FAR CALL
LCSP6: _emit 00 ; INT # or OFFSET
_emit 0x90 ; NOP or OFFSET
_emit 0x90 ; NOP or SEGMENT
_emit 0x90 ; NOP or SEGMENT
;
; Save the result regs
; See the above NOTEs
;
push ebp
mov ebp, eax ; save eax
push ds
push eax ; throw away ss
push eax ; throw away cs
push es
pushfd
push edi
push esi
push edx
push ecx
push ebx
push ebp ; ax results are in bp
;
; Test to see if the A20 Gate needs to be enabled
;
TestA20Gate:
cli
push es
push ds
_emit 0x31 ; xor ax,ax ax = 0
_emit 0xc0
_emit 0x89 ; mov si,ax si = 0
_emit 0xc6
_emit 0x89 ; mov bp,ax bp = 0
_emit 0xc5
_emit 0x8e ; mov ds,ax ds = 0
_emit 0xd8
_emit 0x48 ; dec ax ax = ffff
_emit 0x8e ; mov es,ax es = ffff
_emit 0xc0
_emit 0x8a ; mov cl,[si] cl = ds:[si] = 0000:0000
_emit 0x0c
_emit 0x26 ; es:
_emit 0x8a ; mov ch,[bp+10] ch = es:[bp+10] = ffff:0000+10 = ffff:0010
_emit 0x6e
_emit 0x10
_emit 0xc6 ; mov byte ptr [si],aa ds:[si] = aa 0000:0000 = aa
_emit 0x04
_emit 0xaa
_emit 0x26 ; es:
_emit 0xc6 ; mov byte ptr [bp+10],55 es:[bp+10] = 55 ffff:0010 = 55
_emit 0x46
_emit 0x10
_emit 0x55
_emit 0x80 ; cmp byte ptr [si],aa ds:[si] = 0000:0000
_emit 0x3c
_emit 0xaa
_emit 0x88 ; mov [si],cl ds:[si] = 0000:0000
_emit 0x0c
_emit 0x26 ; es:
_emit 0x88 ; mov [bp+10],ch es:[bp+10] = ffff:0010
_emit 0x6e
_emit 0x10
jnz EnableA20Gate
pop ds
pop es
sti
jmp A20GateEnabled
EnableA20Gate:
pop ds
pop es
sti
;
; Enable A20 Mask
;
_emit 0xb8 ; mov ax,2401h
_emit 0x01
_emit 0x24
_emit 0xcd ; INT 15h
_emit 0x15
jnc TestA20Gate ; Jump if it suceeded
mov ecx,0
Empty8042Loop0:
_emit 0xe7 ; out DELAYPORT,ax
_emit 0xed
_emit 0xe4 ; in al,KBD_STATUS_PORT
_emit 0x64
_emit 0x24 ; and al,02h
_emit 0x02
loopnz Empty8042Loop0
jnz Timeout8042
_emit 0xe7 ; out DELAYPORT,ax
_emit 0xed
_emit 0xb0 ; mov al,WRITE_DATA_PORT_CMD
_emit 0xd1
_emit 0xe6 ; out KBD_STATUS_PORT,al
_emit 0x64
mov ecx,0
Empty8042Loop1:
_emit 0xe7 ; out DELAYPORT,ax
_emit 0xed
_emit 0xe4 ; in al,KBD_STATUS_PORT
_emit 0x64
_emit 0x24 ; and al,02h
_emit 0x02
loopnz Empty8042Loop1
jnz Timeout8042
_emit 0xb0 ; mov al,ENABLE_A20_CMD
_emit 0xdf
_emit 0xe6 ; out KBD_CONTROL_PORT,al
_emit 0x60
mov ecx,0
Empty8042Loop2:
_emit 0xe7 ; out DELAYPORT,ax
_emit 0xed
_emit 0xe4 ; in al,KBD_STATUS_PORT
_emit 0x64
_emit 0x24 ; and al,02h
_emit 0x02
loopnz Empty8042Loop2
mov ecx,25
Delay25uS:
_emit 0xe7 ; out DELAYPORT,ax
_emit 0xed
loop Delay25uS
jmp TestA20Gate
Timeout8042:
A20GateEnabled:
cli
_emit 0xb8 ; mov ax,
LGDT2: _emit 0x00 ; GDTR
_emit 0x00
push eax
_emit 0xb8 ; mov ax,
LGDT1: _emit 0x00 ; GDTR
_emit 0x00
push eax
_emit 0xb8 ; mov ax,
LGDT0: _emit 0x00 ; GDTR
_emit 0x00
push eax
push ss
pop ds
mov ebx,esp
pop eax
pop eax
pop eax
; lgdt fword ptr [bx]
_emit 0x66
_emit 0x0f
_emit 0x01
_emit 0x17
;
; Turn protected mode on
;
_emit 0x66
mov eax, cr0
_emit 0x66
or eax, CR0_PE
_emit 0x66
mov cr0, eax
;
; Return to 32 bit flat mode
; Put flat DS in ax
;
_emit 0xb8 ; mov ax,
LCSP2: _emit 0x00 ; flat ds
_emit 0x00
;
; Return to 32 bit cs
;
_emit 0x66
_emit 0xEA ; jmp far 16:32
LCSP1: _emit 0x00 ; offset
_emit 0x00 ; (LCS90)
_emit 0x00
_emit 0x00
_emit 0x00 ; selector
_emit 0x00 ; (flat CS)
LCS90:
; restore data selector
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
;
; Restore 32bit Idt
;
mov esi, IntThunk
lidt fword ptr LOW_MEMORY_THUNK [esi].IdtDesc
;
; Restore 32bit stack
;
mov ecx, LOW_MEMORY_THUNK [esi].FlatSs
mov ss, cx
mov esp, LOW_MEMORY_THUNK [esi].FlatEsp
xor eax, eax
lldt ax
;
; Restore c regs
;
pop ebx
pop edx
pop ebp
pop esi
pop edi
popfd
ret
LCS99: nop
}
}
VOID
InitializeBiosIntCaller (
VOID
)
{
EFI_PHYSICAL_ADDRESS MemPage;
EFI_STATUS Status;
GDT *CodeGdt, *DataGdt;
UINT32 LowCodeStart, LowCodeEnd, Base;
//
// Allocate 1 page below 1MB to put real mode thunk code in
//
MemPage = ONEMB - 1;
Status = BS->AllocatePages (
AllocateMaxAddress,
EfiBootServicesCode,
sizeof(LOW_MEMORY_THUNK) / 4096 + 1,
&MemPage
);
ASSERT (!EFI_ERROR(Status));
IntThunk = (LOW_MEMORY_THUNK *) MemPage;
//
// Capture the flat gdt, idt, and selector values
//
_asm {
mov ecx, IntThunk
sgdt [ecx].GdtDesc
sidt [ecx].IdtDesc
mov ax, ss
movzx eax, ax
mov [ecx].FlatSs, eax
}
//
// Allocate a new GDT for real-mode code
//
// BUGBUG: we're just assuming that the first selector
// that is not is use is something we can allocate
//
for (CodeGdt = ((GDT *) IntThunk->GdtDesc.Base) + 1; CodeGdt->Present; CodeGdt += 1) ;
//
// Fill in the new descriptor to by our real-mode segment value
//
CodeGdt->Type = 0xA; // code/read
CodeGdt->System = 1;
CodeGdt->Dpl = 0;
CodeGdt->Present = 1;
CodeGdt->Software = 0;
CodeGdt->Reserved = 0;
CodeGdt->DefaultSize = 0; // 16 bit operands
CodeGdt->Granularity = 0;
CodeGdt->LimitHi = 0;
CodeGdt->LimitLo = 0xffff;
Base = ((UINT32) IntThunk);
CodeGdt->BaseHi = (Base >> 24) & 0xFF;
CodeGdt->BaseMid = (Base >> 16) & 0xFF;
CodeGdt->BaseLo = Base & 0xFFFF;
//
// Allocate a new GDT for read-mode data
//
for (DataGdt = CodeGdt; DataGdt->Present; DataGdt += 1) ;
CopyMem (DataGdt, CodeGdt, sizeof(GDT));
DataGdt->Type = 0x2; // read/write data
//
// Compute selector value
//
IntThunk->LowCodeSelector = ((UINT32) CodeGdt) - IntThunk->GdtDesc.Base;
IntThunk->LowDataSelector = ((UINT32) DataGdt) - IntThunk->GdtDesc.Base;
IntThunk->RealModeIdtDesc.Limit = 0xFFFF;
IntThunk->RealModeIdtDesc.Base = 0;
//
// Initialize low real-mode code thunk
//
RealModeTemplate (&LowCodeStart, &LowCodeEnd);
CopyMem (IntThunk->Code, (VOID *) LowCodeStart, LowCodeEnd-LowCodeStart);
BiosIntCallerInitialized = TRUE;
}
BOOLEAN
Int86Available (
VOID
)
{
return BiosIntCallerInitialized;
}
VOID
PlGenerateIrq(
UINT8 irq
)
{
UINT8 interrupt;
interrupt = PlGetVectorFromIrq(irq);
if (interrupt) _asm {
mov ecx, offset PatchInt
mov al, [interrupt]
mov [ecx], al
jmp DoInterrupt
DoInterrupt:
_emit 0xcd
PatchInt: _emit 0
}
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?