Revision: 13922
          http://edk2.svn.sourceforge.net/edk2/?rev=13922&view=rev
Author:   jljusten
Date:     2012-11-02 18:27:55 +0000 (Fri, 02 Nov 2012)
Log Message:
-----------
OvmfPkg: Add LoadLinuxLib library implementation

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 <[email protected]>
Reviewed-by: Laszlo Ersek <[email protected]>
Reviewed-by: Matt Fleming <[email protected]>

Modified Paths:
--------------
    trunk/edk2/OvmfPkg/OvmfPkgIa32.dsc
    trunk/edk2/OvmfPkg/OvmfPkgIa32X64.dsc
    trunk/edk2/OvmfPkg/OvmfPkgX64.dsc

Added Paths:
-----------
    trunk/edk2/OvmfPkg/Library/LoadLinuxLib/
    trunk/edk2/OvmfPkg/Library/LoadLinuxLib/Ia32/
    trunk/edk2/OvmfPkg/Library/LoadLinuxLib/Ia32/JumpToKernel.S
    trunk/edk2/OvmfPkg/Library/LoadLinuxLib/Ia32/JumpToKernel.asm
    trunk/edk2/OvmfPkg/Library/LoadLinuxLib/Linux.c
    trunk/edk2/OvmfPkg/Library/LoadLinuxLib/LinuxGdt.c
    trunk/edk2/OvmfPkg/Library/LoadLinuxLib/LoadLinuxLib.h
    trunk/edk2/OvmfPkg/Library/LoadLinuxLib/LoadLinuxLib.inf
    trunk/edk2/OvmfPkg/Library/LoadLinuxLib/X64/
    trunk/edk2/OvmfPkg/Library/LoadLinuxLib/X64/JumpToKernel.S
    trunk/edk2/OvmfPkg/Library/LoadLinuxLib/X64/JumpToKernel.asm

Added: trunk/edk2/OvmfPkg/Library/LoadLinuxLib/Ia32/JumpToKernel.S
===================================================================
--- trunk/edk2/OvmfPkg/Library/LoadLinuxLib/Ia32/JumpToKernel.S                 
        (rev 0)
+++ trunk/edk2/OvmfPkg/Library/LoadLinuxLib/Ia32/JumpToKernel.S 2012-11-02 
18:27:55 UTC (rev 13922)
@@ -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
+

Added: trunk/edk2/OvmfPkg/Library/LoadLinuxLib/Ia32/JumpToKernel.asm
===================================================================
--- trunk/edk2/OvmfPkg/Library/LoadLinuxLib/Ia32/JumpToKernel.asm               
                (rev 0)
+++ trunk/edk2/OvmfPkg/Library/LoadLinuxLib/Ia32/JumpToKernel.asm       
2012-11-02 18:27:55 UTC (rev 13922)
@@ -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

Added: trunk/edk2/OvmfPkg/Library/LoadLinuxLib/Linux.c
===================================================================
--- trunk/edk2/OvmfPkg/Library/LoadLinuxLib/Linux.c                             
(rev 0)
+++ trunk/edk2/OvmfPkg/Library/LoadLinuxLib/Linux.c     2012-11-02 18:27:55 UTC 
(rev 13922)
@@ -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;
+}
+

Added: trunk/edk2/OvmfPkg/Library/LoadLinuxLib/LinuxGdt.c
===================================================================
--- trunk/edk2/OvmfPkg/Library/LoadLinuxLib/LinuxGdt.c                          
(rev 0)
+++ trunk/edk2/OvmfPkg/Library/LoadLinuxLib/LinuxGdt.c  2012-11-02 18:27:55 UTC 
(rev 13922)
@@ -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);
+}
+

Added: trunk/edk2/OvmfPkg/Library/LoadLinuxLib/LoadLinuxLib.h
===================================================================
--- trunk/edk2/OvmfPkg/Library/LoadLinuxLib/LoadLinuxLib.h                      
        (rev 0)
+++ trunk/edk2/OvmfPkg/Library/LoadLinuxLib/LoadLinuxLib.h      2012-11-02 
18:27:55 UTC (rev 13922)
@@ -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
+

Added: trunk/edk2/OvmfPkg/Library/LoadLinuxLib/LoadLinuxLib.inf
===================================================================
--- trunk/edk2/OvmfPkg/Library/LoadLinuxLib/LoadLinuxLib.inf                    
        (rev 0)
+++ trunk/edk2/OvmfPkg/Library/LoadLinuxLib/LoadLinuxLib.inf    2012-11-02 
18:27:55 UTC (rev 13922)
@@ -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
+

Added: trunk/edk2/OvmfPkg/Library/LoadLinuxLib/X64/JumpToKernel.S
===================================================================
--- trunk/edk2/OvmfPkg/Library/LoadLinuxLib/X64/JumpToKernel.S                  
        (rev 0)
+++ trunk/edk2/OvmfPkg/Library/LoadLinuxLib/X64/JumpToKernel.S  2012-11-02 
18:27:55 UTC (rev 13922)
@@ -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
+

Added: trunk/edk2/OvmfPkg/Library/LoadLinuxLib/X64/JumpToKernel.asm
===================================================================
--- trunk/edk2/OvmfPkg/Library/LoadLinuxLib/X64/JumpToKernel.asm                
                (rev 0)
+++ trunk/edk2/OvmfPkg/Library/LoadLinuxLib/X64/JumpToKernel.asm        
2012-11-02 18:27:55 UTC (rev 13922)
@@ -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

Modified: trunk/edk2/OvmfPkg/OvmfPkgIa32.dsc
===================================================================
--- trunk/edk2/OvmfPkg/OvmfPkgIa32.dsc  2012-11-02 18:26:48 UTC (rev 13921)
+++ trunk/edk2/OvmfPkg/OvmfPkgIa32.dsc  2012-11-02 18:27:55 UTC (rev 13922)
@@ -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)

Modified: trunk/edk2/OvmfPkg/OvmfPkgIa32X64.dsc
===================================================================
--- trunk/edk2/OvmfPkg/OvmfPkgIa32X64.dsc       2012-11-02 18:26:48 UTC (rev 
13921)
+++ trunk/edk2/OvmfPkg/OvmfPkgIa32X64.dsc       2012-11-02 18:27:55 UTC (rev 
13922)
@@ -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)

Modified: trunk/edk2/OvmfPkg/OvmfPkgX64.dsc
===================================================================
--- trunk/edk2/OvmfPkg/OvmfPkgX64.dsc   2012-11-02 18:26:48 UTC (rev 13921)
+++ trunk/edk2/OvmfPkg/OvmfPkgX64.dsc   2012-11-02 18:27:55 UTC (rev 13922)
@@ -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)

This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.


------------------------------------------------------------------------------
LogMeIn Central: Instant, anywhere, Remote PC access and management.
Stay in control, update software, and manage PCs from one command center
Diagnose problems and improve visibility into emerging IT issues
Automate, monitor and manage. Do more in less time with Central
http://p.sf.net/sfu/logmein12331_d2d
_______________________________________________
edk2-commits mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/edk2-commits

Reply via email to