diff options
Diffstat (limited to 'src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuDxe/CpuGdt.c')
-rw-r--r-- | src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuDxe/CpuGdt.c | 183 |
1 files changed, 183 insertions, 0 deletions
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuDxe/CpuGdt.c b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuDxe/CpuGdt.c new file mode 100644 index 00000000..8fed6209 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuDxe/CpuGdt.c @@ -0,0 +1,183 @@ +/** @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.<BR> + 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 + ) +{ +#ifndef VBOX + EFI_STATUS Status; +#endif + GDT_ENTRIES *Gdt; + IA32_DESCRIPTOR Gdtr; +#ifndef VBOX + EFI_PHYSICAL_ADDRESS Memory; +#endif + + // + // 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. + // +#ifndef VBOX + 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; +#else + /* + * Apples bootloader boot.efi for at least OS X Tiger, Leopard and Snow Leopard + * relocates runtime regions which doesn't make sense for the GDT as the GDTR is not + * updated and would point to invalid memory. Allocate the memory as reserved to hopefully + * keep the bootloaders hands off of it, see also OvmfPkg/PlatformPei/Platform.c + * (search for PeiServicesAllocatePages()) for a more detailed explanation of a + * related bug in Apples bootloader. + */ + Gdt = AllocateReservedPool (sizeof (mGdtTemplate) + 8); + ASSERT (Gdt != NULL); + Gdt = ALIGN_POINTER (Gdt, 8); +#endif + + // + // 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); +} |