]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/Library/LoadLinuxLib/Linux.c
OvmfPkg: replace old EFI_D_ debug levels with new DEBUG_ ones
[mirror_edk2.git] / OvmfPkg / Library / LoadLinuxLib / Linux.c
1 /** @file
2
3 Copyright (c) 2011 - 2014, Intel Corporation. All rights reserved.<BR>
4
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6
7 **/
8
9 #include "LoadLinuxLib.h"
10
11
12 /**
13 A simple check of the kernel setup image
14
15 An assumption is made that the size of the data is at least the
16 size of struct boot_params.
17
18 @param[in] KernelSetup - The kernel setup image
19
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
23
24 **/
25 STATIC
26 EFI_STATUS
27 EFIAPI
28 BasicKernelSetupCheck (
29 IN VOID *KernelSetup
30 )
31 {
32 return LoadLinuxCheckKernelSetup(KernelSetup, sizeof (struct boot_params));
33 }
34
35
36 EFI_STATUS
37 EFIAPI
38 LoadLinuxCheckKernelSetup (
39 IN VOID *KernelSetup,
40 IN UINTN KernelSetupSize
41 )
42 {
43 struct boot_params *Bp;
44
45 if (KernelSetup == NULL) {
46 return EFI_INVALID_PARAMETER;
47 }
48
49 if (KernelSetupSize < sizeof (*Bp)) {
50 return EFI_UNSUPPORTED;
51 }
52
53 Bp = (struct boot_params*) KernelSetup;
54
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)
59 ) {
60 return EFI_UNSUPPORTED;
61 } else {
62 return EFI_SUCCESS;
63 }
64 }
65
66
67 UINTN
68 EFIAPI
69 LoadLinuxGetKernelSize (
70 IN VOID *KernelSetup,
71 IN UINTN KernelSize
72 )
73 {
74 struct boot_params *Bp;
75
76 if (EFI_ERROR (BasicKernelSetupCheck (KernelSetup))) {
77 return 0;
78 }
79
80 Bp = (struct boot_params*) KernelSetup;
81
82 if (Bp->hdr.version > 0x20a) {
83 return Bp->hdr.init_size;
84 } else {
85 //
86 // Add extra size for kernel decompression
87 //
88 return 3 * KernelSize;
89 }
90 }
91
92
93 VOID*
94 EFIAPI
95 LoadLinuxAllocateKernelSetupPages (
96 IN UINTN Pages
97 )
98 {
99 EFI_STATUS Status;
100 EFI_PHYSICAL_ADDRESS Address;
101
102 Address = BASE_1GB;
103 Status = gBS->AllocatePages (
104 AllocateMaxAddress,
105 EfiLoaderData,
106 Pages,
107 &Address
108 );
109 if (!EFI_ERROR (Status)) {
110 return (VOID*)(UINTN) Address;
111 } else {
112 return NULL;
113 }
114 }
115
116 EFI_STATUS
117 EFIAPI
118 LoadLinuxInitializeKernelSetup (
119 IN VOID *KernelSetup
120 )
121 {
122 EFI_STATUS Status;
123 UINTN SetupEnd;
124 struct boot_params *Bp;
125
126 Status = BasicKernelSetupCheck (KernelSetup);
127 if (EFI_ERROR (Status)) {
128 return Status;
129 }
130
131 Bp = (struct boot_params*) KernelSetup;
132
133 SetupEnd = 0x202 + (Bp->hdr.jump & 0xff);
134
135 //
136 // Clear all but the setup_header
137 //
138 ZeroMem (KernelSetup, 0x1f1);
139 ZeroMem (((UINT8 *)KernelSetup) + SetupEnd, 4096 - SetupEnd);
140 DEBUG ((DEBUG_INFO, "Cleared kernel setup 0-0x1f1, 0x%Lx-0x1000\n",
141 (UINT64)SetupEnd));
142
143 return EFI_SUCCESS;
144 }
145
146 VOID*
147 EFIAPI
148 LoadLinuxAllocateKernelPages (
149 IN VOID *KernelSetup,
150 IN UINTN Pages
151 )
152 {
153 EFI_STATUS Status;
154 EFI_PHYSICAL_ADDRESS KernelAddress;
155 UINT32 Loop;
156 struct boot_params *Bp;
157
158 if (EFI_ERROR (BasicKernelSetupCheck (KernelSetup))) {
159 return NULL;
160 }
161
162 Bp = (struct boot_params*) KernelSetup;
163
164 for (Loop = 1; Loop < 512; Loop++) {
165 KernelAddress = MultU64x32 (
166 2 * Bp->hdr.kernel_alignment,
167 Loop
168 );
169 Status = gBS->AllocatePages (
170 AllocateAddress,
171 EfiLoaderData,
172 Pages,
173 &KernelAddress
174 );
175 if (!EFI_ERROR (Status)) {
176 return (VOID*)(UINTN) KernelAddress;
177 }
178 }
179
180 return NULL;
181 }
182
183
184 VOID*
185 EFIAPI
186 LoadLinuxAllocateCommandLinePages (
187 IN UINTN Pages
188 )
189 {
190 EFI_STATUS Status;
191 EFI_PHYSICAL_ADDRESS Address;
192
193 Address = 0xa0000;
194 Status = gBS->AllocatePages (
195 AllocateMaxAddress,
196 EfiLoaderData,
197 Pages,
198 &Address
199 );
200 if (!EFI_ERROR (Status)) {
201 return (VOID*)(UINTN) Address;
202 } else {
203 return NULL;
204 }
205 }
206
207
208 VOID*
209 EFIAPI
210 LoadLinuxAllocateInitrdPages (
211 IN VOID *KernelSetup,
212 IN UINTN Pages
213 )
214 {
215 EFI_STATUS Status;
216 EFI_PHYSICAL_ADDRESS Address;
217
218 struct boot_params *Bp;
219
220 if (EFI_ERROR (BasicKernelSetupCheck (KernelSetup))) {
221 return NULL;
222 }
223
224 Bp = (struct boot_params*) KernelSetup;
225
226 Address = (EFI_PHYSICAL_ADDRESS)(UINTN) Bp->hdr.ramdisk_max;
227 Status = gBS->AllocatePages (
228 AllocateMaxAddress,
229 EfiLoaderData,
230 Pages,
231 &Address
232 );
233 if (!EFI_ERROR (Status)) {
234 return (VOID*)(UINTN) Address;
235 } else {
236 return NULL;
237 }
238 }
239
240
241 STATIC
242 VOID
243 SetupLinuxMemmap (
244 IN OUT struct boot_params *Bp
245 )
246 {
247 EFI_STATUS Status;
248 UINT8 TmpMemoryMap[1];
249 UINTN MapKey;
250 UINTN DescriptorSize;
251 UINT32 DescriptorVersion;
252 UINTN MemoryMapSize;
253 EFI_MEMORY_DESCRIPTOR *MemoryMap;
254 EFI_MEMORY_DESCRIPTOR *MemoryMapPtr;
255 UINTN Index;
256 struct efi_info *Efi;
257 struct e820_entry *LastE820;
258 struct e820_entry *E820;
259 UINTN E820EntryCount;
260 EFI_PHYSICAL_ADDRESS LastEndAddr;
261
262 //
263 // Get System MemoryMapSize
264 //
265 MemoryMapSize = sizeof (TmpMemoryMap);
266 Status = gBS->GetMemoryMap (
267 &MemoryMapSize,
268 (EFI_MEMORY_DESCRIPTOR *)TmpMemoryMap,
269 &MapKey,
270 &DescriptorSize,
271 &DescriptorVersion
272 );
273 ASSERT (Status == EFI_BUFFER_TOO_SMALL);
274 //
275 // Enlarge space here, because we will allocate pool now.
276 //
277 MemoryMapSize += EFI_PAGE_SIZE;
278 Status = gBS->AllocatePool (
279 EfiLoaderData,
280 MemoryMapSize,
281 (VOID **) &MemoryMap
282 );
283 ASSERT_EFI_ERROR (Status);
284
285 //
286 // Get System MemoryMap
287 //
288 Status = gBS->GetMemoryMap (
289 &MemoryMapSize,
290 MemoryMap,
291 &MapKey,
292 &DescriptorSize,
293 &DescriptorVersion
294 );
295 ASSERT_EFI_ERROR (Status);
296
297 LastE820 = NULL;
298 E820 = &Bp->e820_map[0];
299 E820EntryCount = 0;
300 LastEndAddr = 0;
301 MemoryMapPtr = MemoryMap;
302 for (Index = 0; Index < (MemoryMapSize / DescriptorSize); Index++) {
303 UINTN E820Type = 0;
304
305 if (MemoryMap->NumberOfPages == 0) {
306 continue;
307 }
308
309 switch(MemoryMap->Type) {
310 case EfiReservedMemoryType:
311 case EfiRuntimeServicesCode:
312 case EfiRuntimeServicesData:
313 case EfiMemoryMappedIO:
314 case EfiMemoryMappedIOPortSpace:
315 case EfiPalCode:
316 E820Type = E820_RESERVED;
317 break;
318
319 case EfiUnusableMemory:
320 E820Type = E820_UNUSABLE;
321 break;
322
323 case EfiACPIReclaimMemory:
324 E820Type = E820_ACPI;
325 break;
326
327 case EfiLoaderCode:
328 case EfiLoaderData:
329 case EfiBootServicesCode:
330 case EfiBootServicesData:
331 case EfiConventionalMemory:
332 E820Type = E820_RAM;
333 break;
334
335 case EfiACPIMemoryNVS:
336 E820Type = E820_NVS;
337 break;
338
339 default:
340 DEBUG ((
341 DEBUG_ERROR,
342 "Invalid EFI memory descriptor type (0x%x)!\n",
343 MemoryMap->Type
344 ));
345 continue;
346 }
347
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);
353 } else {
354 if (E820EntryCount >= ARRAY_SIZE (Bp->e820_map)) {
355 break;
356 }
357 E820->type = (UINT32) E820Type;
358 E820->addr = MemoryMap->PhysicalStart;
359 E820->size = EFI_PAGES_TO_SIZE ((UINTN) MemoryMap->NumberOfPages);
360 LastE820 = E820;
361 LastEndAddr = E820->addr + E820->size;
362 E820++;
363 E820EntryCount++;
364 }
365
366 //
367 // Get next item
368 //
369 MemoryMap = (EFI_MEMORY_DESCRIPTOR *)((UINTN)MemoryMap + DescriptorSize);
370 }
371 Bp->e820_entries = (UINT8) E820EntryCount;
372
373 Efi = &Bp->efi_info;
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;
379 #ifdef MDE_CPU_IA32
380 Efi->efi_loader_signature = SIGNATURE_32 ('E', 'L', '3', '2');
381 #else
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');
385 #endif
386
387 gBS->ExitBootServices (gImageHandle, MapKey);
388 }
389
390
391 EFI_STATUS
392 EFIAPI
393 LoadLinuxSetCommandLine (
394 IN OUT VOID *KernelSetup,
395 IN CHAR8 *CommandLine
396 )
397 {
398 EFI_STATUS Status;
399 struct boot_params *Bp;
400
401 Status = BasicKernelSetupCheck (KernelSetup);
402 if (EFI_ERROR (Status)) {
403 return Status;
404 }
405
406 Bp = (struct boot_params*) KernelSetup;
407
408 Bp->hdr.cmd_line_ptr = (UINT32)(UINTN) CommandLine;
409
410 return EFI_SUCCESS;
411 }
412
413
414 EFI_STATUS
415 EFIAPI
416 LoadLinuxSetInitrd (
417 IN OUT VOID *KernelSetup,
418 IN VOID *Initrd,
419 IN UINTN InitrdSize
420 )
421 {
422 EFI_STATUS Status;
423 struct boot_params *Bp;
424
425 Status = BasicKernelSetupCheck (KernelSetup);
426 if (EFI_ERROR (Status)) {
427 return Status;
428 }
429
430 Bp = (struct boot_params*) KernelSetup;
431
432 Bp->hdr.ramdisk_start = (UINT32)(UINTN) Initrd;
433 Bp->hdr.ramdisk_len = (UINT32) InitrdSize;
434
435 return EFI_SUCCESS;
436 }
437
438
439 STATIC VOID
440 FindBits (
441 unsigned long Mask,
442 UINT8 *Pos,
443 UINT8 *Size
444 )
445 {
446 UINT8 First, Len;
447
448 First = 0;
449 Len = 0;
450
451 if (Mask) {
452 while (!(Mask & 0x1)) {
453 Mask = Mask >> 1;
454 First++;
455 }
456
457 while (Mask & 0x1) {
458 Mask = Mask >> 1;
459 Len++;
460 }
461 }
462 *Pos = First;
463 *Size = Len;
464 }
465
466
467 STATIC
468 EFI_STATUS
469 SetupGraphicsFromGop (
470 struct screen_info *Si,
471 EFI_GRAPHICS_OUTPUT_PROTOCOL *Gop
472 )
473 {
474 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;
475 EFI_STATUS Status;
476 UINTN Size;
477
478 Status = Gop->QueryMode(Gop, Gop->Mode->Mode, &Size, &Info);
479 if (EFI_ERROR (Status)) {
480 return Status;
481 }
482
483 /* We found a GOP */
484
485 /* EFI framebuffer */
486 Si->orig_video_isVGA = 0x70;
487
488 Si->orig_x = 0;
489 Si->orig_y = 0;
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;
496
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;
501 Si->pages = 1;
502 Si->vesapm_seg = 0;
503 Si->vesapm_off = 0;
504
505 if (Info->PixelFormat == PixelRedGreenBlueReserved8BitPerColor) {
506 Si->lfb_depth = 32;
507 Si->red_size = 8;
508 Si->red_pos = 0;
509 Si->green_size = 8;
510 Si->green_pos = 8;
511 Si->blue_size = 8;
512 Si->blue_pos = 16;
513 Si->rsvd_size = 8;
514 Si->rsvd_pos = 24;
515 Si->lfb_linelength = (UINT16) (Info->PixelsPerScanLine * 4);
516
517 } else if (Info->PixelFormat == PixelBlueGreenRedReserved8BitPerColor) {
518 Si->lfb_depth = 32;
519 Si->red_size = 8;
520 Si->red_pos = 16;
521 Si->green_size = 8;
522 Si->green_pos = 8;
523 Si->blue_size = 8;
524 Si->blue_pos = 0;
525 Si->rsvd_size = 8;
526 Si->rsvd_pos = 24;
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);
540 } else {
541 Si->lfb_depth = 4;
542 Si->red_size = 0;
543 Si->red_pos = 0;
544 Si->green_size = 0;
545 Si->green_pos = 0;
546 Si->blue_size = 0;
547 Si->blue_pos = 0;
548 Si->rsvd_size = 0;
549 Si->rsvd_pos = 0;
550 Si->lfb_linelength = Si->lfb_width / 2;
551 }
552
553 return Status;
554 }
555
556
557 STATIC
558 EFI_STATUS
559 SetupGraphics (
560 IN OUT struct boot_params *Bp
561 )
562 {
563 EFI_STATUS Status;
564 EFI_HANDLE *HandleBuffer;
565 UINTN HandleCount;
566 UINTN Index;
567 EFI_GRAPHICS_OUTPUT_PROTOCOL *Gop;
568
569 ZeroMem ((VOID*)&Bp->screen_info, sizeof(Bp->screen_info));
570
571 Status = gBS->LocateHandleBuffer (
572 ByProtocol,
573 &gEfiGraphicsOutputProtocolGuid,
574 NULL,
575 &HandleCount,
576 &HandleBuffer
577 );
578 if (!EFI_ERROR (Status)) {
579 for (Index = 0; Index < HandleCount; Index++) {
580 Status = gBS->HandleProtocol (
581 HandleBuffer[Index],
582 &gEfiGraphicsOutputProtocolGuid,
583 (VOID*) &Gop
584 );
585 if (EFI_ERROR (Status)) {
586 continue;
587 }
588
589 Status = SetupGraphicsFromGop (&Bp->screen_info, Gop);
590 if (!EFI_ERROR (Status)) {
591 FreePool (HandleBuffer);
592 return EFI_SUCCESS;
593 }
594 }
595
596 FreePool (HandleBuffer);
597 }
598
599 return EFI_NOT_FOUND;
600 }
601
602
603 STATIC
604 EFI_STATUS
605 SetupLinuxBootParams (
606 IN OUT struct boot_params *Bp
607 )
608 {
609 SetupGraphics (Bp);
610
611 SetupLinuxMemmap (Bp);
612
613 return EFI_SUCCESS;
614 }
615
616
617 EFI_STATUS
618 EFIAPI
619 LoadLinux (
620 IN VOID *Kernel,
621 IN OUT VOID *KernelSetup
622 )
623 {
624 EFI_STATUS Status;
625 struct boot_params *Bp;
626
627 Status = BasicKernelSetupCheck (KernelSetup);
628 if (EFI_ERROR (Status)) {
629 return Status;
630 }
631
632 Bp = (struct boot_params *) KernelSetup;
633
634 if (Bp->hdr.version < 0x205 || !Bp->hdr.relocatable_kernel) {
635 //
636 // We only support relocatable kernels
637 //
638 return EFI_UNSUPPORTED;
639 }
640
641 InitLinuxDescriptorTables ();
642
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));
647
648 DisableInterrupts ();
649 JumpToUefiKernel ((VOID*) gImageHandle, (VOID*) gST, KernelSetup, Kernel);
650 }
651
652 //
653 // Old kernels without EFI handover protocol
654 //
655 SetupLinuxBootParams (KernelSetup);
656
657 DEBUG ((DEBUG_INFO, "Jumping to kernel\n"));
658 DisableInterrupts ();
659 SetLinuxDescriptorTables ();
660 JumpToKernel (Kernel, (VOID*) KernelSetup);
661
662 return EFI_SUCCESS;
663 }
664