Home | History | Annotate | Download | only in LoadLinuxLib
      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 >= ARRAY_SIZE (Bp->e820_map)) {
    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