3 Copyright (c) 2011 - 2014, 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%Lx-0x1000\n",
154 LoadLinuxAllocateKernelPages (
155 IN VOID
*KernelSetup
,
160 EFI_PHYSICAL_ADDRESS KernelAddress
;
162 struct boot_params
*Bp
;
164 if (EFI_ERROR (BasicKernelSetupCheck (KernelSetup
))) {
168 Bp
= (struct boot_params
*) KernelSetup
;
170 for (Loop
= 1; Loop
< 512; Loop
++) {
171 KernelAddress
= MultU64x32 (
172 2 * Bp
->hdr
.kernel_alignment
,
175 Status
= gBS
->AllocatePages (
181 if (!EFI_ERROR (Status
)) {
182 return (VOID
*)(UINTN
) KernelAddress
;
192 LoadLinuxAllocateCommandLinePages (
197 EFI_PHYSICAL_ADDRESS Address
;
200 Status
= gBS
->AllocatePages (
206 if (!EFI_ERROR (Status
)) {
207 return (VOID
*)(UINTN
) Address
;
216 LoadLinuxAllocateInitrdPages (
217 IN VOID
*KernelSetup
,
222 EFI_PHYSICAL_ADDRESS Address
;
224 struct boot_params
*Bp
;
226 if (EFI_ERROR (BasicKernelSetupCheck (KernelSetup
))) {
230 Bp
= (struct boot_params
*) KernelSetup
;
232 Address
= (EFI_PHYSICAL_ADDRESS
)(UINTN
) Bp
->hdr
.ramdisk_max
;
233 Status
= gBS
->AllocatePages (
239 if (!EFI_ERROR (Status
)) {
240 return (VOID
*)(UINTN
) Address
;
250 IN OUT
struct boot_params
*Bp
254 UINT8 TmpMemoryMap
[1];
256 UINTN DescriptorSize
;
257 UINT32 DescriptorVersion
;
259 EFI_MEMORY_DESCRIPTOR
*MemoryMap
;
260 EFI_MEMORY_DESCRIPTOR
*MemoryMapPtr
;
262 struct efi_info
*Efi
;
263 struct e820_entry
*LastE820
;
264 struct e820_entry
*E820
;
265 UINTN E820EntryCount
;
266 EFI_PHYSICAL_ADDRESS LastEndAddr
;
269 // Get System MemoryMapSize
271 MemoryMapSize
= sizeof (TmpMemoryMap
);
272 Status
= gBS
->GetMemoryMap (
274 (EFI_MEMORY_DESCRIPTOR
*)TmpMemoryMap
,
279 ASSERT (Status
== EFI_BUFFER_TOO_SMALL
);
281 // Enlarge space here, because we will allocate pool now.
283 MemoryMapSize
+= EFI_PAGE_SIZE
;
284 Status
= gBS
->AllocatePool (
289 ASSERT_EFI_ERROR (Status
);
292 // Get System MemoryMap
294 Status
= gBS
->GetMemoryMap (
301 ASSERT_EFI_ERROR (Status
);
304 E820
= &Bp
->e820_map
[0];
307 MemoryMapPtr
= MemoryMap
;
308 for (Index
= 0; Index
< (MemoryMapSize
/ DescriptorSize
); Index
++) {
311 if (MemoryMap
->NumberOfPages
== 0) {
315 switch(MemoryMap
->Type
) {
316 case EfiReservedMemoryType
:
317 case EfiRuntimeServicesCode
:
318 case EfiRuntimeServicesData
:
319 case EfiMemoryMappedIO
:
320 case EfiMemoryMappedIOPortSpace
:
322 E820Type
= E820_RESERVED
;
325 case EfiUnusableMemory
:
326 E820Type
= E820_UNUSABLE
;
329 case EfiACPIReclaimMemory
:
330 E820Type
= E820_ACPI
;
335 case EfiBootServicesCode
:
336 case EfiBootServicesData
:
337 case EfiConventionalMemory
:
341 case EfiACPIMemoryNVS
:
348 "Invalid EFI memory descriptor type (0x%x)!\n",
354 if ((LastE820
!= NULL
) &&
355 (LastE820
->type
== (UINT32
) E820Type
) &&
356 (MemoryMap
->PhysicalStart
== LastEndAddr
)) {
357 LastE820
->size
+= EFI_PAGES_TO_SIZE ((UINTN
) MemoryMap
->NumberOfPages
);
358 LastEndAddr
+= EFI_PAGES_TO_SIZE ((UINTN
) MemoryMap
->NumberOfPages
);
360 if (E820EntryCount
>= (sizeof (Bp
->e820_map
) / sizeof (Bp
->e820_map
[0]))) {
363 E820
->type
= (UINT32
) E820Type
;
364 E820
->addr
= MemoryMap
->PhysicalStart
;
365 E820
->size
= EFI_PAGES_TO_SIZE ((UINTN
) MemoryMap
->NumberOfPages
);
367 LastEndAddr
= E820
->addr
+ E820
->size
;
375 MemoryMap
= (EFI_MEMORY_DESCRIPTOR
*)((UINTN
)MemoryMap
+ DescriptorSize
);
377 Bp
->e820_entries
= (UINT8
) E820EntryCount
;
380 Efi
->efi_systab
= (UINT32
)(UINTN
) gST
;
381 Efi
->efi_memdesc_size
= (UINT32
) DescriptorSize
;
382 Efi
->efi_memdesc_version
= DescriptorVersion
;
383 Efi
->efi_memmap
= (UINT32
)(UINTN
) MemoryMapPtr
;
384 Efi
->efi_memmap_size
= (UINT32
) MemoryMapSize
;
386 Efi
->efi_loader_signature
= SIGNATURE_32 ('E', 'L', '3', '2');
388 Efi
->efi_systab_hi
= (UINT32
) (((UINT64
)(UINTN
) gST
) >> 32);
389 Efi
->efi_memmap_hi
= (UINT32
) (((UINT64
)(UINTN
) MemoryMapPtr
) >> 32);
390 Efi
->efi_loader_signature
= SIGNATURE_32 ('E', 'L', '6', '4');
393 gBS
->ExitBootServices (gImageHandle
, MapKey
);
399 LoadLinuxSetCommandLine (
400 IN OUT VOID
*KernelSetup
,
401 IN CHAR8
*CommandLine
405 struct boot_params
*Bp
;
407 Status
= BasicKernelSetupCheck (KernelSetup
);
408 if (EFI_ERROR (Status
)) {
412 Bp
= (struct boot_params
*) KernelSetup
;
414 Bp
->hdr
.cmd_line_ptr
= (UINT32
)(UINTN
) CommandLine
;
423 IN OUT VOID
*KernelSetup
,
429 struct boot_params
*Bp
;
431 Status
= BasicKernelSetupCheck (KernelSetup
);
432 if (EFI_ERROR (Status
)) {
436 Bp
= (struct boot_params
*) KernelSetup
;
438 Bp
->hdr
.ramdisk_start
= (UINT32
)(UINTN
) Initrd
;
439 Bp
->hdr
.ramdisk_len
= (UINT32
) InitrdSize
;
458 while (!(Mask
& 0x1)) {
475 SetupGraphicsFromGop (
476 struct screen_info
*Si
,
477 EFI_GRAPHICS_OUTPUT_PROTOCOL
*Gop
480 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*Info
;
484 Status
= Gop
->QueryMode(Gop
, Gop
->Mode
->Mode
, &Size
, &Info
);
485 if (EFI_ERROR (Status
)) {
491 /* EFI framebuffer */
492 Si
->orig_video_isVGA
= 0x70;
496 Si
->orig_video_page
= 0;
497 Si
->orig_video_mode
= 0;
498 Si
->orig_video_cols
= 0;
499 Si
->orig_video_lines
= 0;
500 Si
->orig_video_ega_bx
= 0;
501 Si
->orig_video_points
= 0;
503 Si
->lfb_base
= (UINT32
) Gop
->Mode
->FrameBufferBase
;
504 Si
->lfb_size
= (UINT32
) Gop
->Mode
->FrameBufferSize
;
505 Si
->lfb_width
= (UINT16
) Info
->HorizontalResolution
;
506 Si
->lfb_height
= (UINT16
) Info
->VerticalResolution
;
511 if (Info
->PixelFormat
== PixelRedGreenBlueReserved8BitPerColor
) {
521 Si
->lfb_linelength
= (UINT16
) (Info
->PixelsPerScanLine
* 4);
523 } else if (Info
->PixelFormat
== PixelBlueGreenRedReserved8BitPerColor
) {
533 Si
->lfb_linelength
= (UINT16
) (Info
->PixelsPerScanLine
* 4);
534 } else if (Info
->PixelFormat
== PixelBitMask
) {
535 FindBits(Info
->PixelInformation
.RedMask
,
536 &Si
->red_pos
, &Si
->red_size
);
537 FindBits(Info
->PixelInformation
.GreenMask
,
538 &Si
->green_pos
, &Si
->green_size
);
539 FindBits(Info
->PixelInformation
.BlueMask
,
540 &Si
->blue_pos
, &Si
->blue_size
);
541 FindBits(Info
->PixelInformation
.ReservedMask
,
542 &Si
->rsvd_pos
, &Si
->rsvd_size
);
543 Si
->lfb_depth
= Si
->red_size
+ Si
->green_size
+
544 Si
->blue_size
+ Si
->rsvd_size
;
545 Si
->lfb_linelength
= (UINT16
) ((Info
->PixelsPerScanLine
* Si
->lfb_depth
) / 8);
556 Si
->lfb_linelength
= Si
->lfb_width
/ 2;
566 IN OUT
struct boot_params
*Bp
570 EFI_HANDLE
*HandleBuffer
;
573 EFI_GRAPHICS_OUTPUT_PROTOCOL
*Gop
;
575 ZeroMem ((VOID
*)&Bp
->screen_info
, sizeof(Bp
->screen_info
));
577 Status
= gBS
->LocateHandleBuffer (
579 &gEfiGraphicsOutputProtocolGuid
,
584 if (!EFI_ERROR (Status
)) {
585 for (Index
= 0; Index
< HandleCount
; Index
++) {
586 Status
= gBS
->HandleProtocol (
588 &gEfiGraphicsOutputProtocolGuid
,
591 if (EFI_ERROR (Status
)) {
595 Status
= SetupGraphicsFromGop (&Bp
->screen_info
, Gop
);
596 if (!EFI_ERROR (Status
)) {
597 FreePool (HandleBuffer
);
602 FreePool (HandleBuffer
);
605 return EFI_NOT_FOUND
;
611 SetupLinuxBootParams (
612 IN OUT
struct boot_params
*Bp
617 SetupLinuxMemmap (Bp
);
627 IN OUT VOID
*KernelSetup
631 struct boot_params
*Bp
;
633 Status
= BasicKernelSetupCheck (KernelSetup
);
634 if (EFI_ERROR (Status
)) {
638 Bp
= (struct boot_params
*) KernelSetup
;
640 if (Bp
->hdr
.version
< 0x205 || !Bp
->hdr
.relocatable_kernel
) {
642 // We only support relocatable kernels
644 return EFI_UNSUPPORTED
;
647 InitLinuxDescriptorTables ();
649 Bp
->hdr
.code32_start
= (UINT32
)(UINTN
) Kernel
;
650 if (Bp
->hdr
.version
>= 0x20c && Bp
->hdr
.handover_offset
&&
651 (Bp
->hdr
.xloadflags
& (sizeof (UINTN
) == 4 ? BIT2
: BIT3
))) {
652 DEBUG ((EFI_D_INFO
, "Jumping to kernel EFI handover point at ofs %x\n", Bp
->hdr
.handover_offset
));
654 DisableInterrupts ();
655 JumpToUefiKernel ((VOID
*) gImageHandle
, (VOID
*) gST
, KernelSetup
, Kernel
);
659 // Old kernels without EFI handover protocol
661 SetupLinuxBootParams (KernelSetup
);
663 DEBUG ((EFI_D_INFO
, "Jumping to kernel\n"));
664 DisableInterrupts ();
665 SetLinuxDescriptorTables ();
666 JumpToKernel (Kernel
, (VOID
*) KernelSetup
);