Home | History | Annotate | Download | only in PrePiLib
      1 /** @file
      2 
      3   Copyright (c) 2008 - 2009, Apple Inc. 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 <PrePi.h>
     16 
     17 //
     18 // Hack to work in NT32
     19 //
     20 EFI_STATUS
     21 
     22 EFIAPI
     23 
     24 SecWinNtPeiLoadFile (
     25   IN  VOID                    *Pe32Data,
     26   IN  EFI_PHYSICAL_ADDRESS    *ImageAddress,
     27   IN  UINT64                  *ImageSize,
     28   IN  EFI_PHYSICAL_ADDRESS    *EntryPoint
     29   );
     30 
     31 
     32 EFI_STATUS
     33 EFIAPI
     34 LoadPeCoffImage (
     35   IN  VOID                                      *PeCoffImage,
     36   OUT EFI_PHYSICAL_ADDRESS                      *ImageAddress,
     37   OUT UINT64                                    *ImageSize,
     38   OUT EFI_PHYSICAL_ADDRESS                      *EntryPoint
     39   )
     40 {
     41   RETURN_STATUS                 Status;
     42   PE_COFF_LOADER_IMAGE_CONTEXT  ImageContext;
     43   VOID                           *Buffer;
     44 
     45   ZeroMem (&ImageContext, sizeof (ImageContext));
     46 
     47   ImageContext.Handle    = PeCoffImage;
     48   ImageContext.ImageRead = PeCoffLoaderImageReadFromMemory;
     49 
     50   Status = PeCoffLoaderGetImageInfo (&ImageContext);
     51   ASSERT_EFI_ERROR (Status);
     52 
     53 
     54   //
     55   // Allocate Memory for the image
     56   //
     57   Buffer = AllocatePages (EFI_SIZE_TO_PAGES((UINT32)ImageContext.ImageSize));
     58   ASSERT (Buffer != 0);
     59 
     60 
     61   ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)Buffer;
     62 
     63   //
     64   // Load the image to our new buffer
     65   //
     66   Status = PeCoffLoaderLoadImage (&ImageContext);
     67   ASSERT_EFI_ERROR (Status);
     68 
     69   //
     70   // Relocate the image in our new buffer
     71   //
     72   Status = PeCoffLoaderRelocateImage (&ImageContext);
     73   ASSERT_EFI_ERROR (Status);
     74 
     75 
     76   *ImageAddress = ImageContext.ImageAddress;
     77   *ImageSize    = ImageContext.ImageSize;
     78   *EntryPoint   = ImageContext.EntryPoint;
     79 
     80   //
     81   // Flush not needed for all architectures. We could have a processor specific
     82   // function in this library that does the no-op if needed.
     83   //
     84   InvalidateInstructionCacheRange ((VOID *)(UINTN)*ImageAddress, (UINTN)*ImageSize);
     85 
     86   return Status;
     87 }
     88 
     89 
     90 
     91 typedef
     92 VOID
     93 (EFIAPI *DXE_CORE_ENTRY_POINT) (
     94   IN  VOID *HobStart
     95   );
     96 
     97 EFI_STATUS
     98 EFIAPI
     99 LoadDxeCoreFromFfsFile (
    100   IN EFI_PEI_FILE_HANDLE  FileHandle,
    101   IN UINTN                StackSize
    102   )
    103 {
    104   EFI_STATUS              Status;
    105   VOID                    *PeCoffImage;
    106   EFI_PHYSICAL_ADDRESS    ImageAddress;
    107   UINT64                  ImageSize;
    108   EFI_PHYSICAL_ADDRESS    EntryPoint;
    109   VOID                    *BaseOfStack;
    110   VOID                    *TopOfStack;
    111   VOID                    *Hob;
    112   EFI_FV_FILE_INFO        FvFileInfo;
    113 
    114   Status = FfsFindSectionData (EFI_SECTION_PE32, FileHandle, &PeCoffImage);
    115   if (EFI_ERROR  (Status)) {
    116     return Status;
    117   }
    118 
    119 
    120   Status = LoadPeCoffImage (PeCoffImage, &ImageAddress, &ImageSize, &EntryPoint);
    121 // For NT32 Debug  Status = SecWinNtPeiLoadFile (PeCoffImage, &ImageAddress, &ImageSize, &EntryPoint);
    122   ASSERT_EFI_ERROR (Status);
    123 
    124   //
    125   // Extract the DxeCore GUID file name.
    126   //
    127   Status = FfsGetFileInfo (FileHandle, &FvFileInfo);
    128   ASSERT_EFI_ERROR (Status);
    129 
    130   BuildModuleHob (&FvFileInfo.FileName, (EFI_PHYSICAL_ADDRESS)(UINTN)ImageAddress, EFI_SIZE_TO_PAGES ((UINT32) ImageSize) * EFI_PAGE_SIZE, EntryPoint);
    131 
    132   DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Loading DxeCore at 0x%10p EntryPoint=0x%10p\n", (VOID *)(UINTN)ImageAddress, (VOID *)(UINTN)EntryPoint));
    133 
    134   Hob = GetHobList ();
    135   if (StackSize == 0) {
    136     // User the current stack
    137 
    138     ((DXE_CORE_ENTRY_POINT)(UINTN)EntryPoint) (Hob);
    139   } else {
    140 
    141     //
    142     // Allocate 128KB for the Stack
    143     //
    144     BaseOfStack = AllocatePages (EFI_SIZE_TO_PAGES (StackSize));
    145     ASSERT (BaseOfStack != NULL);
    146 
    147     //
    148     // Compute the top of the stack we were allocated. Pre-allocate a UINTN
    149     // for safety.
    150     //
    151     TopOfStack = (VOID *) ((UINTN) BaseOfStack + EFI_SIZE_TO_PAGES (StackSize) * EFI_PAGE_SIZE - CPU_STACK_ALIGNMENT);
    152     TopOfStack = ALIGN_POINTER (TopOfStack, CPU_STACK_ALIGNMENT);
    153 
    154     //
    155     // Update the contents of BSP stack HOB to reflect the real stack info passed to DxeCore.
    156     //
    157     UpdateStackHob ((EFI_PHYSICAL_ADDRESS)(UINTN) BaseOfStack, StackSize);
    158 
    159     SwitchStack (
    160       (SWITCH_STACK_ENTRY_POINT)(UINTN)EntryPoint,
    161       Hob,
    162       NULL,
    163       TopOfStack
    164       );
    165 
    166   }
    167 
    168   // Should never get here as DXE Core does not return
    169   DEBUG ((EFI_D_ERROR, "DxeCore returned\n"));
    170   ASSERT (FALSE);
    171 
    172   return EFI_DEVICE_ERROR;
    173 }
    174 
    175 
    176 
    177 EFI_STATUS
    178 EFIAPI
    179 LoadDxeCoreFromFv (
    180   IN UINTN  *FvInstance,   OPTIONAL
    181   IN UINTN  StackSize
    182   )
    183 {
    184   EFI_STATUS          Status;
    185   EFI_PEI_FV_HANDLE   VolumeHandle;
    186   EFI_PEI_FILE_HANDLE FileHandle = NULL;
    187 
    188   if (FvInstance != NULL) {
    189     //
    190     // Caller passed in a specific FV to try, so only try that one
    191     //
    192     Status = FfsFindNextVolume (*FvInstance, &VolumeHandle);
    193     if (!EFI_ERROR (Status)) {
    194       Status = FfsFindNextFile (EFI_FV_FILETYPE_DXE_CORE, VolumeHandle, &FileHandle);
    195     }
    196   } else {
    197     Status = FfsAnyFvFindFirstFile (EFI_FV_FILETYPE_DXE_CORE, &VolumeHandle, &FileHandle);
    198   }
    199 
    200   if (!EFI_ERROR (Status)) {
    201     return LoadDxeCoreFromFfsFile (FileHandle, StackSize);
    202   }
    203 
    204   return Status;
    205 }
    206 
    207 
    208 EFI_STATUS
    209 EFIAPI
    210 DecompressFirstFv (
    211   VOID
    212   )
    213 {
    214   EFI_STATUS          Status;
    215   EFI_PEI_FV_HANDLE   VolumeHandle;
    216   EFI_PEI_FILE_HANDLE FileHandle;
    217 
    218   Status = FfsAnyFvFindFirstFile (EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE, &VolumeHandle, &FileHandle);
    219   if (!EFI_ERROR (Status)) {
    220     Status = FfsProcessFvFile (FileHandle);
    221   }
    222 
    223   return Status;
    224 }
    225 
    226 
    227