VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/FdtHwInfoParserLib/FdtUtility.c

最後變更 在這個檔案是 99404,由 vboxsync 提交於 2 年 前

Devices/EFI/FirmwareNew: Update to edk2-stable202302 and make it build, bugref:4643

  • 屬性 svn:eol-style 設為 native
檔案大小: 27.6 KB
 
1/** @file
2 Flattened device tree utility.
3
4 Copyright (c) 2021, ARM Limited. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6
7 @par Reference(s):
8 - Device tree Specification - Release v0.3
9 - linux/Documentation/devicetree/bindings/interrupt-controller/arm%2Cgic.yaml
10 - linux//Documentation/devicetree/bindings/interrupt-controller/arm%2Cgic.yaml
11**/
12
13#include <FdtHwInfoParserInclude.h>
14#include "FdtUtility.h"
15
16/** Get the interrupt Id of an interrupt described in a fdt.
17
18 Data must describe a GIC interrupt. A GIC interrupt is on at least
19 3 UINT32 cells.
20 This function DOES NOT SUPPORT extended SPI range and extended PPI range.
21
22 @param [in] Data Pointer to the first cell of an "interrupts" property.
23
24 @retval The interrupt id.
25**/
26UINT32
27EFIAPI
28FdtGetInterruptId (
29 UINT32 CONST *Data
30 )
31{
32 UINT32 IrqType;
33 UINT32 IrqId;
34
35 ASSERT (Data != NULL);
36
37 IrqType = fdt32_to_cpu (Data[IRQ_TYPE_OFFSET]);
38 IrqId = fdt32_to_cpu (Data[IRQ_NUMBER_OFFSET]);
39
40 switch (IrqType) {
41 case DT_SPI_IRQ:
42 IrqId += SPI_OFFSET;
43 break;
44
45 case DT_PPI_IRQ:
46 IrqId += PPI_OFFSET;
47 break;
48
49 default:
50 ASSERT (0);
51 IrqId = 0;
52 }
53
54 return IrqId;
55}
56
57/** Get the ACPI interrupt flags of an interrupt described in a fdt.
58
59 Data must describe a GIC interrupt. A GIC interrupt is on at least
60 3 UINT32 cells.
61
62 PPI interrupt cpu mask on bits [15:8] are ignored.
63
64 @param [in] Data Pointer to the first cell of an "interrupts" property.
65
66 @retval The interrupt flags (for ACPI).
67**/
68UINT32
69EFIAPI
70FdtGetInterruptFlags (
71 UINT32 CONST *Data
72 )
73{
74 UINT32 IrqFlags;
75 UINT32 AcpiIrqFlags;
76
77 ASSERT (Data != NULL);
78
79 IrqFlags = fdt32_to_cpu (Data[IRQ_FLAGS_OFFSET]);
80
81 AcpiIrqFlags = DT_IRQ_IS_EDGE_TRIGGERED (IrqFlags) ? BIT0 : 0;
82 AcpiIrqFlags |= DT_IRQ_IS_ACTIVE_LOW (IrqFlags) ? BIT1 : 0;
83
84 return AcpiIrqFlags;
85}
86
87/** Check whether a node has the input name.
88
89 @param [in] Fdt Pointer to a Flattened Device Tree.
90 @param [in] Node Offset of the node to check the name.
91 @param [in] SearchName Node name to search.
92 This is a NULL terminated string.
93
94 @retval True The node has the input name.
95 @retval FALSE Otherwise, or error.
96**/
97STATIC
98BOOLEAN
99EFIAPI
100FdtNodeHasName (
101 IN CONST VOID *Fdt,
102 IN INT32 Node,
103 IN CONST VOID *SearchName
104 )
105{
106 CONST CHAR8 *NodeName;
107 UINT32 Length;
108
109 if ((Fdt == NULL) ||
110 (SearchName == NULL))
111 {
112 ASSERT (0);
113 return FALSE;
114 }
115
116 // Always compare the whole string. Don't stop at the "@" char.
117 Length = (UINT32)AsciiStrLen (SearchName);
118
119 // Get the address of the node name.
120 NodeName = fdt_offset_ptr (Fdt, Node + FDT_TAGSIZE, Length + 1);
121 if (NodeName == NULL) {
122 return FALSE;
123 }
124
125 // SearchName must be longer than the node name.
126 if (Length > AsciiStrLen (NodeName)) {
127 return FALSE;
128 }
129
130 if (AsciiStrnCmp (NodeName, SearchName, Length) != 0) {
131 return FALSE;
132 }
133
134 // The name matches perfectly, or
135 // the node name is XXX@addr and the XXX matches.
136 if ((NodeName[Length] == '\0') ||
137 (NodeName[Length] == '@'))
138 {
139 return TRUE;
140 }
141
142 return FALSE;
143}
144
145/** Iterate through the list of strings in the Context,
146 and check whether at least one string is matching the
147 "compatible" property of the node.
148
149 @param [in] Fdt Pointer to a Flattened Device Tree.
150 @param [in] Node Offset of the node to operate the check on.
151 @param [in] CompatInfo COMPATIBILITY_INFO containing the list of compatible
152 strings to compare with the "compatible" property
153 of the node.
154
155 @retval TRUE At least one string matched, the node is compatible.
156 @retval FALSE Otherwise, or error.
157**/
158BOOLEAN
159EFIAPI
160FdtNodeIsCompatible (
161 IN CONST VOID *Fdt,
162 IN INT32 Node,
163 IN CONST VOID *CompatInfo
164 )
165{
166 UINT32 Index;
167 CONST COMPATIBILITY_STR *CompatibleTable;
168 UINT32 Count;
169 CONST VOID *Prop;
170 INT32 PropLen;
171
172 if ((Fdt == NULL) ||
173 (CompatInfo == NULL))
174 {
175 ASSERT (0);
176 return FALSE;
177 }
178
179 Count = ((COMPATIBILITY_INFO *)CompatInfo)->Count;
180 CompatibleTable = ((COMPATIBILITY_INFO *)CompatInfo)->CompatTable;
181
182 // Get the "compatible" property.
183 Prop = fdt_getprop (Fdt, Node, "compatible", &PropLen);
184 if ((Prop == NULL) || (PropLen < 0)) {
185 return FALSE;
186 }
187
188 for (Index = 0; Index < Count; Index++) {
189 if (fdt_stringlist_contains (
190 Prop,
191 PropLen,
192 CompatibleTable[Index].CompatStr
193 ))
194 {
195 return TRUE;
196 }
197 } // for
198
199 return FALSE;
200}
201
202/** Check whether a node has a property.
203
204 @param [in] Fdt Pointer to a Flattened Device Tree.
205 @param [in] Node Offset of the node to operate the check on.
206 @param [in] PropertyName Name of the property to search.
207 This is a NULL terminated string.
208
209 @retval True The node has the property.
210 @retval FALSE Otherwise, or error.
211**/
212BOOLEAN
213EFIAPI
214FdtNodeHasProperty (
215 IN CONST VOID *Fdt,
216 IN INT32 Node,
217 IN CONST VOID *PropertyName
218 )
219{
220 INT32 Size;
221 CONST VOID *Prop;
222
223 if ((Fdt == NULL) ||
224 (PropertyName == NULL))
225 {
226 ASSERT (0);
227 return FALSE;
228 }
229
230 Prop = fdt_getprop (Fdt, Node, PropertyName, &Size);
231 if ((Prop == NULL) || (Size < 0)) {
232 return FALSE;
233 }
234
235 return TRUE;
236}
237
238/** Get the next node in the whole DT fulfilling a condition.
239
240 The condition to fulfill is checked by the NodeChecker function.
241 Context is passed to NodeChecker.
242
243 The Device tree is traversed in a depth-first search, starting from Node.
244 The input Node is skipped.
245
246 @param [in] Fdt Pointer to a Flattened Device Tree.
247 @param [in, out] Node At entry: Node offset to start the search.
248 This first node is skipped.
249 Write (-1) to search the whole tree.
250 At exit: If success, contains the offset of
251 the next node fulfilling the
252 condition.
253 @param [in, out] Depth Depth is incremented/decremented of the depth
254 difference between the input Node and the
255 output Node.
256 E.g.: If the output Node is a child node
257 of the input Node, contains (+1).
258 @param [in] NodeChecker Function called to check if the condition
259 is fulfilled.
260 @param [in] Context Context for the NodeChecker.
261
262 @retval EFI_SUCCESS The function completed successfully.
263 @retval EFI_ABORTED An error occurred.
264 @retval EFI_INVALID_PARAMETER Invalid parameter.
265 @retval EFI_NOT_FOUND No matching node found.
266**/
267STATIC
268EFI_STATUS
269EFIAPI
270FdtGetNextCondNode (
271 IN CONST VOID *Fdt,
272 IN OUT INT32 *Node,
273 IN OUT INT32 *Depth,
274 IN NODE_CHECKER_FUNC NodeChecker,
275 IN CONST VOID *Context
276 )
277{
278 INT32 CurrNode;
279
280 if ((Fdt == NULL) ||
281 (Node == NULL) ||
282 (Depth == NULL) ||
283 (NodeChecker == NULL))
284 {
285 ASSERT (0);
286 return EFI_INVALID_PARAMETER;
287 }
288
289 CurrNode = *Node;
290 do {
291 CurrNode = fdt_next_node (Fdt, CurrNode, Depth);
292 if ((CurrNode == -FDT_ERR_NOTFOUND) ||
293 (*Depth < 0))
294 {
295 // End of the tree, no matching node found.
296 return EFI_NOT_FOUND;
297 } else if (CurrNode < 0) {
298 // An error occurred.
299 ASSERT (0);
300 return EFI_ABORTED;
301 }
302 } while (!NodeChecker (Fdt, CurrNode, Context));
303
304 // Matching node found.
305 *Node = CurrNode;
306 return EFI_SUCCESS;
307}
308
309/** Get the next node in a branch fulfilling a condition.
310
311 The condition to fulfill is checked by the NodeChecker function.
312 Context is passed to NodeChecker.
313
314 The Device tree is traversed in a depth-first search, starting from Node.
315 The input Node is skipped.
316
317 @param [in] Fdt Pointer to a Flattened Device Tree.
318 @param [in] FdtBranch Only search in the sub-nodes of this
319 branch.
320 Write (-1) to search the whole tree.
321 @param [in] NodeChecker Function called to check if the condition
322 is fulfilled.
323 @param [in] Context Context for the NodeChecker.
324 @param [in, out] Node At entry: Node offset to start the search.
325 This first node is skipped.
326 Write (-1) to search the whole tree.
327 At exit: If success, contains the offset
328 of the next node in the branch
329 fulfilling the condition.
330
331 @retval EFI_SUCCESS The function completed successfully.
332 @retval EFI_ABORTED An error occurred.
333 @retval EFI_INVALID_PARAMETER Invalid parameter.
334 @retval EFI_NOT_FOUND No matching node found.
335**/
336STATIC
337EFI_STATUS
338EFIAPI
339FdtGetNextCondNodeInBranch (
340 IN CONST VOID *Fdt,
341 IN INT32 FdtBranch,
342 IN NODE_CHECKER_FUNC NodeChecker,
343 IN CONST VOID *Context,
344 IN OUT INT32 *Node
345 )
346{
347 EFI_STATUS Status;
348 INT32 CurrNode;
349 INT32 Depth;
350
351 if ((Fdt == NULL) ||
352 (Node == NULL) ||
353 (NodeChecker == NULL))
354 {
355 ASSERT (0);
356 return EFI_INVALID_PARAMETER;
357 }
358
359 CurrNode = FdtBranch;
360 Depth = 0;
361
362 // First, check the Node is in the sub-nodes of the branch.
363 // This allows to find the relative depth of Node in the branch.
364 if (CurrNode != *Node) {
365 for (CurrNode = fdt_next_node (Fdt, CurrNode, &Depth);
366 (CurrNode >= 0) && (Depth > 0);
367 CurrNode = fdt_next_node (Fdt, CurrNode, &Depth))
368 {
369 if (CurrNode == *Node) {
370 // Node found.
371 break;
372 }
373 } // for
374
375 if ((CurrNode < 0) || (Depth <= 0)) {
376 // Node is not a node in the branch, or an error occurred.
377 ASSERT (0);
378 return EFI_INVALID_PARAMETER;
379 }
380 }
381
382 // Get the next node in the tree fulfilling the condition,
383 // in any branch.
384 Status = FdtGetNextCondNode (
385 Fdt,
386 Node,
387 &Depth,
388 NodeChecker,
389 Context
390 );
391 if (EFI_ERROR (Status)) {
392 ASSERT (Status == EFI_NOT_FOUND);
393 return Status;
394 }
395
396 if (Depth <= 0) {
397 // The node found is not in the right branch.
398 return EFI_NOT_FOUND;
399 }
400
401 return EFI_SUCCESS;
402}
403
404/** Get the next node in a branch having a matching name.
405
406 The Device tree is traversed in a depth-first search, starting from Node.
407 The input Node is skipped.
408
409 @param [in] Fdt Pointer to a Flattened Device Tree.
410 @param [in] FdtBranch Only search in the sub-nodes of this branch.
411 Write (-1) to search the whole tree.
412 @param [in] NodeName The node name to search.
413 This is a NULL terminated string.
414 @param [in, out] Node At entry: Node offset to start the search.
415 This first node is skipped.
416 Write (-1) to search the whole tree.
417 At exit: If success, contains the offset of
418 the next node in the branch
419 having a matching name.
420
421 @retval EFI_SUCCESS The function completed successfully.
422 @retval EFI_ABORTED An error occurred.
423 @retval EFI_INVALID_PARAMETER Invalid parameter.
424 @retval EFI_NOT_FOUND No matching node found.
425**/
426EFI_STATUS
427EFIAPI
428FdtGetNextNamedNodeInBranch (
429 IN CONST VOID *Fdt,
430 IN INT32 FdtBranch,
431 IN CONST CHAR8 *NodeName,
432 IN OUT INT32 *Node
433 )
434{
435 return FdtGetNextCondNodeInBranch (
436 Fdt,
437 FdtBranch,
438 FdtNodeHasName,
439 NodeName,
440 Node
441 );
442}
443
444/** Get the next node in a branch with at least one compatible property.
445
446 The Device tree is traversed in a depth-first search, starting from Node.
447 The input Node is skipped.
448
449 @param [in] Fdt Pointer to a Flattened Device Tree.
450 @param [in] FdtBranch Only search in the sub-nodes of this branch.
451 Write (-1) to search the whole tree.
452 @param [in] CompatNamesInfo Table of compatible strings to compare with
453 the compatible property of the node.
454 @param [in, out] Node At entry: Node offset to start the search.
455 This first node is skipped.
456 Write (-1) to search the whole tree.
457 At exit: If success, contains the offset of
458 the next node in the branch
459 being compatible.
460
461 @retval EFI_SUCCESS The function completed successfully.
462 @retval EFI_ABORTED An error occurred.
463 @retval EFI_INVALID_PARAMETER Invalid parameter.
464 @retval EFI_NOT_FOUND No matching node found.
465**/
466EFI_STATUS
467EFIAPI
468FdtGetNextCompatNodeInBranch (
469 IN CONST VOID *Fdt,
470 IN INT32 FdtBranch,
471 IN CONST COMPATIBILITY_INFO *CompatNamesInfo,
472 IN OUT INT32 *Node
473 )
474{
475 return FdtGetNextCondNodeInBranch (
476 Fdt,
477 FdtBranch,
478 FdtNodeIsCompatible,
479 (CONST VOID *)CompatNamesInfo,
480 Node
481 );
482}
483
484/** Get the next node in a branch having the PropName property.
485
486 The Device tree is traversed in a depth-first search, starting from Node.
487 The input Node is skipped.
488
489 @param [in] Fdt Pointer to a Flattened Device Tree.
490 @param [in] FdtBranch Only search in the sub-nodes of this branch.
491 Write (-1) to search the whole tree.
492 @param [in] PropName Name of the property to search.
493 This is a NULL terminated string.
494 @param [in, out] Node At entry: Node offset to start the search.
495 This first node is skipped.
496 Write (-1) to search the whole tree.
497 At exit: If success, contains the offset of
498 the next node in the branch
499 being compatible.
500
501 @retval EFI_SUCCESS The function completed successfully.
502 @retval EFI_ABORTED An error occurred.
503 @retval EFI_INVALID_PARAMETER Invalid parameter.
504 @retval EFI_NOT_FOUND No matching node found.
505**/
506EFI_STATUS
507EFIAPI
508FdtGetNextPropNodeInBranch (
509 IN CONST VOID *Fdt,
510 IN INT32 FdtBranch,
511 IN CONST CHAR8 *PropName,
512 IN OUT INT32 *Node
513 )
514{
515 return FdtGetNextCondNodeInBranch (
516 Fdt,
517 FdtBranch,
518 FdtNodeHasProperty,
519 (CONST VOID *)PropName,
520 Node
521 );
522}
523
524/** Count the number of Device Tree nodes fulfilling a condition
525 in a Device Tree branch.
526
527 The condition to fulfill is checked by the NodeChecker function.
528 Context is passed to NodeChecker.
529
530 @param [in] Fdt Pointer to a Flattened Device Tree.
531 @param [in] FdtBranch Only search in the sub-nodes of this branch.
532 Write (-1) to search the whole tree.
533 @param [in] NodeChecker Function called to check the condition is
534 fulfilled.
535 @param [in] Context Context for the NodeChecker.
536 @param [out] NodeCount If success, contains the count of nodes
537 fulfilling the condition.
538 Can be 0.
539
540 @retval EFI_SUCCESS The function completed successfully.
541 @retval EFI_ABORTED An error occurred.
542 @retval EFI_INVALID_PARAMETER Invalid parameter.
543**/
544STATIC
545EFI_STATUS
546EFIAPI
547FdtCountCondNodeInBranch (
548 IN CONST VOID *Fdt,
549 IN INT32 FdtBranch,
550 IN NODE_CHECKER_FUNC NodeChecker,
551 IN CONST VOID *Context,
552 OUT UINT32 *NodeCount
553 )
554{
555 EFI_STATUS Status;
556 INT32 CurrNode;
557
558 if ((Fdt == NULL) ||
559 (NodeChecker == NULL) ||
560 (NodeCount == NULL))
561 {
562 ASSERT (0);
563 return EFI_INVALID_PARAMETER;
564 }
565
566 *NodeCount = 0;
567 CurrNode = FdtBranch;
568 while (TRUE) {
569 Status = FdtGetNextCondNodeInBranch (
570 Fdt,
571 FdtBranch,
572 NodeChecker,
573 Context,
574 &CurrNode
575 );
576 if (EFI_ERROR (Status) &&
577 (Status != EFI_NOT_FOUND))
578 {
579 ASSERT (0);
580 return Status;
581 } else if (Status == EFI_NOT_FOUND) {
582 break;
583 }
584
585 (*NodeCount)++;
586 }
587
588 return EFI_SUCCESS;
589}
590
591/** Count the number of nodes in a branch with the input name.
592
593 @param [in] Fdt Pointer to a Flattened Device Tree.
594 @param [in] FdtBranch Only search in the sub-nodes of this branch.
595 Write (-1) to search the whole tree.
596 @param [in] NodeName Node name to search.
597 This is a NULL terminated string.
598 @param [out] NodeCount If success, contains the count of nodes
599 fulfilling the condition.
600 Can be 0.
601
602 @retval EFI_SUCCESS The function completed successfully.
603 @retval EFI_ABORTED An error occurred.
604 @retval EFI_INVALID_PARAMETER Invalid parameter.
605**/
606EFI_STATUS
607EFIAPI
608FdtCountNamedNodeInBranch (
609 IN CONST VOID *Fdt,
610 IN INT32 FdtBranch,
611 IN CONST CHAR8 *NodeName,
612 OUT UINT32 *NodeCount
613 )
614{
615 return FdtCountCondNodeInBranch (
616 Fdt,
617 FdtBranch,
618 FdtNodeHasName,
619 NodeName,
620 NodeCount
621 );
622}
623
624/** Count the number of nodes in a branch with at least
625 one compatible property.
626
627 @param [in] Fdt Pointer to a Flattened Device Tree.
628 @param [in] FdtBranch Only search in the sub-nodes of this branch.
629 Write (-1) to search the whole tree.
630 @param [in] CompatNamesInfo Table of compatible strings to
631 compare with the compatible property
632 of the node.
633 @param [out] NodeCount If success, contains the count of nodes
634 fulfilling the condition.
635 Can be 0.
636
637 @retval EFI_SUCCESS The function completed successfully.
638 @retval EFI_ABORTED An error occurred.
639 @retval EFI_INVALID_PARAMETER Invalid parameter.
640**/
641EFI_STATUS
642EFIAPI
643FdtCountCompatNodeInBranch (
644 IN CONST VOID *Fdt,
645 IN INT32 FdtBranch,
646 IN CONST COMPATIBILITY_INFO *CompatNamesInfo,
647 OUT UINT32 *NodeCount
648 )
649{
650 return FdtCountCondNodeInBranch (
651 Fdt,
652 FdtBranch,
653 FdtNodeIsCompatible,
654 CompatNamesInfo,
655 NodeCount
656 );
657}
658
659/** Count the number of nodes in a branch having the PropName property.
660
661 @param [in] Fdt Pointer to a Flattened Device Tree.
662 @param [in] FdtBranch Only search in the sub-nodes of this branch.
663 Write (-1) to search the whole tree.
664 @param [in] PropName Name of the property to search.
665 This is a NULL terminated string.
666 @param [out] NodeCount If success, contains the count of nodes
667 fulfilling the condition.
668 Can be 0.
669
670 @retval EFI_SUCCESS The function completed successfully.
671 @retval EFI_ABORTED An error occurred.
672 @retval EFI_INVALID_PARAMETER Invalid parameter.
673**/
674EFI_STATUS
675EFIAPI
676FdtCountPropNodeInBranch (
677 IN CONST VOID *Fdt,
678 IN INT32 FdtBranch,
679 IN CONST CHAR8 *PropName,
680 OUT UINT32 *NodeCount
681 )
682{
683 return FdtCountCondNodeInBranch (
684 Fdt,
685 FdtBranch,
686 FdtNodeHasProperty,
687 PropName,
688 NodeCount
689 );
690}
691
692/** Get the interrupt-controller node handling the interrupts of
693 the input node.
694
695 To do this, recursively search a node with either the "interrupt-controller"
696 or the "interrupt-parent" property in the parents of Node.
697
698 Devicetree Specification, Release v0.3,
699 2.4.1 "Properties for Interrupt Generating Devices":
700 Because the hierarchy of the nodes in the interrupt tree
701 might not match the devicetree, the interrupt-parent
702 property is available to make the definition of an
703 interrupt parent explicit. The value is the phandle to the
704 interrupt parent. If this property is missing from a
705 device, its interrupt parent is assumed to be its devicetree
706 parent.
707
708 @param [in] Fdt Pointer to a Flattened Device Tree.
709 @param [in] Node Offset of the node to start the search.
710 @param [out] IntcNode If success, contains the offset of the
711 interrupt-controller node.
712
713 @retval EFI_SUCCESS The function completed successfully.
714 @retval EFI_NOT_FOUND No interrupt-controller node found.
715 @retval EFI_ABORTED An error occurred.
716 @retval EFI_INVALID_PARAMETER Invalid parameter.
717**/
718EFI_STATUS
719EFIAPI
720FdtGetIntcParentNode (
721 IN CONST VOID *Fdt,
722 IN INT32 Node,
723 OUT INT32 *IntcNode
724 )
725{
726 CONST UINT32 *PHandle;
727 INT32 Size;
728 CONST VOID *Prop;
729
730 if ((Fdt == NULL) ||
731 (IntcNode == NULL))
732 {
733 ASSERT (0);
734 return EFI_INVALID_PARAMETER;
735 }
736
737 while (TRUE) {
738 // Check whether the node has the "interrupt-controller" property.
739 Prop = fdt_getprop (Fdt, Node, "interrupt-controller", &Size);
740 if ((Prop != NULL) && (Size >= 0)) {
741 // The interrupt-controller has been found.
742 *IntcNode = Node;
743 return EFI_SUCCESS;
744 } else {
745 // Check whether the node has the "interrupt-parent" property.
746 PHandle = fdt_getprop (Fdt, Node, "interrupt-parent", &Size);
747 if ((PHandle != NULL) && (Size == sizeof (UINT32))) {
748 // The phandle of the interrupt-controller has been found.
749 // Search the node having this phandle and return it.
750 Node = fdt_node_offset_by_phandle (Fdt, fdt32_to_cpu (*PHandle));
751 if (Node < 0) {
752 ASSERT (0);
753 return EFI_ABORTED;
754 }
755
756 *IntcNode = Node;
757 return EFI_SUCCESS;
758 } else if (Size != -FDT_ERR_NOTFOUND) {
759 ASSERT (0);
760 return EFI_ABORTED;
761 }
762 }
763
764 if (Node == 0) {
765 // We are at the root of the tree. Not parent available.
766 return EFI_NOT_FOUND;
767 }
768
769 // Get the parent of the node.
770 Node = fdt_parent_offset (Fdt, Node);
771 if (Node < 0) {
772 // An error occurred.
773 ASSERT (0);
774 return EFI_ABORTED;
775 }
776 } // while
777}
778
779/** Get the "interrupt-cells" property value of the node.
780
781 The "interrupts" property requires to know the number of cells used
782 to encode an interrupt. This information is stored in the
783 interrupt-controller of the input Node.
784
785 @param [in] Fdt Pointer to a Flattened Device Tree (Fdt).
786 @param [in] IntcNode Offset of an interrupt-controller node.
787 @param [out] IntCells If success, contains the "interrupt-cells"
788 property of the IntcNode.
789
790 @retval EFI_SUCCESS The function completed successfully.
791 @retval EFI_INVALID_PARAMETER Invalid parameter.
792 @retval EFI_UNSUPPORTED Unsupported.
793**/
794EFI_STATUS
795EFIAPI
796FdtGetInterruptCellsInfo (
797 IN CONST VOID *Fdt,
798 IN INT32 IntcNode,
799 OUT INT32 *IntCells
800 )
801{
802 CONST UINT32 *Data;
803 INT32 Size;
804
805 if ((Fdt == NULL) ||
806 (IntCells == NULL))
807 {
808 ASSERT (0);
809 return EFI_INVALID_PARAMETER;
810 }
811
812 Data = fdt_getprop (Fdt, IntcNode, "#interrupt-cells", &Size);
813 if ((Data == NULL) || (Size != sizeof (UINT32))) {
814 // If error or not on one UINT32 cell.
815 ASSERT (0);
816 return EFI_ABORTED;
817 }
818
819 *IntCells = fdt32_to_cpu (*Data);
820
821 return EFI_SUCCESS;
822}
823
824/** Get the "#address-cells" and/or "#size-cells" property of the node.
825
826 According to the Device Tree specification, s2.3.5 "#address-cells and
827 #size-cells":
828 "If missing, a client program should assume a default value of 2 for
829 #address-cells, and a value of 1 for #size-cells."
830
831 @param [in] Fdt Pointer to a Flattened Device Tree.
832 @param [in] Node Offset of the node having to get the
833 "#address-cells" and "#size-cells"
834 properties from.
835 @param [out] AddressCells If success, number of address-cells.
836 If the property is not available,
837 default value is 2.
838 @param [out] SizeCells If success, number of size-cells.
839 If the property is not available,
840 default value is 1.
841
842 @retval EFI_SUCCESS The function completed successfully.
843 @retval EFI_ABORTED An error occurred.
844 @retval EFI_INVALID_PARAMETER Invalid parameter.
845**/
846EFI_STATUS
847EFIAPI
848FdtGetAddressInfo (
849 IN CONST VOID *Fdt,
850 IN INT32 Node,
851 OUT INT32 *AddressCells, OPTIONAL
852 OUT INT32 *SizeCells OPTIONAL
853 )
854{
855 if (Fdt == NULL) {
856 ASSERT (0);
857 return EFI_INVALID_PARAMETER;
858 }
859
860 if (AddressCells != NULL) {
861 *AddressCells = fdt_address_cells (Fdt, Node);
862 if (*AddressCells < 0) {
863 ASSERT (0);
864 return EFI_ABORTED;
865 }
866 }
867
868 if (SizeCells != NULL) {
869 *SizeCells = fdt_size_cells (Fdt, Node);
870 if (*SizeCells < 0) {
871 ASSERT (0);
872 return EFI_ABORTED;
873 }
874 }
875
876 return EFI_SUCCESS;
877}
878
879/** Get the "#address-cells" and/or "#size-cells" property of the parent node.
880
881 According to the Device Tree specification, s2.3.5 "#address-cells and
882 #size-cells":
883 "If missing, a client program should assume a default value of 2 for
884 #address-cells, and a value of 1 for #size-cells."
885
886 @param [in] Fdt Pointer to a Flattened Device Tree.
887 @param [in] Node Offset of the node having to get the
888 "#address-cells" and "#size-cells"
889 properties from its parent.
890 @param [out] AddressCells If success, number of address-cells.
891 If the property is not available,
892 default value is 2.
893 @param [out] SizeCells If success, number of size-cells.
894 If the property is not available,
895 default value is 1.
896
897 @retval EFI_SUCCESS The function completed successfully.
898 @retval EFI_ABORTED An error occurred.
899 @retval EFI_INVALID_PARAMETER Invalid parameter.
900**/
901EFI_STATUS
902EFIAPI
903FdtGetParentAddressInfo (
904 IN CONST VOID *Fdt,
905 IN INT32 Node,
906 OUT INT32 *AddressCells, OPTIONAL
907 OUT INT32 *SizeCells OPTIONAL
908 )
909{
910 if (Fdt == NULL) {
911 ASSERT (0);
912 return EFI_INVALID_PARAMETER;
913 }
914
915 Node = fdt_parent_offset (Fdt, Node);
916 if (Node < 0) {
917 // End of the tree, or an error occurred.
918 ASSERT (0);
919 return EFI_ABORTED;
920 }
921
922 return FdtGetAddressInfo (Fdt, Node, AddressCells, SizeCells);
923}
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette