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