4 * Copyright (c) 2016, Linaro Ltd. All rights reserved.<BR>
6 * This program and the accompanying materials are
7 * licensed and made available under the terms and conditions of the BSD License
8 * which accompanies this distribution. The full text of the license may be found at
9 * http://opensource.org/licenses/bsd-license.php
11 * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 #include <Library/BaseLib.h>
17 #include <Library/DebugLib.h>
18 #include <Library/UefiDriverEntryPoint.h>
19 #include <Library/UefiBootServicesTableLib.h>
20 #include <Library/HobLib.h>
23 #include <Guid/FdtHob.h>
25 #include <Protocol/FdtClient.h>
27 STATIC VOID
*mDeviceTreeBase
;
32 IN FDT_CLIENT_PROTOCOL
*This
,
34 IN CONST CHAR8
*PropertyName
,
35 OUT CONST VOID
**Prop
,
36 OUT UINT32
*PropSize OPTIONAL
41 ASSERT (mDeviceTreeBase
!= NULL
);
42 ASSERT (Prop
!= NULL
);
44 *Prop
= fdt_getprop (mDeviceTreeBase
, Node
, PropertyName
, &Len
);
49 if (PropSize
!= NULL
) {
58 IN FDT_CLIENT_PROTOCOL
*This
,
60 IN CONST CHAR8
*PropertyName
,
67 ASSERT (mDeviceTreeBase
!= NULL
);
69 Ret
= fdt_setprop (mDeviceTreeBase
, Node
, PropertyName
, Prop
, PropSize
);
71 return EFI_DEVICE_ERROR
;
80 FindNextCompatibleNode (
81 IN FDT_CLIENT_PROTOCOL
*This
,
82 IN CONST CHAR8
*CompatibleString
,
88 CONST CHAR8
*Type
, *Compatible
;
91 ASSERT (mDeviceTreeBase
!= NULL
);
92 ASSERT (Node
!= NULL
);
94 for (Prev
= PrevNode
;; Prev
= Next
) {
95 Next
= fdt_next_node (mDeviceTreeBase
, Prev
, NULL
);
100 Type
= fdt_getprop (mDeviceTreeBase
, Next
, "compatible", &Len
);
106 // A 'compatible' node may contain a sequence of NUL terminated
107 // compatible strings so check each one
109 for (Compatible
= Type
; Compatible
< Type
+ Len
&& *Compatible
;
110 Compatible
+= 1 + AsciiStrLen (Compatible
)) {
111 if (AsciiStrCmp (CompatibleString
, Compatible
) == 0) {
117 return EFI_NOT_FOUND
;
124 IN FDT_CLIENT_PROTOCOL
*This
,
125 IN CONST CHAR8
*CompatibleString
,
129 return FindNextCompatibleNode (This
, CompatibleString
, 0, Node
);
135 FindCompatibleNodeProperty (
136 IN FDT_CLIENT_PROTOCOL
*This
,
137 IN CONST CHAR8
*CompatibleString
,
138 IN CONST CHAR8
*PropertyName
,
139 OUT CONST VOID
**Prop
,
140 OUT UINT32
*PropSize OPTIONAL
146 Status
= FindCompatibleNode (This
, CompatibleString
, &Node
);
147 if (EFI_ERROR (Status
)) {
151 return GetNodeProperty (This
, Node
, PropertyName
, Prop
, PropSize
);
157 FindCompatibleNodeReg (
158 IN FDT_CLIENT_PROTOCOL
*This
,
159 IN CONST CHAR8
*CompatibleString
,
160 OUT CONST VOID
**Reg
,
161 OUT UINT32
*RegElemSize
,
167 ASSERT (RegSize
!= NULL
);
170 // Get the 'reg' property of this node. For now, we will assume
171 // 8 byte quantities for base and size, respectively.
172 // TODO use #cells root properties instead
174 Status
= FindCompatibleNodeProperty (This
, CompatibleString
, "reg", Reg
,
176 if (EFI_ERROR (Status
)) {
180 if ((*RegSize
% 8) != 0) {
182 "%a: '%a' compatible node has invalid 'reg' property (size == 0x%x)\n",
183 __FUNCTION__
, CompatibleString
, *RegSize
));
184 return EFI_NOT_FOUND
;
194 GetOrInsertChosenNode (
195 IN FDT_CLIENT_PROTOCOL
*This
,
201 ASSERT (mDeviceTreeBase
!= NULL
);
202 ASSERT (Node
!= NULL
);
204 NewNode
= fdt_path_offset (mDeviceTreeBase
, "/chosen");
206 NewNode
= fdt_add_subnode (mDeviceTreeBase
, 0, "/chosen");
210 return EFI_OUT_OF_RESOURCES
;
218 STATIC FDT_CLIENT_PROTOCOL mFdtClientProtocol
= {
222 FindNextCompatibleNode
,
223 FindCompatibleNodeProperty
,
224 FindCompatibleNodeReg
,
225 GetOrInsertChosenNode
,
230 InitializeFdtClientDxe (
231 IN EFI_HANDLE ImageHandle
,
232 IN EFI_SYSTEM_TABLE
*SystemTable
236 VOID
*DeviceTreeBase
;
238 Hob
= GetFirstGuidHob (&gFdtHobGuid
);
239 if (Hob
== NULL
|| GET_GUID_HOB_DATA_SIZE (Hob
) != sizeof (UINT64
)) {
240 return EFI_NOT_FOUND
;
242 DeviceTreeBase
= (VOID
*)(UINTN
)*(UINT64
*)GET_GUID_HOB_DATA (Hob
);
244 if (fdt_check_header (DeviceTreeBase
) != 0) {
245 DEBUG ((EFI_D_ERROR
, "%a: No DTB found @ 0x%p\n", __FUNCTION__
,
247 return EFI_NOT_FOUND
;
250 mDeviceTreeBase
= DeviceTreeBase
;
252 DEBUG ((EFI_D_INFO
, "%a: DTB @ 0x%p\n", __FUNCTION__
, mDeviceTreeBase
));
254 return gBS
->InstallProtocolInterface (&ImageHandle
, &gFdtClientProtocolGuid
,
255 EFI_NATIVE_INTERFACE
, &mFdtClientProtocol
);