]> git.proxmox.com Git - mirror_edk2.git/blame - ArmPlatformPkg/ArmJunoPkg/Drivers/ArmJunoDxe/ArmJunoDxe.c
ArmPlatformPkg: Convert ArmJunoDxe to use common juno revision code
[mirror_edk2.git] / ArmPlatformPkg / ArmJunoPkg / Drivers / ArmJunoDxe / ArmJunoDxe.c
CommitLineData
9f38945f
OM
1/** @file\r
2*\r
21a76332 3* Copyright (c) 2013-2015, ARM Limited. All rights reserved.\r
9f38945f
OM
4*\r
5* This program and the accompanying materials\r
6* are licensed and made available under the terms and conditions of the BSD License\r
7* which accompanies this distribution. The full text of the license may be found at\r
8* http://opensource.org/licenses/bsd-license.php\r
9*\r
10* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12*\r
13**/\r
14\r
15#include "ArmJunoDxeInternal.h"\r
c1fee786 16#include <ArmPlatform.h>\r
6d60dfea
OM
17\r
18#include <Protocol/DevicePathFromText.h>\r
1bb1f35f 19#include <Protocol/PciRootBridgeIo.h>\r
6d60dfea 20\r
1bb1f35f 21#include <Guid/EventGroup.h>\r
6d60dfea
OM
22#include <Guid/GlobalVariable.h>\r
23\r
9f38945f 24#include <Library/ArmShellCmdLib.h>\r
21a76332 25#include <Library/AcpiLib.h>\r
6d60dfea
OM
26#include <Library/BaseMemoryLib.h>\r
27#include <Library/DevicePathLib.h>\r
28#include <Library/MemoryAllocationLib.h>\r
29#include <Library/UefiRuntimeServicesTableLib.h>\r
c1fee786
RC
30#include <Library/IoLib.h>\r
31#include <Library/PrintLib.h>\r
32\r
c1fee786 33\r
05e56470
OM
34// This GUID must match the FILE_GUID in ArmPlatformPkg/ArmJunoPkg/AcpiTables/AcpiTables.inf\r
35STATIC CONST EFI_GUID mJunoAcpiTableFile = { 0xa1dd808e, 0x1e95, 0x4399, { 0xab, 0xc0, 0x65, 0x3c, 0x82, 0xe8, 0x53, 0x0c } };\r
36\r
1bb1f35f
OM
37typedef struct {\r
38 ACPI_HID_DEVICE_PATH AcpiDevicePath;\r
b5ec7f3c 39 PCI_DEVICE_PATH PciDevicePath;\r
1bb1f35f
OM
40 EFI_DEVICE_PATH_PROTOCOL EndDevicePath;\r
41} EFI_PCI_ROOT_BRIDGE_DEVICE_PATH;\r
42\r
43STATIC CONST EFI_PCI_ROOT_BRIDGE_DEVICE_PATH mPciRootComplexDevicePath = {\r
44 {\r
45 { ACPI_DEVICE_PATH,\r
46 ACPI_DP,\r
47 { (UINT8) (sizeof (ACPI_HID_DEVICE_PATH)),\r
48 (UINT8) ((sizeof (ACPI_HID_DEVICE_PATH)) >> 8) }\r
49 },\r
50 EISA_PNP_ID (0x0A03),\r
51 0\r
52 },\r
b5ec7f3c
OM
53 {\r
54 { HARDWARE_DEVICE_PATH,\r
55 HW_PCI_DP,\r
56 { (UINT8) (sizeof (PCI_DEVICE_PATH)),\r
57 (UINT8) ((sizeof (PCI_DEVICE_PATH)) >> 8) }\r
58 },\r
59 0,\r
60 0\r
61 },\r
1bb1f35f
OM
62 {\r
63 END_DEVICE_PATH_TYPE,\r
64 END_ENTIRE_DEVICE_PATH_SUBTYPE,\r
65 { END_DEVICE_PATH_LENGTH, 0 }\r
66 }\r
67};\r
68\r
e0ae2761
OM
69EFI_EVENT mAcpiRegistration = NULL;\r
70\r
1bb1f35f
OM
71/**\r
72 Notification function of the event defined as belonging to the\r
73 EFI_END_OF_DXE_EVENT_GROUP_GUID event group that was created in\r
74 the entry point of the driver.\r
75\r
76 This function is called when an event belonging to the\r
77 EFI_END_OF_DXE_EVENT_GROUP_GUID event group is signalled. Such an\r
78 event is signalled once at the end of the dispatching of all\r
79 drivers (end of the so called DXE phase).\r
80\r
81 @param[in] Event Event declared in the entry point of the driver whose\r
82 notification function is being invoked.\r
83 @param[in] Context NULL\r
84**/\r
85STATIC\r
86VOID\r
87OnEndOfDxe (\r
88 IN EFI_EVENT Event,\r
89 IN VOID *Context\r
90 )\r
91{\r
92 EFI_DEVICE_PATH_PROTOCOL* PciRootComplexDevicePath;\r
93 EFI_HANDLE Handle;\r
94 EFI_STATUS Status;\r
95\r
96 //\r
97 // PCI Root Complex initialization\r
98 // At the end of the DXE phase, we should get all the driver dispatched.\r
99 // Force the PCI Root Complex to be initialized. It allows the OS to skip\r
100 // this step.\r
101 //\r
102 PciRootComplexDevicePath = (EFI_DEVICE_PATH_PROTOCOL*) &mPciRootComplexDevicePath;\r
103 Status = gBS->LocateDevicePath (&gEfiPciRootBridgeIoProtocolGuid,\r
104 &PciRootComplexDevicePath,\r
105 &Handle);\r
106\r
107 Status = gBS->ConnectController (Handle, NULL, PciRootComplexDevicePath, FALSE);\r
108 ASSERT_EFI_ERROR (Status);\r
109}\r
110\r
e0ae2761
OM
111STATIC\r
112BOOLEAN\r
113AcpiTableJunoR0Check (\r
114 IN EFI_ACPI_DESCRIPTION_HEADER *AcpiHeader\r
115 )\r
116{\r
117 return TRUE;\r
118}\r
119\r
120STATIC\r
121BOOLEAN\r
122AcpiTableJunoR1Check (\r
123 IN EFI_ACPI_DESCRIPTION_HEADER *AcpiHeader\r
124 )\r
125{\r
126 return TRUE;\r
127}\r
128\r
58a4bff0
JL
129STATIC\r
130BOOLEAN\r
131AcpiTableJunoR2Check (\r
132 IN EFI_ACPI_DESCRIPTION_HEADER *AcpiHeader\r
133 )\r
134{\r
135 return TRUE;\r
136}\r
137\r
138\r
9f38945f
OM
139EFI_STATUS\r
140EFIAPI\r
141ArmJunoEntryPoint (\r
142 IN EFI_HANDLE ImageHandle,\r
143 IN EFI_SYSTEM_TABLE *SystemTable\r
144 )\r
145{\r
7aec2926
RC
146 EFI_STATUS Status;\r
147 EFI_PHYSICAL_ADDRESS HypBase;\r
148 CHAR16 *TextDevicePath;\r
149 UINTN TextDevicePathSize;\r
150 VOID *Buffer;\r
58a4bff0 151 UINT32 JunoRevision;\r
30cfc3d0 152 EFI_EVENT EndOfDxeEvent;\r
9f38945f
OM
153\r
154 Status = PciEmulationEntryPoint ();\r
155 if (EFI_ERROR (Status)) {\r
156 return Status;\r
157 }\r
158\r
159 //\r
160 // If a hypervisor has been declared then we need to make sure its region is protected at runtime\r
161 //\r
162 // Note: This code is only a workaround for our dummy hypervisor (ArmPkg/Extra/AArch64ToAArch32Shim/)\r
163 // that does not set up (yet) the stage 2 translation table to hide its own memory to EL1.\r
164 //\r
165 if (FixedPcdGet32 (PcdHypFvSize) != 0) {\r
166 // Ensure the hypervisor region is strictly contained into a EFI_PAGE_SIZE-aligned region.\r
167 // The memory must be a multiple of EFI_PAGE_SIZE to ensure we do not reserve more memory than the hypervisor itself.\r
168 // A UEFI Runtime region size granularity cannot be smaller than EFI_PAGE_SIZE. If the hypervisor size is not rounded\r
169 // to this size then there is a risk some non-runtime memory could be visible to the OS view.\r
170 if (((FixedPcdGet32 (PcdHypFvSize) & EFI_PAGE_MASK) == 0) && ((FixedPcdGet32 (PcdHypFvBaseAddress) & EFI_PAGE_MASK) == 0)) {\r
171 // The memory needs to be declared because the DXE core marked it as reserved and removed it from the memory space\r
172 // as it contains the Firmware.\r
173 Status = gDS->AddMemorySpace (\r
174 EfiGcdMemoryTypeSystemMemory,\r
175 FixedPcdGet32 (PcdHypFvBaseAddress), FixedPcdGet32 (PcdHypFvSize),\r
176 EFI_MEMORY_WB | EFI_MEMORY_RUNTIME\r
177 );\r
178 if (!EFI_ERROR (Status)) {\r
179 // We allocate the memory to ensure it is marked as runtime memory\r
180 HypBase = FixedPcdGet32 (PcdHypFvBaseAddress);\r
181 Status = gBS->AllocatePages (AllocateAddress, EfiRuntimeServicesCode,\r
182 EFI_SIZE_TO_PAGES (FixedPcdGet32 (PcdHypFvSize)), &HypBase);\r
183 }\r
184 } else {\r
185 // The hypervisor must be contained into a EFI_PAGE_SIZE-aligned region and its size must also be aligned\r
186 // on a EFI_PAGE_SIZE boundary (ie: 4KB).\r
187 Status = EFI_UNSUPPORTED;\r
188 ASSERT_EFI_ERROR (Status);\r
189 }\r
190\r
191 if (EFI_ERROR (Status)) {\r
192 return Status;\r
193 }\r
194 }\r
195\r
1bb1f35f
OM
196 //\r
197 // Create an event belonging to the "gEfiEndOfDxeEventGroupGuid" group.\r
198 // The "OnEndOfDxe()" function is declared as the call back function.\r
199 // It will be called at the end of the DXE phase when an event of the\r
200 // same group is signalled to inform about the end of the DXE phase.\r
201 // Install the INSTALL_FDT_PROTOCOL protocol.\r
202 //\r
203 Status = gBS->CreateEventEx (\r
204 EVT_NOTIFY_SIGNAL,\r
205 TPL_CALLBACK,\r
206 OnEndOfDxe,\r
207 NULL,\r
208 &gEfiEndOfDxeEventGroupGuid,\r
209 &EndOfDxeEvent\r
210 );\r
211\r
9f38945f
OM
212 // Install dynamic Shell command to run baremetal binaries.\r
213 Status = ShellDynCmdRunAxfInstall (ImageHandle);\r
214 if (EFI_ERROR (Status)) {\r
215 DEBUG ((EFI_D_ERROR, "ArmJunoDxe: Failed to install ShellDynCmdRunAxf\n"));\r
216 }\r
217\r
58a4bff0 218 GetJunoRevision(JunoRevision);\r
c1fee786
RC
219\r
220 //\r
e0ae2761 221 // Try to install the ACPI Tables\r
c1fee786 222 //\r
58a4bff0 223 if (JunoRevision == JUNO_REVISION_R0) {\r
e0ae2761 224 Status = LocateAndInstallAcpiFromFvConditional (&mJunoAcpiTableFile, AcpiTableJunoR0Check);\r
58a4bff0 225 } else if (JunoRevision == JUNO_REVISION_R1) {\r
e0ae2761 226 Status = LocateAndInstallAcpiFromFvConditional (&mJunoAcpiTableFile, AcpiTableJunoR1Check);\r
58a4bff0
JL
227 } else if (JunoRevision == JUNO_REVISION_R2) {\r
228 Status = LocateAndInstallAcpiFromFvConditional (&mJunoAcpiTableFile, AcpiTableJunoR2Check);\r
e0ae2761 229 }\r
e0ae2761 230\r
58a4bff0 231 ASSERT_EFI_ERROR (Status);\r
c1fee786 232\r
e0ae2761 233 //\r
58a4bff0 234 // Setup R1/R2 options if not already done.\r
e0ae2761 235 //\r
58a4bff0 236 if (JunoRevision != JUNO_REVISION_R0) {\r
ad7d95ea
OM
237 // Enable PCI enumeration\r
238 PcdSetBool (PcdPciDisableBusEnumeration, FALSE);\r
e0ae2761
OM
239\r
240 // Declare the related ACPI Tables\r
241 EfiCreateProtocolNotifyEvent (\r
242 &gEfiAcpiTableProtocolGuid,\r
243 TPL_CALLBACK,\r
244 AcpiPciNotificationEvent,\r
245 NULL,\r
246 &mAcpiRegistration\r
247 );\r
7aec2926
RC
248 }\r
249\r
c1fee786
RC
250 //\r
251 // Set up the device path to the FDT.\r
252 //\r
1f40f535 253 TextDevicePath = (CHAR16*)FixedPcdGetPtr (PcdJunoFdtDevicePath);\r
7aec2926
RC
254 if (TextDevicePath != NULL) {\r
255 TextDevicePathSize = StrSize (TextDevicePath);\r
256 Buffer = PcdSetPtr (PcdFdtDevicePaths, &TextDevicePathSize, TextDevicePath);\r
257 Status = (Buffer != NULL) ? EFI_SUCCESS : EFI_BUFFER_TOO_SMALL;\r
258 } else {\r
259 Status = EFI_NOT_FOUND;\r
260 }\r
261\r
05e56470 262 if (EFI_ERROR (Status)) {\r
7aec2926
RC
263 DEBUG (\r
264 (EFI_D_ERROR,\r
265 "ArmJunoDxe: Setting of FDT device path in PcdFdtDevicePaths failed - %r\n", Status)\r
266 );\r
05e56470
OM
267 return Status;\r
268 }\r
21a76332 269\r
c1fee786
RC
270 return Status;\r
271}\r