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 *  This program and the accompanying materials
7 *  are licensed and made available under the terms and conditions of the BSD License
8 *  which accompanies this distribution.  The full text of the license may be found at
9 *  http://opensource.org/licenses/bsd-license.php
10 *
11 *  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 *  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13 *
14 **/
15 
16 #include <Library/BaseLib.h>
17 #include <Library/DebugAgentLib.h>
18 #include <Library/ArmLib.h>
19 
20 #include "PrePeiCore.h"
21 
22 CONST EFI_PEI_TEMPORARY_RAM_SUPPORT_PPI   mTemporaryRamSupportPpi = { PrePeiCoreTemporaryRamSupport };
23 
24 CONST EFI_PEI_PPI_DESCRIPTOR      gCommonPpiTable[] = {
25   {
26     EFI_PEI_PPI_DESCRIPTOR_PPI,
27     &gEfiTemporaryRamSupportPpiGuid,
28     (VOID *) &mTemporaryRamSupportPpi
29   }
30 };
31 
32 VOID
CreatePpiList(OUT UINTN * PpiListSize,OUT EFI_PEI_PPI_DESCRIPTOR ** PpiList)33 CreatePpiList (
34   OUT UINTN                   *PpiListSize,
35   OUT EFI_PEI_PPI_DESCRIPTOR  **PpiList
36   )
37 {
38   EFI_PEI_PPI_DESCRIPTOR *PlatformPpiList;
39   UINTN                   PlatformPpiListSize;
40   UINTN                   ListBase;
41   EFI_PEI_PPI_DESCRIPTOR *LastPpi;
42 
43   // Get the Platform PPIs
44   PlatformPpiListSize = 0;
45   ArmPlatformGetPlatformPpiList (&PlatformPpiListSize, &PlatformPpiList);
46 
47   // Copy the Common and Platform PPis in Temporrary Memory
48   ListBase = PcdGet64 (PcdCPUCoresStackBase);
49   CopyMem ((VOID*)ListBase, gCommonPpiTable, sizeof(gCommonPpiTable));
50   CopyMem ((VOID*)(ListBase + sizeof(gCommonPpiTable)), PlatformPpiList, PlatformPpiListSize);
51 
52   // Set the Terminate flag on the last PPI entry
53   LastPpi = (EFI_PEI_PPI_DESCRIPTOR*)ListBase + ((sizeof(gCommonPpiTable) + PlatformPpiListSize) / sizeof(EFI_PEI_PPI_DESCRIPTOR)) - 1;
54   LastPpi->Flags |= EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST;
55 
56   *PpiList     = (EFI_PEI_PPI_DESCRIPTOR*)ListBase;
57   *PpiListSize = sizeof(gCommonPpiTable) + PlatformPpiListSize;
58 }
59 
60 VOID
CEntryPoint(IN UINTN MpId,IN EFI_PEI_CORE_ENTRY_POINT PeiCoreEntryPoint)61 CEntryPoint (
62   IN  UINTN                     MpId,
63   IN  EFI_PEI_CORE_ENTRY_POINT  PeiCoreEntryPoint
64   )
65 {
66   // Data Cache enabled on Primary core when MMU is enabled.
67   ArmDisableDataCache ();
68   // Invalidate Data cache
69   ArmInvalidateDataCache ();
70   // Invalidate instruction cache
71   ArmInvalidateInstructionCache ();
72   // Enable Instruction Caches on all cores.
73   ArmEnableInstructionCache ();
74 
75   //
76   // Note: Doesn't have to Enable CPU interface in non-secure world,
77   // as Non-secure interface is already enabled in Secure world.
78   //
79 
80   // Write VBAR - The Exception Vector table must be aligned to its requirement
81   // Note: The AArch64 Vector table must be 2k-byte aligned - if this assertion fails ensure
82   // 'Align=4K' is defined into your FDF for this module.
83   ASSERT (((UINTN)PeiVectorTable & ARM_VECTOR_TABLE_ALIGNMENT) == 0);
84   ArmWriteVBar ((UINTN)PeiVectorTable);
85 
86   //Note: The MMU will be enabled by MemoryPeim. Only the primary core will have the MMU on.
87 
88   // If not primary Jump to Secondary Main
89   if (ArmPlatformIsPrimaryCore (MpId)) {
90     // Initialize the Debug Agent for Source Level Debugging
91     InitializeDebugAgent (DEBUG_AGENT_INIT_POSTMEM_SEC, NULL, NULL);
92     SaveAndSetDebugTimerInterrupt (TRUE);
93 
94     // Initialize the platform specific controllers
95     ArmPlatformInitialize (MpId);
96 
97     // Goto primary Main.
98     PrimaryMain (PeiCoreEntryPoint);
99   } else {
100     SecondaryMain (MpId);
101   }
102 
103   // PEI Core should always load and never return
104   ASSERT (FALSE);
105 }
106 
107 EFI_STATUS
108 EFIAPI
PrePeiCoreTemporaryRamSupport(IN CONST EFI_PEI_SERVICES ** PeiServices,IN EFI_PHYSICAL_ADDRESS TemporaryMemoryBase,IN EFI_PHYSICAL_ADDRESS PermanentMemoryBase,IN UINTN CopySize)109 PrePeiCoreTemporaryRamSupport (
110   IN CONST EFI_PEI_SERVICES   **PeiServices,
111   IN EFI_PHYSICAL_ADDRESS     TemporaryMemoryBase,
112   IN EFI_PHYSICAL_ADDRESS     PermanentMemoryBase,
113   IN UINTN                    CopySize
114   )
115 {
116   VOID                             *OldHeap;
117   VOID                             *NewHeap;
118   VOID                             *OldStack;
119   VOID                             *NewStack;
120   UINTN                            HeapSize;
121 
122   HeapSize = ALIGN_VALUE (CopySize / 2, CPU_STACK_ALIGNMENT);
123 
124   OldHeap = (VOID*)(UINTN)TemporaryMemoryBase;
125   NewHeap = (VOID*)((UINTN)PermanentMemoryBase + (CopySize - HeapSize));
126 
127   OldStack = (VOID*)((UINTN)TemporaryMemoryBase + HeapSize);
128   NewStack = (VOID*)(UINTN)PermanentMemoryBase;
129 
130   //
131   // Migrate the temporary memory stack to permanent memory stack.
132   //
133   CopyMem (NewStack, OldStack, CopySize - HeapSize);
134 
135   //
136   // Migrate the temporary memory heap to permanent memory heap.
137   //
138   CopyMem (NewHeap, OldHeap, HeapSize);
139 
140   SecSwitchStack ((UINTN)NewStack - (UINTN)OldStack);
141 
142   return EFI_SUCCESS;
143 }
144