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