--- /dev/null
+/** @file\r
+\r
+ Copyright (c) 2011 - 2012, Intel Corporation. All rights reserved.<BR>\r
+\r
+ This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "LoadLinuxLib.h"\r
+\r
+\r
+/**\r
+ A simple check of the kernel setup image\r
+\r
+ An assumption is made that the size of the data is at least the\r
+ size of struct boot_params.\r
+\r
+ @param[in] KernelSetup - The kernel setup image\r
+\r
+ @retval EFI_SUCCESS - The kernel setup looks valid and supported\r
+ @retval EFI_INVALID_PARAMETER - KernelSetup was NULL\r
+ @retval EFI_UNSUPPORTED - The kernel setup is not valid or supported\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+BasicKernelSetupCheck (\r
+ IN VOID *KernelSetup\r
+ )\r
+{\r
+ return LoadLinuxCheckKernelSetup(KernelSetup, sizeof (struct boot_params));\r
+}\r
+\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+LoadLinuxCheckKernelSetup (\r
+ IN VOID *KernelSetup,\r
+ IN UINTN KernelSetupSize\r
+ )\r
+{\r
+ struct boot_params *Bp;\r
+\r
+ if (KernelSetup == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (KernelSetupSize < sizeof (*Bp)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ Bp = (struct boot_params*) KernelSetup;\r
+\r
+ if ((Bp->hdr.signature != 0xAA55) || // Check boot sector signature\r
+ (Bp->hdr.header != SETUP_HDR) ||\r
+ (Bp->hdr.version < 0x205) // We only support relocatable kernels\r
+ ) {\r
+ return EFI_UNSUPPORTED;\r
+ } else {\r
+ return EFI_SUCCESS;\r
+ }\r
+}\r
+\r
+\r
+UINTN\r
+EFIAPI\r
+LoadLinuxGetKernelSize (\r
+ IN VOID *KernelSetup,\r
+ IN UINTN KernelSize\r
+ )\r
+{\r
+ struct boot_params *Bp;\r
+\r
+ if (EFI_ERROR (BasicKernelSetupCheck (KernelSetup))) {\r
+ return 0;\r
+ }\r
+\r
+ Bp = (struct boot_params*) KernelSetup;\r
+\r
+ if (Bp->hdr.version > 0x20a) {\r
+ return Bp->hdr.init_size;\r
+ } else {\r
+ //\r
+ // Add extra size for kernel decompression\r
+ //\r
+ return 3 * KernelSize;\r
+ }\r
+}\r
+\r
+\r
+VOID*\r
+EFIAPI\r
+LoadLinuxAllocateKernelSetupPages (\r
+ IN UINTN Pages\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_PHYSICAL_ADDRESS Address;\r
+\r
+ Address = BASE_1GB;\r
+ Status = gBS->AllocatePages (\r
+ AllocateMaxAddress,\r
+ EfiLoaderData,\r
+ Pages,\r
+ &Address\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ return (VOID*)(UINTN) Address;\r
+ } else {\r
+ return NULL;\r
+ }\r
+}\r
+\r
+\r
+VOID*\r
+EFIAPI\r
+LoadLinuxAllocateKernelPages (\r
+ IN VOID *KernelSetup,\r
+ IN UINTN Pages\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_PHYSICAL_ADDRESS KernelAddress;\r
+ UINT32 Loop;\r
+ struct boot_params *Bp;\r
+\r
+ if (EFI_ERROR (BasicKernelSetupCheck (KernelSetup))) {\r
+ return NULL;\r
+ }\r
+\r
+ Bp = (struct boot_params*) KernelSetup;\r
+\r
+ for (Loop = 1; Loop < 512; Loop++) {\r
+ KernelAddress = MultU64x32 (\r
+ 2 * Bp->hdr.kernel_alignment,\r
+ Loop\r
+ );\r
+ Status = gBS->AllocatePages (\r
+ AllocateAddress,\r
+ EfiLoaderData,\r
+ Pages,\r
+ &KernelAddress\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ return (VOID*)(UINTN) KernelAddress;\r
+ }\r
+ }\r
+\r
+ return NULL;\r
+}\r
+\r
+\r
+VOID*\r
+EFIAPI\r
+LoadLinuxAllocateCommandLinePages (\r
+ IN UINTN Pages\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_PHYSICAL_ADDRESS Address;\r
+\r
+ Address = 0xa0000;\r
+ Status = gBS->AllocatePages (\r
+ AllocateMaxAddress,\r
+ EfiLoaderData,\r
+ Pages,\r
+ &Address\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ return (VOID*)(UINTN) Address;\r
+ } else {\r
+ return NULL;\r
+ }\r
+}\r
+\r
+\r
+VOID*\r
+EFIAPI\r
+LoadLinuxAllocateInitrdPages (\r
+ IN VOID *KernelSetup,\r
+ IN UINTN Pages\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_PHYSICAL_ADDRESS Address;\r
+\r
+ struct boot_params *Bp;\r
+\r
+ if (EFI_ERROR (BasicKernelSetupCheck (KernelSetup))) {\r
+ return NULL;\r
+ }\r
+\r
+ Bp = (struct boot_params*) KernelSetup;\r
+\r
+ Address = (EFI_PHYSICAL_ADDRESS)(UINTN) Bp->hdr.ramdisk_max;\r
+ Status = gBS->AllocatePages (\r
+ AllocateMaxAddress,\r
+ EfiLoaderData,\r
+ Pages,\r
+ &Address\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ return (VOID*)(UINTN) Address;\r
+ } else {\r
+ return NULL;\r
+ }\r
+}\r
+\r
+\r
+STATIC\r
+VOID\r
+SetupLinuxMemmap (\r
+ IN OUT struct boot_params *Bp\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINT8 TmpMemoryMap[1];\r
+ UINTN MapKey;\r
+ UINTN DescriptorSize;\r
+ UINT32 DescriptorVersion;\r
+ UINTN MemoryMapSize;\r
+ EFI_MEMORY_DESCRIPTOR *MemoryMap;\r
+ EFI_MEMORY_DESCRIPTOR *MemoryMapPtr;\r
+ UINTN Index;\r
+ struct efi_info *Efi;\r
+ struct e820_entry *LastE820;\r
+ struct e820_entry *E820;\r
+ UINTN E820EntryCount;\r
+ EFI_PHYSICAL_ADDRESS LastEndAddr;\r
+\r
+ //\r
+ // Get System MemoryMapSize\r
+ //\r
+ MemoryMapSize = sizeof (TmpMemoryMap);\r
+ Status = gBS->GetMemoryMap (\r
+ &MemoryMapSize,\r
+ (EFI_MEMORY_DESCRIPTOR *)TmpMemoryMap,\r
+ &MapKey,\r
+ &DescriptorSize,\r
+ &DescriptorVersion\r
+ );\r
+ ASSERT (Status == EFI_BUFFER_TOO_SMALL);\r
+ //\r
+ // Enlarge space here, because we will allocate pool now.\r
+ //\r
+ MemoryMapSize += EFI_PAGE_SIZE;\r
+ MemoryMap = AllocatePool (MemoryMapSize);\r
+ ASSERT (MemoryMap != NULL);\r
+\r
+ //\r
+ // Get System MemoryMap\r
+ //\r
+ Status = gBS->GetMemoryMap (\r
+ &MemoryMapSize,\r
+ MemoryMap,\r
+ &MapKey,\r
+ &DescriptorSize,\r
+ &DescriptorVersion\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ LastE820 = NULL;\r
+ E820 = &Bp->e820_map[0];\r
+ E820EntryCount = 0;\r
+ LastEndAddr = 0;\r
+ MemoryMapPtr = MemoryMap;\r
+ for (Index = 0; Index < (MemoryMapSize / DescriptorSize); Index++) {\r
+ UINTN E820Type = 0;\r
+\r
+ if (MemoryMap->NumberOfPages == 0) {\r
+ continue;\r
+ }\r
+\r
+ switch(MemoryMap->Type) {\r
+ case EfiReservedMemoryType:\r
+ case EfiRuntimeServicesCode:\r
+ case EfiRuntimeServicesData:\r
+ case EfiMemoryMappedIO:\r
+ case EfiMemoryMappedIOPortSpace:\r
+ case EfiPalCode:\r
+ E820Type = E820_RESERVED;\r
+ break;\r
+\r
+ case EfiUnusableMemory:\r
+ E820Type = E820_UNUSABLE;\r
+ break;\r
+\r
+ case EfiACPIReclaimMemory:\r
+ E820Type = E820_ACPI;\r
+ break;\r
+\r
+ case EfiLoaderCode:\r
+ case EfiLoaderData:\r
+ case EfiBootServicesCode:\r
+ case EfiBootServicesData:\r
+ case EfiConventionalMemory:\r
+ E820Type = E820_RAM;\r
+ break;\r
+\r
+ case EfiACPIMemoryNVS:\r
+ E820Type = E820_NVS;\r
+ break;\r
+\r
+ default:\r
+ DEBUG ((\r
+ EFI_D_ERROR,\r
+ "Invalid EFI memory descriptor type (0x%x)!\n",\r
+ MemoryMap->Type\r
+ ));\r
+ continue;\r
+ }\r
+\r
+ if ((LastE820 != NULL) &&\r
+ (LastE820->type == (UINT32) E820Type) &&\r
+ (MemoryMap->PhysicalStart == LastEndAddr)) {\r
+ LastE820->size += EFI_PAGES_TO_SIZE (MemoryMap->NumberOfPages);\r
+ LastEndAddr += EFI_PAGES_TO_SIZE (MemoryMap->NumberOfPages);\r
+ } else {\r
+ if (E820EntryCount >= (sizeof (Bp->e820_map) / sizeof (Bp->e820_map[0]))) {\r
+ break;\r
+ }\r
+ E820->type = (UINT32) E820Type;\r
+ E820->addr = MemoryMap->PhysicalStart;\r
+ E820->size = EFI_PAGES_TO_SIZE (MemoryMap->NumberOfPages);\r
+ LastE820 = E820;\r
+ LastEndAddr = E820->addr + E820->size;\r
+ E820++;\r
+ E820EntryCount++;\r
+ }\r
+\r
+ //\r
+ // Get next item\r
+ //\r
+ MemoryMap = (EFI_MEMORY_DESCRIPTOR *)((UINTN)MemoryMap + DescriptorSize);\r
+ }\r
+ Bp->e820_entries = (UINT8) E820EntryCount;\r
+\r
+ Efi = &Bp->efi_info;\r
+ Efi->efi_systab = (UINT32)(UINTN) gST;\r
+ Efi->efi_memdesc_size = (UINT32) DescriptorSize;\r
+ Efi->efi_memdesc_version = DescriptorVersion;\r
+ Efi->efi_memmap = (UINT32)(UINTN) MemoryMapPtr;\r
+ Efi->efi_memmap_size = (UINT32) MemoryMapSize;\r
+#ifdef MDE_CPU_IA32\r
+ Efi->efi_loader_signature = SIGNATURE_32 ('E', 'L', '3', '2');\r
+#else\r
+ Efi->efi_systab_hi = ((UINT64)(UINTN) gST) >> 32;\r
+ Efi->efi_memmap_hi = ((UINT64)(UINTN) MemoryMapPtr) >> 32;\r
+ Efi->efi_loader_signature = SIGNATURE_32 ('E', 'L', '6', '4');\r
+#endif\r
+\r
+ gBS->ExitBootServices (gImageHandle, MapKey);\r
+}\r
+\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+LoadLinuxSetCommandLine (\r
+ IN OUT VOID *KernelSetup,\r
+ IN CHAR8 *CommandLine\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ struct boot_params *Bp;\r
+\r
+ Status = BasicKernelSetupCheck (KernelSetup);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Bp = (struct boot_params*) KernelSetup;\r
+\r
+ Bp->hdr.cmd_line_ptr = (UINT32)(UINTN) CommandLine;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+LoadLinuxSetInitrd (\r
+ IN OUT VOID *KernelSetup,\r
+ IN VOID *Initrd,\r
+ IN UINTN InitrdSize\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ struct boot_params *Bp;\r
+\r
+ Status = BasicKernelSetupCheck (KernelSetup);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Bp = (struct boot_params*) KernelSetup;\r
+\r
+ Bp->hdr.ramdisk_start = (UINT32)(UINTN) Initrd;\r
+ Bp->hdr.ramdisk_len = (UINT32) InitrdSize;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+STATIC VOID\r
+FindBits (\r
+ unsigned long Mask,\r
+ UINT8 *Pos,\r
+ UINT8 *Size\r
+ )\r
+{\r
+ UINT8 First, Len;\r
+\r
+ First = 0;\r
+ Len = 0;\r
+\r
+ if (Mask) {\r
+ while (!(Mask & 0x1)) {\r
+ Mask = Mask >> 1;\r
+ First++;\r
+ }\r
+\r
+ while (Mask & 0x1) {\r
+ Mask = Mask >> 1;\r
+ Len++;\r
+ }\r
+ }\r
+ *Pos = First;\r
+ *Size = Len;\r
+}\r
+\r
+\r
+STATIC\r
+EFI_STATUS\r
+SetupGraphicsFromGop (\r
+ struct screen_info *Si,\r
+ EFI_GRAPHICS_OUTPUT_PROTOCOL *Gop\r
+ )\r
+{\r
+ EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;\r
+ EFI_STATUS Status;\r
+ UINTN Size;\r
+\r
+ Status = Gop->QueryMode(Gop, Gop->Mode->Mode, &Size, &Info);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ /* We found a GOP */\r
+\r
+ /* EFI framebuffer */\r
+ Si->orig_video_isVGA = 0x70;\r
+\r
+ Si->orig_x = 0;\r
+ Si->orig_y = 0;\r
+ Si->orig_video_page = 0;\r
+ Si->orig_video_mode = 0;\r
+ Si->orig_video_cols = 0;\r
+ Si->orig_video_lines = 0;\r
+ Si->orig_video_ega_bx = 0;\r
+ Si->orig_video_points = 0;\r
+\r
+ Si->lfb_base = (UINT32) Gop->Mode->FrameBufferBase;\r
+ Si->lfb_size = (UINT32) Gop->Mode->FrameBufferSize;\r
+ Si->lfb_width = (UINT16) Info->HorizontalResolution;\r
+ Si->lfb_height = (UINT16) Info->VerticalResolution;\r
+ Si->pages = 1;\r
+ Si->vesapm_seg = 0;\r
+ Si->vesapm_off = 0;\r
+\r
+ if (Info->PixelFormat == PixelRedGreenBlueReserved8BitPerColor) {\r
+ Si->lfb_depth = 32;\r
+ Si->red_size = 8;\r
+ Si->red_pos = 0;\r
+ Si->green_size = 8;\r
+ Si->green_pos = 8;\r
+ Si->blue_size = 8;\r
+ Si->blue_pos = 16;\r
+ Si->rsvd_size = 8;\r
+ Si->rsvd_pos = 24;\r
+ Si->lfb_linelength = (UINT16) (Info->PixelsPerScanLine * 4);\r
+\r
+ } else if (Info->PixelFormat == PixelBlueGreenRedReserved8BitPerColor) {\r
+ Si->lfb_depth = 32;\r
+ Si->red_size = 8;\r
+ Si->red_pos = 16;\r
+ Si->green_size = 8;\r
+ Si->green_pos = 8;\r
+ Si->blue_size = 8;\r
+ Si->blue_pos = 0;\r
+ Si->rsvd_size = 8;\r
+ Si->rsvd_pos = 24;\r
+ Si->lfb_linelength = (UINT16) (Info->PixelsPerScanLine * 4);\r
+ } else if (Info->PixelFormat == PixelBitMask) {\r
+ FindBits(Info->PixelInformation.RedMask,\r
+ &Si->red_pos, &Si->red_size);\r
+ FindBits(Info->PixelInformation.GreenMask,\r
+ &Si->green_pos, &Si->green_size);\r
+ FindBits(Info->PixelInformation.BlueMask,\r
+ &Si->blue_pos, &Si->blue_size);\r
+ FindBits(Info->PixelInformation.ReservedMask,\r
+ &Si->rsvd_pos, &Si->rsvd_size);\r
+ Si->lfb_depth = Si->red_size + Si->green_size +\r
+ Si->blue_size + Si->rsvd_size;\r
+ Si->lfb_linelength = (UINT16) ((Info->PixelsPerScanLine * Si->lfb_depth) / 8);\r
+ } else {\r
+ Si->lfb_depth = 4;\r
+ Si->red_size = 0;\r
+ Si->red_pos = 0;\r
+ Si->green_size = 0;\r
+ Si->green_pos = 0;\r
+ Si->blue_size = 0;\r
+ Si->blue_pos = 0;\r
+ Si->rsvd_size = 0;\r
+ Si->rsvd_pos = 0;\r
+ Si->lfb_linelength = Si->lfb_width / 2;\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+\r
+STATIC\r
+EFI_STATUS\r
+SetupGraphics (\r
+ IN OUT struct boot_params *Bp\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_HANDLE *HandleBuffer;\r
+ UINTN HandleCount;\r
+ UINTN Index;\r
+ EFI_GRAPHICS_OUTPUT_PROTOCOL *Gop;\r
+\r
+ ZeroMem ((VOID*)&Bp->screen_info, sizeof(Bp->screen_info));\r
+\r
+ Status = gBS->LocateHandleBuffer (\r
+ ByProtocol,\r
+ &gEfiGraphicsOutputProtocolGuid,\r
+ NULL,\r
+ &HandleCount,\r
+ &HandleBuffer\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ for (Index = 0; Index < HandleCount; Index++) {\r
+ Status = gBS->HandleProtocol (\r
+ HandleBuffer[Index],\r
+ &gEfiGraphicsOutputProtocolGuid,\r
+ (VOID*) &Gop\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ continue;\r
+ }\r
+\r
+ Status = SetupGraphicsFromGop (&Bp->screen_info, Gop);\r
+ if (!EFI_ERROR (Status)) {\r
+ FreePool (HandleBuffer);\r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+\r
+ FreePool (HandleBuffer);\r
+ }\r
+\r
+ return EFI_NOT_FOUND;\r
+}\r
+\r
+\r
+STATIC\r
+EFI_STATUS\r
+SetupLinuxBootParams (\r
+ IN VOID *Kernel,\r
+ IN OUT struct boot_params *Bp\r
+ )\r
+{\r
+ SetupGraphics (Bp);\r
+\r
+ Bp->hdr.code32_start = (UINT32)(UINTN) Kernel;\r
+\r
+ SetupLinuxMemmap (Bp);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+LoadLinux (\r
+ IN VOID *Kernel,\r
+ IN OUT VOID *KernelSetup\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ struct boot_params *Bp;\r
+\r
+ Status = BasicKernelSetupCheck (KernelSetup);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Bp = (struct boot_params *) KernelSetup;\r
+\r
+ if (Bp->hdr.version < 0x205) {\r
+ //\r
+ // We only support relocatable kernels\r
+ //\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ InitLinuxDescriptorTables ();\r
+\r
+ SetupLinuxBootParams (Kernel, (struct boot_params*) KernelSetup);\r
+\r
+ DEBUG ((EFI_D_INFO, "Jumping to kernel\n"));\r
+ DisableInterrupts ();\r
+ SetLinuxDescriptorTables ();\r
+ JumpToKernel (Kernel, (VOID*) KernelSetup);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
--- /dev/null
+/** @file\r
+ Initialize GDT for Linux.\r
+\r
+ Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>\r
+ This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "LoadLinuxLib.h"\r
+\r
+\r
+//\r
+// Local structure definitions\r
+//\r
+\r
+#pragma pack (1)\r
+\r
+//\r
+// Global Descriptor Entry structures\r
+//\r
+\r
+typedef struct _GDT_ENTRY {\r
+ UINT16 Limit15_0;\r
+ UINT16 Base15_0;\r
+ UINT8 Base23_16;\r
+ UINT8 Type;\r
+ UINT8 Limit19_16_and_flags;\r
+ UINT8 Base31_24;\r
+} GDT_ENTRY;\r
+\r
+typedef\r
+struct _GDT_ENTRIES {\r
+ GDT_ENTRY Null;\r
+ GDT_ENTRY Null2;\r
+ GDT_ENTRY Linear;\r
+ GDT_ENTRY LinearCode;\r
+ GDT_ENTRY TaskSegment;\r
+ GDT_ENTRY Spare4;\r
+ GDT_ENTRY Spare5;\r
+} GDT_ENTRIES;\r
+\r
+#pragma pack ()\r
+\r
+STATIC GDT_ENTRIES *mGdt = NULL;\r
+\r
+//\r
+// Global descriptor table (GDT) Template\r
+//\r
+STATIC GDT_ENTRIES GdtTemplate = {\r
+ //\r
+ // Null\r
+ //\r
+ {\r
+ 0x0, // limit 15:0\r
+ 0x0, // base 15:0\r
+ 0x0, // base 23:16\r
+ 0x0, // type\r
+ 0x0, // limit 19:16, flags\r
+ 0x0, // base 31:24\r
+ },\r
+ //\r
+ // Null2\r
+ //\r
+ {\r
+ 0x0, // limit 15:0\r
+ 0x0, // base 15:0\r
+ 0x0, // base 23:16\r
+ 0x0, // type\r
+ 0x0, // limit 19:16, flags\r
+ 0x0, // base 31:24\r
+ },\r
+ //\r
+ // Linear\r
+ //\r
+ {\r
+ 0x0FFFF, // limit 0xFFFFF\r
+ 0x0, // base 0\r
+ 0x0,\r
+ 0x09A, // present, ring 0, data, expand-up, writable\r
+ 0x0CF, // page-granular, 32-bit\r
+ 0x0,\r
+ },\r
+ //\r
+ // LinearCode\r
+ //\r
+ {\r
+ 0x0FFFF, // limit 0xFFFFF\r
+ 0x0, // base 0\r
+ 0x0,\r
+ 0x092, // present, ring 0, data, expand-up, writable\r
+ 0x0CF, // page-granular, 32-bit\r
+ 0x0,\r
+ },\r
+ //\r
+ // TaskSegment\r
+ //\r
+ {\r
+ 0x0, // limit 0\r
+ 0x0, // base 0\r
+ 0x0,\r
+ 0x089, // ?\r
+ 0x080, // ?\r
+ 0x0,\r
+ },\r
+ //\r
+ // Spare4\r
+ //\r
+ {\r
+ 0x0, // limit 0\r
+ 0x0, // base 0\r
+ 0x0,\r
+ 0x0, // present, ring 0, data, expand-up, writable\r
+ 0x0, // page-granular, 32-bit\r
+ 0x0,\r
+ },\r
+ //\r
+ // Spare5\r
+ //\r
+ {\r
+ 0x0, // limit 0\r
+ 0x0, // base 0\r
+ 0x0,\r
+ 0x0, // present, ring 0, data, expand-up, writable\r
+ 0x0, // page-granular, 32-bit\r
+ 0x0,\r
+ },\r
+};\r
+\r
+/**\r
+ Initialize Global Descriptor Table.\r
+\r
+**/\r
+VOID\r
+InitLinuxDescriptorTables (\r
+ VOID\r
+ )\r
+{\r
+ //\r
+ // Allocate Runtime Data for the GDT\r
+ //\r
+ mGdt = AllocateRuntimePool (sizeof (GdtTemplate) + 8);\r
+ ASSERT (mGdt != NULL);\r
+ mGdt = ALIGN_POINTER (mGdt, 8);\r
+\r
+ //\r
+ // Initialize all GDT entries\r
+ //\r
+ CopyMem (mGdt, &GdtTemplate, sizeof (GdtTemplate));\r
+\r
+}\r
+\r
+/**\r
+ Initialize Global Descriptor Table.\r
+\r
+**/\r
+VOID\r
+SetLinuxDescriptorTables (\r
+ VOID\r
+ )\r
+{\r
+ IA32_DESCRIPTOR GdtPtr;\r
+ IA32_DESCRIPTOR IdtPtr;\r
+\r
+ //\r
+ // Write GDT register\r
+ //\r
+ GdtPtr.Base = (UINT32)(UINTN)(VOID*) mGdt;\r
+ GdtPtr.Limit = (UINT16) (sizeof (GdtTemplate) - 1);\r
+ AsmWriteGdtr (&GdtPtr);\r
+\r
+ IdtPtr.Base = (UINT32) 0;\r
+ IdtPtr.Limit = (UINT16) 0;\r
+ AsmWriteIdtr (&IdtPtr);\r
+}\r
+\r