Home | History | Annotate | Download | only in EfiLdr
      1 /*++
      2 
      3 Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
      4 This program and the accompanying materials
      5 are licensed and made available under the terms and conditions of the BSD License
      6 which accompanies this distribution.  The full text of the license may be found at
      7 http://opensource.org/licenses/bsd-license.php
      8 
      9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     11 
     12 Module Name:
     13   EfiLoader.c
     14 
     15 Abstract:
     16 
     17 Revision History:
     18 
     19 --*/
     20 
     21 #include "EfiLdr.h"
     22 #include "Support.h"
     23 #include "Debug.h"
     24 #include "PeLoader.h"
     25 #include "LzmaDecompress.h"
     26 
     27 EFILDR_LOADED_IMAGE    DxeCoreImage;
     28 EFILDR_LOADED_IMAGE    DxeIplImage;
     29 
     30 VOID
     31 SystemHang (
     32   CHAR8        *Message
     33   )
     34 {
     35   PrintString (
     36     "%s## FATAL ERROR ##: Fail to load DUET images! System hang!\n",
     37     Message
     38     );
     39   CpuDeadLoop();
     40 }
     41 
     42 VOID
     43 EfiLoader (
     44   UINT32    BiosMemoryMapBaseAddress
     45   )
     46 {
     47   BIOS_MEMORY_MAP       *BiosMemoryMap;
     48   EFILDR_IMAGE          *EFILDRImage;
     49   EFI_MEMORY_DESCRIPTOR EfiMemoryDescriptor[EFI_MAX_MEMORY_DESCRIPTORS];
     50   EFI_STATUS            Status;
     51   UINTN                 NumberOfMemoryMapEntries;
     52   UINT32                DestinationSize;
     53   UINT32                ScratchSize;
     54   UINTN                 BfvPageNumber;
     55   UINTN                 BfvBase;
     56   EFI_MAIN_ENTRYPOINT   EfiMainEntrypoint;
     57   EFILDRHANDOFF         Handoff;
     58   UINTN                 Index;
     59 
     60   ClearScreen();
     61 
     62   PrintHeader ('A');
     63 
     64   PrintString ("Enter DUET Loader...\n");
     65   PrintString ("BiosMemoryMapBaseAddress = %x\n", (UINTN) BiosMemoryMapBaseAddress);
     66 
     67   //
     68   // Add all EfiConventionalMemory descriptors to the table.  If there are partial pages, then
     69   // round the start address up to the next page, and round the length down to a page boundry.
     70   //
     71   BiosMemoryMap = (BIOS_MEMORY_MAP *) (UINTN) BiosMemoryMapBaseAddress;
     72   NumberOfMemoryMapEntries = 0;
     73   GenMemoryMap (&NumberOfMemoryMapEntries, EfiMemoryDescriptor, BiosMemoryMap);
     74 
     75   PrintString ("Get %d entries of memory map!\n", NumberOfMemoryMapEntries);
     76 
     77   //
     78   // Get information on where the image is in memory
     79   //
     80   EFILDRImage  = (EFILDR_IMAGE *)(UINTN)(EFILDR_HEADER_ADDRESS + sizeof(EFILDR_HEADER));
     81 
     82 
     83   //
     84   // Point to the 4th image (Bfv)
     85   //
     86   EFILDRImage += 3;
     87 
     88   //
     89   // Decompress the image
     90   //
     91   PrintString (
     92     "Decompress BFV image, Image Address = %x Offset = %x\n",
     93     (UINTN) (EFILDR_HEADER_ADDRESS + EFILDRImage->Offset),
     94     (UINTN) EFILDRImage->Offset
     95     );
     96   Status = LzmaUefiDecompressGetInfo (
     97              (VOID *)(UINTN)(EFILDR_HEADER_ADDRESS + EFILDRImage->Offset),
     98              EFILDRImage->Length,
     99              &DestinationSize,
    100              &ScratchSize
    101              );
    102 
    103   if (EFI_ERROR (Status)) {
    104     SystemHang ("Failed to get decompress information for BFV!\n");
    105   }
    106 
    107   PrintString ("BFV decompress: DestinationSize = %x, ScratchSize = %x\n", (UINTN) DestinationSize, (UINTN) ScratchSize);
    108   Status =  LzmaUefiDecompress (
    109     (VOID *)(UINTN)(EFILDR_HEADER_ADDRESS + EFILDRImage->Offset),
    110     EFILDRImage->Length,
    111     (VOID *)(UINTN)EFI_DECOMPRESSED_BUFFER_ADDRESS,
    112     (VOID *)(UINTN)((EFI_DECOMPRESSED_BUFFER_ADDRESS + DestinationSize + 0x1000) & 0xfffff000)
    113     );
    114 
    115 
    116   if (EFI_ERROR (Status)) {
    117     SystemHang ("Failed to decompress BFV!\n");
    118   }
    119 
    120   BfvPageNumber = EFI_SIZE_TO_PAGES (DestinationSize);
    121   BfvBase = (UINTN) FindSpace (BfvPageNumber, &NumberOfMemoryMapEntries, EfiMemoryDescriptor, EfiRuntimeServicesData, EFI_MEMORY_WB);
    122   if (BfvBase == 0) {
    123     SystemHang ("Failed to find free space to hold decompressed BFV\n");
    124   }
    125   ZeroMem ((VOID *)(UINTN)BfvBase, BfvPageNumber * EFI_PAGE_SIZE);
    126   CopyMem ((VOID *)(UINTN)BfvBase, (VOID *)(UINTN)EFI_DECOMPRESSED_BUFFER_ADDRESS, DestinationSize);
    127 
    128   PrintHeader ('B');
    129 
    130   //
    131   // Point to the 2nd image (DxeIpl)
    132   //
    133 
    134   EFILDRImage -= 2;
    135 
    136   //
    137   // Decompress the image
    138   //
    139   PrintString (
    140     "Decompress DxeIpl image, Image Address = %x Offset = %x\n",
    141     (UINTN) (EFILDR_HEADER_ADDRESS + EFILDRImage->Offset),
    142     (UINTN) EFILDRImage->Offset
    143     );
    144 
    145   Status = LzmaUefiDecompressGetInfo (
    146              (VOID *)(UINTN)(EFILDR_HEADER_ADDRESS + EFILDRImage->Offset),
    147              EFILDRImage->Length,
    148              &DestinationSize,
    149              &ScratchSize
    150              );
    151   if (EFI_ERROR (Status)) {
    152     SystemHang ("Failed to get decompress information for DxeIpl!\n");
    153   }
    154 
    155   Status = LzmaUefiDecompress (
    156              (VOID *)(UINTN)(EFILDR_HEADER_ADDRESS + EFILDRImage->Offset),
    157              EFILDRImage->Length,
    158              (VOID *)(UINTN)EFI_DECOMPRESSED_BUFFER_ADDRESS,
    159              (VOID *)(UINTN)((EFI_DECOMPRESSED_BUFFER_ADDRESS + DestinationSize + 0x1000) & 0xfffff000)
    160              );
    161   if (EFI_ERROR (Status)) {
    162     SystemHang ("Failed to decompress DxeIpl image\n");
    163   }
    164 
    165   PrintString ("Start load DxeIpl PE image\n");
    166 
    167   //
    168   // Load and relocate the EFI PE/COFF Firmware Image
    169   //
    170   Status = EfiLdrPeCoffLoadPeImage (
    171              (VOID *)(UINTN)(EFI_DECOMPRESSED_BUFFER_ADDRESS),
    172              &DxeIplImage,
    173              &NumberOfMemoryMapEntries,
    174              EfiMemoryDescriptor
    175              );
    176   if (EFI_ERROR (Status)) {
    177     SystemHang ("Failed to load and relocate DxeIpl PE image!\n");
    178   }
    179   PrintString (
    180     "DxeIpl PE image is successed loaded at %lx, entry=%p\n",
    181     DxeIplImage.ImageBasePage,
    182     DxeIplImage.EntryPoint
    183     );
    184 
    185 PrintHeader ('C');
    186 
    187   //
    188   // Point to the 3rd image (DxeMain)
    189   //
    190   EFILDRImage++;
    191 
    192   //
    193   // Decompress the image
    194   //
    195   PrintString (
    196     "Decompress DxeMain FV image, Image Address = %x Offset = %x\n",
    197     (UINTN)(EFILDR_HEADER_ADDRESS + EFILDRImage->Offset),
    198     (UINTN) EFILDRImage->Offset
    199     );
    200 
    201   Status = LzmaUefiDecompressGetInfo (
    202              (VOID *)(UINTN)(EFILDR_HEADER_ADDRESS + EFILDRImage->Offset),
    203              EFILDRImage->Length,
    204              &DestinationSize,
    205              &ScratchSize
    206              );
    207   if (EFI_ERROR (Status)) {
    208     SystemHang ("Failed to get decompress information for DxeMain FV image!\n");
    209   }
    210 
    211   Status = LzmaUefiDecompress (
    212              (VOID *)(UINTN)(EFILDR_HEADER_ADDRESS + EFILDRImage->Offset),
    213               EFILDRImage->Length,
    214              (VOID *)(UINTN)EFI_DECOMPRESSED_BUFFER_ADDRESS,
    215              (VOID *)(UINTN)((EFI_DECOMPRESSED_BUFFER_ADDRESS + DestinationSize + 0x1000) & 0xfffff000)
    216              );
    217   if (EFI_ERROR (Status)) {
    218     SystemHang ("Failed to decompress DxeMain FV image!\n");
    219   }
    220 
    221   //
    222   // Load and relocate the EFI PE/COFF Firmware Image
    223   //
    224   Status = EfiLdrPeCoffLoadPeImage (
    225              (VOID *)(UINTN)(EFI_DECOMPRESSED_BUFFER_ADDRESS),
    226              &DxeCoreImage,
    227              &NumberOfMemoryMapEntries,
    228              EfiMemoryDescriptor
    229              );
    230   if (EFI_ERROR (Status)) {
    231     SystemHang ("Failed to load/relocate DxeMain!\n");
    232   }
    233   PrintString (
    234     "DxeCore PE image is successed loaded at %lx, entry=%p\n",
    235     DxeCoreImage.ImageBasePage,
    236     DxeCoreImage.EntryPoint
    237     );
    238 
    239 PrintHeader ('E');
    240 
    241   //
    242   // Display the table of memory descriptors.
    243   //
    244   PrintString ("\nEFI Memory Descriptors\n");
    245   for (Index = 0; Index < NumberOfMemoryMapEntries; Index++) {
    246     PrintString (
    247       "Type = %x Start = %08lx NumberOfPages = %08lx\n",
    248       EfiMemoryDescriptor[Index].Type, EfiMemoryDescriptor[Index].PhysicalStart, EfiMemoryDescriptor[Index].NumberOfPages
    249       );
    250   }
    251 
    252   //
    253   // Jump to EFI Firmware
    254   //
    255 
    256   if (DxeIplImage.EntryPoint != NULL) {
    257 
    258     Handoff.MemDescCount      = NumberOfMemoryMapEntries;
    259     Handoff.MemDesc           = EfiMemoryDescriptor;
    260     Handoff.BfvBase           = (VOID *)(UINTN)BfvBase;
    261     Handoff.BfvSize           = BfvPageNumber * EFI_PAGE_SIZE;
    262     Handoff.DxeIplImageBase   = (VOID *)(UINTN)DxeIplImage.ImageBasePage;
    263     Handoff.DxeIplImageSize   = DxeIplImage.NoPages * EFI_PAGE_SIZE;
    264     Handoff.DxeCoreImageBase  = (VOID *)(UINTN)DxeCoreImage.ImageBasePage;
    265     Handoff.DxeCoreImageSize  = DxeCoreImage.NoPages * EFI_PAGE_SIZE;
    266     Handoff.DxeCoreEntryPoint = (VOID *)(UINTN)DxeCoreImage.EntryPoint;
    267 
    268     PrintString ("Transfer to DxeIpl ...EntryPoint = %p\n", DxeIplImage.EntryPoint);
    269 
    270     EfiMainEntrypoint = (EFI_MAIN_ENTRYPOINT) DxeIplImage.EntryPoint;
    271     EfiMainEntrypoint (&Handoff);
    272   }
    273 
    274 PrintHeader ('F');
    275 
    276   //
    277   // There was a problem loading the image, so HALT the system.
    278   //
    279 
    280   SystemHang ("Failed to jump to DxeIpl!\n");
    281 }
    282 
    283 EFI_STATUS
    284 EFIAPI
    285 _ModuleEntryPoint (
    286   UINT32    BiosMemoryMapBaseAddress
    287   )
    288 {
    289   SerialPortInitialize ();
    290   EfiLoader(BiosMemoryMapBaseAddress);
    291   return EFI_SUCCESS;
    292 }
    293 
    294 
    295