]> git.proxmox.com Git - mirror_edk2.git/commitdiff
OvmfPkg: Add LoadLinuxLib library implementation
authorjljusten <jljusten@6f19259b-4bc3-4df7-8a09-765794883524>
Fri, 2 Nov 2012 18:27:55 +0000 (18:27 +0000)
committerjljusten <jljusten@6f19259b-4bc3-4df7-8a09-765794883524>
Fri, 2 Nov 2012 18:27:55 +0000 (18:27 +0000)
This code is based on efilinux's bzimage support.
git://git.kernel.org/pub/scm/boot/efilinux/efilinux.git

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jordan Justen <jordan.l.justen@intel.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Matt Fleming <matt.fleming@intel.com>
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@13922 6f19259b-4bc3-4df7-8a09-765794883524

OvmfPkg/Library/LoadLinuxLib/Ia32/JumpToKernel.S [new file with mode: 0644]
OvmfPkg/Library/LoadLinuxLib/Ia32/JumpToKernel.asm [new file with mode: 0644]
OvmfPkg/Library/LoadLinuxLib/Linux.c [new file with mode: 0644]
OvmfPkg/Library/LoadLinuxLib/LinuxGdt.c [new file with mode: 0644]
OvmfPkg/Library/LoadLinuxLib/LoadLinuxLib.h [new file with mode: 0644]
OvmfPkg/Library/LoadLinuxLib/LoadLinuxLib.inf [new file with mode: 0644]
OvmfPkg/Library/LoadLinuxLib/X64/JumpToKernel.S [new file with mode: 0644]
OvmfPkg/Library/LoadLinuxLib/X64/JumpToKernel.asm [new file with mode: 0644]
OvmfPkg/OvmfPkgIa32.dsc
OvmfPkg/OvmfPkgIa32X64.dsc
OvmfPkg/OvmfPkgX64.dsc

