Home | History | Annotate | Download | only in PrePi
      1 /** @file
      2 *
      3 *  Copyright (c) 2011-2014, ARM Limited. All rights reserved.
      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 <PiPei.h>
     16 
     17 #include <Library/DebugAgentLib.h>
     18 #include <Library/PrePiLib.h>
     19 #include <Library/PrintLib.h>
     20 #include <Library/PeCoffGetEntryPointLib.h>
     21 #include <Library/PrePiHobListPointerLib.h>
     22 #include <Library/TimerLib.h>
     23 #include <Library/PerformanceLib.h>
     24 
     25 #include <Ppi/GuidedSectionExtraction.h>
     26 #include <Ppi/ArmMpCoreInfo.h>
     27 #include <Guid/LzmaDecompress.h>
     28 
     29 #include "PrePi.h"
     30 #include "LzmaDecompress.h"
     31 
     32 #define IS_XIP() (((UINT32)FixedPcdGet32 (PcdFdBaseAddress) > mSystemMemoryEnd) || \
     33                   ((FixedPcdGet32 (PcdFdBaseAddress) + FixedPcdGet32 (PcdFdSize)) < FixedPcdGet64 (PcdSystemMemoryBase)))
     34 
     35 EFI_STATUS
     36 EFIAPI
     37 ExtractGuidedSectionLibConstructor (
     38   VOID
     39   );
     40 
     41 EFI_STATUS
     42 EFIAPI
     43 LzmaDecompressLibConstructor (
     44   VOID
     45   );
     46 
     47 EFI_STATUS
     48 GetPlatformPpi (
     49   IN  EFI_GUID  *PpiGuid,
     50   OUT VOID      **Ppi
     51   )
     52 {
     53   UINTN                   PpiListSize;
     54   UINTN                   PpiListCount;
     55   EFI_PEI_PPI_DESCRIPTOR  *PpiList;
     56   UINTN                   Index;
     57 
     58   PpiListSize = 0;
     59   ArmPlatformGetPlatformPpiList (&PpiListSize, &PpiList);
     60   PpiListCount = PpiListSize / sizeof(EFI_PEI_PPI_DESCRIPTOR);
     61   for (Index = 0; Index < PpiListCount; Index++, PpiList++) {
     62     if (CompareGuid (PpiList->Guid, PpiGuid) == TRUE) {
     63       *Ppi = PpiList->Ppi;
     64       return EFI_SUCCESS;
     65     }
     66   }
     67 
     68   return EFI_NOT_FOUND;
     69 }
     70 
     71 VOID
     72 PrePiMain (
     73   IN  UINTN                     UefiMemoryBase,
     74   IN  UINTN                     StacksBase,
     75   IN  UINT64                    StartTimeStamp
     76   )
     77 {
     78   EFI_HOB_HANDOFF_INFO_TABLE*   HobList;
     79   ARM_MP_CORE_INFO_PPI*         ArmMpCoreInfoPpi;
     80   UINTN                         ArmCoreCount;
     81   ARM_CORE_INFO*                ArmCoreInfoTable;
     82   EFI_STATUS                    Status;
     83   CHAR8                         Buffer[100];
     84   UINTN                         CharCount;
     85   UINTN                         StacksSize;
     86 
     87   // If ensure the FD is either part of the System Memory or totally outside of the System Memory (XIP)
     88   ASSERT (IS_XIP() ||
     89           ((FixedPcdGet32 (PcdFdBaseAddress) >= FixedPcdGet64 (PcdSystemMemoryBase)) &&
     90            ((UINT32)(FixedPcdGet32 (PcdFdBaseAddress) + FixedPcdGet32 (PcdFdSize)) <= (UINT32)mSystemMemoryEnd)));
     91 
     92   // Initialize the architecture specific bits
     93   ArchInitialize ();
     94 
     95   // Initialize the Serial Port
     96   SerialPortInitialize ();
     97   CharCount = AsciiSPrint (Buffer,sizeof (Buffer),"UEFI firmware (version %s built at %a on %a)\n\r",
     98     (CHAR16*)PcdGetPtr(PcdFirmwareVersionString), __TIME__, __DATE__);
     99   SerialPortWrite ((UINT8 *) Buffer, CharCount);
    100 
    101   // Initialize the Debug Agent for Source Level Debugging
    102   InitializeDebugAgent (DEBUG_AGENT_INIT_POSTMEM_SEC, NULL, NULL);
    103   SaveAndSetDebugTimerInterrupt (TRUE);
    104 
    105   // Declare the PI/UEFI memory region
    106   HobList = HobConstructor (
    107     (VOID*)UefiMemoryBase,
    108     FixedPcdGet32 (PcdSystemMemoryUefiRegionSize),
    109     (VOID*)UefiMemoryBase,
    110     (VOID*)StacksBase  // The top of the UEFI Memory is reserved for the stacks
    111     );
    112   PrePeiSetHobList (HobList);
    113 
    114   // Initialize MMU and Memory HOBs (Resource Descriptor HOBs)
    115   Status = MemoryPeim (UefiMemoryBase, FixedPcdGet32 (PcdSystemMemoryUefiRegionSize));
    116   ASSERT_EFI_ERROR (Status);
    117 
    118   // Create the Stacks HOB (reserve the memory for all stacks)
    119   if (ArmIsMpCore ()) {
    120     StacksSize = PcdGet32 (PcdCPUCorePrimaryStackSize) +
    121                  ((FixedPcdGet32 (PcdCoreCount) - 1) * FixedPcdGet32 (PcdCPUCoreSecondaryStackSize));
    122   } else {
    123     StacksSize = PcdGet32 (PcdCPUCorePrimaryStackSize);
    124   }
    125   BuildStackHob (StacksBase, StacksSize);
    126 
    127   //TODO: Call CpuPei as a library
    128   BuildCpuHob (PcdGet8 (PcdPrePiCpuMemorySize), PcdGet8 (PcdPrePiCpuIoSize));
    129 
    130   if (ArmIsMpCore ()) {
    131     // Only MP Core platform need to produce gArmMpCoreInfoPpiGuid
    132     Status = GetPlatformPpi (&gArmMpCoreInfoPpiGuid, (VOID**)&ArmMpCoreInfoPpi);
    133 
    134     // On MP Core Platform we must implement the ARM MP Core Info PPI (gArmMpCoreInfoPpiGuid)
    135     ASSERT_EFI_ERROR (Status);
    136 
    137     // Build the MP Core Info Table
    138     ArmCoreCount = 0;
    139     Status = ArmMpCoreInfoPpi->GetMpCoreInfo (&ArmCoreCount, &ArmCoreInfoTable);
    140     if (!EFI_ERROR(Status) && (ArmCoreCount > 0)) {
    141       // Build MPCore Info HOB
    142       BuildGuidDataHob (&gArmMpCoreInfoGuid, ArmCoreInfoTable, sizeof (ARM_CORE_INFO) * ArmCoreCount);
    143     }
    144   }
    145 
    146   // Set the Boot Mode
    147   SetBootMode (ArmPlatformGetBootMode ());
    148 
    149   // Initialize Platform HOBs (CpuHob and FvHob)
    150   Status = PlatformPeim ();
    151   ASSERT_EFI_ERROR (Status);
    152 
    153   // Now, the HOB List has been initialized, we can register performance information
    154   PERF_START (NULL, "PEI", NULL, StartTimeStamp);
    155 
    156   // SEC phase needs to run library constructors by hand.
    157   ExtractGuidedSectionLibConstructor ();
    158   LzmaDecompressLibConstructor ();
    159 
    160   // Build HOBs to pass up our version of stuff the DXE Core needs to save space
    161   BuildPeCoffLoaderHob ();
    162   BuildExtractSectionHob (
    163     &gLzmaCustomDecompressGuid,
    164     LzmaGuidedSectionGetInfo,
    165     LzmaGuidedSectionExtraction
    166     );
    167 
    168   // Assume the FV that contains the SEC (our code) also contains a compressed FV.
    169   Status = DecompressFirstFv ();
    170   ASSERT_EFI_ERROR (Status);
    171 
    172   // Load the DXE Core and transfer control to it
    173   Status = LoadDxeCoreFromFv (NULL, 0);
    174   ASSERT_EFI_ERROR (Status);
    175 }
    176 
    177 VOID
    178 CEntryPoint (
    179   IN  UINTN                     MpId,
    180   IN  UINTN                     UefiMemoryBase,
    181   IN  UINTN                     StacksBase
    182   )
    183 {
    184   UINT64   StartTimeStamp;
    185 
    186   ASSERT(!ArmIsMpCore() || (PcdGet32 (PcdCoreCount) > 1));
    187 
    188   // Initialize the platform specific controllers
    189   ArmPlatformInitialize (MpId);
    190 
    191   if (ArmPlatformIsPrimaryCore (MpId) && PerformanceMeasurementEnabled ()) {
    192     // Initialize the Timer Library to setup the Timer HW controller
    193     TimerConstructor ();
    194     // We cannot call yet the PerformanceLib because the HOB List has not been initialized
    195     StartTimeStamp = GetPerformanceCounter ();
    196   } else {
    197     StartTimeStamp = 0;
    198   }
    199 
    200   // Data Cache enabled on Primary core when MMU is enabled.
    201   ArmDisableDataCache ();
    202   // Invalidate Data cache
    203   ArmInvalidateDataCache ();
    204   // Invalidate instruction cache
    205   ArmInvalidateInstructionCache ();
    206   // Enable Instruction Caches on all cores.
    207   ArmEnableInstructionCache ();
    208 
    209   // Define the Global Variable region when we are not running in XIP
    210   if (!IS_XIP()) {
    211     if (ArmPlatformIsPrimaryCore (MpId)) {
    212       if (ArmIsMpCore()) {
    213         // Signal the Global Variable Region is defined (event: ARM_CPU_EVENT_DEFAULT)
    214         ArmCallSEV ();
    215       }
    216     } else {
    217       // Wait the Primay core has defined the address of the Global Variable region (event: ARM_CPU_EVENT_DEFAULT)
    218       ArmCallWFE ();
    219     }
    220   }
    221 
    222   // If not primary Jump to Secondary Main
    223   if (ArmPlatformIsPrimaryCore (MpId)) {
    224     // Goto primary Main.
    225     PrimaryMain (UefiMemoryBase, StacksBase, StartTimeStamp);
    226   } else {
    227     SecondaryMain (MpId);
    228   }
    229 
    230   // DXE Core should always load and never return
    231   ASSERT (FALSE);
    232 }
    233 
    234