summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--OvmfPkg/Library/LoadLinuxLib/Ia32/JumpToKernel.S29
-rw-r--r--OvmfPkg/Library/LoadLinuxLib/Ia32/JumpToKernel.asm35
-rw-r--r--OvmfPkg/Library/LoadLinuxLib/Linux.c627
-rw-r--r--OvmfPkg/Library/LoadLinuxLib/LinuxGdt.c181
-rw-r--r--OvmfPkg/Library/LoadLinuxLib/LoadLinuxLib.h50
-rw-r--r--OvmfPkg/Library/LoadLinuxLib/LoadLinuxLib.inf50
-rw-r--r--OvmfPkg/Library/LoadLinuxLib/X64/JumpToKernel.S30
-rw-r--r--OvmfPkg/Library/LoadLinuxLib/X64/JumpToKernel.asm34
-rw-r--r--OvmfPkg/OvmfPkgIa32.dsc1
-rw-r--r--OvmfPkg/OvmfPkgIa32X64.dsc1
-rw-r--r--OvmfPkg/OvmfPkgX64.dsc1
11 files changed, 1039 insertions, 0 deletions
diff --git a/OvmfPkg/Library/LoadLinuxLib/Ia32/JumpToKernel.S b/OvmfPkg/Library/LoadLinuxLib/Ia32/JumpToKernel.S
new file mode 100644
index 0000000000..b8cd4ca515
--- /dev/null
+++ b/OvmfPkg/Library/LoadLinuxLib/Ia32/JumpToKernel.S
@@ -0,0 +1,29 @@
+#------------------------------------------------------------------------------
+#
+# Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
+#
+# 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.
+#
+#------------------------------------------------------------------------------
+
+ASM_GLOBAL ASM_PFX(JumpToKernel)
+
+#------------------------------------------------------------------------------
+# VOID
+# EFIAPI
+# JumpToKernel (
+# VOID *KernelStart,
+# VOID *KernelBootParams
+# );
+#------------------------------------------------------------------------------
+ASM_PFX(JumpToKernel):
+ movl 0x8(%esp), %esi
+ calll 0x4(%esp)
+ ret
+
diff --git a/OvmfPkg/Library/LoadLinuxLib/Ia32/JumpToKernel.asm b/OvmfPkg/Library/LoadLinuxLib/Ia32/JumpToKernel.asm
new file mode 100644
index 0000000000..a8f3965f9a
--- /dev/null
+++ b/OvmfPkg/Library/LoadLinuxLib/Ia32/JumpToKernel.asm
@@ -0,0 +1,35 @@
+;------------------------------------------------------------------------------
+;
+; Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
+;
+; 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.
+;
+;------------------------------------------------------------------------------
+
+ .586p
+ .model flat,C
+ .code
+
+;------------------------------------------------------------------------------
+; VOID
+; EFIAPI
+; JumpToKernel (
+; VOID *KernelStart,
+; VOID *KernelBootParams
+; );
+;------------------------------------------------------------------------------
+JumpToKernel PROC
+
+ mov esi, [esp + 8]
+ call DWORD PTR [esp + 4]
+ ret
+
+JumpToKernel ENDP
+
+END
diff --git a/OvmfPkg/Library/LoadLinuxLib/Linux.c b/OvmfPkg/Library/LoadLinuxLib/Linux.c
new file mode 100644
index 0000000000..96c985bc2d
--- /dev/null
+++ b/OvmfPkg/Library/LoadLinuxLib/Linux.c
@@ -0,0 +1,627 @@
+/** @file
+
+ Copyright (c) 2011 - 2012, Intel Corporation. All rights reserved.<BR>
+
+ 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.
+
+**/
+
+#include "LoadLinuxLib.h"
+
+
+/**
+ A simple check of the kernel setup image
+
+ An assumption is made that the size of the data is at least the
+ size of struct boot_params.
+
+ @param[in] KernelSetup - The kernel setup image
+
+ @retval EFI_SUCCESS - The kernel setup looks valid and supported
+ @retval EFI_INVALID_PARAMETER - KernelSetup was NULL
+ @retval EFI_UNSUPPORTED - The kernel setup is not valid or supported
+
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+BasicKernelSetupCheck (
+ IN VOID *KernelSetup
+ )
+{
+ return LoadLinuxCheckKernelSetup(KernelSetup, sizeof (struct boot_params));
+}
+
+
+EFI_STATUS
+EFIAPI
+LoadLinuxCheckKernelSetup (
+ IN VOID *KernelSetup,
+ IN UINTN KernelSetupSize
+ )
+{
+ struct boot_params *Bp;
+
+ if (KernelSetup == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (KernelSetupSize < sizeof (*Bp)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Bp = (struct boot_params*) KernelSetup;
+
+ if ((Bp->hdr.signature != 0xAA55) || // Check boot sector signature
+ (Bp->hdr.header != SETUP_HDR) ||
+ (Bp->hdr.version < 0x205) // We only support relocatable kernels
+ ) {
+ return EFI_UNSUPPORTED;
+ } else {
+ return EFI_SUCCESS;
+ }
+}
+
+
+UINTN
+EFIAPI
+LoadLinuxGetKernelSize (
+ IN VOID *KernelSetup,
+ IN UINTN KernelSize
+ )
+{
+ struct boot_params *Bp;
+
+ if (EFI_ERROR (BasicKernelSetupCheck (KernelSetup))) {
+ return 0;
+ }
+
+ Bp = (struct boot_params*) KernelSetup;
+
+ if (Bp->hdr.version > 0x20a) {
+ return Bp->hdr.init_size;
+ } else {
+ //
+ // Add extra size for kernel decompression
+ //
+ return 3 * KernelSize;
+ }
+}
+
+
+VOID*
+EFIAPI
+LoadLinuxAllocateKernelSetupPages (
+ IN UINTN Pages
+ )
+{
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS Address;
+
+ Address = BASE_1GB;
+ Status = gBS->AllocatePages (
+ AllocateMaxAddress,
+ EfiLoaderData,
+ Pages,
+ &Address
+ );
+ if (!EFI_ERROR (Status)) {
+ return (VOID*)(UINTN) Address;
+ } else {
+ return NULL;
+ }
+}
+
+
+VOID*
+EFIAPI
+LoadLinuxAllocateKernelPages (
+ IN VOID *KernelSetup,
+ IN UINTN Pages
+ )
+{
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS KernelAddress;
+ UINT32 Loop;
+ struct boot_params *Bp;
+
+ if (EFI_ERROR (BasicKernelSetupCheck (KernelSetup))) {
+ return NULL;
+ }
+
+ Bp = (struct boot_params*) KernelSetup;
+
+ for (Loop = 1; Loop < 512; Loop++) {
+ KernelAddress = MultU64x32 (
+ 2 * Bp->hdr.kernel_alignment,
+ Loop
+ );
+ Status = gBS->AllocatePages (
+ AllocateAddress,
+ EfiLoaderData,
+ Pages,
+ &KernelAddress
+ );
+ if (!EFI_ERROR (Status)) {
+ return (VOID*)(UINTN) KernelAddress;
+ }
+ }
+
+ return NULL;
+}
+
+
+VOID*
+EFIAPI
+LoadLinuxAllocateCommandLinePages (
+ IN UINTN Pages
+ )
+{
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS Address;
+
+ Address = 0xa0000;
+ Status = gBS->AllocatePages (
+ AllocateMaxAddress,
+ EfiLoaderData,
+ Pages,
+ &Address
+ );
+ if (!EFI_ERROR (Status)) {
+ return (VOID*)(UINTN) Address;
+ } else {
+ return NULL;
+ }
+}
+
+
+VOID*
+EFIAPI
+LoadLinuxAllocateInitrdPages (
+ IN VOID *KernelSetup,
+ IN UINTN Pages
+ )
+{
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS Address;
+
+ struct boot_params *Bp;
+
+ if (EFI_ERROR (BasicKernelSetupCheck (KernelSetup))) {
+ return NULL;
+ }
+
+ Bp = (struct boot_params*) KernelSetup;
+
+ Address = (EFI_PHYSICAL_ADDRESS)(UINTN) Bp->hdr.ramdisk_max;
+ Status = gBS->AllocatePages (
+ AllocateMaxAddress,
+ EfiLoaderData,
+ Pages,
+ &Address
+ );
+ if (!EFI_ERROR (Status)) {
+ return (VOID*)(UINTN) Address;
+ } else {
+ return NULL;
+ }
+}
+
+
+STATIC
+VOID
+SetupLinuxMemmap (
+ IN OUT struct boot_params *Bp
+ )
+{
+ EFI_STATUS Status;
+ UINT8 TmpMemoryMap[1];
+ UINTN MapKey;
+ UINTN DescriptorSize;
+ UINT32 DescriptorVersion;
+ UINTN MemoryMapSize;
+ EFI_MEMORY_DESCRIPTOR *MemoryMap;
+ EFI_MEMORY_DESCRIPTOR *MemoryMapPtr;
+ UINTN Index;
+ struct efi_info *Efi;
+ struct e820_entry *LastE820;
+ struct e820_entry *E820;
+ UINTN E820EntryCount;
+ EFI_PHYSICAL_ADDRESS LastEndAddr;
+
+ //
+ // Get System MemoryMapSize
+ //
+ MemoryMapSize = sizeof (TmpMemoryMap);
+ Status = gBS->GetMemoryMap (
+ &MemoryMapSize,
+ (EFI_MEMORY_DESCRIPTOR *)TmpMemoryMap,
+ &MapKey,
+ &DescriptorSize,
+ &DescriptorVersion
+ );
+ ASSERT (Status == EFI_BUFFER_TOO_SMALL);
+ //
+ // Enlarge space here, because we will allocate pool now.
+ //
+ MemoryMapSize += EFI_PAGE_SIZE;
+ MemoryMap = AllocatePool (MemoryMapSize);
+ ASSERT (MemoryMap != NULL);
+
+ //
+ // Get System MemoryMap
+ //
+ Status = gBS->GetMemoryMap (
+ &MemoryMapSize,
+ MemoryMap,
+ &MapKey,
+ &DescriptorSize,
+ &DescriptorVersion
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ LastE820 = NULL;
+ E820 = &Bp->e820_map[0];
+ E820EntryCount = 0;
+ LastEndAddr = 0;
+ MemoryMapPtr = MemoryMap;
+ for (Index = 0; Index < (MemoryMapSize / DescriptorSize); Index++) {
+ UINTN E820Type = 0;
+
+ if (MemoryMap->NumberOfPages == 0) {
+ continue;
+ }
+
+ switch(MemoryMap->Type) {
+ case EfiReservedMemoryType:
+ case EfiRuntimeServicesCode:
+ case EfiRuntimeServicesData:
+ case EfiMemoryMappedIO:
+ case EfiMemoryMappedIOPortSpace:
+ case EfiPalCode:
+ E820Type = E820_RESERVED;
+ break;
+
+ case EfiUnusableMemory:
+ E820Type = E820_UNUSABLE;
+ break;
+
+ case EfiACPIReclaimMemory:
+ E820Type = E820_ACPI;
+ break;
+
+ case EfiLoaderCode:
+ case EfiLoaderData:
+ case EfiBootServicesCode:
+ case EfiBootServicesData:
+ case EfiConventionalMemory:
+ E820Type = E820_RAM;
+ break;
+
+ case EfiACPIMemoryNVS:
+ E820Type = E820_NVS;
+ break;
+
+ default:
+ DEBUG ((
+ EFI_D_ERROR,
+ "Invalid EFI memory descriptor type (0x%x)!\n",
+ MemoryMap->Type
+ ));
+ continue;
+ }
+
+ if ((LastE820 != NULL) &&
+ (LastE820->type == (UINT32) E820Type) &&
+ (MemoryMap->PhysicalStart == LastEndAddr)) {
+ LastE820->size += EFI_PAGES_TO_SIZE (MemoryMap->NumberOfPages);
+ LastEndAddr += EFI_PAGES_TO_SIZE (MemoryMap->NumberOfPages);
+ } else {
+ if (E820EntryCount >= (sizeof (Bp->e820_map) / sizeof (Bp->e820_map[0]))) {
+ break;
+ }
+ E820->type = (UINT32) E820Type;
+ E820->addr = MemoryMap->PhysicalStart;
+ E820->size = EFI_PAGES_TO_SIZE (MemoryMap->NumberOfPages);
+ LastE820 = E820;
+ LastEndAddr = E820->addr + E820->size;
+ E820++;
+ E820EntryCount++;
+ }
+
+ //
+ // Get next item
+ //
+ MemoryMap = (EFI_MEMORY_DESCRIPTOR *)((UINTN)MemoryMap + DescriptorSize);
+ }
+ Bp->e820_entries = (UINT8) E820EntryCount;
+
+ Efi = &Bp->efi_info;
+ Efi->efi_systab = (UINT32)(UINTN) gST;
+ Efi->efi_memdesc_size = (UINT32) DescriptorSize;
+ Efi->efi_memdesc_version = DescriptorVersion;
+ Efi->efi_memmap = (UINT32)(UINTN) MemoryMapPtr;
+ Efi->efi_memmap_size = (UINT32) MemoryMapSize;
+#ifdef MDE_CPU_IA32
+ Efi->efi_loader_signature = SIGNATURE_32 ('E', 'L', '3', '2');
+#else
+ Efi->efi_systab_hi = ((UINT64)(UINTN) gST) >> 32;
+ Efi->efi_memmap_hi = ((UINT64)(UINTN) MemoryMapPtr) >> 32;
+ Efi->efi_loader_signature = SIGNATURE_32 ('E', 'L', '6', '4');
+#endif
+
+ gBS->ExitBootServices (gImageHandle, MapKey);
+}
+
+
+EFI_STATUS
+EFIAPI
+LoadLinuxSetCommandLine (
+ IN OUT VOID *KernelSetup,
+ IN CHAR8 *CommandLine
+ )
+{
+ EFI_STATUS Status;
+ struct boot_params *Bp;
+
+ Status = BasicKernelSetupCheck (KernelSetup);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Bp = (struct boot_params*) KernelSetup;
+
+ Bp->hdr.cmd_line_ptr = (UINT32)(UINTN) CommandLine;
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+EFIAPI
+LoadLinuxSetInitrd (
+ IN OUT VOID *KernelSetup,
+ IN VOID *Initrd,
+ IN UINTN InitrdSize
+ )
+{
+ EFI_STATUS Status;
+ struct boot_params *Bp;
+
+ Status = BasicKernelSetupCheck (KernelSetup);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Bp = (struct boot_params*) KernelSetup;
+
+ Bp->hdr.ramdisk_start = (UINT32)(UINTN) Initrd;
+ Bp->hdr.ramdisk_len = (UINT32) InitrdSize;
+
+ return EFI_SUCCESS;
+}
+
+
+STATIC VOID
+FindBits (
+ unsigned long Mask,
+ UINT8 *Pos,
+ UINT8 *Size
+ )
+{
+ UINT8 First, Len;
+
+ First = 0;
+ Len = 0;
+
+ if (Mask) {
+ while (!(Mask & 0x1)) {
+ Mask = Mask >> 1;
+ First++;
+ }
+
+ while (Mask & 0x1) {
+ Mask = Mask >> 1;
+ Len++;
+ }
+ }
+ *Pos = First;
+ *Size = Len;
+}
+
+
+STATIC
+EFI_STATUS
+SetupGraphicsFromGop (
+ struct screen_info *Si,
+ EFI_GRAPHICS_OUTPUT_PROTOCOL *Gop
+ )
+{
+ EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;
+ EFI_STATUS Status;
+ UINTN Size;
+
+ Status = Gop->QueryMode(Gop, Gop->Mode->Mode, &Size, &Info);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ /* We found a GOP */
+
+ /* EFI framebuffer */
+ Si->orig_video_isVGA = 0x70;
+
+ Si->orig_x = 0;
+ Si->orig_y = 0;
+ Si->orig_video_page = 0;
+ Si->orig_video_mode = 0;
+ Si->orig_video_cols = 0;
+ Si->orig_video_lines = 0;
+ Si->orig_video_ega_bx = 0;
+ Si->orig_video_points = 0;
+
+ Si->lfb_base = (UINT32) Gop->Mode->FrameBufferBase;
+ Si->lfb_size = (UINT32) Gop->Mode->FrameBufferSize;
+ Si->lfb_width = (UINT16) Info->HorizontalResolution;
+ Si->lfb_height = (UINT16) Info->VerticalResolution;
+ Si->pages = 1;
+ Si->vesapm_seg = 0;
+ Si->vesapm_off = 0;
+
+ if (Info->PixelFormat == PixelRedGreenBlueReserved8BitPerColor) {
+ Si->lfb_depth = 32;
+ Si->red_size = 8;
+ Si->red_pos = 0;
+ Si->green_size = 8;
+ Si->green_pos = 8;
+ Si->blue_size = 8;
+ Si->blue_pos = 16;
+ Si->rsvd_size = 8;
+ Si->rsvd_pos = 24;
+ Si->lfb_linelength = (UINT16) (Info->PixelsPerScanLine * 4);
+
+ } else if (Info->PixelFormat == PixelBlueGreenRedReserved8BitPerColor) {
+ Si->lfb_depth = 32;
+ Si->red_size = 8;
+ Si->red_pos = 16;
+ Si->green_size = 8;
+ Si->green_pos = 8;
+ Si->blue_size = 8;
+ Si->blue_pos = 0;
+ Si->rsvd_size = 8;
+ Si->rsvd_pos = 24;
+ Si->lfb_linelength = (UINT16) (Info->PixelsPerScanLine * 4);
+ } else if (Info->PixelFormat == PixelBitMask) {
+ FindBits(Info->PixelInformation.RedMask,
+ &Si->red_pos, &Si->red_size);
+ FindBits(Info->PixelInformation.GreenMask,
+ &Si->green_pos, &Si->green_size);
+ FindBits(Info->PixelInformation.BlueMask,
+ &Si->blue_pos, &Si->blue_size);
+ FindBits(Info->PixelInformation.ReservedMask,
+ &Si->rsvd_pos, &Si->rsvd_size);
+ Si->lfb_depth = Si->red_size + Si->green_size +
+ Si->blue_size + Si->rsvd_size;
+ Si->lfb_linelength = (UINT16) ((Info->PixelsPerScanLine * Si->lfb_depth) / 8);
+ } else {
+ Si->lfb_depth = 4;
+ Si->red_size = 0;
+ Si->red_pos = 0;
+ Si->green_size = 0;
+ Si->green_pos = 0;
+ Si->blue_size = 0;
+ Si->blue_pos = 0;
+ Si->rsvd_size = 0;
+ Si->rsvd_pos = 0;
+ Si->lfb_linelength = Si->lfb_width / 2;
+ }
+
+ return Status;
+}
+
+
+STATIC
+EFI_STATUS
+SetupGraphics (
+ IN OUT struct boot_params *Bp
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE *HandleBuffer;
+ UINTN HandleCount;
+ UINTN Index;
+ EFI_GRAPHICS_OUTPUT_PROTOCOL *Gop;
+
+ ZeroMem ((VOID*)&Bp->screen_info, sizeof(Bp->screen_info));
+
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiGraphicsOutputProtocolGuid,
+ NULL,
+ &HandleCount,
+ &HandleBuffer
+ );
+ if (!EFI_ERROR (Status)) {
+ for (Index = 0; Index < HandleCount; Index++) {
+ Status = gBS->HandleProtocol (
+ HandleBuffer[Index],
+ &gEfiGraphicsOutputProtocolGuid,
+ (VOID*) &Gop
+ );
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+
+ Status = SetupGraphicsFromGop (&Bp->screen_info, Gop);
+ if (!EFI_ERROR (Status)) {
+ FreePool (HandleBuffer);
+ return EFI_SUCCESS;
+ }
+ }
+
+ FreePool (HandleBuffer);
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+
+STATIC
+EFI_STATUS
+SetupLinuxBootParams (
+ IN VOID *Kernel,
+ IN OUT struct boot_params *Bp
+ )
+{
+ SetupGraphics (Bp);
+
+ Bp->hdr.code32_start = (UINT32)(UINTN) Kernel;
+
+ SetupLinuxMemmap (Bp);
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+EFIAPI
+LoadLinux (
+ IN VOID *Kernel,
+ IN OUT VOID *KernelSetup
+ )
+{
+ EFI_STATUS Status;
+ struct boot_params *Bp;
+
+ Status = BasicKernelSetupCheck (KernelSetup);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Bp = (struct boot_params *) KernelSetup;
+
+ if (Bp->hdr.version < 0x205) {
+ //
+ // We only support relocatable kernels
+ //
+ return EFI_UNSUPPORTED;
+ }
+
+ InitLinuxDescriptorTables ();
+
+ SetupLinuxBootParams (Kernel, (struct boot_params*) KernelSetup);
+
+ DEBUG ((EFI_D_INFO, "Jumping to kernel\n"));
+ DisableInterrupts ();
+ SetLinuxDescriptorTables ();
+ JumpToKernel (Kernel, (VOID*) KernelSetup);
+
+ return EFI_SUCCESS;
+}
+
diff --git a/OvmfPkg/Library/LoadLinuxLib/LinuxGdt.c b/OvmfPkg/Library/LoadLinuxLib/LinuxGdt.c
new file mode 100644
index 0000000000..4e20436246
--- /dev/null
+++ b/OvmfPkg/Library/LoadLinuxLib/LinuxGdt.c
@@ -0,0 +1,181 @@
+/** @file
+ Initialize GDT for Linux.
+
+ Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
+ 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.
+
+**/
+
+#include "LoadLinuxLib.h"
+
+
+//
+// Local structure definitions
+//
+
+#pragma pack (1)
+
+//
+// Global Descriptor Entry structures
+//
+
+typedef struct _GDT_ENTRY {
+ UINT16 Limit15_0;
+ UINT16 Base15_0;
+ UINT8 Base23_16;
+ UINT8 Type;
+ UINT8 Limit19_16_and_flags;
+ UINT8 Base31_24;
+} GDT_ENTRY;
+
+typedef
+struct _GDT_ENTRIES {
+ GDT_ENTRY Null;
+ GDT_ENTRY Null2;
+ GDT_ENTRY Linear;
+ GDT_ENTRY LinearCode;
+ GDT_ENTRY TaskSegment;
+ GDT_ENTRY Spare4;
+ GDT_ENTRY Spare5;
+} GDT_ENTRIES;
+
+#pragma pack ()
+
+STATIC GDT_ENTRIES *mGdt = NULL;
+
+//
+// Global descriptor table (GDT) Template
+//
+STATIC GDT_ENTRIES GdtTemplate = {
+ //
+ // Null
+ //
+ {
+ 0x0, // limit 15:0
+ 0x0, // base 15:0
+ 0x0, // base 23:16
+ 0x0, // type
+ 0x0, // limit 19:16, flags
+ 0x0, // base 31:24
+ },
+ //
+ // Null2
+ //
+ {
+ 0x0, // limit 15:0
+ 0x0, // base 15:0
+ 0x0, // base 23:16
+ 0x0, // type
+ 0x0, // limit 19:16, flags
+ 0x0, // base 31:24
+ },
+ //
+ // Linear
+ //
+ {
+ 0x0FFFF, // limit 0xFFFFF
+ 0x0, // base 0
+ 0x0,
+ 0x09A, // present, ring 0, data, expand-up, writable
+ 0x0CF, // page-granular, 32-bit
+ 0x0,
+ },
+ //
+ // LinearCode
+ //
+ {
+ 0x0FFFF, // limit 0xFFFFF
+ 0x0, // base 0
+ 0x0,
+ 0x092, // present, ring 0, data, expand-up, writable
+ 0x0CF, // page-granular, 32-bit
+ 0x0,
+ },
+ //
+ // TaskSegment
+ //
+ {
+ 0x0, // limit 0
+ 0x0, // base 0
+ 0x0,
+ 0x089, // ?
+ 0x080, // ?
+ 0x0,
+ },
+ //
+ // Spare4
+ //
+ {
+ 0x0, // limit 0
+ 0x0, // base 0
+ 0x0,
+ 0x0, // present, ring 0, data, expand-up, writable
+ 0x0, // page-granular, 32-bit
+ 0x0,
+ },
+ //
+ // Spare5
+ //
+ {
+ 0x0, // limit 0
+ 0x0, // base 0
+ 0x0,
+ 0x0, // present, ring 0, data, expand-up, writable
+ 0x0, // page-granular, 32-bit
+ 0x0,
+ },
+};
+
+/**
+ Initialize Global Descriptor Table.
+
+**/
+VOID
+InitLinuxDescriptorTables (
+ VOID
+ )
+{
+ //
+ // Allocate Runtime Data for the GDT
+ //
+ mGdt = AllocateRuntimePool (sizeof (GdtTemplate) + 8);
+ ASSERT (mGdt != NULL);
+ mGdt = ALIGN_POINTER (mGdt, 8);
+
+ //
+ // Initialize all GDT entries
+ //
+ CopyMem (mGdt, &GdtTemplate, sizeof (GdtTemplate));
+
+}
+
+/**
+ Initialize Global Descriptor Table.
+
+**/
+VOID
+SetLinuxDescriptorTables (
+ VOID
+ )
+{
+ IA32_DESCRIPTOR GdtPtr;
+ IA32_DESCRIPTOR IdtPtr;
+
+ //
+ // Write GDT register
+ //
+ GdtPtr.Base = (UINT32)(UINTN)(VOID*) mGdt;
+ GdtPtr.Limit = (UINT16) (sizeof (GdtTemplate) - 1);
+ AsmWriteGdtr (&GdtPtr);
+
+ IdtPtr.Base = (UINT32) 0;
+ IdtPtr.Limit = (UINT16) 0;
+ AsmWriteIdtr (&IdtPtr);
+}
+
diff --git a/OvmfPkg/Library/LoadLinuxLib/LoadLinuxLib.h b/OvmfPkg/Library/LoadLinuxLib/LoadLinuxLib.h
new file mode 100644
index 0000000000..f869797262
--- /dev/null
+++ b/OvmfPkg/Library/LoadLinuxLib/LoadLinuxLib.h
@@ -0,0 +1,50 @@
+/** @file
+ Boot UEFI Linux.
+
+ Copyright (c) 2008 - 2011, Intel Corporation. All rights reserved.<BR>
+
+ 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.
+
+**/
+
+#ifndef _LOAD_LINUX_LIB_INCLUDED_
+#define _LOAD_LINUX_LIB_INCLUDED_
+
+#include <Uefi.h>
+#include <Library/LoadLinuxLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+
+#include <IndustryStandard/LinuxBzimage.h>
+
+#include <Protocol/GraphicsOutput.h>
+
+VOID
+EFIAPI
+JumpToKernel (
+ VOID *KernelStart,
+ VOID *KernelBootParams
+ );
+
+VOID
+InitLinuxDescriptorTables (
+ VOID
+ );
+
+VOID
+SetLinuxDescriptorTables (
+ VOID
+ );
+
+#endif
+
diff --git a/OvmfPkg/Library/LoadLinuxLib/LoadLinuxLib.inf b/OvmfPkg/Library/LoadLinuxLib/LoadLinuxLib.inf
new file mode 100644
index 0000000000..b8f987c477
--- /dev/null
+++ b/OvmfPkg/Library/LoadLinuxLib/LoadLinuxLib.inf
@@ -0,0 +1,50 @@
+## @file
+#
+# Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.<BR>
+#
+# 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.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = LoadLinuxLib
+ FILE_GUID = eaec1915-65a0-43a9-bf0b-a76438da61db
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = LoadLinuxLib
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[Sources.common]
+ Linux.c
+ LinuxGdt.c
+
+[Sources.IA32]
+ Ia32/JumpToKernel.asm
+ Ia32/JumpToKernel.S
+
+[Sources.X64]
+ X64/JumpToKernel.asm
+ X64/JumpToKernel.S
+
+[Packages]
+ MdePkg/MdePkg.dec
+ OvmfPkg/OvmfPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ DebugLib
+ MemoryAllocationLib
+ BaseMemoryLib
+
diff --git a/OvmfPkg/Library/LoadLinuxLib/X64/JumpToKernel.S b/OvmfPkg/Library/LoadLinuxLib/X64/JumpToKernel.S
new file mode 100644
index 0000000000..9ae755b067
--- /dev/null
+++ b/OvmfPkg/Library/LoadLinuxLib/X64/JumpToKernel.S
@@ -0,0 +1,30 @@
+#------------------------------------------------------------------------------
+#
+# Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
+#
+# 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.
+#
+#------------------------------------------------------------------------------
+
+ASM_GLOBAL ASM_PFX(JumpToKernel)
+
+#------------------------------------------------------------------------------
+# VOID
+# EFIAPI
+# JumpToKernel (
+# VOID *KernelStart, // %rcx
+# VOID *KernelBootParams // %rdx
+# );
+#------------------------------------------------------------------------------
+ASM_PFX(JumpToKernel):
+ movq %rdx, %rsi
+ addq $0x200, %rcx
+ callq %rcx
+ ret
+
diff --git a/OvmfPkg/Library/LoadLinuxLib/X64/JumpToKernel.asm b/OvmfPkg/Library/LoadLinuxLib/X64/JumpToKernel.asm
new file mode 100644
index 0000000000..ed53321c23
--- /dev/null
+++ b/OvmfPkg/Library/LoadLinuxLib/X64/JumpToKernel.asm
@@ -0,0 +1,34 @@
+;------------------------------------------------------------------------------
+;
+; Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
+;
+; 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.
+;
+;------------------------------------------------------------------------------
+
+ .code
+
+;------------------------------------------------------------------------------
+; VOID
+; EFIAPI
+; JumpToKernel (
+; VOID *KernelStart, // rcx
+; VOID *KernelBootParams // rdx
+; );
+;------------------------------------------------------------------------------
+JumpToKernel PROC
+
+ mov rsi, rdx
+ add rcx, 200h
+ call rcx
+ ret
+
+JumpToKernel ENDP
+
+END
diff --git a/OvmfPkg/OvmfPkgIa32.dsc b/OvmfPkg/OvmfPkgIa32.dsc
index bd86572413..c99cee3965 100644
--- a/OvmfPkg/OvmfPkgIa32.dsc
+++ b/OvmfPkg/OvmfPkgIa32.dsc
@@ -98,6 +98,7 @@
SerializeVariablesLib|OvmfPkg/Library/SerializeVariablesLib/SerializeVariablesLib.inf
QemuFwCfgLib|OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLib.inf
VirtioLib|OvmfPkg/Library/VirtioLib/VirtioLib.inf
+ LoadLinuxLib|OvmfPkg/Library/LoadLinuxLib/LoadLinuxLib.inf
LockBoxLib|MdeModulePkg/Library/LockBoxNullLib/LockBoxNullLib.inf
!ifdef $(SOURCE_DEBUG_ENABLE)
diff --git a/OvmfPkg/OvmfPkgIa32X64.dsc b/OvmfPkg/OvmfPkgIa32X64.dsc
index 0a1609f313..9173aae70e 100644
--- a/OvmfPkg/OvmfPkgIa32X64.dsc
+++ b/OvmfPkg/OvmfPkgIa32X64.dsc
@@ -103,6 +103,7 @@
SerializeVariablesLib|OvmfPkg/Library/SerializeVariablesLib/SerializeVariablesLib.inf
QemuFwCfgLib|OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLib.inf
VirtioLib|OvmfPkg/Library/VirtioLib/VirtioLib.inf
+ LoadLinuxLib|OvmfPkg/Library/LoadLinuxLib/LoadLinuxLib.inf
LockBoxLib|MdeModulePkg/Library/LockBoxNullLib/LockBoxNullLib.inf
!ifdef $(SOURCE_DEBUG_ENABLE)
diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc
index b24d1b9df0..dce9ce1086 100644
--- a/OvmfPkg/OvmfPkgX64.dsc
+++ b/OvmfPkg/OvmfPkgX64.dsc
@@ -103,6 +103,7 @@
SerializeVariablesLib|OvmfPkg/Library/SerializeVariablesLib/SerializeVariablesLib.inf
QemuFwCfgLib|OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLib.inf
VirtioLib|OvmfPkg/Library/VirtioLib/VirtioLib.inf
+ LoadLinuxLib|OvmfPkg/Library/LoadLinuxLib/LoadLinuxLib.inf
LockBoxLib|MdeModulePkg/Library/LockBoxNullLib/LockBoxNullLib.inf
!ifdef $(SOURCE_DEBUG_ENABLE)