mirror of
https://github.com/acidanthera/audk.git
synced 2025-04-08 17:05:09 +02:00
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 <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
This commit is contained in:
parent
f6c6c02028
commit
3c0a051fa2
29
OvmfPkg/Library/LoadLinuxLib/Ia32/JumpToKernel.S
Normal file
29
OvmfPkg/Library/LoadLinuxLib/Ia32/JumpToKernel.S
Normal file
@ -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
|
||||
|
35
OvmfPkg/Library/LoadLinuxLib/Ia32/JumpToKernel.asm
Normal file
35
OvmfPkg/Library/LoadLinuxLib/Ia32/JumpToKernel.asm
Normal file
@ -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
|
627
OvmfPkg/Library/LoadLinuxLib/Linux.c
Normal file
627
OvmfPkg/Library/LoadLinuxLib/Linux.c
Normal file
@ -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;
|
||||
}
|
||||
|
181
OvmfPkg/Library/LoadLinuxLib/LinuxGdt.c
Normal file
181
OvmfPkg/Library/LoadLinuxLib/LinuxGdt.c
Normal file
@ -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);
|
||||
}
|
||||
|
50
OvmfPkg/Library/LoadLinuxLib/LoadLinuxLib.h
Normal file
50
OvmfPkg/Library/LoadLinuxLib/LoadLinuxLib.h
Normal file
@ -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
|
||||
|
50
OvmfPkg/Library/LoadLinuxLib/LoadLinuxLib.inf
Normal file
50
OvmfPkg/Library/LoadLinuxLib/LoadLinuxLib.inf
Normal file
@ -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
|
||||
|
30
OvmfPkg/Library/LoadLinuxLib/X64/JumpToKernel.S
Normal file
30
OvmfPkg/Library/LoadLinuxLib/X64/JumpToKernel.S
Normal file
@ -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
|
||||
|
34
OvmfPkg/Library/LoadLinuxLib/X64/JumpToKernel.asm
Normal file
34
OvmfPkg/Library/LoadLinuxLib/X64/JumpToKernel.asm
Normal file
@ -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
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user