]> git.proxmox.com Git - mirror_edk2.git/blame - ArmVirtPkg/VirtFdtDxe/VirtFdtDxe.c
ArmVirtPkg/VirtFdtDxe: drop PCI host bridge handling
[mirror_edk2.git] / ArmVirtPkg / VirtFdtDxe / VirtFdtDxe.c
CommitLineData
ad106932
AB
1/** @file\r
2* Device tree enumeration DXE driver for ARM Virtual Machines\r
3*\r
4* Copyright (c) 2014, Linaro Ltd. All rights reserved.<BR>\r
5*\r
6* This program and the accompanying materials are\r
7* licensed and made available under the terms and conditions of the BSD License\r
8* which accompanies this distribution. The full text of the license may be found at\r
9* http://opensource.org/licenses/bsd-license.php\r
10*\r
11* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13*\r
14**/\r
15\r
16#include <Library/BaseLib.h>\r
17#include <Library/DebugLib.h>\r
18#include <Library/UefiLib.h>\r
19#include <Library/BaseMemoryLib.h>\r
20#include <Library/UefiDriverEntryPoint.h>\r
21#include <Library/MemoryAllocationLib.h>\r
22#include <Library/UefiBootServicesTableLib.h>\r
23#include <Library/VirtioMmioDeviceLib.h>\r
24#include <Library/DevicePathLib.h>\r
25#include <Library/PcdLib.h>\r
26#include <Library/DxeServicesLib.h>\r
cc667df0 27#include <Library/HobLib.h>\r
ad106932 28#include <libfdt.h>\r
6abe83c3 29#include <Library/XenIoMmioLib.h>\r
ad106932
AB
30\r
31#include <Guid/Fdt.h>\r
73bb8e68 32#include <Guid/VirtioMmioTransport.h>\r
cc667df0 33#include <Guid/FdtHob.h>\r
ad106932
AB
34\r
35#pragma pack (1)\r
36typedef struct {\r
37 VENDOR_DEVICE_PATH Vendor;\r
38 UINT64 PhysBase;\r
39 EFI_DEVICE_PATH_PROTOCOL End;\r
40} VIRTIO_TRANSPORT_DEVICE_PATH;\r
41#pragma pack ()\r
42\r
43typedef enum {\r
44 PropertyTypeUnknown,\r
ad106932
AB
45 PropertyTypeRtc,\r
46 PropertyTypeVirtio,\r
47 PropertyTypeUart,\r
6abe83c3 48 PropertyTypeXen,\r
ad106932
AB
49} PROPERTY_TYPE;\r
50\r
51typedef struct {\r
52 PROPERTY_TYPE Type;\r
65bb13b0 53 CHAR8 Compatible[32];\r
ad106932
AB
54} PROPERTY;\r
55\r
56STATIC CONST PROPERTY CompatibleProperties[] = {\r
65bb13b0
LE
57 { PropertyTypeRtc, "arm,pl031" },\r
58 { PropertyTypeVirtio, "virtio,mmio" },\r
59 { PropertyTypeUart, "arm,pl011" },\r
6abe83c3 60 { PropertyTypeXen, "xen,xen" },\r
65bb13b0 61 { PropertyTypeUnknown, "" }\r
ad106932
AB
62};\r
63\r
ad106932
AB
64STATIC\r
65PROPERTY_TYPE\r
66GetTypeFromNode (\r
67 IN CONST CHAR8 *NodeType,\r
68 IN UINTN Size\r
69 )\r
70{\r
71 CONST CHAR8 *Compatible;\r
72 CONST PROPERTY *CompatibleProperty;\r
73\r
74 //\r
75 // A 'compatible' node may contain a sequence of NULL terminated\r
76 // compatible strings so check each one\r
77 //\r
78 for (Compatible = NodeType; Compatible < NodeType + Size && *Compatible;\r
79 Compatible += 1 + AsciiStrLen (Compatible)) {\r
80 for (CompatibleProperty = CompatibleProperties; CompatibleProperty->Compatible[0]; CompatibleProperty++) {\r
81 if (AsciiStrCmp (CompatibleProperty->Compatible, Compatible) == 0) {\r
82 return CompatibleProperty->Type;\r
83 }\r
84 }\r
85 }\r
86 return PropertyTypeUnknown;\r
87}\r
88\r
89EFI_STATUS\r
90EFIAPI\r
91InitializeVirtFdtDxe (\r
92 IN EFI_HANDLE ImageHandle,\r
93 IN EFI_SYSTEM_TABLE *SystemTable\r
94 )\r
95{\r
cc667df0 96 VOID *Hob;\r
ad106932
AB
97 VOID *DeviceTreeBase;\r
98 INT32 Node, Prev;\r
99 INT32 RtcNode;\r
100 EFI_STATUS Status;\r
101 CONST CHAR8 *Type;\r
102 INT32 Len;\r
103 PROPERTY_TYPE PropType;\r
104 CONST VOID *RegProp;\r
105 VIRTIO_TRANSPORT_DEVICE_PATH *DevicePath;\r
106 EFI_HANDLE Handle;\r
107 UINT64 RegBase;\r
ad106932 108\r
cc667df0
AB
109 Hob = GetFirstGuidHob(&gFdtHobGuid);\r
110 if (Hob == NULL || GET_GUID_HOB_DATA_SIZE (Hob) != sizeof (UINT64)) {\r
111 return EFI_NOT_FOUND;\r
112 }\r
113 DeviceTreeBase = (VOID *)(UINTN)*(UINT64 *)GET_GUID_HOB_DATA (Hob);\r
ad106932
AB
114\r
115 if (fdt_check_header (DeviceTreeBase) != 0) {\r
116 DEBUG ((EFI_D_ERROR, "%a: No DTB found @ 0x%p\n", __FUNCTION__, DeviceTreeBase));\r
117 return EFI_NOT_FOUND;\r
118 }\r
119\r
ad106932
AB
120 DEBUG ((EFI_D_INFO, "%a: DTB @ 0x%p\n", __FUNCTION__, DeviceTreeBase));\r
121\r
122 RtcNode = -1;\r
123 //\r
124 // Now enumerate the nodes and install peripherals that we are interested in,\r
125 // i.e., GIC, RTC and virtio MMIO nodes\r
126 //\r
127 for (Prev = 0;; Prev = Node) {\r
128 Node = fdt_next_node (DeviceTreeBase, Prev, NULL);\r
129 if (Node < 0) {\r
130 break;\r
131 }\r
132\r
133 Type = fdt_getprop (DeviceTreeBase, Node, "compatible", &Len);\r
134 if (Type == NULL) {\r
135 continue;\r
136 }\r
137\r
138 PropType = GetTypeFromNode (Type, Len);\r
139 if (PropType == PropertyTypeUnknown) {\r
140 continue;\r
141 }\r
142\r
143 //\r
144 // Get the 'reg' property of this node. For now, we will assume\r
145 // 8 byte quantities for base and size, respectively.\r
146 // TODO use #cells root properties instead\r
147 //\r
148 RegProp = fdt_getprop (DeviceTreeBase, Node, "reg", &Len);\r
479d5c41 149 ASSERT (RegProp != NULL);\r
ad106932
AB
150\r
151 switch (PropType) {\r
152 case PropertyTypeVirtio:\r
153 ASSERT (Len == 16);\r
154 //\r
155 // Create a unique device path for this transport on the fly\r
156 //\r
157 RegBase = fdt64_to_cpu (((UINT64 *)RegProp)[0]);\r
158 DevicePath = (VIRTIO_TRANSPORT_DEVICE_PATH *)CreateDeviceNode (\r
159 HARDWARE_DEVICE_PATH,\r
160 HW_VENDOR_DP,\r
161 sizeof (VIRTIO_TRANSPORT_DEVICE_PATH));\r
162 if (DevicePath == NULL) {\r
163 DEBUG ((EFI_D_ERROR, "%a: Out of memory\n", __FUNCTION__));\r
164 break;\r
165 }\r
166\r
73bb8e68
LE
167 CopyMem (&DevicePath->Vendor.Guid, &gVirtioMmioTransportGuid,\r
168 sizeof (EFI_GUID));\r
ad106932
AB
169 DevicePath->PhysBase = RegBase;\r
170 SetDevicePathNodeLength (&DevicePath->Vendor,\r
171 sizeof (*DevicePath) - sizeof (DevicePath->End));\r
172 SetDevicePathEndNode (&DevicePath->End);\r
173\r
174 Handle = NULL;\r
175 Status = gBS->InstallProtocolInterface (&Handle,\r
176 &gEfiDevicePathProtocolGuid, EFI_NATIVE_INTERFACE,\r
177 DevicePath);\r
178 if (EFI_ERROR (Status)) {\r
179 DEBUG ((EFI_D_ERROR, "%a: Failed to install the EFI_DEVICE_PATH "\r
180 "protocol on a new handle (Status == %r)\n",\r
181 __FUNCTION__, Status));\r
182 FreePool (DevicePath);\r
183 break;\r
184 }\r
185\r
186 Status = VirtioMmioInstallDevice (RegBase, Handle);\r
187 if (EFI_ERROR (Status)) {\r
188 DEBUG ((EFI_D_ERROR, "%a: Failed to install VirtIO transport @ 0x%Lx "\r
189 "on handle %p (Status == %r)\n", __FUNCTION__, RegBase,\r
190 Handle, Status));\r
191\r
192 Status = gBS->UninstallProtocolInterface (Handle,\r
193 &gEfiDevicePathProtocolGuid, DevicePath);\r
194 ASSERT_EFI_ERROR (Status);\r
195 FreePool (DevicePath);\r
196 }\r
197 break;\r
198\r
ad106932
AB
199 case PropertyTypeRtc:\r
200 ASSERT (Len == 16);\r
201\r
202 RegBase = fdt64_to_cpu (((UINT64 *)RegProp)[0]);\r
203 ASSERT (RegBase < MAX_UINT32);\r
204\r
205 PcdSet32 (PcdPL031RtcBase, (UINT32)RegBase);\r
206\r
207 DEBUG ((EFI_D_INFO, "Found PL031 RTC @ 0x%Lx\n", RegBase));\r
208 RtcNode = Node;\r
209 break;\r
210\r
6abe83c3
AB
211 case PropertyTypeXen:\r
212 ASSERT (Len == 16);\r
213\r
214 //\r
215 // Retrieve the reg base from this node and wire it up to the\r
216 // MMIO flavor of the XenBus root device I/O protocol\r
217 //\r
218 RegBase = fdt64_to_cpu (((UINT64 *)RegProp)[0]);\r
219 Handle = NULL;\r
220 Status = XenIoMmioInstall (&Handle, RegBase);\r
221 if (EFI_ERROR (Status)) {\r
222 DEBUG ((EFI_D_ERROR, "%a: XenIoMmioInstall () failed on a new handle "\r
223 "(Status == %r)\n", __FUNCTION__, Status));\r
224 break;\r
225 }\r
226\r
227 DEBUG ((EFI_D_INFO, "Found Xen node with Grant table @ 0x%Lx\n", RegBase));\r
228\r
229 break;\r
230\r
ad106932
AB
231 default:\r
232 break;\r
233 }\r
234 }\r
235\r
7a63d291
AB
236 if (!FeaturePcdGet (PcdPureAcpiBoot)) {\r
237 //\r
238 // Only install the FDT as a configuration table if we want to leave it up\r
239 // to the OS to decide whether it prefers ACPI over DT.\r
8b816c62 240 //\r
7a63d291
AB
241 Status = gBS->InstallConfigurationTable (&gFdtTableGuid, DeviceTreeBase);\r
242 ASSERT_EFI_ERROR (Status);\r
243\r
8b816c62 244 //\r
7a63d291
AB
245 // UEFI takes ownership of the RTC hardware, and exposes its functionality\r
246 // through the UEFI Runtime Services GetTime, SetTime, etc. This means we\r
247 // need to disable it in the device tree to prevent the OS from attaching its\r
248 // device driver as well.\r
8b816c62 249 //\r
7a63d291
AB
250 if ((RtcNode != -1) &&\r
251 fdt_setprop_string (DeviceTreeBase, RtcNode, "status",\r
252 "disabled") != 0) {\r
253 DEBUG ((EFI_D_WARN, "Failed to set PL031 status to 'disabled'\n"));\r
8b816c62 254 }\r
8b816c62 255 }\r
ad106932
AB
256 return EFI_SUCCESS;\r
257}\r