]> git.proxmox.com Git - mirror_edk2.git/blob - DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlCodeGen.c
DynamicTablesPkg: AML code generation for a Package
[mirror_edk2.git] / DynamicTablesPkg / Library / Common / AmlLib / CodeGen / AmlCodeGen.c
1 /** @file
2 AML Code Generation.
3
4 Copyright (c) 2020 - 2021, Arm Limited. All rights reserved.<BR>
5
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7 **/
8
9 #include <AmlNodeDefines.h>
10
11 #include <AcpiTableGenerator.h>
12
13 #include <AmlCoreInterface.h>
14 #include <AmlEncoding/Aml.h>
15 #include <Tree/AmlNode.h>
16 #include <Tree/AmlTree.h>
17 #include <String/AmlString.h>
18 #include <Utils/AmlUtility.h>
19
20 /** Utility function to link a node when returning from a CodeGen function.
21
22 @param [in] Node Newly created node.
23 @param [in] ParentNode If provided, set ParentNode as the parent
24 of the node created.
25 @param [out] NewObjectNode If not NULL:
26 - and Success, contains the created Node.
27 - and Error, reset to NULL.
28
29 @retval EFI_SUCCESS The function completed successfully.
30 @retval EFI_INVALID_PARAMETER Invalid parameter.
31 **/
32 STATIC
33 EFI_STATUS
34 EFIAPI
35 LinkNode (
36 IN AML_OBJECT_NODE * Node,
37 IN AML_NODE_HEADER * ParentNode,
38 OUT AML_OBJECT_NODE ** NewObjectNode
39 )
40 {
41 EFI_STATUS Status;
42
43 if (NewObjectNode != NULL) {
44 *NewObjectNode = NULL;
45 }
46
47 // Add RdNode as the last element.
48 if (ParentNode != NULL) {
49 Status = AmlVarListAddTail (ParentNode, (AML_NODE_HEADER*)Node);
50 if (EFI_ERROR (Status)) {
51 ASSERT (0);
52 return Status;
53 }
54 }
55
56 if (NewObjectNode != NULL) {
57 *NewObjectNode = Node;
58 }
59
60 return EFI_SUCCESS;
61 }
62
63 /** AML code generation for DefinitionBlock.
64
65 Create a Root Node handle.
66 It is the caller's responsibility to free the allocated memory
67 with the AmlDeleteTree function.
68
69 AmlCodeGenDefinitionBlock (TableSignature, OemID, TableID, OEMRevision) is
70 equivalent to the following ASL code:
71 DefinitionBlock (AMLFileName, TableSignature, ComplianceRevision,
72 OemID, TableID, OEMRevision) {}
73 with the ComplianceRevision set to 2 and the AMLFileName is ignored.
74
75 @param[in] TableSignature 4-character ACPI signature.
76 Must be 'DSDT' or 'SSDT'.
77 @param[in] OemId 6-character string OEM identifier.
78 @param[in] OemTableId 8-character string OEM table identifier.
79 @param[in] OemRevision OEM revision number.
80 @param[out] NewRootNode Pointer to the root node representing a
81 Definition Block.
82
83 @retval EFI_SUCCESS Success.
84 @retval EFI_INVALID_PARAMETER Invalid parameter.
85 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
86 **/
87 EFI_STATUS
88 EFIAPI
89 AmlCodeGenDefinitionBlock (
90 IN CONST CHAR8 * TableSignature,
91 IN CONST CHAR8 * OemId,
92 IN CONST CHAR8 * OemTableId,
93 IN UINT32 OemRevision,
94 OUT AML_ROOT_NODE ** NewRootNode
95 )
96 {
97 EFI_STATUS Status;
98 EFI_ACPI_DESCRIPTION_HEADER AcpiHeader;
99
100 if ((TableSignature == NULL) ||
101 (OemId == NULL) ||
102 (OemTableId == NULL) ||
103 (NewRootNode == NULL)) {
104 ASSERT (0);
105 return EFI_INVALID_PARAMETER;
106 }
107
108 CopyMem (&AcpiHeader.Signature, TableSignature, 4);
109 AcpiHeader.Length = sizeof (EFI_ACPI_DESCRIPTION_HEADER);
110 AcpiHeader.Revision = 2;
111 CopyMem (&AcpiHeader.OemId, OemId, 6);
112 CopyMem (&AcpiHeader.OemTableId, OemTableId, 8);
113 AcpiHeader.OemRevision = OemRevision;
114 AcpiHeader.CreatorId = TABLE_GENERATOR_CREATOR_ID_ARM;
115 AcpiHeader.CreatorRevision = CREATE_REVISION (1, 0);
116
117 Status = AmlCreateRootNode (&AcpiHeader, NewRootNode);
118 ASSERT_EFI_ERROR (Status);
119
120 return Status;
121 }
122
123 /** AML code generation for a String object node.
124
125 @param [in] String Pointer to a NULL terminated string.
126 @param [out] NewObjectNode If success, contains the created
127 String object node.
128
129 @retval EFI_SUCCESS Success.
130 @retval EFI_INVALID_PARAMETER Invalid parameter.
131 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
132 **/
133 STATIC
134 EFI_STATUS
135 EFIAPI
136 AmlCodeGenString (
137 IN CHAR8 * String,
138 OUT AML_OBJECT_NODE ** NewObjectNode
139 )
140 {
141 EFI_STATUS Status;
142 AML_OBJECT_NODE * ObjectNode;
143 AML_DATA_NODE * DataNode;
144
145 if ((String == NULL) ||
146 (NewObjectNode == NULL)) {
147 ASSERT (0);
148 return EFI_INVALID_PARAMETER;
149 }
150
151 DataNode = NULL;
152
153 Status = AmlCreateObjectNode (
154 AmlGetByteEncodingByOpCode (AML_STRING_PREFIX, 0),
155 0,
156 &ObjectNode
157 );
158 if (EFI_ERROR (Status)) {
159 ASSERT (0);
160 return Status;
161 }
162
163 Status = AmlCreateDataNode (
164 EAmlNodeDataTypeString,
165 (UINT8*)String,
166 (UINT32)AsciiStrLen (String) + 1,
167 &DataNode
168 );
169 if (EFI_ERROR (Status)) {
170 ASSERT (0);
171 goto error_handler;
172 }
173
174 Status = AmlSetFixedArgument (
175 ObjectNode,
176 EAmlParseIndexTerm0,
177 (AML_NODE_HEADER*)DataNode
178 );
179 if (EFI_ERROR (Status)) {
180 ASSERT (0);
181 AmlDeleteTree ((AML_NODE_HEADER*)DataNode);
182 goto error_handler;
183 }
184
185 *NewObjectNode = ObjectNode;
186 return Status;
187
188 error_handler:
189 AmlDeleteTree ((AML_NODE_HEADER*)ObjectNode);
190 return Status;
191 }
192
193 /** AML code generation for an Integer object node.
194
195 @param [in] Integer Integer of the Integer object node.
196 @param [out] NewObjectNode If success, contains the created
197 Integer object node.
198
199 @retval EFI_SUCCESS Success.
200 @retval EFI_INVALID_PARAMETER Invalid parameter.
201 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
202 **/
203 STATIC
204 EFI_STATUS
205 EFIAPI
206 AmlCodeGenInteger (
207 IN UINT64 Integer,
208 OUT AML_OBJECT_NODE ** NewObjectNode
209 )
210 {
211 EFI_STATUS Status;
212 INT8 ValueWidthDiff;
213
214 if (NewObjectNode == NULL) {
215 ASSERT (0);
216 return EFI_INVALID_PARAMETER;
217 }
218
219 // Create an object node containing Zero.
220 Status = AmlCreateObjectNode (
221 AmlGetByteEncodingByOpCode (AML_ZERO_OP, 0),
222 0,
223 NewObjectNode
224 );
225 if (EFI_ERROR (Status)) {
226 ASSERT (0);
227 return Status;
228 }
229
230 // Update the object node with integer value.
231 Status = AmlNodeSetIntegerValue (*NewObjectNode, Integer, &ValueWidthDiff);
232 if (EFI_ERROR (Status)) {
233 ASSERT (0);
234 AmlDeleteTree ((AML_NODE_HEADER*)*NewObjectNode);
235 }
236
237 return Status;
238 }
239
240 /** AML code generation for a Package object node.
241
242 The package generated is empty. New elements can be added via its
243 list of variable arguments.
244
245 @param [out] NewObjectNode If success, contains the created
246 Package object node.
247
248 @retval EFI_SUCCESS Success.
249 @retval EFI_INVALID_PARAMETER Invalid parameter.
250 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
251 **/
252 STATIC
253 EFI_STATUS
254 EFIAPI
255 AmlCodeGenPackage (
256 OUT AML_OBJECT_NODE ** NewObjectNode
257 )
258 {
259 EFI_STATUS Status;
260 AML_DATA_NODE * DataNode;
261 UINT8 NodeCount;
262
263 if (NewObjectNode == NULL) {
264 ASSERT (0);
265 return EFI_INVALID_PARAMETER;
266 }
267
268 NodeCount = 0;
269
270 // Create an object node.
271 // PkgLen is 2:
272 // - one byte to store the PkgLength
273 // - one byte for the NumElements.
274 // Cf ACPI6.3, s20.2.5 "Term Objects Encoding"
275 // DefPackage := PackageOp PkgLength NumElements PackageElementList
276 // NumElements := ByteData
277 Status = AmlCreateObjectNode (
278 AmlGetByteEncodingByOpCode (AML_PACKAGE_OP, 0),
279 2,
280 NewObjectNode
281 );
282 if (EFI_ERROR (Status)) {
283 ASSERT (0);
284 return Status;
285 }
286
287 // NumElements is a ByteData.
288 Status = AmlCreateDataNode (
289 EAmlNodeDataTypeUInt,
290 &NodeCount,
291 sizeof (NodeCount),
292 &DataNode
293 );
294 if (EFI_ERROR (Status)) {
295 ASSERT (0);
296 goto error_handler;
297 }
298
299 Status = AmlSetFixedArgument (
300 *NewObjectNode,
301 EAmlParseIndexTerm0,
302 (AML_NODE_HEADER*)DataNode
303 );
304 if (EFI_ERROR (Status)) {
305 ASSERT (0);
306 goto error_handler;
307 }
308
309 return Status;
310
311 error_handler:
312 AmlDeleteTree ((AML_NODE_HEADER*)*NewObjectNode);
313 if (DataNode != NULL) {
314 AmlDeleteTree ((AML_NODE_HEADER*)DataNode);
315 }
316 return Status;
317 }
318
319 /** AML code generation for a Name object node.
320
321 @param [in] NameString The new variable name.
322 Must be a NULL-terminated ASL NameString
323 e.g.: "DEV0", "DV15.DEV0", etc.
324 This input string is copied.
325 @param [in] Object Object associated to the NameString.
326 @param [in] ParentNode If provided, set ParentNode as the parent
327 of the node created.
328 @param [out] NewObjectNode If success, contains the created node.
329
330 @retval EFI_SUCCESS Success.
331 @retval EFI_INVALID_PARAMETER Invalid parameter.
332 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
333 **/
334 STATIC
335 EFI_STATUS
336 EFIAPI
337 AmlCodeGenName (
338 IN CONST CHAR8 * NameString,
339 IN AML_OBJECT_NODE * Object,
340 IN AML_NODE_HEADER * ParentNode, OPTIONAL
341 OUT AML_OBJECT_NODE ** NewObjectNode OPTIONAL
342 )
343 {
344 EFI_STATUS Status;
345 AML_OBJECT_NODE * ObjectNode;
346 AML_DATA_NODE * DataNode;
347 CHAR8 * AmlNameString;
348 UINT32 AmlNameStringSize;
349
350 if ((NameString == NULL) ||
351 (Object == NULL) ||
352 ((ParentNode == NULL) && (NewObjectNode == NULL))) {
353 ASSERT (0);
354 return EFI_INVALID_PARAMETER;
355 }
356
357 ObjectNode = NULL;
358 DataNode = NULL;
359 AmlNameString = NULL;
360
361 Status = ConvertAslNameToAmlName (NameString, &AmlNameString);
362 if (EFI_ERROR (Status)) {
363 ASSERT (0);
364 return Status;
365 }
366
367 Status = AmlGetNameStringSize (AmlNameString, &AmlNameStringSize);
368 if (EFI_ERROR (Status)) {
369 ASSERT (0);
370 goto error_handler1;
371 }
372
373 Status = AmlCreateObjectNode (
374 AmlGetByteEncodingByOpCode (AML_NAME_OP, 0),
375 0,
376 &ObjectNode
377 );
378 if (EFI_ERROR (Status)) {
379 ASSERT (0);
380 goto error_handler1;
381 }
382
383 Status = AmlCreateDataNode (
384 EAmlNodeDataTypeNameString,
385 (UINT8*)AmlNameString,
386 AmlNameStringSize,
387 &DataNode
388 );
389 if (EFI_ERROR (Status)) {
390 ASSERT (0);
391 goto error_handler2;
392 }
393
394 Status = AmlSetFixedArgument (
395 ObjectNode,
396 EAmlParseIndexTerm0,
397 (AML_NODE_HEADER*)DataNode
398 );
399 if (EFI_ERROR (Status)) {
400 ASSERT (0);
401 AmlDeleteTree ((AML_NODE_HEADER*)DataNode);
402 goto error_handler2;
403 }
404
405 Status = AmlSetFixedArgument (
406 ObjectNode,
407 EAmlParseIndexTerm1,
408 (AML_NODE_HEADER*)Object
409 );
410 if (EFI_ERROR (Status)) {
411 ASSERT (0);
412 goto error_handler2;
413 }
414
415 Status = LinkNode (
416 ObjectNode,
417 ParentNode,
418 NewObjectNode
419 );
420 if (EFI_ERROR (Status)) {
421 ASSERT (0);
422 goto error_handler2;
423 }
424
425 // Free AmlNameString before returning as it is copied
426 // in the call to AmlCreateDataNode().
427 goto error_handler1;
428
429 error_handler2:
430 if (ObjectNode != NULL) {
431 AmlDeleteTree ((AML_NODE_HEADER*)ObjectNode);
432 }
433
434 error_handler1:
435 if (AmlNameString != NULL) {
436 FreePool (AmlNameString);
437 }
438
439 return Status;
440 }
441
442 /** AML code generation for a Name object node, containing a String.
443
444 AmlCodeGenNameString ("_HID", "HID0000", ParentNode, NewObjectNode) is
445 equivalent of the following ASL code:
446 Name(_HID, "HID0000")
447
448 @param [in] NameString The new variable name.
449 Must be a NULL-terminated ASL NameString
450 e.g.: "DEV0", "DV15.DEV0", etc.
451 The input string is copied.
452 @param [in] String NULL terminated String to associate to the
453 NameString.
454 @param [in] ParentNode If provided, set ParentNode as the parent
455 of the node created.
456 @param [out] NewObjectNode If success, contains the created node.
457
458 @retval EFI_SUCCESS Success.
459 @retval EFI_INVALID_PARAMETER Invalid parameter.
460 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
461 **/
462 EFI_STATUS
463 EFIAPI
464 AmlCodeGenNameString (
465 IN CONST CHAR8 * NameString,
466 IN CHAR8 * String,
467 IN AML_NODE_HEADER * ParentNode, OPTIONAL
468 OUT AML_OBJECT_NODE ** NewObjectNode OPTIONAL
469 )
470 {
471 EFI_STATUS Status;
472 AML_OBJECT_NODE * ObjectNode;
473
474 if ((NameString == NULL) ||
475 (String == NULL) ||
476 ((ParentNode == NULL) && (NewObjectNode == NULL))) {
477 ASSERT (0);
478 return EFI_INVALID_PARAMETER;
479 }
480
481 Status = AmlCodeGenString (String, &ObjectNode);
482 if (EFI_ERROR (Status)) {
483 ASSERT (0);
484 return Status;
485 }
486
487 Status = AmlCodeGenName (
488 NameString,
489 ObjectNode,
490 ParentNode,
491 NewObjectNode
492 );
493 if (EFI_ERROR (Status)) {
494 ASSERT (0);
495 AmlDeleteTree ((AML_NODE_HEADER*)ObjectNode);
496 }
497
498 return Status;
499 }
500
501 /** AML code generation for a Name object node, containing an Integer.
502
503 AmlCodeGenNameInteger ("_UID", 1, ParentNode, NewObjectNode) is
504 equivalent of the following ASL code:
505 Name(_UID, One)
506
507 @param [in] NameString The new variable name.
508 Must be a NULL-terminated ASL NameString
509 e.g.: "DEV0", "DV15.DEV0", etc.
510 The input string is copied.
511 @param [in] Integer Integer to associate to the NameString.
512 @param [in] ParentNode If provided, set ParentNode as the parent
513 of the node created.
514 @param [out] NewObjectNode If success, contains the created node.
515
516 @retval EFI_SUCCESS Success.
517 @retval EFI_INVALID_PARAMETER Invalid parameter.
518 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
519 **/
520 EFI_STATUS
521 EFIAPI
522 AmlCodeGenNameInteger (
523 IN CONST CHAR8 * NameString,
524 IN UINT64 Integer,
525 IN AML_NODE_HEADER * ParentNode, OPTIONAL
526 OUT AML_OBJECT_NODE ** NewObjectNode OPTIONAL
527 )
528 {
529 EFI_STATUS Status;
530 AML_OBJECT_NODE * ObjectNode;
531
532 if ((NameString == NULL) ||
533 ((ParentNode == NULL) && (NewObjectNode == NULL))) {
534 ASSERT (0);
535 return EFI_INVALID_PARAMETER;
536 }
537
538 Status = AmlCodeGenInteger (Integer, &ObjectNode);
539 if (EFI_ERROR (Status)) {
540 ASSERT (0);
541 return Status;
542 }
543
544 Status = AmlCodeGenName (
545 NameString,
546 ObjectNode,
547 ParentNode,
548 NewObjectNode
549 );
550 if (EFI_ERROR (Status)) {
551 ASSERT (0);
552 AmlDeleteTree ((AML_NODE_HEADER*)ObjectNode);
553 }
554
555 return Status;
556 }
557
558 /** AML code generation for a Device object node.
559
560 AmlCodeGenDevice ("COM0", ParentNode, NewObjectNode) is
561 equivalent of the following ASL code:
562 Device(COM0) {}
563
564 @param [in] NameString The new Device's name.
565 Must be a NULL-terminated ASL NameString
566 e.g.: "DEV0", "DV15.DEV0", etc.
567 The input string is copied.
568 @param [in] ParentNode If provided, set ParentNode as the parent
569 of the node created.
570 @param [out] NewObjectNode If success, contains the created node.
571
572 @retval EFI_SUCCESS Success.
573 @retval EFI_INVALID_PARAMETER Invalid parameter.
574 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
575 **/
576 EFI_STATUS
577 EFIAPI
578 AmlCodeGenDevice (
579 IN CONST CHAR8 * NameString,
580 IN AML_NODE_HEADER * ParentNode, OPTIONAL
581 OUT AML_OBJECT_NODE ** NewObjectNode OPTIONAL
582 )
583 {
584 EFI_STATUS Status;
585 AML_OBJECT_NODE * ObjectNode;
586 AML_DATA_NODE * DataNode;
587 CHAR8 * AmlNameString;
588 UINT32 AmlNameStringSize;
589
590 if ((NameString == NULL) ||
591 ((ParentNode == NULL) && (NewObjectNode == NULL))) {
592 ASSERT (0);
593 return EFI_INVALID_PARAMETER;
594 }
595
596 ObjectNode = NULL;
597 DataNode = NULL;
598 AmlNameString = NULL;
599
600 Status = ConvertAslNameToAmlName (NameString, &AmlNameString);
601 if (EFI_ERROR (Status)) {
602 ASSERT (0);
603 return Status;
604 }
605
606 Status = AmlGetNameStringSize (AmlNameString, &AmlNameStringSize);
607 if (EFI_ERROR (Status)) {
608 ASSERT (0);
609 goto error_handler1;
610 }
611
612 Status = AmlCreateObjectNode (
613 AmlGetByteEncodingByOpCode (AML_EXT_OP, AML_EXT_DEVICE_OP),
614 AmlNameStringSize + AmlComputePkgLengthWidth (AmlNameStringSize),
615 &ObjectNode
616 );
617 if (EFI_ERROR (Status)) {
618 ASSERT (0);
619 goto error_handler1;
620 }
621
622 Status = AmlCreateDataNode (
623 EAmlNodeDataTypeNameString,
624 (UINT8*)AmlNameString,
625 AmlNameStringSize,
626 &DataNode
627 );
628 if (EFI_ERROR (Status)) {
629 ASSERT (0);
630 goto error_handler2;
631 }
632
633 Status = AmlSetFixedArgument (
634 ObjectNode,
635 EAmlParseIndexTerm0,
636 (AML_NODE_HEADER*)DataNode
637 );
638 if (EFI_ERROR (Status)) {
639 ASSERT (0);
640 AmlDeleteTree ((AML_NODE_HEADER*)DataNode);
641 goto error_handler2;
642 }
643
644 Status = LinkNode (
645 ObjectNode,
646 ParentNode,
647 NewObjectNode
648 );
649 if (EFI_ERROR (Status)) {
650 ASSERT (0);
651 goto error_handler2;
652 }
653
654 // Free AmlNameString before returning as it is copied
655 // in the call to AmlCreateDataNode().
656 goto error_handler1;
657
658 error_handler2:
659 if (ObjectNode != NULL) {
660 AmlDeleteTree ((AML_NODE_HEADER*)ObjectNode);
661 }
662
663 error_handler1:
664 if (AmlNameString != NULL) {
665 FreePool (AmlNameString);
666 }
667
668 return Status;
669 }
670
671 /** AML code generation for a Scope object node.
672
673 AmlCodeGenScope ("_SB", ParentNode, NewObjectNode) is
674 equivalent of the following ASL code:
675 Scope(_SB) {}
676
677 @param [in] NameString The new Scope's name.
678 Must be a NULL-terminated ASL NameString
679 e.g.: "DEV0", "DV15.DEV0", etc.
680 The input string is copied.
681 @param [in] ParentNode If provided, set ParentNode as the parent
682 of the node created.
683 @param [out] NewObjectNode If success, contains the created node.
684
685 @retval EFI_SUCCESS Success.
686 @retval EFI_INVALID_PARAMETER Invalid parameter.
687 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
688 **/
689 EFI_STATUS
690 EFIAPI
691 AmlCodeGenScope (
692 IN CONST CHAR8 * NameString,
693 IN AML_NODE_HEADER * ParentNode, OPTIONAL
694 OUT AML_OBJECT_NODE ** NewObjectNode OPTIONAL
695 )
696 {
697 EFI_STATUS Status;
698 AML_OBJECT_NODE * ObjectNode;
699 AML_DATA_NODE * DataNode;
700 CHAR8 * AmlNameString;
701 UINT32 AmlNameStringSize;
702
703 if ((NameString == NULL) ||
704 ((ParentNode == NULL) && (NewObjectNode == NULL))) {
705 ASSERT (0);
706 return EFI_INVALID_PARAMETER;
707 }
708
709 ObjectNode = NULL;
710 DataNode = NULL;
711 AmlNameString = NULL;
712
713 Status = ConvertAslNameToAmlName (NameString, &AmlNameString);
714 if (EFI_ERROR (Status)) {
715 ASSERT (0);
716 return Status;
717 }
718
719 Status = AmlGetNameStringSize (AmlNameString, &AmlNameStringSize);
720 if (EFI_ERROR (Status)) {
721 ASSERT (0);
722 goto error_handler1;
723 }
724
725 Status = AmlCreateObjectNode (
726 AmlGetByteEncodingByOpCode (AML_SCOPE_OP, 0),
727 AmlNameStringSize + AmlComputePkgLengthWidth (AmlNameStringSize),
728 &ObjectNode
729 );
730 if (EFI_ERROR (Status)) {
731 ASSERT (0);
732 goto error_handler1;
733 }
734
735 Status = AmlCreateDataNode (
736 EAmlNodeDataTypeNameString,
737 (UINT8*)AmlNameString,
738 AmlNameStringSize,
739 &DataNode
740 );
741 if (EFI_ERROR (Status)) {
742 ASSERT (0);
743 goto error_handler2;
744 }
745
746 Status = AmlSetFixedArgument (
747 ObjectNode,
748 EAmlParseIndexTerm0,
749 (AML_NODE_HEADER*)DataNode
750 );
751 if (EFI_ERROR (Status)) {
752 ASSERT (0);
753 AmlDeleteTree ((AML_NODE_HEADER*)DataNode);
754 goto error_handler2;
755 }
756
757 Status = LinkNode (
758 ObjectNode,
759 ParentNode,
760 NewObjectNode
761 );
762 if (EFI_ERROR (Status)) {
763 ASSERT (0);
764 goto error_handler2;
765 }
766
767 // Free AmlNameString before returning as it is copied
768 // in the call to AmlCreateDataNode().
769 goto error_handler1;
770
771 error_handler2:
772 if (ObjectNode != NULL) {
773 AmlDeleteTree ((AML_NODE_HEADER*)ObjectNode);
774 }
775
776 error_handler1:
777 if (AmlNameString != NULL) {
778 FreePool (AmlNameString);
779 }
780
781 return Status;
782 }