TianoCore EDK2 master
Loading...
Searching...
No Matches
Linux.c
Go to the documentation of this file.
1
9#include "LoadLinuxLib.h"
10
26EFIAPI
28 IN VOID *KernelSetup
29 )
30{
31 return LoadLinuxCheckKernelSetup (KernelSetup, sizeof (struct boot_params));
32}
33
35EFIAPI
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
66EFIAPI
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
90VOID *
91EFIAPI
93 IN UINTN Pages
94 )
95{
96 EFI_STATUS Status;
98
99 Address = BASE_1GB;
100 Status = gBS->AllocatePages (
103 Pages,
104 &Address
105 );
106 if (!EFI_ERROR (Status)) {
107 return (VOID *)(UINTN)Address;
108 } else {
109 return NULL;
110 }
111}
112
114EFIAPI
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
146VOID *
147EFIAPI
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 (
172 Pages,
173 &KernelAddress
174 );
175 if (!EFI_ERROR (Status)) {
176 return (VOID *)(UINTN)KernelAddress;
177 }
178 }
179
180 return NULL;
181}
182
183VOID *
184EFIAPI
186 IN UINTN Pages
187 )
188{
189 EFI_STATUS Status;
190 EFI_PHYSICAL_ADDRESS Address;
191
192 Address = 0xa0000;
193 Status = gBS->AllocatePages (
196 Pages,
197 &Address
198 );
199 if (!EFI_ERROR (Status)) {
200 return (VOID *)(UINTN)Address;
201 } else {
202 return NULL;
203 }
204}
205
206VOID *
207EFIAPI
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 (
228 Pages,
229 &Address
230 );
231 if (!EFI_ERROR (Status)) {
232 return (VOID *)(UINTN)Address;
233 } else {
234 return NULL;
235 }
236}
237
238STATIC
239VOID
240SetupLinuxMemmap (
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 (
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) {
312 case EfiPalCode:
313 E820Type = E820_RESERVED;
314 break;
315
317 E820Type = E820_UNUSABLE;
318 break;
319
321 E820Type = E820_ACPI;
322 break;
323
324 case EfiLoaderCode:
325 case EfiLoaderData:
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
391EFIAPI
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
413EFIAPI
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
436STATIC VOID
437FindBits (
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
464STATIC
466SetupGraphicsFromGop (
467 struct screen_info *Si,
469 )
470{
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
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);
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
564STATIC
566SetupGraphics (
567 IN OUT struct boot_params *Bp
568 )
569{
570 EFI_STATUS Status;
571 EFI_HANDLE *HandleBuffer;
572 UINTN HandleCount;
573 UINTN Index;
575
576 ZeroMem ((VOID *)&Bp->screen_info, sizeof (Bp->screen_info));
577
578 Status = gBS->LocateHandleBuffer (
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
609STATIC
611SetupLinuxBootParams (
612 IN OUT struct boot_params *Bp
613 )
614{
615 SetupGraphics (Bp);
616
617 SetupLinuxMemmap (Bp);
618
619 return EFI_SUCCESS;
620}
621
623EFIAPI
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
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
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"));
666 JumpToKernel (Kernel, (VOID *)KernelSetup);
667
668 return EFI_SUCCESS;
669}
UINT64 UINTN
VOID EFIAPI DisableInterrupts(VOID)
Definition: CpuBreakpoint.c:54
UINT64 EFIAPI MultU64x32(IN UINT64 Multiplicand, IN UINT32 Multiplier)
Definition: MultU64x32.c:27
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
VOID EFIAPI FreePool(IN VOID *Buffer)
EFI_STATUS EFIAPI LoadLinuxInitializeKernelSetup(IN VOID *KernelSetup)
Definition: Linux.c:115
VOID *EFIAPI LoadLinuxAllocateCommandLinePages(IN UINTN Pages)
Definition: Linux.c:185
UINTN EFIAPI LoadLinuxGetKernelSize(IN VOID *KernelSetup, IN UINTN KernelSize)
Definition: Linux.c:67
STATIC EFI_STATUS EFIAPI BasicKernelSetupCheck(IN VOID *KernelSetup)
Definition: Linux.c:27
VOID *EFIAPI LoadLinuxAllocateKernelPages(IN VOID *KernelSetup, IN UINTN Pages)
Definition: Linux.c:148
EFI_STATUS EFIAPI LoadLinuxSetCommandLine(IN OUT VOID *KernelSetup, IN CHAR8 *CommandLine)
Definition: Linux.c:392
EFI_STATUS EFIAPI LoadLinux(IN VOID *Kernel, IN OUT VOID *KernelSetup)
Definition: Linux.c:624
EFI_STATUS EFIAPI LoadLinuxCheckKernelSetup(IN VOID *KernelSetup, IN UINTN KernelSetupSize)
Definition: Linux.c:36
VOID *EFIAPI LoadLinuxAllocateKernelSetupPages(IN UINTN Pages)
Definition: Linux.c:92
VOID *EFIAPI LoadLinuxAllocateInitrdPages(IN VOID *KernelSetup, IN UINTN Pages)
Definition: Linux.c:208
EFI_STATUS EFIAPI LoadLinuxSetInitrd(IN OUT VOID *KernelSetup, IN VOID *Initrd, IN UINTN InitrdSize)
Definition: Linux.c:414
VOID InitLinuxDescriptorTables(VOID)
Definition: LinuxGdt.c:133
VOID SetLinuxDescriptorTables(VOID)
Definition: LinuxGdt.c:155
#define NULL
Definition: Base.h:319
#define STATIC
Definition: Base.h:264
#define ARRAY_SIZE(Array)
Definition: Base.h:1393
#define IN
Definition: Base.h:279
#define SIGNATURE_32(A, B, C, D)
Definition: Base.h:1310
#define OUT
Definition: Base.h:284
#define ASSERT_EFI_ERROR(StatusParameter)
Definition: DebugLib.h:462
#define DEBUG(Expression)
Definition: DebugLib.h:434
@ PixelBitMask
@ PixelRedGreenBlueReserved8BitPerColor
@ PixelBlueGreenRedReserved8BitPerColor
UINT64 EFI_PHYSICAL_ADDRESS
Definition: UefiBaseType.h:50
#define EFI_PAGES_TO_SIZE(Pages)
Definition: UefiBaseType.h:213
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
VOID * EFI_HANDLE
Definition: UefiBaseType.h:33
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_SYSTEM_TABLE * gST
EFI_HANDLE gImageHandle
EFI_BOOT_SERVICES * gBS
@ EfiUnusableMemory
@ EfiBootServicesData
@ EfiReservedMemoryType
@ EfiBootServicesCode
@ EfiConventionalMemory
@ EfiLoaderData
@ EfiACPIMemoryNVS
@ EfiMemoryMappedIOPortSpace
@ EfiACPIReclaimMemory
@ EfiLoaderCode
@ EfiMemoryMappedIO
@ EfiPalCode
@ EfiRuntimeServicesCode
@ EfiRuntimeServicesData
@ ByProtocol
Definition: UefiSpec.h:1518
@ AllocateMaxAddress
Definition: UefiSpec.h:38
@ AllocateAddress
Definition: UefiSpec.h:42
EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE * Mode
EFI_GRAPHICS_PIXEL_FORMAT PixelFormat
EFI_PHYSICAL_ADDRESS FrameBufferBase
Definition: LinuxBzimage.h:75