diff --git a/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf b/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf index 8115a4a310..9ee0ebfe3d 100644 --- a/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf +++ b/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf @@ -40,6 +40,8 @@ Ia32/VirtualMemory.c Ia32/DxeLoadFunc.c Ia32/ImageRead.c + Ia32/IdtVectorAsm.asm + Ia32/IdtVectorAsm.S | GCC [Sources.X64] X64/DxeLoadFunc.c @@ -99,6 +101,7 @@ gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplBuildShareCodeHobs [FeaturePcd.IA32] + gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplEnableIdt gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode diff --git a/MdeModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c b/MdeModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c index 63ee2af396..bdece76187 100644 --- a/MdeModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c +++ b/MdeModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c @@ -46,6 +46,11 @@ GLOBAL_REMOVE_IF_UNREFERENCED CONST IA32_DESCRIPTOR gGdt = { (UINTN) gGdtEntries }; +GLOBAL_REMOVE_IF_UNREFERENCED IA32_DESCRIPTOR gLidtDescriptor = { + sizeof (X64_IDT_GATE_DESCRIPTOR) * 32 - 1, + 0 +}; + VOID HandOffToDxeCore ( IN EFI_PHYSICAL_ADDRESS DxeCoreEntryPoint, @@ -57,6 +62,11 @@ HandOffToDxeCore ( EFI_PHYSICAL_ADDRESS BaseOfStack; EFI_PHYSICAL_ADDRESS TopOfStack; UINTN PageTables; + X64_IDT_GATE_DESCRIPTOR *IdtTable; + UINTN SizeOfTemplate; + VOID *TemplateBase; + EFI_PHYSICAL_ADDRESS VectorAddress; + UINT32 Index; Status = PeiServicesAllocatePages (EfiBootServicesData, EFI_SIZE_TO_PAGES (STACK_SIZE), &BaseOfStack); ASSERT_EFI_ERROR (Status); @@ -95,7 +105,40 @@ HandOffToDxeCore ( ASSERT_EFI_ERROR (Status); AsmWriteCr3 (PageTables); - // + + + if (FeaturePcdGet (PcdDxeIplEnableIdt)) { + SizeOfTemplate = AsmGetVectorTemplatInfo (&TemplateBase); + + Status = PeiServicesAllocatePages ( + EfiBootServicesData, + EFI_SIZE_TO_PAGES((SizeOfTemplate + sizeof (X64_IDT_GATE_DESCRIPTOR)) * 32), + &VectorAddress + ); + + ASSERT_EFI_ERROR (Status); + + IdtTable = (X64_IDT_GATE_DESCRIPTOR *) (UINTN) (VectorAddress + SizeOfTemplate * 32); + for (Index = 0; Index < 32; Index++) { + IdtTable[Index].Ia32IdtEntry.Bits.GateType = 0x8e; + IdtTable[Index].Ia32IdtEntry.Bits.Reserved_0 = 0; + IdtTable[Index].Ia32IdtEntry.Bits.Selector = SYS_CODE64_SEL; + + IdtTable[Index].Ia32IdtEntry.Bits.OffsetLow = (UINT16) VectorAddress; + IdtTable[Index].Ia32IdtEntry.Bits.OffsetHigh = (UINT16) (VectorAddress >> 16); + IdtTable[Index].Offset32To63 = (UINT32) (VectorAddress >> 32); + IdtTable[Index].Reserved = 0; + + CopyMem ((VOID *) (UINTN) VectorAddress, TemplateBase, SizeOfTemplate); + AsmVectorFixup ((VOID *) (UINTN) VectorAddress, (UINT8) Index); + + VectorAddress += SizeOfTemplate; + } + + gLidtDescriptor.Base = (UINTN) IdtTable; + AsmWriteIdtr (&gLidtDescriptor); + } + // // Go to Long Mode. Interrupts will not get turned on until the CPU AP is loaded. // Call x64 drivers passing in single argument, a pointer to the HOBs. // diff --git a/MdeModulePkg/Core/DxeIplPeim/Ia32/IdtVectorAsm.S b/MdeModulePkg/Core/DxeIplPeim/Ia32/IdtVectorAsm.S new file mode 100644 index 0000000000..cbfcf6126a --- /dev/null +++ b/MdeModulePkg/Core/DxeIplPeim/Ia32/IdtVectorAsm.S @@ -0,0 +1,88 @@ +/* +;------------------------------------------------------------------------------- +; +; Copyright (c) 2007, Intel Corporation +; All rights reserved. This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php + +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; +; Module Name: +; +; IdtVectorAsm.S +; +; Abstract: +; +; +;-------------------------------------------------------------------- -------- +*/ + + .text + .code32 + + + .align 8 + .globl ASM_PFX(AsmGetVectorTemplatInfo) + .globl ASM_PFX(AsmVectorFixup) +/* +; +;----------------------------------------------------------------------- +; Template of IDT Vector Handlers. +; +;----------------------------------------------------------------------- +*/ +@VectorTemplateBase: + pushl %eax + .byte 0x6a # push #VectorNum +@VectorNum: + .byte 0 + movl CommonInterruptEntry, %eax + jmp *%eax +@VectorTemplateEnd: + + +ASM_PFX(AsmGetVectorTemplatInfo): + movl 4(%esp), %ecx + movl $@VectorTemplateBase, (%ecx) + movl $(@VectorTemplateEnd - @VectorTemplateBase), %eax + ret + +ASM_PFX(AsmVectorFixup): + movl 8(%esp), %eax + movl 4(%esp), %ecx + movb %al, (@VectorNum - @VectorTemplateBase)(%ecx) + ret + +/* +; The follow algorithm is used for the common interrupt routine. + +; +; +---------------------+ <-- 16-byte aligned ensured by processor +; + Old SS + +; +---------------------+ +; + Old RSP + +; +---------------------+ +; + RFlags + +; +---------------------+ +; + CS + +; +---------------------+ +; + RIP + +; +---------------------+ +; + Error Code + +; +---------------------+ +; + Vector Number + +; +---------------------+ +*/ + +CommonInterruptEntry: + cli +@@: + jmp @@ + + + + diff --git a/MdeModulePkg/Core/DxeIplPeim/Ia32/IdtVectorAsm.asm b/MdeModulePkg/Core/DxeIplPeim/Ia32/IdtVectorAsm.asm new file mode 100644 index 0000000000..46b49994a9 --- /dev/null +++ b/MdeModulePkg/Core/DxeIplPeim/Ia32/IdtVectorAsm.asm @@ -0,0 +1,95 @@ +;------------------------------------------------------------------------------- +; +; Copyright (c) 2007, Intel Corporation +; All rights reserved. This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php + +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; +; Module Name: +; +; IdtVectorAsm.asm +; +; Abstract: +; +; +;------------------------------------------------------------------------------- + + + .686p + .model flat,C + .code + +; +;------------------------------------------------------------------------------ +; Generic IDT Vector Handlers for the Host. +; +;------------------------------------------------------------------------------ + +ALIGN 8 +PUBLIC AsmGetVectorTemplatInfo +PUBLIC AsmVectorFixup + +PUBLIC AsmVectorFixup + +@VectorTemplateBase: + push eax + db 6ah ; push #VectorNumber +@VectorNum: + db 0 + mov eax, CommonInterruptEntry + jmp eax +@VectorTemplateEnd: + + +AsmGetVectorTemplatInfo PROC + mov ecx, [esp + 4] + mov [ecx], @VectorTemplateBase + mov eax, (@VectorTemplateEnd - @VectorTemplateBase) + ret +AsmGetVectorTemplatInfo ENDP + + +AsmVectorFixup PROC + mov eax, dword ptr [esp + 8] + mov ecx, [esp + 4] + mov [ecx + (@VectorNum - @VectorTemplateBase)], al + ret +AsmVectorFixup ENDP + + +;---------------------------------------; +; CommonInterruptEntry ; +;---------------------------------------; +; The follow algorithm is used for the common interrupt routine. + +; +; +---------------------+ <-- 16-byte aligned ensured by processor +; + Old SS + +; +---------------------+ +; + Old RSP + +; +---------------------+ +; + RFlags + +; +---------------------+ +; + CS + +; +---------------------+ +; + RIP + +; +---------------------+ +; + Error Code + +; +---------------------+ +; + Vector Number + +; +---------------------+ + +CommonInterruptEntry PROC + cli + + jmp $ +CommonInterruptEntry ENDP + +END + + diff --git a/MdeModulePkg/Core/DxeIplPeim/Ia32/VirtualMemory.h b/MdeModulePkg/Core/DxeIplPeim/Ia32/VirtualMemory.h index 89a7f2eceb..18fbcb907d 100644 --- a/MdeModulePkg/Core/DxeIplPeim/Ia32/VirtualMemory.h +++ b/MdeModulePkg/Core/DxeIplPeim/Ia32/VirtualMemory.h @@ -49,6 +49,12 @@ typedef union { UINT64 Uint64; } IA32_GDT; +typedef struct { + IA32_IDT_GATE_DESCRIPTOR Ia32IdtEntry; + UINT32 Offset32To63; + UINT32 Reserved; +} X64_IDT_GATE_DESCRIPTOR; + // // Page-Map Level-4 Offset (PML4) and // Page-Directory-Pointer Offset (PDPE) entries 4K & 2MB @@ -104,4 +110,38 @@ CreateIdentityMappingPageTables ( ) ; + +/** + + Fix up the vector number in the vector code. + + @param VectorBase Base address of the vector handler. + + @param VectorNum Index of vector. + +**/ +VOID +EFIAPI +AsmVectorFixup ( + VOID *VectorBase, + UINT8 VectorNum + ); + + +/** + + Get the information of vector template. + + @param TemplateBase Base address of the template code. + + @return Size of the Template code. + +**/ +UINTN +EFIAPI +AsmGetVectorTemplatInfo ( + OUT VOID **TemplateBase + ); + + #endif diff --git a/MdeModulePkg/MdeModulePkg.dec b/MdeModulePkg/MdeModulePkg.dec index 7b0f6607f5..b0027fe61c 100644 --- a/MdeModulePkg/MdeModulePkg.dec +++ b/MdeModulePkg/MdeModulePkg.dec @@ -161,5 +161,6 @@ [PcdsFeatureFlag.IA32] gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode|TRUE|BOOLEAN|0x0001003b + gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplEnableIdt|FALSE|BOOLEAN|0x0001003d diff --git a/MdeModulePkg/MdeModulePkg.dsc b/MdeModulePkg/MdeModulePkg.dsc index d06c02000b..5da6d7658c 100644 --- a/MdeModulePkg/MdeModulePkg.dsc +++ b/MdeModulePkg/MdeModulePkg.dsc @@ -302,6 +302,7 @@ [PcdsFeatureFlag.IA32] gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode|TRUE + gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplEnableIdt|FALSE [PcdsFixedAtBuild.common] gEfiMdePkgTokenSpaceGuid.PcdMaximumUnicodeStringLength|1000000 diff --git a/Nt32Pkg/Nt32Pkg.dsc b/Nt32Pkg/Nt32Pkg.dsc index a54ff4de2a..afdf42df1c 100644 --- a/Nt32Pkg/Nt32Pkg.dsc +++ b/Nt32Pkg/Nt32Pkg.dsc @@ -297,6 +297,7 @@ gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdStatusCodeUseMemory|FALSE gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdStatusCodeUseOEM|TRUE gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode|FALSE + gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplEnableIdt|FALSE gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSupportEfiDecompress|TRUE gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSupportTianoDecompress|TRUE gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSupportCustomDecompress|TRUE