]> git.proxmox.com Git - mirror_edk2.git/blame - ArmVirtPkg/VirtFdtDxe/VirtFdtDxe.c
ArmVirtPkg/VirtFdtDxe: move FDT config table installation to FdtClientDxe
[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 30\r
73bb8e68 31#include <Guid/VirtioMmioTransport.h>\r
cc667df0 32#include <Guid/FdtHob.h>\r
ad106932
AB
33\r
34#pragma pack (1)\r
35typedef struct {\r
36 VENDOR_DEVICE_PATH Vendor;\r
37 UINT64 PhysBase;\r
38 EFI_DEVICE_PATH_PROTOCOL End;\r
39} VIRTIO_TRANSPORT_DEVICE_PATH;\r
40#pragma pack ()\r
41\r
42typedef enum {\r
43 PropertyTypeUnknown,\r
ad106932 44 PropertyTypeVirtio,\r
6abe83c3 45 PropertyTypeXen,\r
ad106932
AB
46} PROPERTY_TYPE;\r
47\r
48typedef struct {\r
49 PROPERTY_TYPE Type;\r
65bb13b0 50 CHAR8 Compatible[32];\r
ad106932
AB
51} PROPERTY;\r
52\r
53STATIC CONST PROPERTY CompatibleProperties[] = {\r
65bb13b0 54 { PropertyTypeVirtio, "virtio,mmio" },\r
6abe83c3 55 { PropertyTypeXen, "xen,xen" },\r
65bb13b0 56 { PropertyTypeUnknown, "" }\r
ad106932
AB
57};\r
58\r
ad106932
AB
59STATIC\r
60PROPERTY_TYPE\r
61GetTypeFromNode (\r
62 IN CONST CHAR8 *NodeType,\r
63 IN UINTN Size\r
64 )\r
65{\r
66 CONST CHAR8 *Compatible;\r
67 CONST PROPERTY *CompatibleProperty;\r
68\r
69 //\r
70 // A 'compatible' node may contain a sequence of NULL terminated\r
71 // compatible strings so check each one\r
72 //\r
73 for (Compatible = NodeType; Compatible < NodeType + Size && *Compatible;\r
74 Compatible += 1 + AsciiStrLen (Compatible)) {\r
75 for (CompatibleProperty = CompatibleProperties; CompatibleProperty->Compatible[0]; CompatibleProperty++) {\r
76 if (AsciiStrCmp (CompatibleProperty->Compatible, Compatible) == 0) {\r
77 return CompatibleProperty->Type;\r
78 }\r
79 }\r
80 }\r
81 return PropertyTypeUnknown;\r
82}\r
83\r
84EFI_STATUS\r
85EFIAPI\r
86InitializeVirtFdtDxe (\r
87 IN EFI_HANDLE ImageHandle,\r
88 IN EFI_SYSTEM_TABLE *SystemTable\r
89 )\r
90{\r
cc667df0 91 VOID *Hob;\r
ad106932
AB
92 VOID *DeviceTreeBase;\r
93 INT32 Node, Prev;\r
ad106932
AB
94 EFI_STATUS Status;\r
95 CONST CHAR8 *Type;\r
96 INT32 Len;\r
97 PROPERTY_TYPE PropType;\r
98 CONST VOID *RegProp;\r
99 VIRTIO_TRANSPORT_DEVICE_PATH *DevicePath;\r
100 EFI_HANDLE Handle;\r
101 UINT64 RegBase;\r
ad106932 102\r
cc667df0
AB
103 Hob = GetFirstGuidHob(&gFdtHobGuid);\r
104 if (Hob == NULL || GET_GUID_HOB_DATA_SIZE (Hob) != sizeof (UINT64)) {\r
105 return EFI_NOT_FOUND;\r
106 }\r
107 DeviceTreeBase = (VOID *)(UINTN)*(UINT64 *)GET_GUID_HOB_DATA (Hob);\r
ad106932
AB
108\r
109 if (fdt_check_header (DeviceTreeBase) != 0) {\r
110 DEBUG ((EFI_D_ERROR, "%a: No DTB found @ 0x%p\n", __FUNCTION__, DeviceTreeBase));\r
111 return EFI_NOT_FOUND;\r
112 }\r
113\r
ad106932
AB
114 DEBUG ((EFI_D_INFO, "%a: DTB @ 0x%p\n", __FUNCTION__, DeviceTreeBase));\r
115\r
ad106932
AB
116 //\r
117 // Now enumerate the nodes and install peripherals that we are interested in,\r
118 // i.e., GIC, RTC and virtio MMIO nodes\r
119 //\r
120 for (Prev = 0;; Prev = Node) {\r
121 Node = fdt_next_node (DeviceTreeBase, Prev, NULL);\r
122 if (Node < 0) {\r
123 break;\r
124 }\r
125\r
126 Type = fdt_getprop (DeviceTreeBase, Node, "compatible", &Len);\r
127 if (Type == NULL) {\r
128 continue;\r
129 }\r
130\r
131 PropType = GetTypeFromNode (Type, Len);\r
132 if (PropType == PropertyTypeUnknown) {\r
133 continue;\r
134 }\r
135\r
136 //\r
137 // Get the 'reg' property of this node. For now, we will assume\r
138 // 8 byte quantities for base and size, respectively.\r
139 // TODO use #cells root properties instead\r
140 //\r
141 RegProp = fdt_getprop (DeviceTreeBase, Node, "reg", &Len);\r
479d5c41 142 ASSERT (RegProp != NULL);\r
ad106932
AB
143\r
144 switch (PropType) {\r
145 case PropertyTypeVirtio:\r
146 ASSERT (Len == 16);\r
147 //\r
148 // Create a unique device path for this transport on the fly\r
149 //\r
150 RegBase = fdt64_to_cpu (((UINT64 *)RegProp)[0]);\r
151 DevicePath = (VIRTIO_TRANSPORT_DEVICE_PATH *)CreateDeviceNode (\r
152 HARDWARE_DEVICE_PATH,\r
153 HW_VENDOR_DP,\r
154 sizeof (VIRTIO_TRANSPORT_DEVICE_PATH));\r
155 if (DevicePath == NULL) {\r
156 DEBUG ((EFI_D_ERROR, "%a: Out of memory\n", __FUNCTION__));\r
157 break;\r
158 }\r
159\r
73bb8e68
LE
160 CopyMem (&DevicePath->Vendor.Guid, &gVirtioMmioTransportGuid,\r
161 sizeof (EFI_GUID));\r
ad106932
AB
162 DevicePath->PhysBase = RegBase;\r
163 SetDevicePathNodeLength (&DevicePath->Vendor,\r
164 sizeof (*DevicePath) - sizeof (DevicePath->End));\r
165 SetDevicePathEndNode (&DevicePath->End);\r
166\r
167 Handle = NULL;\r
168 Status = gBS->InstallProtocolInterface (&Handle,\r
169 &gEfiDevicePathProtocolGuid, EFI_NATIVE_INTERFACE,\r
170 DevicePath);\r
171 if (EFI_ERROR (Status)) {\r
172 DEBUG ((EFI_D_ERROR, "%a: Failed to install the EFI_DEVICE_PATH "\r
173 "protocol on a new handle (Status == %r)\n",\r
174 __FUNCTION__, Status));\r
175 FreePool (DevicePath);\r
176 break;\r
177 }\r
178\r
179 Status = VirtioMmioInstallDevice (RegBase, Handle);\r
180 if (EFI_ERROR (Status)) {\r
181 DEBUG ((EFI_D_ERROR, "%a: Failed to install VirtIO transport @ 0x%Lx "\r
182 "on handle %p (Status == %r)\n", __FUNCTION__, RegBase,\r
183 Handle, Status));\r
184\r
185 Status = gBS->UninstallProtocolInterface (Handle,\r
186 &gEfiDevicePathProtocolGuid, DevicePath);\r
187 ASSERT_EFI_ERROR (Status);\r
188 FreePool (DevicePath);\r
189 }\r
190 break;\r
191\r
6abe83c3
AB
192 case PropertyTypeXen:\r
193 ASSERT (Len == 16);\r
194\r
195 //\r
196 // Retrieve the reg base from this node and wire it up to the\r
197 // MMIO flavor of the XenBus root device I/O protocol\r
198 //\r
199 RegBase = fdt64_to_cpu (((UINT64 *)RegProp)[0]);\r
200 Handle = NULL;\r
201 Status = XenIoMmioInstall (&Handle, RegBase);\r
202 if (EFI_ERROR (Status)) {\r
203 DEBUG ((EFI_D_ERROR, "%a: XenIoMmioInstall () failed on a new handle "\r
204 "(Status == %r)\n", __FUNCTION__, Status));\r
205 break;\r
206 }\r
207\r
208 DEBUG ((EFI_D_INFO, "Found Xen node with Grant table @ 0x%Lx\n", RegBase));\r
209\r
210 break;\r
211\r
ad106932
AB
212 default:\r
213 break;\r
214 }\r
215 }\r
216\r
ad106932
AB
217 return EFI_SUCCESS;\r
218}\r