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