From: jljusten Date: Fri, 2 Nov 2012 18:27:55 +0000 (+0000) Subject: OvmfPkg: Add LoadLinuxLib library implementation X-Git-Tag: edk2-stable201903~12903 X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=commitdiff_plain;h=3c0a051fa2bc443cee65d25fda74771f47cbb8eb 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 Reviewed-by: Laszlo Ersek Reviewed-by: Matt Fleming git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@13922 6f19259b-4bc3-4df7-8a09-765794883524 --- 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.
+# +# 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.
+; +; 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.
+ + 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.
+ 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.
+ + 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 +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +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.
+# +# 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.
+# +# 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.
+; +; 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)