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