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