LoadLinux() is looking at the wrong field for the kernel's EFI handover protocol flags. It's not currently possible for JumpToUefiKernel() to ever be called (even accidentally) because BIT2 and BIT3 of Bp->hdr.load_flags are never set in modern kernels, which means that control is always transferred to the kernel via the legacy entry point. Look at the correct field so that the EFI handover protocol is used whenever it's available. Contributed-under: TianoCore Contribution Agreement 1.0 Cc: David Woodhouse <David.Woodhouse@intel.com> Cc: Jordan Justen <jordan.l.justen@intel.com> Cc: Borislav Petkov <bp@suse.de> Signed-off-by: Matt Fleming <matt.fleming@intel.com> Reviewed-by: Jordan Justen <jordan.l.justen@intel.com> git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@14721 6f19259b-4bc3-4df7-8a09-765794883524
670 lines
16 KiB
C
670 lines
16 KiB
C
/** @file
|
|
|
|
Copyright (c) 2011 - 2013, 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
|
|
(!Bp->hdr.relocatable_kernel)
|
|
) {
|
|
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;
|
|
}
|
|
}
|
|
|
|
EFI_STATUS
|
|
EFIAPI
|
|
LoadLinuxInitializeKernelSetup (
|
|
IN VOID *KernelSetup
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINTN SetupEnd;
|
|
struct boot_params *Bp;
|
|
|
|
Status = BasicKernelSetupCheck (KernelSetup);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
Bp = (struct boot_params*) KernelSetup;
|
|
|
|
SetupEnd = 0x202 + (Bp->hdr.jump & 0xff);
|
|
|
|
//
|
|
// Clear all but the setup_header
|
|
//
|
|
ZeroMem (KernelSetup, 0x1f1);
|
|
ZeroMem (((UINT8 *)KernelSetup) + SetupEnd, 4096 - SetupEnd);
|
|
DEBUG ((EFI_D_INFO, "Cleared kernel setup 0-0x1f1, 0x%x-0x1000\n", SetupEnd));
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
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;
|
|
Status = gBS->AllocatePool (
|
|
EfiLoaderData,
|
|
MemoryMapSize,
|
|
(VOID **) &MemoryMap
|
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
//
|
|
// 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 ((UINTN) MemoryMap->NumberOfPages);
|
|
LastEndAddr += EFI_PAGES_TO_SIZE ((UINTN) 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 ((UINTN) 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 OUT struct boot_params *Bp
|
|
)
|
|
{
|
|
SetupGraphics (Bp);
|
|
|
|
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 || !Bp->hdr.relocatable_kernel) {
|
|
//
|
|
// We only support relocatable kernels
|
|
//
|
|
return EFI_UNSUPPORTED;
|
|
}
|
|
|
|
InitLinuxDescriptorTables ();
|
|
|
|
Bp->hdr.code32_start = (UINT32)(UINTN) Kernel;
|
|
if (Bp->hdr.version >= 0x20c && Bp->hdr.handover_offset &&
|
|
(Bp->hdr.xloadflags & (sizeof (UINTN) == 4 ? BIT2 : BIT3))) {
|
|
DEBUG ((EFI_D_INFO, "Jumping to kernel EFI handover point at ofs %x\n", Bp->hdr.handover_offset));
|
|
|
|
DisableInterrupts ();
|
|
JumpToUefiKernel ((VOID*) gImageHandle, (VOID*) gST, KernelSetup, Kernel);
|
|
}
|
|
|
|
//
|
|
// Old kernels without EFI handover protocol
|
|
//
|
|
SetupLinuxBootParams (KernelSetup);
|
|
|
|
DEBUG ((EFI_D_INFO, "Jumping to kernel\n"));
|
|
DisableInterrupts ();
|
|
SetLinuxDescriptorTables ();
|
|
JumpToKernel (Kernel, (VOID*) KernelSetup);
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|