1 /** @file
2 *  Main file supporting the transition to PEI Core in Normal World for Versatile Express
3 *
4 *  Copyright (c) 2011-2014, ARM Limited. All rights reserved.
5 *
6 *  SPDX-License-Identifier: BSD-2-Clause-Patent
7 *
8 **/
9 
10 #include <Library/BaseLib.h>
11 #include <Library/CacheMaintenanceLib.h>
12 #include <Library/DebugAgentLib.h>
13 #include <Library/ArmLib.h>
14 
15 #include "PrePeiCore.h"
16 
17 CONST EFI_PEI_TEMPORARY_RAM_SUPPORT_PPI   mTemporaryRamSupportPpi = { PrePeiCoreTemporaryRamSupport };
18 
19 CONST EFI_PEI_PPI_DESCRIPTOR      gCommonPpiTable[] = {
20   {
21     EFI_PEI_PPI_DESCRIPTOR_PPI,
22     &gEfiTemporaryRamSupportPpiGuid,
23     (VOID *) &mTemporaryRamSupportPpi
24   }
25 };
26 
27 VOID
CreatePpiList(OUT UINTN * PpiListSize,OUT EFI_PEI_PPI_DESCRIPTOR ** PpiList)28 CreatePpiList (
29   OUT UINTN                   *PpiListSize,
30   OUT EFI_PEI_PPI_DESCRIPTOR  **PpiList
31   )
32 {
33   EFI_PEI_PPI_DESCRIPTOR *PlatformPpiList;
34   UINTN                   PlatformPpiListSize;
35   UINTN                   ListBase;
36   EFI_PEI_PPI_DESCRIPTOR *LastPpi;
37 
38   // Get the Platform PPIs
39   PlatformPpiListSize = 0;
40   ArmPlatformGetPlatformPpiList (&PlatformPpiListSize, &PlatformPpiList);
41 
42   // Copy the Common and Platform PPis in Temporary Memory
43   ListBase = PcdGet64 (PcdCPUCoresStackBase);
44   CopyMem ((VOID*)ListBase, gCommonPpiTable, sizeof(gCommonPpiTable));
45   CopyMem ((VOID*)(ListBase + sizeof(gCommonPpiTable)), PlatformPpiList, PlatformPpiListSize);
46 
47   // Set the Terminate flag on the last PPI entry
48   LastPpi = (EFI_PEI_PPI_DESCRIPTOR*)ListBase + ((sizeof(gCommonPpiTable) + PlatformPpiListSize) / sizeof(EFI_PEI_PPI_DESCRIPTOR)) - 1;
49   LastPpi->Flags |= EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST;
50 
51   *PpiList     = (EFI_PEI_PPI_DESCRIPTOR*)ListBase;
52   *PpiListSize = sizeof(gCommonPpiTable) + PlatformPpiListSize;
53 }
54 
55 VOID
CEntryPoint(IN UINTN MpId,IN EFI_PEI_CORE_ENTRY_POINT PeiCoreEntryPoint)56 CEntryPoint (
57   IN  UINTN                     MpId,
58   IN  EFI_PEI_CORE_ENTRY_POINT  PeiCoreEntryPoint
59   )
60 {
61   // Data Cache enabled on Primary core when MMU is enabled.
62   ArmDisableDataCache ();
63   // Invalidate instruction cache
64   ArmInvalidateInstructionCache ();
65   // Enable Instruction Caches on all cores.
66   ArmEnableInstructionCache ();
67 
68   InvalidateDataCacheRange ((VOID *)(UINTN)PcdGet64 (PcdCPUCoresStackBase),
69                             PcdGet32 (PcdCPUCorePrimaryStackSize));
70 
71   //
72   // Note: Doesn't have to Enable CPU interface in non-secure world,
73   // as Non-secure interface is already enabled in Secure world.
74   //
75 
76   // Write VBAR - The Exception Vector table must be aligned to its requirement
77   // Note: The AArch64 Vector table must be 2k-byte aligned - if this assertion fails ensure
78   // 'Align=4K' is defined into your FDF for this module.
79   ASSERT (((UINTN)PeiVectorTable & ARM_VECTOR_TABLE_ALIGNMENT) == 0);
80   ArmWriteVBar ((UINTN)PeiVectorTable);
81 
82   // Enable Floating Point
83   if (FixedPcdGet32 (PcdVFPEnabled)) {
84     ArmEnableVFP ();
85   }
86 
87   //Note: The MMU will be enabled by MemoryPeim. Only the primary core will have the MMU on.
88 
89   // If not primary Jump to Secondary Main
90   if (ArmPlatformIsPrimaryCore (MpId)) {
91     // Initialize the Debug Agent for Source Level Debugging
92     InitializeDebugAgent (DEBUG_AGENT_INIT_POSTMEM_SEC, NULL, NULL);
93     SaveAndSetDebugTimerInterrupt (TRUE);
94 
95     // Initialize the platform specific controllers
96     ArmPlatformInitialize (MpId);
97 
98     // Goto primary Main.
99     PrimaryMain (PeiCoreEntryPoint);
100   } else {
101     SecondaryMain (MpId);
102   }
103 
104   // PEI Core should always load and never return
105   ASSERT (FALSE);
106 }
107 
108 EFI_STATUS
109 EFIAPI
PrePeiCoreTemporaryRamSupport(IN CONST EFI_PEI_SERVICES ** PeiServices,IN EFI_PHYSICAL_ADDRESS TemporaryMemoryBase,IN EFI_PHYSICAL_ADDRESS PermanentMemoryBase,IN UINTN CopySize)110 PrePeiCoreTemporaryRamSupport (
111   IN CONST EFI_PEI_SERVICES   **PeiServices,
112   IN EFI_PHYSICAL_ADDRESS     TemporaryMemoryBase,
113   IN EFI_PHYSICAL_ADDRESS     PermanentMemoryBase,
114   IN UINTN                    CopySize
115   )
116 {
117   VOID                             *OldHeap;
118   VOID                             *NewHeap;
119   VOID                             *OldStack;
120   VOID                             *NewStack;
121   UINTN                            HeapSize;
122 
123   HeapSize = ALIGN_VALUE (CopySize / 2, CPU_STACK_ALIGNMENT);
124 
125   OldHeap = (VOID*)(UINTN)TemporaryMemoryBase;
126   NewHeap = (VOID*)((UINTN)PermanentMemoryBase + (CopySize - HeapSize));
127 
128   OldStack = (VOID*)((UINTN)TemporaryMemoryBase + HeapSize);
129   NewStack = (VOID*)(UINTN)PermanentMemoryBase;
130 
131   //
132   // Migrate the temporary memory stack to permanent memory stack.
133   //
134   CopyMem (NewStack, OldStack, CopySize - HeapSize);
135 
136   //
137   // Migrate the temporary memory heap to permanent memory heap.
138   //
139   CopyMem (NewHeap, OldHeap, HeapSize);
140 
141   SecSwitchStack ((UINTN)NewStack - (UINTN)OldStack);
142 
143   return EFI_SUCCESS;
144 }
145