3 Copyright (c) 2011 - 2014, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
9 #include "LoadLinuxLib.h"
13 A simple check of the kernel setup image
15 An assumption is made that the size of the data is at least the
16 size of struct boot_params.
18 @param[in] KernelSetup - The kernel setup image
20 @retval EFI_SUCCESS - The kernel setup looks valid and supported
21 @retval EFI_INVALID_PARAMETER - KernelSetup was NULL
22 @retval EFI_UNSUPPORTED - The kernel setup is not valid or supported
28 BasicKernelSetupCheck (
32 return LoadLinuxCheckKernelSetup(KernelSetup
, sizeof (struct boot_params
));
38 LoadLinuxCheckKernelSetup (
40 IN UINTN KernelSetupSize
43 struct boot_params
*Bp
;
45 if (KernelSetup
== NULL
) {
46 return EFI_INVALID_PARAMETER
;
49 if (KernelSetupSize
< sizeof (*Bp
)) {
50 return EFI_UNSUPPORTED
;
53 Bp
= (struct boot_params
*) KernelSetup
;
55 if ((Bp
->hdr
.signature
!= 0xAA55) || // Check boot sector signature
56 (Bp
->hdr
.header
!= SETUP_HDR
) ||
57 (Bp
->hdr
.version
< 0x205) || // We only support relocatable kernels
58 (!Bp
->hdr
.relocatable_kernel
)
60 return EFI_UNSUPPORTED
;
69 LoadLinuxGetKernelSize (
74 struct boot_params
*Bp
;
76 if (EFI_ERROR (BasicKernelSetupCheck (KernelSetup
))) {
80 Bp
= (struct boot_params
*) KernelSetup
;
82 if (Bp
->hdr
.version
> 0x20a) {
83 return Bp
->hdr
.init_size
;
86 // Add extra size for kernel decompression
88 return 3 * KernelSize
;
95 LoadLinuxAllocateKernelSetupPages (
100 EFI_PHYSICAL_ADDRESS Address
;
103 Status
= gBS
->AllocatePages (
109 if (!EFI_ERROR (Status
)) {
110 return (VOID
*)(UINTN
) Address
;
118 LoadLinuxInitializeKernelSetup (
124 struct boot_params
*Bp
;
126 Status
= BasicKernelSetupCheck (KernelSetup
);
127 if (EFI_ERROR (Status
)) {
131 Bp
= (struct boot_params
*) KernelSetup
;
133 SetupEnd
= 0x202 + (Bp
->hdr
.jump
& 0xff);
136 // Clear all but the setup_header
138 ZeroMem (KernelSetup
, 0x1f1);
139 ZeroMem (((UINT8
*)KernelSetup
) + SetupEnd
, 4096 - SetupEnd
);
140 DEBUG ((DEBUG_INFO
, "Cleared kernel setup 0-0x1f1, 0x%Lx-0x1000\n",
148 LoadLinuxAllocateKernelPages (
149 IN VOID
*KernelSetup
,
154 EFI_PHYSICAL_ADDRESS KernelAddress
;
156 struct boot_params
*Bp
;
158 if (EFI_ERROR (BasicKernelSetupCheck (KernelSetup
))) {
162 Bp
= (struct boot_params
*) KernelSetup
;
164 for (Loop
= 1; Loop
< 512; Loop
++) {
165 KernelAddress
= MultU64x32 (
166 2 * Bp
->hdr
.kernel_alignment
,
169 Status
= gBS
->AllocatePages (
175 if (!EFI_ERROR (Status
)) {
176 return (VOID
*)(UINTN
) KernelAddress
;
186 LoadLinuxAllocateCommandLinePages (
191 EFI_PHYSICAL_ADDRESS Address
;
194 Status
= gBS
->AllocatePages (
200 if (!EFI_ERROR (Status
)) {
201 return (VOID
*)(UINTN
) Address
;
210 LoadLinuxAllocateInitrdPages (
211 IN VOID
*KernelSetup
,
216 EFI_PHYSICAL_ADDRESS Address
;
218 struct boot_params
*Bp
;
220 if (EFI_ERROR (BasicKernelSetupCheck (KernelSetup
))) {
224 Bp
= (struct boot_params
*) KernelSetup
;
226 Address
= (EFI_PHYSICAL_ADDRESS
)(UINTN
) Bp
->hdr
.ramdisk_max
;
227 Status
= gBS
->AllocatePages (
233 if (!EFI_ERROR (Status
)) {
234 return (VOID
*)(UINTN
) Address
;
244 IN OUT
struct boot_params
*Bp
248 UINT8 TmpMemoryMap
[1];
250 UINTN DescriptorSize
;
251 UINT32 DescriptorVersion
;
253 EFI_MEMORY_DESCRIPTOR
*MemoryMap
;
254 EFI_MEMORY_DESCRIPTOR
*MemoryMapPtr
;
256 struct efi_info
*Efi
;
257 struct e820_entry
*LastE820
;
258 struct e820_entry
*E820
;
259 UINTN E820EntryCount
;
260 EFI_PHYSICAL_ADDRESS LastEndAddr
;
263 // Get System MemoryMapSize
265 MemoryMapSize
= sizeof (TmpMemoryMap
);
266 Status
= gBS
->GetMemoryMap (
268 (EFI_MEMORY_DESCRIPTOR
*)TmpMemoryMap
,
273 ASSERT (Status
== EFI_BUFFER_TOO_SMALL
);
275 // Enlarge space here, because we will allocate pool now.
277 MemoryMapSize
+= EFI_PAGE_SIZE
;
278 Status
= gBS
->AllocatePool (
283 ASSERT_EFI_ERROR (Status
);
286 // Get System MemoryMap
288 Status
= gBS
->GetMemoryMap (
295 ASSERT_EFI_ERROR (Status
);
298 E820
= &Bp
->e820_map
[0];
301 MemoryMapPtr
= MemoryMap
;
302 for (Index
= 0; Index
< (MemoryMapSize
/ DescriptorSize
); Index
++) {
305 if (MemoryMap
->NumberOfPages
== 0) {
309 switch(MemoryMap
->Type
) {
310 case EfiReservedMemoryType
:
311 case EfiRuntimeServicesCode
:
312 case EfiRuntimeServicesData
:
313 case EfiMemoryMappedIO
:
314 case EfiMemoryMappedIOPortSpace
:
316 E820Type
= E820_RESERVED
;
319 case EfiUnusableMemory
:
320 E820Type
= E820_UNUSABLE
;
323 case EfiACPIReclaimMemory
:
324 E820Type
= E820_ACPI
;
329 case EfiBootServicesCode
:
330 case EfiBootServicesData
:
331 case EfiConventionalMemory
:
335 case EfiACPIMemoryNVS
:
342 "Invalid EFI memory descriptor type (0x%x)!\n",
348 if ((LastE820
!= NULL
) &&
349 (LastE820
->type
== (UINT32
) E820Type
) &&
350 (MemoryMap
->PhysicalStart
== LastEndAddr
)) {
351 LastE820
->size
+= EFI_PAGES_TO_SIZE ((UINTN
) MemoryMap
->NumberOfPages
);
352 LastEndAddr
+= EFI_PAGES_TO_SIZE ((UINTN
) MemoryMap
->NumberOfPages
);
354 if (E820EntryCount
>= ARRAY_SIZE (Bp
->e820_map
)) {
357 E820
->type
= (UINT32
) E820Type
;
358 E820
->addr
= MemoryMap
->PhysicalStart
;
359 E820
->size
= EFI_PAGES_TO_SIZE ((UINTN
) MemoryMap
->NumberOfPages
);
361 LastEndAddr
= E820
->addr
+ E820
->size
;
369 MemoryMap
= (EFI_MEMORY_DESCRIPTOR
*)((UINTN
)MemoryMap
+ DescriptorSize
);
371 Bp
->e820_entries
= (UINT8
) E820EntryCount
;
374 Efi
->efi_systab
= (UINT32
)(UINTN
) gST
;
375 Efi
->efi_memdesc_size
= (UINT32
) DescriptorSize
;
376 Efi
->efi_memdesc_version
= DescriptorVersion
;
377 Efi
->efi_memmap
= (UINT32
)(UINTN
) MemoryMapPtr
;
378 Efi
->efi_memmap_size
= (UINT32
) MemoryMapSize
;
380 Efi
->efi_loader_signature
= SIGNATURE_32 ('E', 'L', '3', '2');
382 Efi
->efi_systab_hi
= (UINT32
) (((UINT64
)(UINTN
) gST
) >> 32);
383 Efi
->efi_memmap_hi
= (UINT32
) (((UINT64
)(UINTN
) MemoryMapPtr
) >> 32);
384 Efi
->efi_loader_signature
= SIGNATURE_32 ('E', 'L', '6', '4');
387 gBS
->ExitBootServices (gImageHandle
, MapKey
);
393 LoadLinuxSetCommandLine (
394 IN OUT VOID
*KernelSetup
,
395 IN CHAR8
*CommandLine
399 struct boot_params
*Bp
;
401 Status
= BasicKernelSetupCheck (KernelSetup
);
402 if (EFI_ERROR (Status
)) {
406 Bp
= (struct boot_params
*) KernelSetup
;
408 Bp
->hdr
.cmd_line_ptr
= (UINT32
)(UINTN
) CommandLine
;
417 IN OUT VOID
*KernelSetup
,
423 struct boot_params
*Bp
;
425 Status
= BasicKernelSetupCheck (KernelSetup
);
426 if (EFI_ERROR (Status
)) {
430 Bp
= (struct boot_params
*) KernelSetup
;
432 Bp
->hdr
.ramdisk_start
= (UINT32
)(UINTN
) Initrd
;
433 Bp
->hdr
.ramdisk_len
= (UINT32
) InitrdSize
;
452 while (!(Mask
& 0x1)) {
469 SetupGraphicsFromGop (
470 struct screen_info
*Si
,
471 EFI_GRAPHICS_OUTPUT_PROTOCOL
*Gop
474 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*Info
;
478 Status
= Gop
->QueryMode(Gop
, Gop
->Mode
->Mode
, &Size
, &Info
);
479 if (EFI_ERROR (Status
)) {
485 /* EFI framebuffer */
486 Si
->orig_video_isVGA
= 0x70;
490 Si
->orig_video_page
= 0;
491 Si
->orig_video_mode
= 0;
492 Si
->orig_video_cols
= 0;
493 Si
->orig_video_lines
= 0;
494 Si
->orig_video_ega_bx
= 0;
495 Si
->orig_video_points
= 0;
497 Si
->lfb_base
= (UINT32
) Gop
->Mode
->FrameBufferBase
;
498 Si
->lfb_size
= (UINT32
) Gop
->Mode
->FrameBufferSize
;
499 Si
->lfb_width
= (UINT16
) Info
->HorizontalResolution
;
500 Si
->lfb_height
= (UINT16
) Info
->VerticalResolution
;
505 if (Info
->PixelFormat
== PixelRedGreenBlueReserved8BitPerColor
) {
515 Si
->lfb_linelength
= (UINT16
) (Info
->PixelsPerScanLine
* 4);
517 } else if (Info
->PixelFormat
== PixelBlueGreenRedReserved8BitPerColor
) {
527 Si
->lfb_linelength
= (UINT16
) (Info
->PixelsPerScanLine
* 4);
528 } else if (Info
->PixelFormat
== PixelBitMask
) {
529 FindBits(Info
->PixelInformation
.RedMask
,
530 &Si
->red_pos
, &Si
->red_size
);
531 FindBits(Info
->PixelInformation
.GreenMask
,
532 &Si
->green_pos
, &Si
->green_size
);
533 FindBits(Info
->PixelInformation
.BlueMask
,
534 &Si
->blue_pos
, &Si
->blue_size
);
535 FindBits(Info
->PixelInformation
.ReservedMask
,
536 &Si
->rsvd_pos
, &Si
->rsvd_size
);
537 Si
->lfb_depth
= Si
->red_size
+ Si
->green_size
+
538 Si
->blue_size
+ Si
->rsvd_size
;
539 Si
->lfb_linelength
= (UINT16
) ((Info
->PixelsPerScanLine
* Si
->lfb_depth
) / 8);
550 Si
->lfb_linelength
= Si
->lfb_width
/ 2;
560 IN OUT
struct boot_params
*Bp
564 EFI_HANDLE
*HandleBuffer
;
567 EFI_GRAPHICS_OUTPUT_PROTOCOL
*Gop
;
569 ZeroMem ((VOID
*)&Bp
->screen_info
, sizeof(Bp
->screen_info
));
571 Status
= gBS
->LocateHandleBuffer (
573 &gEfiGraphicsOutputProtocolGuid
,
578 if (!EFI_ERROR (Status
)) {
579 for (Index
= 0; Index
< HandleCount
; Index
++) {
580 Status
= gBS
->HandleProtocol (
582 &gEfiGraphicsOutputProtocolGuid
,
585 if (EFI_ERROR (Status
)) {
589 Status
= SetupGraphicsFromGop (&Bp
->screen_info
, Gop
);
590 if (!EFI_ERROR (Status
)) {
591 FreePool (HandleBuffer
);
596 FreePool (HandleBuffer
);
599 return EFI_NOT_FOUND
;
605 SetupLinuxBootParams (
606 IN OUT
struct boot_params
*Bp
611 SetupLinuxMemmap (Bp
);
621 IN OUT VOID
*KernelSetup
625 struct boot_params
*Bp
;
627 Status
= BasicKernelSetupCheck (KernelSetup
);
628 if (EFI_ERROR (Status
)) {
632 Bp
= (struct boot_params
*) KernelSetup
;
634 if (Bp
->hdr
.version
< 0x205 || !Bp
->hdr
.relocatable_kernel
) {
636 // We only support relocatable kernels
638 return EFI_UNSUPPORTED
;
641 InitLinuxDescriptorTables ();
643 Bp
->hdr
.code32_start
= (UINT32
)(UINTN
) Kernel
;
644 if (Bp
->hdr
.version
>= 0x20c && Bp
->hdr
.handover_offset
&&
645 (Bp
->hdr
.xloadflags
& (sizeof (UINTN
) == 4 ? BIT2
: BIT3
))) {
646 DEBUG ((DEBUG_INFO
, "Jumping to kernel EFI handover point at ofs %x\n", Bp
->hdr
.handover_offset
));
648 DisableInterrupts ();
649 JumpToUefiKernel ((VOID
*) gImageHandle
, (VOID
*) gST
, KernelSetup
, Kernel
);
653 // Old kernels without EFI handover protocol
655 SetupLinuxBootParams (KernelSetup
);
657 DEBUG ((DEBUG_INFO
, "Jumping to kernel\n"));
658 DisableInterrupts ();
659 SetLinuxDescriptorTables ();
660 JumpToKernel (Kernel
, (VOID
*) KernelSetup
);