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 Status
= gBS
->AllocatePool (
288 ASSERT_EFI_ERROR (Status
);
291 // Get System MemoryMap
293 Status
= gBS
->GetMemoryMap (
300 ASSERT_EFI_ERROR (Status
);
303 E820
= &Bp
->e820_map
[0];
306 MemoryMapPtr
= MemoryMap
;
307 for (Index
= 0; Index
< (MemoryMapSize
/ DescriptorSize
); Index
++) {
310 if (MemoryMap
->NumberOfPages
== 0) {
314 switch(MemoryMap
->Type
) {
315 case EfiReservedMemoryType
:
316 case EfiRuntimeServicesCode
:
317 case EfiRuntimeServicesData
:
318 case EfiMemoryMappedIO
:
319 case EfiMemoryMappedIOPortSpace
:
321 E820Type
= E820_RESERVED
;
324 case EfiUnusableMemory
:
325 E820Type
= E820_UNUSABLE
;
328 case EfiACPIReclaimMemory
:
329 E820Type
= E820_ACPI
;
334 case EfiBootServicesCode
:
335 case EfiBootServicesData
:
336 case EfiConventionalMemory
:
340 case EfiACPIMemoryNVS
:
347 "Invalid EFI memory descriptor type (0x%x)!\n",
353 if ((LastE820
!= NULL
) &&
354 (LastE820
->type
== (UINT32
) E820Type
) &&
355 (MemoryMap
->PhysicalStart
== LastEndAddr
)) {
356 LastE820
->size
+= EFI_PAGES_TO_SIZE ((UINTN
) MemoryMap
->NumberOfPages
);
357 LastEndAddr
+= EFI_PAGES_TO_SIZE ((UINTN
) MemoryMap
->NumberOfPages
);
359 if (E820EntryCount
>= (sizeof (Bp
->e820_map
) / sizeof (Bp
->e820_map
[0]))) {
362 E820
->type
= (UINT32
) E820Type
;
363 E820
->addr
= MemoryMap
->PhysicalStart
;
364 E820
->size
= EFI_PAGES_TO_SIZE ((UINTN
) MemoryMap
->NumberOfPages
);
366 LastEndAddr
= E820
->addr
+ E820
->size
;
374 MemoryMap
= (EFI_MEMORY_DESCRIPTOR
*)((UINTN
)MemoryMap
+ DescriptorSize
);
376 Bp
->e820_entries
= (UINT8
) E820EntryCount
;
379 Efi
->efi_systab
= (UINT32
)(UINTN
) gST
;
380 Efi
->efi_memdesc_size
= (UINT32
) DescriptorSize
;
381 Efi
->efi_memdesc_version
= DescriptorVersion
;
382 Efi
->efi_memmap
= (UINT32
)(UINTN
) MemoryMapPtr
;
383 Efi
->efi_memmap_size
= (UINT32
) MemoryMapSize
;
385 Efi
->efi_loader_signature
= SIGNATURE_32 ('E', 'L', '3', '2');
387 Efi
->efi_systab_hi
= ((UINT64
)(UINTN
) gST
) >> 32;
388 Efi
->efi_memmap_hi
= ((UINT64
)(UINTN
) MemoryMapPtr
) >> 32;
389 Efi
->efi_loader_signature
= SIGNATURE_32 ('E', 'L', '6', '4');
392 gBS
->ExitBootServices (gImageHandle
, MapKey
);
398 LoadLinuxSetCommandLine (
399 IN OUT VOID
*KernelSetup
,
400 IN CHAR8
*CommandLine
404 struct boot_params
*Bp
;
406 Status
= BasicKernelSetupCheck (KernelSetup
);
407 if (EFI_ERROR (Status
)) {
411 Bp
= (struct boot_params
*) KernelSetup
;
413 Bp
->hdr
.cmd_line_ptr
= (UINT32
)(UINTN
) CommandLine
;
422 IN OUT VOID
*KernelSetup
,
428 struct boot_params
*Bp
;
430 Status
= BasicKernelSetupCheck (KernelSetup
);
431 if (EFI_ERROR (Status
)) {
435 Bp
= (struct boot_params
*) KernelSetup
;
437 Bp
->hdr
.ramdisk_start
= (UINT32
)(UINTN
) Initrd
;
438 Bp
->hdr
.ramdisk_len
= (UINT32
) InitrdSize
;
457 while (!(Mask
& 0x1)) {
474 SetupGraphicsFromGop (
475 struct screen_info
*Si
,
476 EFI_GRAPHICS_OUTPUT_PROTOCOL
*Gop
479 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*Info
;
483 Status
= Gop
->QueryMode(Gop
, Gop
->Mode
->Mode
, &Size
, &Info
);
484 if (EFI_ERROR (Status
)) {
490 /* EFI framebuffer */
491 Si
->orig_video_isVGA
= 0x70;
495 Si
->orig_video_page
= 0;
496 Si
->orig_video_mode
= 0;
497 Si
->orig_video_cols
= 0;
498 Si
->orig_video_lines
= 0;
499 Si
->orig_video_ega_bx
= 0;
500 Si
->orig_video_points
= 0;
502 Si
->lfb_base
= (UINT32
) Gop
->Mode
->FrameBufferBase
;
503 Si
->lfb_size
= (UINT32
) Gop
->Mode
->FrameBufferSize
;
504 Si
->lfb_width
= (UINT16
) Info
->HorizontalResolution
;
505 Si
->lfb_height
= (UINT16
) Info
->VerticalResolution
;
510 if (Info
->PixelFormat
== PixelRedGreenBlueReserved8BitPerColor
) {
520 Si
->lfb_linelength
= (UINT16
) (Info
->PixelsPerScanLine
* 4);
522 } else if (Info
->PixelFormat
== PixelBlueGreenRedReserved8BitPerColor
) {
532 Si
->lfb_linelength
= (UINT16
) (Info
->PixelsPerScanLine
* 4);
533 } else if (Info
->PixelFormat
== PixelBitMask
) {
534 FindBits(Info
->PixelInformation
.RedMask
,
535 &Si
->red_pos
, &Si
->red_size
);
536 FindBits(Info
->PixelInformation
.GreenMask
,
537 &Si
->green_pos
, &Si
->green_size
);
538 FindBits(Info
->PixelInformation
.BlueMask
,
539 &Si
->blue_pos
, &Si
->blue_size
);
540 FindBits(Info
->PixelInformation
.ReservedMask
,
541 &Si
->rsvd_pos
, &Si
->rsvd_size
);
542 Si
->lfb_depth
= Si
->red_size
+ Si
->green_size
+
543 Si
->blue_size
+ Si
->rsvd_size
;
544 Si
->lfb_linelength
= (UINT16
) ((Info
->PixelsPerScanLine
* Si
->lfb_depth
) / 8);
555 Si
->lfb_linelength
= Si
->lfb_width
/ 2;
565 IN OUT
struct boot_params
*Bp
569 EFI_HANDLE
*HandleBuffer
;
572 EFI_GRAPHICS_OUTPUT_PROTOCOL
*Gop
;
574 ZeroMem ((VOID
*)&Bp
->screen_info
, sizeof(Bp
->screen_info
));
576 Status
= gBS
->LocateHandleBuffer (
578 &gEfiGraphicsOutputProtocolGuid
,
583 if (!EFI_ERROR (Status
)) {
584 for (Index
= 0; Index
< HandleCount
; Index
++) {
585 Status
= gBS
->HandleProtocol (
587 &gEfiGraphicsOutputProtocolGuid
,
590 if (EFI_ERROR (Status
)) {
594 Status
= SetupGraphicsFromGop (&Bp
->screen_info
, Gop
);
595 if (!EFI_ERROR (Status
)) {
596 FreePool (HandleBuffer
);
601 FreePool (HandleBuffer
);
604 return EFI_NOT_FOUND
;
610 SetupLinuxBootParams (
611 IN OUT
struct boot_params
*Bp
616 SetupLinuxMemmap (Bp
);
626 IN OUT VOID
*KernelSetup
630 struct boot_params
*Bp
;
632 Status
= BasicKernelSetupCheck (KernelSetup
);
633 if (EFI_ERROR (Status
)) {
637 Bp
= (struct boot_params
*) KernelSetup
;
639 if (Bp
->hdr
.version
< 0x205 || !Bp
->hdr
.relocatable_kernel
) {
641 // We only support relocatable kernels
643 return EFI_UNSUPPORTED
;
646 InitLinuxDescriptorTables ();
648 Bp
->hdr
.code32_start
= (UINT32
)(UINTN
) Kernel
;
649 if (Bp
->hdr
.version
>= 0x20c && Bp
->hdr
.handover_offset
&&
650 (Bp
->hdr
.load_flags
& (sizeof (UINTN
) == 4 ? BIT2
: BIT3
))) {
651 DEBUG ((EFI_D_INFO
, "Jumping to kernel EFI handover point at ofs %x\n", Bp
->hdr
.handover_offset
));
653 DisableInterrupts ();
654 JumpToUefiKernel ((VOID
*) gImageHandle
, (VOID
*) gST
, KernelSetup
, Kernel
);
658 // Old kernels without EFI handover protocol
660 SetupLinuxBootParams (KernelSetup
);
662 DEBUG ((EFI_D_INFO
, "Jumping to kernel\n"));
663 DisableInterrupts ();
664 SetLinuxDescriptorTables ();
665 JumpToKernel (Kernel
, (VOID
*) KernelSetup
);