ArmVirtPkg/FdtClientDxe: supplement missing EFIAPI calling conv specifiers
[mirror_edk2.git] / ArmVirtPkg / FdtClientDxe / FdtClientDxe.c
CommitLineData
30740795
AB
1/** @file\r
2* FDT client driver\r
3*\r
4* Copyright (c) 2016, 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/UefiDriverEntryPoint.h>\r
19#include <Library/UefiBootServicesTableLib.h>\r
20#include <Library/HobLib.h>\r
21#include <libfdt.h>\r
22\r
1e7143d8 23#include <Guid/Fdt.h>\r
30740795
AB
24#include <Guid/FdtHob.h>\r
25\r
26#include <Protocol/FdtClient.h>\r
27\r
28STATIC VOID *mDeviceTreeBase;\r
29\r
30STATIC\r
31EFI_STATUS\r
eec1ba7d 32EFIAPI\r
30740795
AB
33GetNodeProperty (\r
34 IN FDT_CLIENT_PROTOCOL *This,\r
35 IN INT32 Node,\r
36 IN CONST CHAR8 *PropertyName,\r
37 OUT CONST VOID **Prop,\r
38 OUT UINT32 *PropSize OPTIONAL\r
39 )\r
40{\r
41 INT32 Len;\r
42\r
43 ASSERT (mDeviceTreeBase != NULL);\r
44 ASSERT (Prop != NULL);\r
45\r
46 *Prop = fdt_getprop (mDeviceTreeBase, Node, PropertyName, &Len);\r
47 if (*Prop == NULL) {\r
48 return EFI_NOT_FOUND;\r
49 }\r
50\r
51 if (PropSize != NULL) {\r
52 *PropSize = Len;\r
53 }\r
54 return EFI_SUCCESS;\r
55}\r
56\r
57STATIC\r
58EFI_STATUS\r
eec1ba7d 59EFIAPI\r
30740795
AB
60SetNodeProperty (\r
61 IN FDT_CLIENT_PROTOCOL *This,\r
62 IN INT32 Node,\r
63 IN CONST CHAR8 *PropertyName,\r
64 IN CONST VOID *Prop,\r
65 IN UINT32 PropSize\r
66 )\r
67{\r
68 INT32 Ret;\r
69\r
70 ASSERT (mDeviceTreeBase != NULL);\r
71\r
72 Ret = fdt_setprop (mDeviceTreeBase, Node, PropertyName, Prop, PropSize);\r
73 if (Ret != 0) {\r
74 return EFI_DEVICE_ERROR;\r
75 }\r
76\r
77 return EFI_SUCCESS;\r
78}\r
79\r
80STATIC\r
81EFI_STATUS\r
82EFIAPI\r
83FindNextCompatibleNode (\r
84 IN FDT_CLIENT_PROTOCOL *This,\r
85 IN CONST CHAR8 *CompatibleString,\r
86 IN INT32 PrevNode,\r
87 OUT INT32 *Node\r
88 )\r
89{\r
90 INT32 Prev, Next;\r
91 CONST CHAR8 *Type, *Compatible;\r
92 INT32 Len;\r
93\r
94 ASSERT (mDeviceTreeBase != NULL);\r
95 ASSERT (Node != NULL);\r
96\r
97 for (Prev = PrevNode;; Prev = Next) {\r
98 Next = fdt_next_node (mDeviceTreeBase, Prev, NULL);\r
99 if (Next < 0) {\r
100 break;\r
101 }\r
102\r
103 Type = fdt_getprop (mDeviceTreeBase, Next, "compatible", &Len);\r
104 if (Type == NULL) {\r
105 continue;\r
106 }\r
107\r
108 //\r
109 // A 'compatible' node may contain a sequence of NUL terminated\r
110 // compatible strings so check each one\r
111 //\r
112 for (Compatible = Type; Compatible < Type + Len && *Compatible;\r
113 Compatible += 1 + AsciiStrLen (Compatible)) {\r
114 if (AsciiStrCmp (CompatibleString, Compatible) == 0) {\r
115 *Node = Next;\r
116 return EFI_SUCCESS;\r
117 }\r
118 }\r
119 }\r
120 return EFI_NOT_FOUND;\r
121}\r
122\r
123STATIC\r
124EFI_STATUS\r
125EFIAPI\r
126FindCompatibleNode (\r
127 IN FDT_CLIENT_PROTOCOL *This,\r
128 IN CONST CHAR8 *CompatibleString,\r
129 OUT INT32 *Node\r
130 )\r
131{\r
132 return FindNextCompatibleNode (This, CompatibleString, 0, Node);\r
133}\r
134\r
135STATIC\r
136EFI_STATUS\r
137EFIAPI\r
138FindCompatibleNodeProperty (\r
139 IN FDT_CLIENT_PROTOCOL *This,\r
140 IN CONST CHAR8 *CompatibleString,\r
141 IN CONST CHAR8 *PropertyName,\r
142 OUT CONST VOID **Prop,\r
143 OUT UINT32 *PropSize OPTIONAL\r
144 )\r
145{\r
146 EFI_STATUS Status;\r
147 INT32 Node;\r
148\r
149 Status = FindCompatibleNode (This, CompatibleString, &Node);\r
150 if (EFI_ERROR (Status)) {\r
151 return Status;\r
152 }\r
153\r
154 return GetNodeProperty (This, Node, PropertyName, Prop, PropSize);\r
155}\r
156\r
157STATIC\r
158EFI_STATUS\r
159EFIAPI\r
160FindCompatibleNodeReg (\r
161 IN FDT_CLIENT_PROTOCOL *This,\r
162 IN CONST CHAR8 *CompatibleString,\r
163 OUT CONST VOID **Reg,\r
cfc8d51c
AB
164 OUT UINTN *AddressCells,\r
165 OUT UINTN *SizeCells,\r
30740795
AB
166 OUT UINT32 *RegSize\r
167 )\r
168{\r
169 EFI_STATUS Status;\r
170\r
171 ASSERT (RegSize != NULL);\r
172\r
173 //\r
174 // Get the 'reg' property of this node. For now, we will assume\r
175 // 8 byte quantities for base and size, respectively.\r
176 // TODO use #cells root properties instead\r
177 //\r
178 Status = FindCompatibleNodeProperty (This, CompatibleString, "reg", Reg,\r
179 RegSize);\r
180 if (EFI_ERROR (Status)) {\r
181 return Status;\r
182 }\r
183\r
38ed4a9e 184 if ((*RegSize % 16) != 0) {\r
30740795
AB
185 DEBUG ((EFI_D_ERROR,\r
186 "%a: '%a' compatible node has invalid 'reg' property (size == 0x%x)\n",\r
187 __FUNCTION__, CompatibleString, *RegSize));\r
188 return EFI_NOT_FOUND;\r
189 }\r
190\r
cfc8d51c
AB
191 *AddressCells = 2;\r
192 *SizeCells = 2;\r
30740795
AB
193\r
194 return EFI_SUCCESS;\r
195}\r
196\r
969d2eb3
AB
197STATIC\r
198EFI_STATUS\r
199EFIAPI\r
200FindNextMemoryNodeReg (\r
201 IN FDT_CLIENT_PROTOCOL *This,\r
202 IN INT32 PrevNode,\r
203 OUT INT32 *Node,\r
204 OUT CONST VOID **Reg,\r
205 OUT UINTN *AddressCells,\r
206 OUT UINTN *SizeCells,\r
207 OUT UINT32 *RegSize\r
208 )\r
209{\r
210 INT32 Prev, Next;\r
211 CONST CHAR8 *DeviceType;\r
212 INT32 Len;\r
213 EFI_STATUS Status;\r
214\r
215 ASSERT (mDeviceTreeBase != NULL);\r
216 ASSERT (Node != NULL);\r
217\r
218 for (Prev = PrevNode;; Prev = Next) {\r
219 Next = fdt_next_node (mDeviceTreeBase, Prev, NULL);\r
220 if (Next < 0) {\r
221 break;\r
222 }\r
223\r
224 DeviceType = fdt_getprop (mDeviceTreeBase, Next, "device_type", &Len);\r
225 if (DeviceType != NULL && AsciiStrCmp (DeviceType, "memory") == 0) {\r
226 //\r
227 // Get the 'reg' property of this memory node. For now, we will assume\r
228 // 8 byte quantities for base and size, respectively.\r
229 // TODO use #cells root properties instead\r
230 //\r
231 Status = GetNodeProperty (This, Next, "reg", Reg, RegSize);\r
232 if (EFI_ERROR (Status)) {\r
233 DEBUG ((EFI_D_WARN,\r
234 "%a: ignoring memory node with no 'reg' property\n",\r
235 __FUNCTION__));\r
236 continue;\r
237 }\r
238 if ((*RegSize % 16) != 0) {\r
239 DEBUG ((EFI_D_WARN,\r
240 "%a: ignoring memory node with invalid 'reg' property (size == 0x%x)\n",\r
241 __FUNCTION__, *RegSize));\r
242 continue;\r
243 }\r
244\r
245 *Node = Next;\r
246 *AddressCells = 2;\r
247 *SizeCells = 2;\r
248 return EFI_SUCCESS;\r
249 }\r
250 }\r
251 return EFI_NOT_FOUND;\r
252}\r
253\r
254STATIC\r
255EFI_STATUS\r
256EFIAPI\r
257FindMemoryNodeReg (\r
258 IN FDT_CLIENT_PROTOCOL *This,\r
259 OUT INT32 *Node,\r
260 OUT CONST VOID **Reg,\r
261 OUT UINTN *AddressCells,\r
262 OUT UINTN *SizeCells,\r
263 OUT UINT32 *RegSize\r
264 )\r
265{\r
266 return FindNextMemoryNodeReg (This, 0, Node, Reg, AddressCells, SizeCells,\r
267 RegSize);\r
268}\r
269\r
30740795
AB
270STATIC\r
271EFI_STATUS\r
eec1ba7d 272EFIAPI\r
30740795
AB
273GetOrInsertChosenNode (\r
274 IN FDT_CLIENT_PROTOCOL *This,\r
275 OUT INT32 *Node\r
276 )\r
277{\r
278 INT32 NewNode;\r
279\r
280 ASSERT (mDeviceTreeBase != NULL);\r
281 ASSERT (Node != NULL);\r
282\r
283 NewNode = fdt_path_offset (mDeviceTreeBase, "/chosen");\r
284 if (NewNode < 0) {\r
285 NewNode = fdt_add_subnode (mDeviceTreeBase, 0, "/chosen");\r
286 }\r
287\r
288 if (NewNode < 0) {\r
289 return EFI_OUT_OF_RESOURCES;\r
290 }\r
291\r
292 *Node = NewNode;\r
293\r
294 return EFI_SUCCESS;\r
295}\r
296\r
297STATIC FDT_CLIENT_PROTOCOL mFdtClientProtocol = {\r
298 GetNodeProperty,\r
299 SetNodeProperty,\r
300 FindCompatibleNode,\r
301 FindNextCompatibleNode,\r
302 FindCompatibleNodeProperty,\r
303 FindCompatibleNodeReg,\r
969d2eb3
AB
304 FindMemoryNodeReg,\r
305 FindNextMemoryNodeReg,\r
30740795
AB
306 GetOrInsertChosenNode,\r
307};\r
308\r
309EFI_STATUS\r
310EFIAPI\r
311InitializeFdtClientDxe (\r
312 IN EFI_HANDLE ImageHandle,\r
313 IN EFI_SYSTEM_TABLE *SystemTable\r
314 )\r
315{\r
316 VOID *Hob;\r
317 VOID *DeviceTreeBase;\r
1e7143d8 318 EFI_STATUS Status;\r
30740795
AB
319\r
320 Hob = GetFirstGuidHob (&gFdtHobGuid);\r
321 if (Hob == NULL || GET_GUID_HOB_DATA_SIZE (Hob) != sizeof (UINT64)) {\r
322 return EFI_NOT_FOUND;\r
323 }\r
324 DeviceTreeBase = (VOID *)(UINTN)*(UINT64 *)GET_GUID_HOB_DATA (Hob);\r
325\r
326 if (fdt_check_header (DeviceTreeBase) != 0) {\r
327 DEBUG ((EFI_D_ERROR, "%a: No DTB found @ 0x%p\n", __FUNCTION__,\r
328 DeviceTreeBase));\r
329 return EFI_NOT_FOUND;\r
330 }\r
331\r
332 mDeviceTreeBase = DeviceTreeBase;\r
333\r
334 DEBUG ((EFI_D_INFO, "%a: DTB @ 0x%p\n", __FUNCTION__, mDeviceTreeBase));\r
335\r
1e7143d8
AB
336 if (!FeaturePcdGet (PcdPureAcpiBoot)) {\r
337 //\r
338 // Only install the FDT as a configuration table if we want to leave it up\r
339 // to the OS to decide whether it prefers ACPI over DT.\r
340 //\r
341 Status = gBS->InstallConfigurationTable (&gFdtTableGuid, DeviceTreeBase);\r
342 ASSERT_EFI_ERROR (Status);\r
343 }\r
344\r
30740795
AB
345 return gBS->InstallProtocolInterface (&ImageHandle, &gFdtClientProtocolGuid,\r
346 EFI_NATIVE_INTERFACE, &mFdtClientProtocol);\r
347}\r