85a9c108aea4902f7e64faf5beb505b5eeb1a63c
[mirror_edk2.git] / StandaloneMmPkg / Drivers / StandaloneMmCpu / AArch64 / StandaloneMmCpu.c
1 /** @file\r
2 \r
3   Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>\r
4   Copyright (c) 2016 HP Development Company, L.P.\r
5   Copyright (c) 2016 - 2018, ARM Limited. All rights reserved.\r
6 \r
7   This program and the accompanying materials\r
8   are licensed and made available under the terms and conditions of the BSD License\r
9   which accompanies this distribution.  The full text of the license may be found at\r
10   http://opensource.org/licenses/bsd-license.php\r
11 \r
12   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
13   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
14 \r
15 **/\r
16 \r
17 #include <Base.h>\r
18 #include <Pi/PiMmCis.h>\r
19 #include <Library/AArch64/StandaloneMmCoreEntryPoint.h>\r
20 #include <Library/DebugLib.h>\r
21 #include <Library/ArmSvcLib.h>\r
22 #include <Library/ArmLib.h>\r
23 #include <Library/BaseMemoryLib.h>\r
24 #include <Library/HobLib.h>\r
25 \r
26 #include <Protocol/DebugSupport.h> // for EFI_SYSTEM_CONTEXT\r
27 \r
28 #include <Guid/ZeroGuid.h>\r
29 #include <Guid/MmramMemoryReserve.h>\r
30 \r
31 \r
32 #include "StandaloneMmCpu.h"\r
33 \r
34 // GUID to identify HOB with whereabouts of communication buffer with Normal\r
35 // World\r
36 extern EFI_GUID gEfiStandaloneMmNonSecureBufferGuid;\r
37 \r
38 // GUID to identify HOB where the entry point of this CPU driver will be\r
39 // populated to allow the entry point driver to invoke it upon receipt of an\r
40 // event\r
41 extern EFI_GUID gEfiArmTfCpuDriverEpDescriptorGuid;\r
42 \r
43 //\r
44 // Private copy of the MM system table for future use\r
45 //\r
46 EFI_MM_SYSTEM_TABLE *mMmst = NULL;\r
47 \r
48 //\r
49 // Globals used to initialize the protocol\r
50 //\r
51 STATIC EFI_HANDLE            mMmCpuHandle = NULL;\r
52 \r
53 EFI_STATUS\r
54 GetGuidedHobData (\r
55   IN  VOID *HobList,\r
56   IN  CONST EFI_GUID *HobGuid,\r
57   OUT VOID **HobData\r
58   )\r
59 {\r
60   EFI_HOB_GUID_TYPE *Hob;\r
61 \r
62   if (!HobList || !HobGuid || !HobData)\r
63     return EFI_INVALID_PARAMETER;\r
64 \r
65   Hob = GetNextGuidHob (HobGuid, HobList);\r
66   if (!Hob)\r
67     return EFI_NOT_FOUND;\r
68 \r
69   *HobData = GET_GUID_HOB_DATA (Hob);\r
70   if (!HobData)\r
71     return EFI_NOT_FOUND;\r
72 \r
73   return EFI_SUCCESS;\r
74 }\r
75 \r
76 EFI_STATUS\r
77 StandloneMmCpuInitialize (\r
78   IN EFI_HANDLE         ImageHandle,  // not actual imagehandle\r
79   IN EFI_MM_SYSTEM_TABLE   *SystemTable  // not actual systemtable\r
80   )\r
81 {\r
82   ARM_TF_CPU_DRIVER_EP_DESCRIPTOR *CpuDriverEntryPointDesc;\r
83   EFI_CONFIGURATION_TABLE         *ConfigurationTable;\r
84   MP_INFORMATION_HOB_DATA         *MpInformationHobData;\r
85   EFI_MMRAM_DESCRIPTOR            *NsCommBufMmramRange;\r
86   EFI_STATUS                       Status;\r
87   EFI_HANDLE                       DispatchHandle;\r
88   UINT32                           MpInfoSize;\r
89   UINTN                            Index;\r
90   UINTN                            ArraySize;\r
91   VOID                            *HobStart;\r
92 \r
93   ASSERT (SystemTable != NULL);\r
94   mMmst = SystemTable;\r
95 \r
96   // publish the MM config protocol so the MM core can register its entry point\r
97   Status = mMmst->MmInstallProtocolInterface (\r
98                     &mMmCpuHandle,\r
99                     &gEfiMmConfigurationProtocolGuid,\r
100                     EFI_NATIVE_INTERFACE,\r
101                     &mMmConfig\r
102                     );\r
103   if (EFI_ERROR (Status)) {\r
104     return Status;\r
105   }\r
106 \r
107   // register the root MMI handler\r
108   Status = mMmst->MmiHandlerRegister (\r
109                     PiMmCpuTpFwRootMmiHandler,\r
110                     NULL,\r
111                     &DispatchHandle\r
112                     );\r
113   if (EFI_ERROR (Status)) {\r
114     return Status;\r
115   }\r
116 \r
117   // Retrieve the Hoblist from the MMST to extract the details of the NS\r
118   // communication buffer that has been reserved by S-EL1/EL3\r
119   ConfigurationTable = mMmst->MmConfigurationTable;\r
120   for (Index = 0; Index < mMmst->NumberOfTableEntries; Index++) {\r
121     if (CompareGuid (&gEfiHobListGuid, &(ConfigurationTable[Index].VendorGuid))) {\r
122       break;\r
123     }\r
124   }\r
125 \r
126   // Bail out if the Hoblist could not be found\r
127   if (Index >= mMmst->NumberOfTableEntries) {\r
128     DEBUG ((DEBUG_INFO, "Hoblist not found - 0x%x\n", Index));\r
129     return EFI_OUT_OF_RESOURCES;\r
130   }\r
131 \r
132   HobStart = ConfigurationTable[Index].VendorTable;\r
133 \r
134   //\r
135   // Locate the HOB with the buffer to populate the entry point of this driver\r
136   //\r
137   Status = GetGuidedHobData (\r
138              HobStart,\r
139              &gEfiArmTfCpuDriverEpDescriptorGuid,\r
140              (VOID **) &CpuDriverEntryPointDesc\r
141              );\r
142   if (EFI_ERROR (Status)) {\r
143     DEBUG ((DEBUG_INFO, "ArmTfCpuDriverEpDesc HOB data extraction failed - 0x%x\n", Status));\r
144     return Status;\r
145   }\r
146 \r
147   // Share the entry point of the CPU driver\r
148   DEBUG ((DEBUG_INFO, "Sharing Cpu Driver EP *0x%lx = 0x%lx\n",\r
149           (UINT64) CpuDriverEntryPointDesc->ArmTfCpuDriverEpPtr,\r
150           (UINT64) PiMmStandloneArmTfCpuDriverEntry));\r
151   *(CpuDriverEntryPointDesc->ArmTfCpuDriverEpPtr) = PiMmStandloneArmTfCpuDriverEntry;\r
152 \r
153   // Find the descriptor that contains the whereabouts of the buffer for\r
154   // communication with the Normal world.\r
155   Status = GetGuidedHobData (\r
156              HobStart,\r
157              &gEfiStandaloneMmNonSecureBufferGuid,\r
158              (VOID **) &NsCommBufMmramRange\r
159              );\r
160   if (EFI_ERROR (Status)) {\r
161     DEBUG ((DEBUG_INFO, "NsCommBufMmramRange HOB data extraction failed - 0x%x\n", Status));\r
162     return Status;\r
163   }\r
164 \r
165   DEBUG ((DEBUG_INFO, "mNsCommBuffer.PhysicalStart - 0x%lx\n", (UINT64) NsCommBufMmramRange->PhysicalStart));\r
166   DEBUG ((DEBUG_INFO, "mNsCommBuffer.PhysicalSize - 0x%lx\n", (UINT64) NsCommBufMmramRange->PhysicalSize));\r
167 \r
168   CopyMem (&mNsCommBuffer, NsCommBufMmramRange, sizeof(EFI_MMRAM_DESCRIPTOR));\r
169   DEBUG ((DEBUG_INFO, "mNsCommBuffer: 0x%016lx - 0x%lx\n", mNsCommBuffer.CpuStart, mNsCommBuffer.PhysicalSize));\r
170 \r
171   //\r
172   // Extract the MP information from the Hoblist\r
173   //\r
174   Status = GetGuidedHobData (\r
175              HobStart,\r
176              &gMpInformationHobGuid,\r
177              (VOID **) &MpInformationHobData\r
178              );\r
179   if (EFI_ERROR (Status)) {\r
180     DEBUG ((DEBUG_INFO, "MpInformationHob extraction failed - 0x%x\n", Status));\r
181     return Status;\r
182   }\r
183 \r
184   //\r
185   // Allocate memory for the MP information and copy over the MP information\r
186   // passed by Trusted Firmware. Use the number of processors passed in the HOB\r
187   // to copy the processor information\r
188   //\r
189   MpInfoSize = sizeof (MP_INFORMATION_HOB_DATA) +\r
190                (sizeof (EFI_PROCESSOR_INFORMATION) *\r
191                MpInformationHobData->NumberOfProcessors);\r
192   Status = mMmst->MmAllocatePool (\r
193                     EfiRuntimeServicesData,\r
194                     MpInfoSize,\r
195                     (VOID **) &mMpInformationHobData\r
196                     );\r
197   if (EFI_ERROR (Status)) {\r
198     DEBUG ((DEBUG_INFO, "mMpInformationHobData mem alloc failed - 0x%x\n", Status));\r
199     return Status;\r
200   }\r
201 \r
202   CopyMem (mMpInformationHobData, MpInformationHobData, MpInfoSize);\r
203 \r
204   // Print MP information\r
205   DEBUG ((DEBUG_INFO, "mMpInformationHobData: 0x%016lx - 0x%lx\n",\r
206           mMpInformationHobData->NumberOfProcessors,\r
207           mMpInformationHobData->NumberOfEnabledProcessors));\r
208   for (Index = 0; Index < mMpInformationHobData->NumberOfProcessors; Index++) {\r
209     DEBUG ((DEBUG_INFO, "mMpInformationHobData[0x%lx]: %d, %d, %d\n",\r
210             mMpInformationHobData->ProcessorInfoBuffer[Index].ProcessorId,\r
211             mMpInformationHobData->ProcessorInfoBuffer[Index].Location.Package,\r
212             mMpInformationHobData->ProcessorInfoBuffer[Index].Location.Core,\r
213             mMpInformationHobData->ProcessorInfoBuffer[Index].Location.Thread));\r
214   }\r
215 \r
216   //\r
217   // Allocate memory for a table to hold pointers to a\r
218   // EFI_MM_COMMUNICATE_HEADER for each CPU\r
219   //\r
220   ArraySize = sizeof (EFI_MM_COMMUNICATE_HEADER *) *\r
221               mMpInformationHobData->NumberOfEnabledProcessors;\r
222   Status = mMmst->MmAllocatePool (\r
223                     EfiRuntimeServicesData,\r
224                     ArraySize,\r
225                     (VOID **) &PerCpuGuidedEventContext\r
226                     );\r
227   if (EFI_ERROR (Status)) {\r
228     DEBUG ((DEBUG_INFO, "PerCpuGuidedEventContext mem alloc failed - 0x%x\n", Status));\r
229     return Status;\r
230   }\r
231   return Status;\r
232 }\r