diff --git a/OvmfPkg/Library/LoadLinuxLib/Ia32/JumpToKernel.S b/OvmfPkg/Library/LoadLinuxLib/Ia32/JumpToKernel.S
new file mode 100644 (file)
index 0000000..b8cd4ca
--- /dev/null
@@ -0,0 +1,29 @@
+#------------------------------------------------------------------------------\r
+#\r
+# Copyright (c) 2006 - 2011, 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
+ASM_GLOBAL ASM_PFX(JumpToKernel)\r
+\r
+#------------------------------------------------------------------------------\r
+# VOID\r
+# EFIAPI\r
+# JumpToKernel (\r
+#   VOID *KernelStart,\r
+#   VOID *KernelBootParams\r
+#   );\r
+#------------------------------------------------------------------------------\r
+ASM_PFX(JumpToKernel):\r
+    movl    0x8(%esp), %esi\r
+    calll   0x4(%esp)\r
+    ret\r
+\r
diff --git a/OvmfPkg/Library/LoadLinuxLib/Ia32/JumpToKernel.asm b/OvmfPkg/Library/LoadLinuxLib/Ia32/JumpToKernel.asm
new file mode 100644 (file)
index 0000000..a8f3965
--- /dev/null
@@ -0,0 +1,35 @@
+;------------------------------------------------------------------------------\r
+;\r
+; Copyright (c) 2006 - 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
+  .586p\r
+  .model flat,C\r
+  .code\r
+\r
+;------------------------------------------------------------------------------\r
+; VOID\r
+; EFIAPI\r
+; JumpToKernel (\r
+;   VOID *KernelStart,\r
+;   VOID *KernelBootParams\r
+;   );\r
+;------------------------------------------------------------------------------\r
+JumpToKernel PROC\r
+\r
+    mov     esi, [esp + 8]\r
+    call    DWORD PTR [esp + 4]\r
+    ret\r
+\r
+JumpToKernel ENDP\r
+\r
+END\r
diff --git a/OvmfPkg/Library/LoadLinuxLib/Linux.c b/OvmfPkg/Library/LoadLinuxLib/Linux.c
new file mode 100644 (file)
index 0000000..96c985b
--- /dev/null
@@ -0,0 +1,627 @@
+/** @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
diff --git a/OvmfPkg/Library/LoadLinuxLib/LinuxGdt.c b/OvmfPkg/Library/LoadLinuxLib/LinuxGdt.c
new file mode 100644 (file)
index 0000000..4e20436
--- /dev/null
@@ -0,0 +1,181 @@
+/** @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
diff --git a/OvmfPkg/Library/LoadLinuxLib/LoadLinuxLib.h b/OvmfPkg/Library/LoadLinuxLib/LoadLinuxLib.h
new file mode 100644 (file)
index 0000000..f869797
--- /dev/null
@@ -0,0 +1,50 @@
+/** @file\r
+  Boot UEFI Linux.\r
+\r
+  Copyright (c) 2008 - 2011, 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
+#ifndef _LOAD_LINUX_LIB_INCLUDED_\r
+#define _LOAD_LINUX_LIB_INCLUDED_\r
+\r
+#include <Uefi.h>\r
+#include <Library/LoadLinuxLib.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/UefiRuntimeServicesTableLib.h>\r
+\r
+#include <IndustryStandard/LinuxBzimage.h>\r
+\r
+#include <Protocol/GraphicsOutput.h>\r
+\r
+VOID\r
+EFIAPI\r
+JumpToKernel (\r
+  VOID *KernelStart,\r
+  VOID *KernelBootParams\r
+  );\r
+\r
+VOID\r
+InitLinuxDescriptorTables (\r
+  VOID\r
+  );\r
+\r
+VOID\r
+SetLinuxDescriptorTables (\r
+  VOID\r
+  );\r
+\r
+#endif\r
+\r
diff --git a/OvmfPkg/Library/LoadLinuxLib/LoadLinuxLib.inf b/OvmfPkg/Library/LoadLinuxLib/LoadLinuxLib.inf
new file mode 100644 (file)
index 0000000..b8f987c
--- /dev/null
@@ -0,0 +1,50 @@
+## @file\r
+#\r
+#  Copyright (c) 2008 - 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
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = LoadLinuxLib\r
+  FILE_GUID                      = eaec1915-65a0-43a9-bf0b-a76438da61db\r
+  MODULE_TYPE                    = BASE\r
+  VERSION_STRING                 = 1.0\r
+  LIBRARY_CLASS                  = LoadLinuxLib\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+#  VALID_ARCHITECTURES           = IA32 X64\r
+#\r
+\r
+[Sources.common]\r
+  Linux.c\r
+  LinuxGdt.c\r
+\r
+[Sources.IA32]\r
+  Ia32/JumpToKernel.asm\r
+  Ia32/JumpToKernel.S\r
+\r
+[Sources.X64]\r
+  X64/JumpToKernel.asm\r
+  X64/JumpToKernel.S\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  OvmfPkg/OvmfPkg.dec\r
+\r
+[LibraryClasses]\r
+  BaseLib\r
+  DebugLib\r
+  MemoryAllocationLib\r
+  BaseMemoryLib\r
+\r
diff --git a/OvmfPkg/Library/LoadLinuxLib/X64/JumpToKernel.S b/OvmfPkg/Library/LoadLinuxLib/X64/JumpToKernel.S
new file mode 100644 (file)
index 0000000..9ae755b
--- /dev/null
@@ -0,0 +1,30 @@
+#------------------------------------------------------------------------------\r
+#\r
+# Copyright (c) 2006 - 2011, 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
+ASM_GLOBAL ASM_PFX(JumpToKernel)\r
+\r
+#------------------------------------------------------------------------------\r
+# VOID\r
+# EFIAPI\r
+# JumpToKernel (\r
+#   VOID *KernelStart,         // %rcx\r
+#   VOID *KernelBootParams     // %rdx\r
+#   );\r
+#------------------------------------------------------------------------------\r
+ASM_PFX(JumpToKernel):\r
+    movq    %rdx, %rsi\r
+    addq    $0x200, %rcx\r
+    callq   %rcx\r
+    ret\r
+\r
diff --git a/OvmfPkg/Library/LoadLinuxLib/X64/JumpToKernel.asm b/OvmfPkg/Library/LoadLinuxLib/X64/JumpToKernel.asm
new file mode 100644 (file)
index 0000000..ed53321
--- /dev/null
@@ -0,0 +1,34 @@
+;------------------------------------------------------------------------------\r
+;\r
+; Copyright (c) 2006 - 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
+  .code\r
+\r
+;------------------------------------------------------------------------------\r
+; VOID\r
+; EFIAPI\r
+; JumpToKernel (\r
+;   VOID *KernelStart,         // rcx\r
+;   VOID *KernelBootParams     // rdx\r
+;   );\r
+;------------------------------------------------------------------------------\r
+JumpToKernel PROC\r
+\r
+    mov     rsi, rdx\r
+    add     rcx, 200h\r
+    call    rcx\r
+    ret\r
+\r
+JumpToKernel ENDP\r
+\r
+END\r
index bd8657241330934b86e141ca3c72fcac6d4a459b..c99cee39651b86d799fd271a23354cd6b2cfb1df 100644 (file)
@@ -98,6 +98,7 @@
   SerializeVariablesLib|OvmfPkg/Library/SerializeVariablesLib/SerializeVariablesLib.inf\r
   QemuFwCfgLib|OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLib.inf\r
   VirtioLib|OvmfPkg/Library/VirtioLib/VirtioLib.inf\r
+  LoadLinuxLib|OvmfPkg/Library/LoadLinuxLib/LoadLinuxLib.inf\r
   LockBoxLib|MdeModulePkg/Library/LockBoxNullLib/LockBoxNullLib.inf\r
 \r
 !ifdef $(SOURCE_DEBUG_ENABLE)\r
index 0a1609f3137d0c35a96493d6f9bfd0b0cf247cd4..9173aae70e6b6475ecefb101ec748dfb04a41a61 100644 (file)
   SerializeVariablesLib|OvmfPkg/Library/SerializeVariablesLib/SerializeVariablesLib.inf\r
   QemuFwCfgLib|OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLib.inf\r
   VirtioLib|OvmfPkg/Library/VirtioLib/VirtioLib.inf\r
+  LoadLinuxLib|OvmfPkg/Library/LoadLinuxLib/LoadLinuxLib.inf\r
   LockBoxLib|MdeModulePkg/Library/LockBoxNullLib/LockBoxNullLib.inf\r
 \r
 !ifdef $(SOURCE_DEBUG_ENABLE)\r
index b24d1b9df09c6e0036a97ab464969bdac72b6149..dce9ce108698ba60c97485b7966022da6c1750c8 100644 (file)
   SerializeVariablesLib|OvmfPkg/Library/SerializeVariablesLib/SerializeVariablesLib.inf\r
   QemuFwCfgLib|OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLib.inf\r
   VirtioLib|OvmfPkg/Library/VirtioLib/VirtioLib.inf\r
+  LoadLinuxLib|OvmfPkg/Library/LoadLinuxLib/LoadLinuxLib.inf\r
   LockBoxLib|MdeModulePkg/Library/LockBoxNullLib/LockBoxNullLib.inf\r
 \r
 !ifdef $(SOURCE_DEBUG_ENABLE)\r