/** @file C based implementation of IA32 interrupt handling only requiring a minimal assembly interrupt entry point. Copyright (c) 2006 - 2021, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include "CpuDxe.h" #include "CpuGdt.h" // // Global descriptor table (GDT) Template // STATIC GDT_ENTRIES mGdtTemplate = { // // NULL_SEL // { 0x0, // limit 15:0 0x0, // base 15:0 0x0, // base 23:16 0x0, // type 0x0, // limit 19:16, flags 0x0, // base 31:24 }, // // LINEAR_SEL // { 0x0FFFF, // limit 15:0 0x0, // base 15:0 0x0, // base 23:16 0x092, // present, ring 0, data, read/write 0x0CF, // page-granular, 32-bit 0x0, }, // // LINEAR_CODE_SEL // { 0x0FFFF, // limit 15:0 0x0, // base 15:0 0x0, // base 23:16 0x09F, // present, ring 0, code, execute/read, conforming, accessed 0x0CF, // page-granular, 32-bit 0x0, }, // // SYS_DATA_SEL // { 0x0FFFF, // limit 15:0 0x0, // base 15:0 0x0, // base 23:16 0x093, // present, ring 0, data, read/write, accessed 0x0CF, // page-granular, 32-bit 0x0, }, // // SYS_CODE_SEL // { 0x0FFFF, // limit 15:0 0x0, // base 15:0 0x0, // base 23:16 0x09A, // present, ring 0, code, execute/read 0x0CF, // page-granular, 32-bit 0x0, }, // // SYS_CODE16_SEL // { 0x0FFFF, // limit 15:0 0x0, // base 15:0 0x0, // base 23:16 0x09A, // present, ring 0, code, execute/read 0x08F, // page-granular, 16-bit 0x0, // base 31:24 }, // // LINEAR_DATA64_SEL // { 0x0FFFF, // limit 15:0 0x0, // base 15:0 0x0, // base 23:16 0x092, // present, ring 0, data, read/write 0x0CF, // page-granular, 32-bit 0x0, }, // // LINEAR_CODE64_SEL // { 0x0FFFF, // limit 15:0 0x0, // base 15:0 0x0, // base 23:16 0x09A, // present, ring 0, code, execute/read 0x0AF, // page-granular, 64-bit code 0x0, // base (high) }, // // SPARE5_SEL // { 0x0, // limit 15:0 0x0, // base 15:0 0x0, // base 23:16 0x0, // type 0x0, // limit 19:16, flags 0x0, // base 31:24 }, }; /** Initialize Global Descriptor Table. **/ VOID InitGlobalDescriptorTable ( VOID ) { EFI_STATUS Status; GDT_ENTRIES *Gdt; IA32_DESCRIPTOR Gdtr; EFI_PHYSICAL_ADDRESS Memory; // // Allocate Runtime Data below 4GB for the GDT // AP uses the same GDT when it's waken up from real mode so // the GDT needs to be below 4GB. // Memory = SIZE_4GB - 1; Status = gBS->AllocatePages ( AllocateMaxAddress, EfiRuntimeServicesData, EFI_SIZE_TO_PAGES (sizeof (mGdtTemplate)), &Memory ); ASSERT_EFI_ERROR (Status); ASSERT ((Memory != 0) && (Memory < SIZE_4GB)); Gdt = (GDT_ENTRIES *)(UINTN)Memory; // // Initialize all GDT entries // CopyMem (Gdt, &mGdtTemplate, sizeof (mGdtTemplate)); // // Write GDT register // Gdtr.Base = (UINT32)(UINTN)Gdt; Gdtr.Limit = (UINT16)(sizeof (mGdtTemplate) - 1); AsmWriteGdtr (&Gdtr); // // Update selector (segment) registers base on new GDT // SetCodeSelector ((UINT16)CPU_CODE_SEL); SetDataSelectors ((UINT16)CPU_DATA_SEL); }