]> git.proxmox.com Git - mirror_edk2.git/blob - ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Aest/AestParser.c
ShellPkg: Apply uncrustify changes
[mirror_edk2.git] / ShellPkg / Library / UefiShellAcpiViewCommandLib / Parsers / Aest / AestParser.c
1 /** @file
2 AEST table parser
3
4 Copyright (c) 2020, Arm Limited.
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6
7 @par Reference(s):
8 - ACPI for the Armv8 RAS Extensions 1.1 Platform Design Document,
9 dated 28 September 2020.
10 (https://developer.arm.com/documentation/den0085/0101/)
11 **/
12
13 #include <Library/PrintLib.h>
14 #include <Library/UefiLib.h>
15 #include <IndustryStandard/ArmErrorSourceTable.h>
16 #include "AcpiParser.h"
17 #include "AcpiView.h"
18 #include "AcpiViewConfig.h"
19
20 // Local variables
21 STATIC ACPI_DESCRIPTION_HEADER_INFO AcpiHdrInfo;
22 STATIC UINT8 *AestNodeType;
23 STATIC UINT16 *AestNodeLength;
24 STATIC UINT32 *NodeDataOffset;
25 STATIC UINT32 *NodeInterfaceOffset;
26 STATIC UINT32 *NodeInterruptArrayOffset;
27 STATIC UINT32 *NodeInterruptCount;
28 STATIC UINT32 *ProcessorId;
29 STATIC UINT8 *ProcessorFlags;
30 STATIC UINT8 *ProcessorResourceType;
31
32 /**
33 Validate Processor Flags.
34
35 @param [in] Ptr Pointer to the start of the field data.
36 @param [in] Context Pointer to context specific information e.g. this
37 could be a pointer to the ACPI table header.
38 **/
39 STATIC
40 VOID
41 EFIAPI
42 ValidateProcessorFlags (
43 IN UINT8 *Ptr,
44 IN VOID *Context
45 )
46 {
47 // If the global or shared node flag is set then the ACPI Processor ID
48 // field must be set to 0 and ignored.
49 if (((*Ptr & 0x3) != 0) && (*ProcessorId != 0)) {
50 IncrementErrorCount ();
51 Print (
52 L"\nERROR: 'ACPI Processor ID' field must be set to 0 for global"
53 L" or shared nodes."
54 );
55 }
56 }
57
58 /**
59 Validate GIC Interface Type.
60
61 @param [in] Ptr Pointer to the start of the field data.
62 @param [in] Context Pointer to context specific information e.g. this
63 could be a pointer to the ACPI table header.
64 **/
65 STATIC
66 VOID
67 EFIAPI
68 ValidateGicInterfaceType (
69 IN UINT8 *Ptr,
70 IN VOID *Context
71 )
72 {
73 UINT32 GicInterfaceType;
74
75 GicInterfaceType = *(UINT32 *)Ptr;
76 if (GicInterfaceType > 3) {
77 IncrementErrorCount ();
78 Print (L"\nError: Invalid GIC Interface type %d", GicInterfaceType);
79 }
80 }
81
82 /**
83 Validate Interface Type.
84
85 @param [in] Ptr Pointer to the start of the field data.
86 @param [in] Context Pointer to context specific information e.g. this
87 could be a pointer to the ACPI table header.
88 **/
89 STATIC
90 VOID
91 EFIAPI
92 ValidateInterfaceType (
93 IN UINT8 *Ptr,
94 IN VOID *Context
95 )
96 {
97 if (*Ptr > 1) {
98 IncrementErrorCount ();
99 Print (L"\nError: Interface type should be 0 or 1");
100 }
101 }
102
103 /**
104 Validate Interrupt Type.
105
106 @param [in] Ptr Pointer to the start of the field data.
107 @param [in] Context Pointer to context specific information e.g. this
108 could be a pointer to the ACPI table header.
109 **/
110 STATIC
111 VOID
112 EFIAPI
113 ValidateInterruptType (
114 IN UINT8 *Ptr,
115 IN VOID *Context
116 )
117 {
118 if (*Ptr > 1) {
119 IncrementErrorCount ();
120 Print (L"\nError: Interrupt type should be 0 or 1");
121 }
122 }
123
124 /**
125 Validate interrupt flags.
126
127 @param [in] Ptr Pointer to the start of the field data.
128 @param [in] Context Pointer to context specific information e.g. this
129 could be a pointer to the ACPI table header.
130 **/
131 STATIC
132 VOID
133 EFIAPI
134 ValidateInterruptFlags (
135 IN UINT8 *Ptr,
136 IN VOID *Context
137 )
138 {
139 if ((*Ptr & 0xfe) != 0) {
140 IncrementErrorCount ();
141 Print (L"\nError: Reserved Flag bits not set to 0");
142 }
143 }
144
145 /**
146 Dumps 16 bytes of data.
147
148 @param [in] Format Optional format string for tracing the data.
149 @param [in] Ptr Pointer to the start of the buffer.
150 **/
151 VOID
152 EFIAPI
153 DumpVendorSpecificData (
154 IN CONST CHAR16 *Format OPTIONAL,
155 IN UINT8 *Ptr
156 )
157 {
158 Print (
159 L"%02X %02X %02X %02X %02X %02X %02X %02X\n",
160 Ptr[0],
161 Ptr[1],
162 Ptr[2],
163 Ptr[3],
164 Ptr[4],
165 Ptr[5],
166 Ptr[6],
167 Ptr[7]
168 );
169
170 Print (
171 L"%*a %02X %02X %02X %02X %02X %02X %02X %02X",
172 OUTPUT_FIELD_COLUMN_WIDTH,
173 "",
174 Ptr[8],
175 Ptr[9],
176 Ptr[10],
177 Ptr[11],
178 Ptr[12],
179 Ptr[13],
180 Ptr[14],
181 Ptr[15]
182 );
183 }
184
185 /**
186 An ACPI_PARSER array describing the ACPI AEST Table.
187 **/
188 STATIC CONST ACPI_PARSER AestParser[] = {
189 PARSE_ACPI_HEADER (&AcpiHdrInfo)
190 };
191
192 /**
193 An ACPI_PARSER array describing the AEST Node Header.
194 **/
195 STATIC CONST ACPI_PARSER AestNodeHeaderParser[] = {
196 { L"Type", 1, 0, L"%d", NULL, (VOID **)&AestNodeType, NULL, NULL },
197 { L"Length", 2, 1, L"%d", NULL, (VOID **)&AestNodeLength, NULL, NULL },
198 { L"Reserved", 1, 3, L"0x%x", NULL, NULL, NULL, NULL },
199 { L"Node Data Offset", 4, 4, L"%d", NULL, (VOID **)&NodeDataOffset, NULL, NULL },
200 { L"Node Interface Offset", 4, 8, L"%d", NULL,
201 (VOID **)&NodeInterfaceOffset, NULL, NULL },
202 { L"Node Interrupt Array Offset", 4, 12, L"%d", NULL,
203 (VOID **)&NodeInterruptArrayOffset, NULL, NULL },
204 { L"Node Interrupt Count", 4, 16, L"%d", NULL,
205 (VOID **)&NodeInterruptCount, NULL, NULL },
206 { L"Timestamp Rate", 8, 20, L"%ld", NULL, NULL, NULL, NULL },
207 { L"Reserved1", 8, 28, L"0x%lx", NULL, NULL, NULL, NULL },
208 { L"Error Injection Countdown Rate", 8, 36, L"%ld", NULL, NULL, NULL, NULL }
209 // Node specific data...
210 // Node interface...
211 // Node interrupt array...
212 };
213
214 /**
215 An ACPI_PARSER array describing the Processor error node specific data.
216 **/
217 STATIC CONST ACPI_PARSER AestProcessorStructure[] = {
218 { L"ACPI Processor ID", 4, 0, L"0x%x", NULL, (VOID **)&ProcessorId, NULL, NULL },
219 { L"Resource Type", 1, 4, L"%d", NULL, (VOID **)&ProcessorResourceType, NULL,
220 NULL },
221 { L"Reserved", 1, 5, L"0x%x", NULL, NULL, NULL, NULL },
222 { L"Flags", 1, 6, L"0x%x", NULL, (VOID **)&ProcessorFlags,
223 ValidateProcessorFlags, NULL },
224 { L"Revision", 1, 7, L"%d", NULL, NULL, NULL, NULL },
225 { L"Processor Affinity Level Indicator", 8, 8, L"0x%lx", NULL, NULL, NULL,
226 NULL },
227 // Resource specific data...
228 };
229
230 /**
231 An ACPI_PARSER array describing the processor cache resource substructure.
232 **/
233 STATIC CONST ACPI_PARSER AestProcessorCacheResourceSubstructure[] = {
234 { L"Cache reference ID", 4, 0, L"0x%x", NULL, NULL, NULL, NULL },
235 { L"Reserved", 4, 4, L"%d", NULL, NULL, NULL, NULL }
236 };
237
238 /**
239 An ACPI_PARSER array describing the processor TLB resource substructure.
240 **/
241 STATIC CONST ACPI_PARSER AestProcessorTlbResourceSubstructure[] = {
242 { L"TLB reference ID", 4, 0, L"0x%x", NULL, NULL, NULL, NULL },
243 { L"Reserved", 4, 4, L"%d", NULL, NULL, NULL, NULL }
244 };
245
246 /**
247 An ACPI_PARSER array describing the processor generic resource substructure.
248 **/
249 STATIC CONST ACPI_PARSER AestProcessorGenericResourceSubstructure[] = {
250 { L"Vendor-defined data", 4, 0, L"%x", NULL, NULL, NULL, NULL }
251 };
252
253 /**
254 An ACPI_PARSER array describing the memory controller structure.
255 **/
256 STATIC CONST ACPI_PARSER AestMemoryControllerStructure[] = {
257 { L"Proximity Domain", 4, 0, L"0x%x", NULL, NULL, NULL, NULL }
258 };
259
260 /**
261 An ACPI_PARSER array describing the SMMU structure.
262 **/
263 STATIC CONST ACPI_PARSER AestSmmuStructure[] = {
264 { L"IORT Node reference ID", 4, 0, L"0x%x", NULL, NULL, NULL, NULL },
265 { L"SubComponent reference ID", 4, 4, L"0x%x", NULL, NULL, NULL, NULL }
266 };
267
268 /**
269 An ACPI_PARSER array describing the vendor-defined structure.
270 **/
271 STATIC CONST ACPI_PARSER AestVendorDefinedStructure[] = {
272 { L"Hardware ID", 4, 0, L"0x%x", NULL, NULL, NULL, NULL },
273 { L"Unique ID", 4, 4, L"0x%x", NULL, NULL, NULL, NULL },
274 { L"Vendor-specific data", 16, 8, NULL, DumpVendorSpecificData, NULL, NULL }
275 };
276
277 /**
278 An ACPI_PARSER array describing the GIC structure.
279 **/
280 STATIC CONST ACPI_PARSER AestGicStructure[] = {
281 { L"GIC Interface Type", 4, 0, L"0x%x", NULL, NULL, ValidateGicInterfaceType,
282 NULL },
283 { L"GIC Interface reference ID", 4, 4, L"0x%x", NULL, NULL, NULL, NULL}
284 };
285
286 /**
287 An ACPI_PARSER array describing the node interface.
288 **/
289 STATIC CONST ACPI_PARSER AestNodeInterface[] = {
290 { L"Interface Type", 1, 0, L"%d", NULL, NULL, ValidateInterfaceType, NULL },
291 { L"Reserved", 3, 1, L"%x %x %x", Dump3Chars, NULL, NULL, NULL },
292 { L"Flags", 4, 4, L"0x%x", NULL, NULL, NULL, NULL },
293 { L"Base Address", 8, 8, L"0x%lx", NULL, NULL, NULL, NULL },
294 { L"Start Error Record Index", 4, 16, L"0x%x", NULL, NULL, NULL, NULL },
295 { L"Number of Error Records", 4, 20, L"0x%x", NULL, NULL, NULL, NULL },
296 { L"Error Records Implemented", 8, 24, L"0x%lx", NULL, NULL, NULL, NULL },
297 { L"Error Records Support", 8, 32, L"0x%lx", NULL, NULL, NULL, NULL },
298 { L"Addressing mode", 8, 40, L"0x%lx", NULL, NULL, NULL, NULL }
299 };
300
301 /**
302 An ACPI_PARSER array describing the node interrupts.
303 **/
304 STATIC CONST ACPI_PARSER AestNodeInterrupt[] = {
305 { L"Interrupt Type", 1, 0, L"%d", NULL, NULL, ValidateInterruptType, NULL },
306 { L"Reserved", 2, 1, L"0x%x", NULL, NULL, NULL, NULL },
307 { L"Interrupt Flags", 1, 3, L"0x%x", NULL, NULL, ValidateInterruptFlags, NULL },
308 { L"Interrupt GSIV", 4, 4, L"0x%x", NULL, NULL, NULL, NULL },
309 { L"ID", 1, 8, L"0x%x", NULL, NULL, NULL, NULL },
310 { L"Reserved1", 3, 9, L"%x %x %x", Dump3Chars, NULL, NULL, NULL }
311 };
312
313 /**
314 Parses the Processor Error Node structure along with its resource
315 specific data.
316
317 @param [in] Ptr Pointer to the start of the Processor node.
318 @param [in] Length Maximum length of the Processor node.
319 **/
320 STATIC
321 VOID
322 DumpProcessorNode (
323 IN UINT8 *Ptr,
324 IN UINT32 Length
325 )
326 {
327 UINT32 Offset;
328
329 Offset = ParseAcpi (
330 TRUE,
331 2,
332 "Processor",
333 Ptr,
334 Length,
335 PARSER_PARAMS (AestProcessorStructure)
336 );
337
338 // Check if the values used to control the parsing logic have been
339 // successfully read.
340 if ((ProcessorId == NULL) ||
341 (ProcessorResourceType == NULL) ||
342 (ProcessorFlags == NULL))
343 {
344 IncrementErrorCount ();
345 Print (
346 L"ERROR: Insufficient Processor Error Node length. Length = %d.\n",
347 Length
348 );
349 return;
350 }
351
352 switch (*ProcessorResourceType) {
353 case EFI_ACPI_AEST_PROCESSOR_RESOURCE_TYPE_CACHE:
354 ParseAcpi (
355 TRUE,
356 2,
357 "Cache Resource",
358 Ptr + Offset,
359 Length - Offset,
360 PARSER_PARAMS (AestProcessorCacheResourceSubstructure)
361 );
362 break;
363 case EFI_ACPI_AEST_PROCESSOR_RESOURCE_TYPE_TLB:
364 ParseAcpi (
365 TRUE,
366 2,
367 "TLB Resource",
368 Ptr + Offset,
369 Length - Offset,
370 PARSER_PARAMS (AestProcessorTlbResourceSubstructure)
371 );
372 break;
373 case EFI_ACPI_AEST_PROCESSOR_RESOURCE_TYPE_GENERIC:
374 ParseAcpi (
375 TRUE,
376 2,
377 "Generic Resource",
378 Ptr + Offset,
379 Length - Offset,
380 PARSER_PARAMS (AestProcessorGenericResourceSubstructure)
381 );
382 break;
383 default:
384 IncrementErrorCount ();
385 Print (L"ERROR: Invalid Processor Resource Type.");
386 return;
387 } // switch
388 }
389
390 /**
391 Parses the Memory Controller node.
392
393 @param [in] Ptr Pointer to the start of the Memory Controller node.
394 @param [in] Length Maximum length of the Memory Controller node.
395 **/
396 STATIC
397 VOID
398 DumpMemoryControllerNode (
399 IN UINT8 *Ptr,
400 IN UINT32 Length
401 )
402 {
403 ParseAcpi (
404 TRUE,
405 2,
406 "Memory Controller",
407 Ptr,
408 Length,
409 PARSER_PARAMS (AestMemoryControllerStructure)
410 );
411 }
412
413 /**
414 Parses the SMMU node.
415
416 @param [in] Ptr Pointer to the start of the SMMU node.
417 @param [in] Length Maximum length of the SMMU node.
418 **/
419 STATIC
420 VOID
421 DumpSmmuNode (
422 IN UINT8 *Ptr,
423 IN UINT32 Length
424 )
425 {
426 ParseAcpi (
427 TRUE,
428 2,
429 "SMMU",
430 Ptr,
431 Length,
432 PARSER_PARAMS (AestSmmuStructure)
433 );
434 }
435
436 /**
437 Parses the Vendor-defined structure.
438
439 @param [in] Ptr Pointer to the start of the Vendor-defined node.
440 @param [in] Length Maximum length of the Vendor-defined node.
441 **/
442 STATIC
443 VOID
444 DumpVendorDefinedNode (
445 IN UINT8 *Ptr,
446 IN UINT32 Length
447 )
448 {
449 ParseAcpi (
450 TRUE,
451 2,
452 "Vendor-defined",
453 Ptr,
454 Length,
455 PARSER_PARAMS (AestVendorDefinedStructure)
456 );
457 }
458
459 /**
460 Parses the GIC node.
461
462 @param [in] Ptr Pointer to the start of the GIC node.
463 @param [in] Length Maximum length of the GIC node.
464 **/
465 STATIC
466 VOID
467 DumpGicNode (
468 IN UINT8 *Ptr,
469 IN UINT32 Length
470 )
471 {
472 ParseAcpi (
473 TRUE,
474 2,
475 "GIC",
476 Ptr,
477 Length,
478 PARSER_PARAMS (AestGicStructure)
479 );
480 }
481
482 /**
483 Parses the Node Interface structure.
484
485 @param [in] Ptr Pointer to the start of the Node Interface Structure.
486 @param [in] Length Maximum length of the Node Interface Structure.
487 **/
488 STATIC
489 VOID
490 DumpNodeInterface (
491 IN UINT8 *Ptr,
492 IN UINT32 Length
493 )
494 {
495 ParseAcpi (
496 TRUE,
497 2,
498 "Node Interface",
499 Ptr,
500 Length,
501 PARSER_PARAMS (AestNodeInterface)
502 );
503 }
504
505 /**
506 Parses the Node Interrupts Structure.
507
508 @param [in] Ptr Pointer to the start of the Node Interrupt array.
509 @param [in] Length Maximum length of the Node Interrupt array.
510 @param [in] InterruptCount Number if interrupts in the Node Interrupts array.
511 **/
512 STATIC
513 VOID
514 DumpNodeInterrupts (
515 IN UINT8 *Ptr,
516 IN UINT32 Length,
517 IN UINT32 InterruptCount
518 )
519 {
520 UINT32 Offset;
521 UINT32 Index;
522 CHAR8 Buffer[64];
523
524 if (Length < (InterruptCount * sizeof (EFI_ACPI_AEST_INTERRUPT_STRUCT))) {
525 IncrementErrorCount ();
526 Print (
527 L"ERROR: Node not long enough for Interrupt Array.\n" \
528 L" Length left = %d, Required = %d, Interrupt Count = %d\n",
529 Length,
530 (InterruptCount * sizeof (EFI_ACPI_AEST_INTERRUPT_STRUCT)),
531 InterruptCount
532 );
533 return;
534 }
535
536 Offset = 0;
537 for (Index = 0; Index < InterruptCount; Index++) {
538 AsciiSPrint (
539 Buffer,
540 sizeof (Buffer),
541 "Node Interrupt [%d]",
542 Index
543 );
544
545 Offset += ParseAcpi (
546 TRUE,
547 4,
548 Buffer,
549 Ptr + Offset,
550 Length - Offset,
551 PARSER_PARAMS (AestNodeInterrupt)
552 );
553 } // for
554 }
555
556 /**
557 Parses a single AEST Node Structure.
558
559 @param [in] Ptr Pointer to the start of the Node.
560 @param [in] Length Maximum length of the Node.
561 @param [in] NodeType AEST node type.
562 @param [in] DataOffset Offset to the node data.
563 @param [in] InterfaceOffset Offset to the node interface data.
564 @param [in] InterruptArrayOffset Offset to the node interrupt array.
565 @param [in] InterruptCount Number of interrupts.
566 **/
567 STATIC
568 VOID
569 DumpAestNodeStructure (
570 IN UINT8 *Ptr,
571 IN UINT32 Length,
572 IN UINT8 NodeType,
573 IN UINT32 DataOffset,
574 IN UINT32 InterfaceOffset,
575 IN UINT32 InterruptArrayOffset,
576 IN UINT32 InterruptCount
577 )
578 {
579 UINT32 Offset;
580 UINT32 RemainingLength;
581 UINT8 *NodeDataPtr;
582
583 Offset = ParseAcpi (
584 TRUE,
585 2,
586 "Node Structure",
587 Ptr,
588 Length,
589 PARSER_PARAMS (AestNodeHeaderParser)
590 );
591
592 if ((Offset > DataOffset) || (DataOffset > Length)) {
593 IncrementErrorCount ();
594 Print (
595 L"ERROR: Invalid Node Data Offset: %d.\n" \
596 L" It should be between %d and %d.\n",
597 DataOffset,
598 Offset,
599 Length
600 );
601 }
602
603 if ((Offset > InterfaceOffset) || (InterfaceOffset > Length)) {
604 IncrementErrorCount ();
605 Print (
606 L"ERROR: Invalid Node Interface Offset: %d.\n" \
607 L" It should be between %d and %d.\n",
608 InterfaceOffset,
609 Offset,
610 Length
611 );
612 }
613
614 if ((Offset > InterruptArrayOffset) || (InterruptArrayOffset > Length)) {
615 IncrementErrorCount ();
616 Print (
617 L"ERROR: Invalid Node Interrupt Array Offset: %d.\n" \
618 L" It should be between %d and %d.\n",
619 InterruptArrayOffset,
620 Offset,
621 Length
622 );
623 }
624
625 // Parse Node Data Field.
626 NodeDataPtr = Ptr + DataOffset;
627 RemainingLength = Length - DataOffset;
628 switch (NodeType) {
629 case EFI_ACPI_AEST_NODE_TYPE_PROCESSOR:
630 DumpProcessorNode (NodeDataPtr, RemainingLength);
631 break;
632 case EFI_ACPI_AEST_NODE_TYPE_MEMORY:
633 DumpMemoryControllerNode (NodeDataPtr, RemainingLength);
634 break;
635 case EFI_ACPI_AEST_NODE_TYPE_SMMU:
636 DumpSmmuNode (NodeDataPtr, RemainingLength);
637 break;
638 case EFI_ACPI_AEST_NODE_TYPE_VENDOR_DEFINED:
639 DumpVendorDefinedNode (NodeDataPtr, RemainingLength);
640 break;
641 case EFI_ACPI_AEST_NODE_TYPE_GIC:
642 DumpGicNode (NodeDataPtr, RemainingLength);
643 break;
644 default:
645 IncrementErrorCount ();
646 Print (L"ERROR: Invalid Error Node Type.\n");
647 return;
648 } // switch
649
650 // Parse the Interface Field.
651 DumpNodeInterface (
652 Ptr + InterfaceOffset,
653 Length - InterfaceOffset
654 );
655
656 // Parse the Node Interrupt Array.
657 DumpNodeInterrupts (
658 Ptr + InterruptArrayOffset,
659 Length - InterruptArrayOffset,
660 InterruptCount
661 );
662
663 return;
664 }
665
666 /**
667 This function parses the ACPI AEST table.
668 When trace is enabled this function parses the AEST table and
669 traces the ACPI table fields.
670
671 This function also performs validation of the ACPI table fields.
672
673 @param [in] Trace If TRUE, trace the ACPI fields.
674 @param [in] Ptr Pointer to the start of the buffer.
675 @param [in] AcpiTableLength Length of the ACPI table.
676 @param [in] AcpiTableRevision Revision of the ACPI table.
677 **/
678 VOID
679 EFIAPI
680 ParseAcpiAest (
681 IN BOOLEAN Trace,
682 IN UINT8 *Ptr,
683 IN UINT32 AcpiTableLength,
684 IN UINT8 AcpiTableRevision
685 )
686 {
687 UINT32 Offset;
688 UINT8 *NodePtr;
689
690 if (!Trace) {
691 return;
692 }
693
694 Offset = ParseAcpi (
695 TRUE,
696 0,
697 "AEST",
698 Ptr,
699 AcpiTableLength,
700 PARSER_PARAMS (AestParser)
701 );
702
703 while (Offset < AcpiTableLength) {
704 NodePtr = Ptr + Offset;
705
706 ParseAcpi (
707 FALSE,
708 0,
709 NULL,
710 NodePtr,
711 AcpiTableLength - Offset,
712 PARSER_PARAMS (AestNodeHeaderParser)
713 );
714
715 // Check if the values used to control the parsing logic have been
716 // successfully read.
717 if ((AestNodeType == NULL) ||
718 (AestNodeLength == NULL) ||
719 (NodeDataOffset == NULL) ||
720 (NodeInterfaceOffset == NULL) ||
721 (NodeInterruptArrayOffset == NULL) ||
722 (NodeInterruptCount == NULL))
723 {
724 IncrementErrorCount ();
725 Print (
726 L"ERROR: Insufficient length left for Node Structure.\n" \
727 L" Length left = %d.\n",
728 AcpiTableLength - Offset
729 );
730 return;
731 }
732
733 // Validate AEST Node length
734 if ((*AestNodeLength == 0) ||
735 ((Offset + (*AestNodeLength)) > AcpiTableLength))
736 {
737 IncrementErrorCount ();
738 Print (
739 L"ERROR: Invalid AEST Node length. " \
740 L"Length = %d. Offset = %d. AcpiTableLength = %d.\n",
741 *AestNodeLength,
742 Offset,
743 AcpiTableLength
744 );
745 return;
746 }
747
748 DumpAestNodeStructure (
749 NodePtr,
750 *AestNodeLength,
751 *AestNodeType,
752 *NodeDataOffset,
753 *NodeInterfaceOffset,
754 *NodeInterruptArrayOffset,
755 *NodeInterruptCount
756 );
757
758 Offset += *AestNodeLength;
759 } // while
760 }