3 Copyright (c) 2011 - 2013, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 #include "LoadLinuxLib.h"
19 A simple check of the kernel setup image
21 An assumption is made that the size of the data is at least the
22 size of struct boot_params.
24 @param[in] KernelSetup - The kernel setup image
26 @retval EFI_SUCCESS - The kernel setup looks valid and supported
27 @retval EFI_INVALID_PARAMETER - KernelSetup was NULL
28 @retval EFI_UNSUPPORTED - The kernel setup is not valid or supported
34 BasicKernelSetupCheck (
38 return LoadLinuxCheckKernelSetup(KernelSetup
, sizeof (struct boot_params
));
44 LoadLinuxCheckKernelSetup (
46 IN UINTN KernelSetupSize
49 struct boot_params
*Bp
;
51 if (KernelSetup
== NULL
) {
52 return EFI_INVALID_PARAMETER
;
55 if (KernelSetupSize
< sizeof (*Bp
)) {
56 return EFI_UNSUPPORTED
;
59 Bp
= (struct boot_params
*) KernelSetup
;
61 if ((Bp
->hdr
.signature
!= 0xAA55) || // Check boot sector signature
62 (Bp
->hdr
.header
!= SETUP_HDR
) ||
63 (Bp
->hdr
.version
< 0x205) || // We only support relocatable kernels
64 (!Bp
->hdr
.relocatable_kernel
)
66 return EFI_UNSUPPORTED
;
75 LoadLinuxGetKernelSize (
80 struct boot_params
*Bp
;
82 if (EFI_ERROR (BasicKernelSetupCheck (KernelSetup
))) {
86 Bp
= (struct boot_params
*) KernelSetup
;
88 if (Bp
->hdr
.version
> 0x20a) {
89 return Bp
->hdr
.init_size
;
92 // Add extra size for kernel decompression
94 return 3 * KernelSize
;
101 LoadLinuxAllocateKernelSetupPages (
106 EFI_PHYSICAL_ADDRESS Address
;
109 Status
= gBS
->AllocatePages (
115 if (!EFI_ERROR (Status
)) {
116 return (VOID
*)(UINTN
) Address
;
124 LoadLinuxInitializeKernelSetup (
130 struct boot_params
*Bp
;
132 Status
= BasicKernelSetupCheck (KernelSetup
);
133 if (EFI_ERROR (Status
)) {
137 Bp
= (struct boot_params
*) KernelSetup
;
139 SetupEnd
= 0x202 + (Bp
->hdr
.jump
& 0xff);
142 // Clear all but the setup_header
144 ZeroMem (KernelSetup
, 0x1f1);
145 ZeroMem (((UINT8
*)KernelSetup
) + SetupEnd
, 4096 - SetupEnd
);
146 DEBUG ((EFI_D_INFO
, "Cleared kernel setup 0-0x1f1, 0x%x-0x1000\n", SetupEnd
));
153 LoadLinuxAllocateKernelPages (
154 IN VOID
*KernelSetup
,
159 EFI_PHYSICAL_ADDRESS KernelAddress
;
161 struct boot_params
*Bp
;
163 if (EFI_ERROR (BasicKernelSetupCheck (KernelSetup
))) {
167 Bp
= (struct boot_params
*) KernelSetup
;
169 for (Loop
= 1; Loop
< 512; Loop
++) {
170 KernelAddress
= MultU64x32 (
171 2 * Bp
->hdr
.kernel_alignment
,
174 Status
= gBS
->AllocatePages (
180 if (!EFI_ERROR (Status
)) {
181 return (VOID
*)(UINTN
) KernelAddress
;
191 LoadLinuxAllocateCommandLinePages (
196 EFI_PHYSICAL_ADDRESS Address
;
199 Status
= gBS
->AllocatePages (
205 if (!EFI_ERROR (Status
)) {
206 return (VOID
*)(UINTN
) Address
;
215 LoadLinuxAllocateInitrdPages (
216 IN VOID
*KernelSetup
,
221 EFI_PHYSICAL_ADDRESS Address
;
223 struct boot_params
*Bp
;
225 if (EFI_ERROR (BasicKernelSetupCheck (KernelSetup
))) {
229 Bp
= (struct boot_params
*) KernelSetup
;
231 Address
= (EFI_PHYSICAL_ADDRESS
)(UINTN
) Bp
->hdr
.ramdisk_max
;
232 Status
= gBS
->AllocatePages (
238 if (!EFI_ERROR (Status
)) {
239 return (VOID
*)(UINTN
) Address
;
249 IN OUT
struct boot_params
*Bp
253 UINT8 TmpMemoryMap
[1];
255 UINTN DescriptorSize
;
256 UINT32 DescriptorVersion
;
258 EFI_MEMORY_DESCRIPTOR
*MemoryMap
;
259 EFI_MEMORY_DESCRIPTOR
*MemoryMapPtr
;
261 struct efi_info
*Efi
;
262 struct e820_entry
*LastE820
;
263 struct e820_entry
*E820
;
264 UINTN E820EntryCount
;
265 EFI_PHYSICAL_ADDRESS LastEndAddr
;
268 // Get System MemoryMapSize
270 MemoryMapSize
= sizeof (TmpMemoryMap
);
271 Status
= gBS
->GetMemoryMap (
273 (EFI_MEMORY_DESCRIPTOR
*)TmpMemoryMap
,
278 ASSERT (Status
== EFI_BUFFER_TOO_SMALL
);
280 // Enlarge space here, because we will allocate pool now.
282 MemoryMapSize
+= EFI_PAGE_SIZE
;
283 MemoryMap
= AllocatePool (MemoryMapSize
);
284 ASSERT (MemoryMap
!= NULL
);
287 // Get System MemoryMap
289 Status
= gBS
->GetMemoryMap (
296 ASSERT_EFI_ERROR (Status
);
299 E820
= &Bp
->e820_map
[0];
302 MemoryMapPtr
= MemoryMap
;
303 for (Index
= 0; Index
< (MemoryMapSize
/ DescriptorSize
); Index
++) {
306 if (MemoryMap
->NumberOfPages
== 0) {
310 switch(MemoryMap
->Type
) {
311 case EfiReservedMemoryType
:
312 case EfiRuntimeServicesCode
:
313 case EfiRuntimeServicesData
:
314 case EfiMemoryMappedIO
:
315 case EfiMemoryMappedIOPortSpace
:
317 E820Type
= E820_RESERVED
;
320 case EfiUnusableMemory
:
321 E820Type
= E820_UNUSABLE
;
324 case EfiACPIReclaimMemory
:
325 E820Type
= E820_ACPI
;
330 case EfiBootServicesCode
:
331 case EfiBootServicesData
:
332 case EfiConventionalMemory
:
336 case EfiACPIMemoryNVS
:
343 "Invalid EFI memory descriptor type (0x%x)!\n",
349 if ((LastE820
!= NULL
) &&
350 (LastE820
->type
== (UINT32
) E820Type
) &&
351 (MemoryMap
->PhysicalStart
== LastEndAddr
)) {
352 LastE820
->size
+= EFI_PAGES_TO_SIZE (MemoryMap
->NumberOfPages
);
353 LastEndAddr
+= EFI_PAGES_TO_SIZE (MemoryMap
->NumberOfPages
);
355 if (E820EntryCount
>= (sizeof (Bp
->e820_map
) / sizeof (Bp
->e820_map
[0]))) {
358 E820
->type
= (UINT32
) E820Type
;
359 E820
->addr
= MemoryMap
->PhysicalStart
;
360 E820
->size
= EFI_PAGES_TO_SIZE (MemoryMap
->NumberOfPages
);
362 LastEndAddr
= E820
->addr
+ E820
->size
;
370 MemoryMap
= (EFI_MEMORY_DESCRIPTOR
*)((UINTN
)MemoryMap
+ DescriptorSize
);
372 Bp
->e820_entries
= (UINT8
) E820EntryCount
;
375 Efi
->efi_systab
= (UINT32
)(UINTN
) gST
;
376 Efi
->efi_memdesc_size
= (UINT32
) DescriptorSize
;
377 Efi
->efi_memdesc_version
= DescriptorVersion
;
378 Efi
->efi_memmap
= (UINT32
)(UINTN
) MemoryMapPtr
;
379 Efi
->efi_memmap_size
= (UINT32
) MemoryMapSize
;
381 Efi
->efi_loader_signature
= SIGNATURE_32 ('E', 'L', '3', '2');
383 Efi
->efi_systab_hi
= ((UINT64
)(UINTN
) gST
) >> 32;
384 Efi
->efi_memmap_hi
= ((UINT64
)(UINTN
) MemoryMapPtr
) >> 32;
385 Efi
->efi_loader_signature
= SIGNATURE_32 ('E', 'L', '6', '4');
388 gBS
->ExitBootServices (gImageHandle
, MapKey
);
394 LoadLinuxSetCommandLine (
395 IN OUT VOID
*KernelSetup
,
396 IN CHAR8
*CommandLine
400 struct boot_params
*Bp
;
402 Status
= BasicKernelSetupCheck (KernelSetup
);
403 if (EFI_ERROR (Status
)) {
407 Bp
= (struct boot_params
*) KernelSetup
;
409 Bp
->hdr
.cmd_line_ptr
= (UINT32
)(UINTN
) CommandLine
;
418 IN OUT VOID
*KernelSetup
,
424 struct boot_params
*Bp
;
426 Status
= BasicKernelSetupCheck (KernelSetup
);
427 if (EFI_ERROR (Status
)) {
431 Bp
= (struct boot_params
*) KernelSetup
;
433 Bp
->hdr
.ramdisk_start
= (UINT32
)(UINTN
) Initrd
;
434 Bp
->hdr
.ramdisk_len
= (UINT32
) InitrdSize
;
453 while (!(Mask
& 0x1)) {
470 SetupGraphicsFromGop (
471 struct screen_info
*Si
,
472 EFI_GRAPHICS_OUTPUT_PROTOCOL
*Gop
475 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*Info
;
479 Status
= Gop
->QueryMode(Gop
, Gop
->Mode
->Mode
, &Size
, &Info
);
480 if (EFI_ERROR (Status
)) {
486 /* EFI framebuffer */
487 Si
->orig_video_isVGA
= 0x70;
491 Si
->orig_video_page
= 0;
492 Si
->orig_video_mode
= 0;
493 Si
->orig_video_cols
= 0;
494 Si
->orig_video_lines
= 0;
495 Si
->orig_video_ega_bx
= 0;
496 Si
->orig_video_points
= 0;
498 Si
->lfb_base
= (UINT32
) Gop
->Mode
->FrameBufferBase
;
499 Si
->lfb_size
= (UINT32
) Gop
->Mode
->FrameBufferSize
;
500 Si
->lfb_width
= (UINT16
) Info
->HorizontalResolution
;
501 Si
->lfb_height
= (UINT16
) Info
->VerticalResolution
;
506 if (Info
->PixelFormat
== PixelRedGreenBlueReserved8BitPerColor
) {
516 Si
->lfb_linelength
= (UINT16
) (Info
->PixelsPerScanLine
* 4);
518 } else if (Info
->PixelFormat
== PixelBlueGreenRedReserved8BitPerColor
) {
528 Si
->lfb_linelength
= (UINT16
) (Info
->PixelsPerScanLine
* 4);
529 } else if (Info
->PixelFormat
== PixelBitMask
) {
530 FindBits(Info
->PixelInformation
.RedMask
,
531 &Si
->red_pos
, &Si
->red_size
);
532 FindBits(Info
->PixelInformation
.GreenMask
,
533 &Si
->green_pos
, &Si
->green_size
);
534 FindBits(Info
->PixelInformation
.BlueMask
,
535 &Si
->blue_pos
, &Si
->blue_size
);
536 FindBits(Info
->PixelInformation
.ReservedMask
,
537 &Si
->rsvd_pos
, &Si
->rsvd_size
);
538 Si
->lfb_depth
= Si
->red_size
+ Si
->green_size
+
539 Si
->blue_size
+ Si
->rsvd_size
;
540 Si
->lfb_linelength
= (UINT16
) ((Info
->PixelsPerScanLine
* Si
->lfb_depth
) / 8);
551 Si
->lfb_linelength
= Si
->lfb_width
/ 2;
561 IN OUT
struct boot_params
*Bp
565 EFI_HANDLE
*HandleBuffer
;
568 EFI_GRAPHICS_OUTPUT_PROTOCOL
*Gop
;
570 ZeroMem ((VOID
*)&Bp
->screen_info
, sizeof(Bp
->screen_info
));
572 Status
= gBS
->LocateHandleBuffer (
574 &gEfiGraphicsOutputProtocolGuid
,
579 if (!EFI_ERROR (Status
)) {
580 for (Index
= 0; Index
< HandleCount
; Index
++) {
581 Status
= gBS
->HandleProtocol (
583 &gEfiGraphicsOutputProtocolGuid
,
586 if (EFI_ERROR (Status
)) {
590 Status
= SetupGraphicsFromGop (&Bp
->screen_info
, Gop
);
591 if (!EFI_ERROR (Status
)) {
592 FreePool (HandleBuffer
);
597 FreePool (HandleBuffer
);
600 return EFI_NOT_FOUND
;
606 SetupLinuxBootParams (
607 IN OUT
struct boot_params
*Bp
612 SetupLinuxMemmap (Bp
);
622 IN OUT VOID
*KernelSetup
626 struct boot_params
*Bp
;
628 Status
= BasicKernelSetupCheck (KernelSetup
);
629 if (EFI_ERROR (Status
)) {
633 Bp
= (struct boot_params
*) KernelSetup
;
635 if (Bp
->hdr
.version
< 0x205 || !Bp
->hdr
.relocatable_kernel
) {
637 // We only support relocatable kernels
639 return EFI_UNSUPPORTED
;
642 InitLinuxDescriptorTables ();
644 Bp
->hdr
.code32_start
= (UINT32
)(UINTN
) Kernel
;
645 if (Bp
->hdr
.version
>= 0x20c && Bp
->hdr
.handover_offset
&&
646 (Bp
->hdr
.load_flags
& (sizeof (UINTN
) == 4 ? BIT2
: BIT3
))) {
647 DEBUG ((EFI_D_INFO
, "Jumping to kernel EFI handover point at ofs %x\n", Bp
->hdr
.handover_offset
));
649 DisableInterrupts ();
650 JumpToUefiKernel ((VOID
*) gImageHandle
, (VOID
*) gST
, KernelSetup
, Kernel
);
654 // Old kernels without EFI handover protocol
656 SetupLinuxBootParams (KernelSetup
);
658 DEBUG ((EFI_D_INFO
, "Jumping to kernel\n"));
659 DisableInterrupts ();
660 SetLinuxDescriptorTables ();
661 JumpToKernel (Kernel
, (VOID
*) KernelSetup
);