]> git.proxmox.com Git - mirror_edk2.git/blame - DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlCodeGen.c
DynamicTablesPkg: Change OPTIONAL keyword usage style
[mirror_edk2.git] / DynamicTablesPkg / Library / Common / AmlLib / CodeGen / AmlCodeGen.c
CommitLineData
3a681567
PG
1/** @file\r
2 AML Code Generation.\r
3\r
1e33479b 4 Copyright (c) 2020 - 2021, Arm Limited. All rights reserved.<BR>\r
3a681567
PG
5\r
6 SPDX-License-Identifier: BSD-2-Clause-Patent\r
7**/\r
8\r
9#include <AmlNodeDefines.h>\r
10\r
11#include <AcpiTableGenerator.h>\r
12\r
13#include <AmlCoreInterface.h>\r
14#include <AmlEncoding/Aml.h>\r
a5e36ad9 15#include <Api/AmlApiHelper.h>\r
ce15936f 16#include <CodeGen/AmlResourceDataCodeGen.h>\r
3a681567
PG
17#include <Tree/AmlNode.h>\r
18#include <Tree/AmlTree.h>\r
19#include <String/AmlString.h>\r
20#include <Utils/AmlUtility.h>\r
21\r
22/** Utility function to link a node when returning from a CodeGen function.\r
23\r
24 @param [in] Node Newly created node.\r
25 @param [in] ParentNode If provided, set ParentNode as the parent\r
26 of the node created.\r
2dd7dd39
PG
27 @param [out] NewObjectNode If not NULL:\r
28 - and Success, contains the created Node.\r
29 - and Error, reset to NULL.\r
3a681567
PG
30\r
31 @retval EFI_SUCCESS The function completed successfully.\r
32 @retval EFI_INVALID_PARAMETER Invalid parameter.\r
33**/\r
34STATIC\r
35EFI_STATUS\r
36EFIAPI\r
37LinkNode (\r
38 IN AML_OBJECT_NODE * Node,\r
39 IN AML_NODE_HEADER * ParentNode,\r
5e0b708f 40 OUT AML_OBJECT_NODE ** NewObjectNode\r
3a681567
PG
41 )\r
42{\r
43 EFI_STATUS Status;\r
44\r
45 if (NewObjectNode != NULL) {\r
2dd7dd39 46 *NewObjectNode = NULL;\r
3a681567
PG
47 }\r
48\r
49 // Add RdNode as the last element.\r
50 if (ParentNode != NULL) {\r
51 Status = AmlVarListAddTail (ParentNode, (AML_NODE_HEADER*)Node);\r
52 if (EFI_ERROR (Status)) {\r
53 ASSERT (0);\r
54 return Status;\r
55 }\r
56 }\r
57\r
2dd7dd39
PG
58 if (NewObjectNode != NULL) {\r
59 *NewObjectNode = Node;\r
60 }\r
61\r
3a681567
PG
62 return EFI_SUCCESS;\r
63}\r
64\r
65/** AML code generation for DefinitionBlock.\r
66\r
67 Create a Root Node handle.\r
68 It is the caller's responsibility to free the allocated memory\r
69 with the AmlDeleteTree function.\r
70\r
71 AmlCodeGenDefinitionBlock (TableSignature, OemID, TableID, OEMRevision) is\r
72 equivalent to the following ASL code:\r
73 DefinitionBlock (AMLFileName, TableSignature, ComplianceRevision,\r
74 OemID, TableID, OEMRevision) {}\r
75 with the ComplianceRevision set to 2 and the AMLFileName is ignored.\r
76\r
77 @param[in] TableSignature 4-character ACPI signature.\r
78 Must be 'DSDT' or 'SSDT'.\r
79 @param[in] OemId 6-character string OEM identifier.\r
80 @param[in] OemTableId 8-character string OEM table identifier.\r
81 @param[in] OemRevision OEM revision number.\r
5e0b708f 82 @param[out] NewRootNode Pointer to the root node representing a\r
3a681567
PG
83 Definition Block.\r
84\r
85 @retval EFI_SUCCESS Success.\r
86 @retval EFI_INVALID_PARAMETER Invalid parameter.\r
87 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
88**/\r
89EFI_STATUS\r
90EFIAPI\r
91AmlCodeGenDefinitionBlock (\r
92 IN CONST CHAR8 * TableSignature,\r
93 IN CONST CHAR8 * OemId,\r
94 IN CONST CHAR8 * OemTableId,\r
95 IN UINT32 OemRevision,\r
96 OUT AML_ROOT_NODE ** NewRootNode\r
97 )\r
98{\r
99 EFI_STATUS Status;\r
100 EFI_ACPI_DESCRIPTION_HEADER AcpiHeader;\r
101\r
102 if ((TableSignature == NULL) ||\r
103 (OemId == NULL) ||\r
104 (OemTableId == NULL) ||\r
105 (NewRootNode == NULL)) {\r
106 ASSERT (0);\r
107 return EFI_INVALID_PARAMETER;\r
108 }\r
109\r
110 CopyMem (&AcpiHeader.Signature, TableSignature, 4);\r
111 AcpiHeader.Length = sizeof (EFI_ACPI_DESCRIPTION_HEADER);\r
112 AcpiHeader.Revision = 2;\r
113 CopyMem (&AcpiHeader.OemId, OemId, 6);\r
114 CopyMem (&AcpiHeader.OemTableId, OemTableId, 8);\r
115 AcpiHeader.OemRevision = OemRevision;\r
116 AcpiHeader.CreatorId = TABLE_GENERATOR_CREATOR_ID_ARM;\r
117 AcpiHeader.CreatorRevision = CREATE_REVISION (1, 0);\r
118\r
119 Status = AmlCreateRootNode (&AcpiHeader, NewRootNode);\r
120 ASSERT_EFI_ERROR (Status);\r
121\r
122 return Status;\r
123}\r
124\r
125/** AML code generation for a String object node.\r
126\r
127 @param [in] String Pointer to a NULL terminated string.\r
128 @param [out] NewObjectNode If success, contains the created\r
129 String object node.\r
130\r
131 @retval EFI_SUCCESS Success.\r
132 @retval EFI_INVALID_PARAMETER Invalid parameter.\r
133 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
134**/\r
135STATIC\r
136EFI_STATUS\r
137EFIAPI\r
138AmlCodeGenString (\r
139 IN CHAR8 * String,\r
140 OUT AML_OBJECT_NODE ** NewObjectNode\r
141 )\r
142{\r
143 EFI_STATUS Status;\r
144 AML_OBJECT_NODE * ObjectNode;\r
145 AML_DATA_NODE * DataNode;\r
146\r
147 if ((String == NULL) ||\r
148 (NewObjectNode == NULL)) {\r
149 ASSERT (0);\r
150 return EFI_INVALID_PARAMETER;\r
151 }\r
152\r
3a681567
PG
153 DataNode = NULL;\r
154\r
155 Status = AmlCreateObjectNode (\r
156 AmlGetByteEncodingByOpCode (AML_STRING_PREFIX, 0),\r
157 0,\r
158 &ObjectNode\r
159 );\r
160 if (EFI_ERROR (Status)) {\r
161 ASSERT (0);\r
162 return Status;\r
163 }\r
164\r
165 Status = AmlCreateDataNode (\r
166 EAmlNodeDataTypeString,\r
167 (UINT8*)String,\r
168 (UINT32)AsciiStrLen (String) + 1,\r
169 &DataNode\r
170 );\r
171 if (EFI_ERROR (Status)) {\r
172 ASSERT (0);\r
173 goto error_handler;\r
174 }\r
175\r
176 Status = AmlSetFixedArgument (\r
177 ObjectNode,\r
178 EAmlParseIndexTerm0,\r
179 (AML_NODE_HEADER*)DataNode\r
180 );\r
181 if (EFI_ERROR (Status)) {\r
182 ASSERT (0);\r
183 AmlDeleteTree ((AML_NODE_HEADER*)DataNode);\r
184 goto error_handler;\r
185 }\r
186\r
187 *NewObjectNode = ObjectNode;\r
188 return Status;\r
189\r
190error_handler:\r
37bd0817 191 AmlDeleteTree ((AML_NODE_HEADER*)ObjectNode);\r
3a681567
PG
192 return Status;\r
193}\r
194\r
195/** AML code generation for an Integer object node.\r
196\r
197 @param [in] Integer Integer of the Integer object node.\r
198 @param [out] NewObjectNode If success, contains the created\r
199 Integer object node.\r
200\r
201 @retval EFI_SUCCESS Success.\r
202 @retval EFI_INVALID_PARAMETER Invalid parameter.\r
203 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
204**/\r
205STATIC\r
206EFI_STATUS\r
207EFIAPI\r
208AmlCodeGenInteger (\r
209 IN UINT64 Integer,\r
210 OUT AML_OBJECT_NODE ** NewObjectNode\r
211 )\r
212{\r
213 EFI_STATUS Status;\r
214 INT8 ValueWidthDiff;\r
215\r
216 if (NewObjectNode == NULL) {\r
217 ASSERT (0);\r
218 return EFI_INVALID_PARAMETER;\r
219 }\r
220\r
221 // Create an object node containing Zero.\r
222 Status = AmlCreateObjectNode (\r
223 AmlGetByteEncodingByOpCode (AML_ZERO_OP, 0),\r
224 0,\r
225 NewObjectNode\r
226 );\r
227 if (EFI_ERROR (Status)) {\r
228 ASSERT (0);\r
229 return Status;\r
230 }\r
231\r
232 // Update the object node with integer value.\r
233 Status = AmlNodeSetIntegerValue (*NewObjectNode, Integer, &ValueWidthDiff);\r
234 if (EFI_ERROR (Status)) {\r
235 ASSERT (0);\r
236 AmlDeleteTree ((AML_NODE_HEADER*)*NewObjectNode);\r
237 }\r
238\r
239 return Status;\r
240}\r
241\r
1e33479b
PG
242/** AML code generation for a Package object node.\r
243\r
244 The package generated is empty. New elements can be added via its\r
245 list of variable arguments.\r
246\r
247 @param [out] NewObjectNode If success, contains the created\r
248 Package object node.\r
249\r
250 @retval EFI_SUCCESS Success.\r
251 @retval EFI_INVALID_PARAMETER Invalid parameter.\r
252 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
253**/\r
254STATIC\r
255EFI_STATUS\r
256EFIAPI\r
257AmlCodeGenPackage (\r
258 OUT AML_OBJECT_NODE ** NewObjectNode\r
259 )\r
260{\r
261 EFI_STATUS Status;\r
262 AML_DATA_NODE * DataNode;\r
263 UINT8 NodeCount;\r
264\r
265 if (NewObjectNode == NULL) {\r
266 ASSERT (0);\r
267 return EFI_INVALID_PARAMETER;\r
268 }\r
269\r
270 NodeCount = 0;\r
271\r
272 // Create an object node.\r
273 // PkgLen is 2:\r
274 // - one byte to store the PkgLength\r
275 // - one byte for the NumElements.\r
276 // Cf ACPI6.3, s20.2.5 "Term Objects Encoding"\r
277 // DefPackage := PackageOp PkgLength NumElements PackageElementList\r
278 // NumElements := ByteData\r
279 Status = AmlCreateObjectNode (\r
280 AmlGetByteEncodingByOpCode (AML_PACKAGE_OP, 0),\r
281 2,\r
282 NewObjectNode\r
283 );\r
284 if (EFI_ERROR (Status)) {\r
285 ASSERT (0);\r
286 return Status;\r
287 }\r
288\r
289 // NumElements is a ByteData.\r
290 Status = AmlCreateDataNode (\r
291 EAmlNodeDataTypeUInt,\r
292 &NodeCount,\r
293 sizeof (NodeCount),\r
294 &DataNode\r
295 );\r
296 if (EFI_ERROR (Status)) {\r
297 ASSERT (0);\r
298 goto error_handler;\r
299 }\r
300\r
301 Status = AmlSetFixedArgument (\r
302 *NewObjectNode,\r
303 EAmlParseIndexTerm0,\r
304 (AML_NODE_HEADER*)DataNode\r
305 );\r
306 if (EFI_ERROR (Status)) {\r
307 ASSERT (0);\r
308 goto error_handler;\r
309 }\r
310\r
311 return Status;\r
312\r
313error_handler:\r
314 AmlDeleteTree ((AML_NODE_HEADER*)*NewObjectNode);\r
315 if (DataNode != NULL) {\r
316 AmlDeleteTree ((AML_NODE_HEADER*)DataNode);\r
317 }\r
318 return Status;\r
319}\r
320\r
ce15936f
PG
321/** AML code generation for a Buffer object node.\r
322\r
323 To create a Buffer object node with an empty buffer,\r
324 call the function with (Buffer=NULL, BufferSize=0).\r
325\r
326 @param [in] Buffer Buffer to set for the created Buffer\r
327 object node. The Buffer's content is copied.\r
328 NULL if there is no buffer to set for\r
329 the Buffer node.\r
330 @param [in] BufferSize Size of the Buffer.\r
331 0 if there is no buffer to set for\r
332 the Buffer node.\r
333 @param [out] NewObjectNode If success, contains the created\r
334 Buffer object node.\r
335\r
336 @retval EFI_SUCCESS Success.\r
337 @retval EFI_INVALID_PARAMETER Invalid parameter.\r
338 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
339**/\r
340STATIC\r
341EFI_STATUS\r
342EFIAPI\r
343AmlCodeGenBuffer (\r
fe2d8189
MK
344 IN CONST UINT8 * Buffer OPTIONAL,\r
345 IN UINT32 BufferSize OPTIONAL,\r
ce15936f
PG
346 OUT AML_OBJECT_NODE ** NewObjectNode\r
347 )\r
348{\r
349 EFI_STATUS Status;\r
350 AML_OBJECT_NODE * BufferNode;\r
351 AML_OBJECT_NODE * BufferSizeNode;\r
352 UINT32 BufferSizeNodeSize;\r
353 AML_DATA_NODE * DataNode;\r
354 UINT32 PkgLen;\r
355\r
356 // Buffer and BufferSize must be either both set, or both clear.\r
357 if ((NewObjectNode == NULL) ||\r
358 ((Buffer == NULL) != (BufferSize == 0))) {\r
359 ASSERT (0);\r
360 return EFI_INVALID_PARAMETER;\r
361 }\r
362\r
363 BufferNode = NULL;\r
364 DataNode = NULL;\r
365\r
366 // Cf ACPI 6.3 specification, s20.2.5.4 "Type 2 Opcodes Encoding"\r
367 // DefBuffer := BufferOp PkgLength BufferSize ByteList\r
368 // BufferOp := 0x11\r
369 // BufferSize := TermArg => Integer\r
370\r
371 Status = AmlCodeGenInteger (BufferSize, &BufferSizeNode);\r
372 if (EFI_ERROR (Status)) {\r
373 ASSERT (0);\r
374 return Status;\r
375 }\r
376\r
377 // Get the number of bytes required to encode the BufferSizeNode.\r
378 Status = AmlComputeSize (\r
379 (AML_NODE_HEADER*)BufferSizeNode,\r
380 &BufferSizeNodeSize\r
381 );\r
382 if (EFI_ERROR (Status)) {\r
383 ASSERT (0);\r
384 goto error_handler;\r
385 }\r
386\r
387 // Compute the size to write in the PkgLen.\r
388 Status = AmlComputePkgLength (BufferSizeNodeSize + BufferSize, &PkgLen);\r
389 if (EFI_ERROR (Status)) {\r
390 ASSERT (0);\r
391 goto error_handler;\r
392 }\r
393\r
394 // Create an object node for the buffer.\r
395 Status = AmlCreateObjectNode (\r
396 AmlGetByteEncodingByOpCode (AML_BUFFER_OP, 0),\r
397 PkgLen,\r
398 &BufferNode\r
399 );\r
400 if (EFI_ERROR (Status)) {\r
401 ASSERT (0);\r
402 goto error_handler;\r
403 }\r
404\r
405 // Set the BufferSizeNode as a fixed argument of the BufferNode.\r
406 Status = AmlSetFixedArgument (\r
407 BufferNode,\r
408 EAmlParseIndexTerm0,\r
409 (AML_NODE_HEADER*)BufferSizeNode\r
410 );\r
411 if (EFI_ERROR (Status)) {\r
412 ASSERT (0);\r
413 goto error_handler;\r
414 }\r
415\r
416 // BufferSizeNode is now attached.\r
417 BufferSizeNode = NULL;\r
418\r
419 // If there is a buffer, create a DataNode and attach it to the BufferNode.\r
420 if (Buffer != NULL) {\r
421 Status = AmlCreateDataNode (\r
422 EAmlNodeDataTypeRaw,\r
423 Buffer,\r
424 BufferSize,\r
425 &DataNode\r
426 );\r
427 if (EFI_ERROR (Status)) {\r
428 ASSERT (0);\r
429 goto error_handler;\r
430 }\r
431\r
432 Status = AmlVarListAddTail (\r
433 (AML_NODE_HEADER*)BufferNode,\r
434 (AML_NODE_HEADER*)DataNode\r
435 );\r
436 if (EFI_ERROR (Status)) {\r
437 ASSERT (0);\r
438 goto error_handler;\r
439 }\r
440 }\r
441\r
442 *NewObjectNode = BufferNode;\r
443 return Status;\r
444\r
445error_handler:\r
446 if (BufferSizeNode != NULL) {\r
447 AmlDeleteTree ((AML_NODE_HEADER*)BufferSizeNode);\r
448 }\r
449 if (BufferNode != NULL) {\r
450 AmlDeleteTree ((AML_NODE_HEADER*)BufferNode);\r
451 }\r
452 if (DataNode != NULL) {\r
453 AmlDeleteTree ((AML_NODE_HEADER*)DataNode);\r
454 }\r
455 return Status;\r
456}\r
457\r
458/** AML code generation for a ResourceTemplate.\r
459\r
460 "ResourceTemplate" is a macro defined in ACPI 6.3, s19.3.3\r
461 "ASL Resource Templates". It allows to store resource data elements.\r
462\r
463 In AML, a ResourceTemplate is implemented as a Buffer storing resource\r
464 data elements. An EndTag resource data descriptor must be at the end\r
465 of the list of resource data elements.\r
466 This function generates a Buffer node with an EndTag resource data\r
467 descriptor. It can be seen as an empty list of resource data elements.\r
468\r
469 @param [out] NewObjectNode If success, contains the created\r
470 ResourceTemplate object node.\r
471\r
472 @retval EFI_SUCCESS Success.\r
473 @retval EFI_INVALID_PARAMETER Invalid parameter.\r
474 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
475**/\r
476STATIC\r
477EFI_STATUS\r
478EFIAPI\r
479AmlCodeGenResourceTemplate (\r
480 OUT AML_OBJECT_NODE ** NewObjectNode\r
481 )\r
482{\r
483 EFI_STATUS Status;\r
484 AML_OBJECT_NODE * BufferNode;\r
485\r
486 if (NewObjectNode == NULL) {\r
487 ASSERT (0);\r
488 return EFI_INVALID_PARAMETER;\r
489 }\r
490\r
491 // Create a BufferNode with an empty buffer.\r
492 Status = AmlCodeGenBuffer (NULL, 0, &BufferNode);\r
493 if (EFI_ERROR (Status)) {\r
494 ASSERT (0);\r
495 return Status;\r
496 }\r
497\r
498 // Create an EndTag resource data element and attach it to the Buffer.\r
499 Status = AmlCodeGenEndTag (0, BufferNode, NULL);\r
500 if (EFI_ERROR (Status)) {\r
501 ASSERT (0);\r
502 AmlDeleteTree ((AML_NODE_HEADER*)BufferNode);\r
503 return Status;\r
504 }\r
505\r
506 *NewObjectNode = BufferNode;\r
507 return Status;\r
508}\r
509\r
3a681567
PG
510/** AML code generation for a Name object node.\r
511\r
512 @param [in] NameString The new variable name.\r
513 Must be a NULL-terminated ASL NameString\r
514 e.g.: "DEV0", "DV15.DEV0", etc.\r
515 This input string is copied.\r
516 @param [in] Object Object associated to the NameString.\r
517 @param [in] ParentNode If provided, set ParentNode as the parent\r
518 of the node created.\r
519 @param [out] NewObjectNode If success, contains the created node.\r
520\r
521 @retval EFI_SUCCESS Success.\r
522 @retval EFI_INVALID_PARAMETER Invalid parameter.\r
523 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
524**/\r
525STATIC\r
526EFI_STATUS\r
527EFIAPI\r
528AmlCodeGenName (\r
529 IN CONST CHAR8 * NameString,\r
530 IN AML_OBJECT_NODE * Object,\r
fe2d8189 531 IN AML_NODE_HEADER * ParentNode OPTIONAL,\r
3a681567
PG
532 OUT AML_OBJECT_NODE ** NewObjectNode OPTIONAL\r
533 )\r
534{\r
535 EFI_STATUS Status;\r
536 AML_OBJECT_NODE * ObjectNode;\r
537 AML_DATA_NODE * DataNode;\r
538 CHAR8 * AmlNameString;\r
539 UINT32 AmlNameStringSize;\r
540\r
541 if ((NameString == NULL) ||\r
542 (Object == NULL) ||\r
543 ((ParentNode == NULL) && (NewObjectNode == NULL))) {\r
544 ASSERT (0);\r
545 return EFI_INVALID_PARAMETER;\r
546 }\r
547\r
548 ObjectNode = NULL;\r
549 DataNode = NULL;\r
550 AmlNameString = NULL;\r
551\r
552 Status = ConvertAslNameToAmlName (NameString, &AmlNameString);\r
553 if (EFI_ERROR (Status)) {\r
554 ASSERT (0);\r
555 return Status;\r
556 }\r
557\r
558 Status = AmlGetNameStringSize (AmlNameString, &AmlNameStringSize);\r
559 if (EFI_ERROR (Status)) {\r
560 ASSERT (0);\r
561 goto error_handler1;\r
562 }\r
563\r
564 Status = AmlCreateObjectNode (\r
565 AmlGetByteEncodingByOpCode (AML_NAME_OP, 0),\r
566 0,\r
567 &ObjectNode\r
568 );\r
569 if (EFI_ERROR (Status)) {\r
570 ASSERT (0);\r
571 goto error_handler1;\r
572 }\r
573\r
574 Status = AmlCreateDataNode (\r
575 EAmlNodeDataTypeNameString,\r
576 (UINT8*)AmlNameString,\r
577 AmlNameStringSize,\r
578 &DataNode\r
579 );\r
580 if (EFI_ERROR (Status)) {\r
581 ASSERT (0);\r
582 goto error_handler2;\r
583 }\r
584\r
585 Status = AmlSetFixedArgument (\r
586 ObjectNode,\r
587 EAmlParseIndexTerm0,\r
588 (AML_NODE_HEADER*)DataNode\r
589 );\r
590 if (EFI_ERROR (Status)) {\r
591 ASSERT (0);\r
592 AmlDeleteTree ((AML_NODE_HEADER*)DataNode);\r
593 goto error_handler2;\r
594 }\r
595\r
596 Status = AmlSetFixedArgument (\r
597 ObjectNode,\r
598 EAmlParseIndexTerm1,\r
599 (AML_NODE_HEADER*)Object\r
600 );\r
601 if (EFI_ERROR (Status)) {\r
602 ASSERT (0);\r
603 goto error_handler2;\r
604 }\r
605\r
606 Status = LinkNode (\r
607 ObjectNode,\r
608 ParentNode,\r
609 NewObjectNode\r
610 );\r
611 if (EFI_ERROR (Status)) {\r
612 ASSERT (0);\r
613 goto error_handler2;\r
614 }\r
615\r
616 // Free AmlNameString before returning as it is copied\r
617 // in the call to AmlCreateDataNode().\r
618 goto error_handler1;\r
619\r
620error_handler2:\r
621 if (ObjectNode != NULL) {\r
622 AmlDeleteTree ((AML_NODE_HEADER*)ObjectNode);\r
623 }\r
624\r
625error_handler1:\r
626 if (AmlNameString != NULL) {\r
627 FreePool (AmlNameString);\r
628 }\r
629\r
630 return Status;\r
631}\r
632\r
633/** AML code generation for a Name object node, containing a String.\r
634\r
635 AmlCodeGenNameString ("_HID", "HID0000", ParentNode, NewObjectNode) is\r
636 equivalent of the following ASL code:\r
637 Name(_HID, "HID0000")\r
638\r
639 @param [in] NameString The new variable name.\r
640 Must be a NULL-terminated ASL NameString\r
641 e.g.: "DEV0", "DV15.DEV0", etc.\r
642 The input string is copied.\r
643 @param [in] String NULL terminated String to associate to the\r
644 NameString.\r
645 @param [in] ParentNode If provided, set ParentNode as the parent\r
646 of the node created.\r
647 @param [out] NewObjectNode If success, contains the created node.\r
648\r
649 @retval EFI_SUCCESS Success.\r
650 @retval EFI_INVALID_PARAMETER Invalid parameter.\r
651 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
652**/\r
653EFI_STATUS\r
654EFIAPI\r
655AmlCodeGenNameString (\r
656 IN CONST CHAR8 * NameString,\r
657 IN CHAR8 * String,\r
fe2d8189 658 IN AML_NODE_HEADER * ParentNode OPTIONAL,\r
3a681567
PG
659 OUT AML_OBJECT_NODE ** NewObjectNode OPTIONAL\r
660 )\r
661{\r
662 EFI_STATUS Status;\r
663 AML_OBJECT_NODE * ObjectNode;\r
664\r
665 if ((NameString == NULL) ||\r
666 (String == NULL) ||\r
667 ((ParentNode == NULL) && (NewObjectNode == NULL))) {\r
668 ASSERT (0);\r
669 return EFI_INVALID_PARAMETER;\r
670 }\r
671\r
672 Status = AmlCodeGenString (String, &ObjectNode);\r
673 if (EFI_ERROR (Status)) {\r
674 ASSERT (0);\r
675 return Status;\r
676 }\r
677\r
678 Status = AmlCodeGenName (\r
679 NameString,\r
680 ObjectNode,\r
681 ParentNode,\r
682 NewObjectNode\r
683 );\r
684 if (EFI_ERROR (Status)) {\r
685 ASSERT (0);\r
686 AmlDeleteTree ((AML_NODE_HEADER*)ObjectNode);\r
687 }\r
688\r
689 return Status;\r
690}\r
691\r
692/** AML code generation for a Name object node, containing an Integer.\r
693\r
694 AmlCodeGenNameInteger ("_UID", 1, ParentNode, NewObjectNode) is\r
695 equivalent of the following ASL code:\r
696 Name(_UID, One)\r
697\r
698 @param [in] NameString The new variable name.\r
699 Must be a NULL-terminated ASL NameString\r
700 e.g.: "DEV0", "DV15.DEV0", etc.\r
701 The input string is copied.\r
702 @param [in] Integer Integer to associate to the NameString.\r
703 @param [in] ParentNode If provided, set ParentNode as the parent\r
704 of the node created.\r
705 @param [out] NewObjectNode If success, contains the created node.\r
706\r
707 @retval EFI_SUCCESS Success.\r
708 @retval EFI_INVALID_PARAMETER Invalid parameter.\r
709 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
710**/\r
711EFI_STATUS\r
712EFIAPI\r
713AmlCodeGenNameInteger (\r
714 IN CONST CHAR8 * NameString,\r
715 IN UINT64 Integer,\r
fe2d8189 716 IN AML_NODE_HEADER * ParentNode OPTIONAL,\r
3a681567
PG
717 OUT AML_OBJECT_NODE ** NewObjectNode OPTIONAL\r
718 )\r
719{\r
720 EFI_STATUS Status;\r
721 AML_OBJECT_NODE * ObjectNode;\r
722\r
723 if ((NameString == NULL) ||\r
724 ((ParentNode == NULL) && (NewObjectNode == NULL))) {\r
725 ASSERT (0);\r
726 return EFI_INVALID_PARAMETER;\r
727 }\r
728\r
729 Status = AmlCodeGenInteger (Integer, &ObjectNode);\r
730 if (EFI_ERROR (Status)) {\r
731 ASSERT (0);\r
732 return Status;\r
733 }\r
734\r
735 Status = AmlCodeGenName (\r
736 NameString,\r
737 ObjectNode,\r
738 ParentNode,\r
739 NewObjectNode\r
740 );\r
741 if (EFI_ERROR (Status)) {\r
742 ASSERT (0);\r
743 AmlDeleteTree ((AML_NODE_HEADER*)ObjectNode);\r
744 }\r
745\r
746 return Status;\r
747}\r
748\r
749/** AML code generation for a Device object node.\r
750\r
751 AmlCodeGenDevice ("COM0", ParentNode, NewObjectNode) is\r
752 equivalent of the following ASL code:\r
753 Device(COM0) {}\r
754\r
755 @param [in] NameString The new Device's name.\r
756 Must be a NULL-terminated ASL NameString\r
757 e.g.: "DEV0", "DV15.DEV0", etc.\r
758 The input string is copied.\r
759 @param [in] ParentNode If provided, set ParentNode as the parent\r
760 of the node created.\r
761 @param [out] NewObjectNode If success, contains the created node.\r
762\r
763 @retval EFI_SUCCESS Success.\r
764 @retval EFI_INVALID_PARAMETER Invalid parameter.\r
765 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
766**/\r
767EFI_STATUS\r
768EFIAPI\r
769AmlCodeGenDevice (\r
770 IN CONST CHAR8 * NameString,\r
fe2d8189 771 IN AML_NODE_HEADER * ParentNode OPTIONAL,\r
3a681567
PG
772 OUT AML_OBJECT_NODE ** NewObjectNode OPTIONAL\r
773 )\r
774{\r
775 EFI_STATUS Status;\r
776 AML_OBJECT_NODE * ObjectNode;\r
777 AML_DATA_NODE * DataNode;\r
778 CHAR8 * AmlNameString;\r
779 UINT32 AmlNameStringSize;\r
780\r
781 if ((NameString == NULL) ||\r
782 ((ParentNode == NULL) && (NewObjectNode == NULL))) {\r
783 ASSERT (0);\r
784 return EFI_INVALID_PARAMETER;\r
785 }\r
786\r
787 ObjectNode = NULL;\r
788 DataNode = NULL;\r
789 AmlNameString = NULL;\r
790\r
791 Status = ConvertAslNameToAmlName (NameString, &AmlNameString);\r
792 if (EFI_ERROR (Status)) {\r
793 ASSERT (0);\r
794 return Status;\r
795 }\r
796\r
797 Status = AmlGetNameStringSize (AmlNameString, &AmlNameStringSize);\r
798 if (EFI_ERROR (Status)) {\r
799 ASSERT (0);\r
800 goto error_handler1;\r
801 }\r
802\r
803 Status = AmlCreateObjectNode (\r
804 AmlGetByteEncodingByOpCode (AML_EXT_OP, AML_EXT_DEVICE_OP),\r
805 AmlNameStringSize + AmlComputePkgLengthWidth (AmlNameStringSize),\r
806 &ObjectNode\r
807 );\r
808 if (EFI_ERROR (Status)) {\r
809 ASSERT (0);\r
810 goto error_handler1;\r
811 }\r
812\r
813 Status = AmlCreateDataNode (\r
814 EAmlNodeDataTypeNameString,\r
815 (UINT8*)AmlNameString,\r
816 AmlNameStringSize,\r
817 &DataNode\r
818 );\r
819 if (EFI_ERROR (Status)) {\r
820 ASSERT (0);\r
821 goto error_handler2;\r
822 }\r
823\r
824 Status = AmlSetFixedArgument (\r
825 ObjectNode,\r
826 EAmlParseIndexTerm0,\r
827 (AML_NODE_HEADER*)DataNode\r
828 );\r
829 if (EFI_ERROR (Status)) {\r
830 ASSERT (0);\r
831 AmlDeleteTree ((AML_NODE_HEADER*)DataNode);\r
832 goto error_handler2;\r
833 }\r
834\r
835 Status = LinkNode (\r
836 ObjectNode,\r
837 ParentNode,\r
838 NewObjectNode\r
839 );\r
840 if (EFI_ERROR (Status)) {\r
841 ASSERT (0);\r
842 goto error_handler2;\r
843 }\r
844\r
845 // Free AmlNameString before returning as it is copied\r
846 // in the call to AmlCreateDataNode().\r
847 goto error_handler1;\r
848\r
849error_handler2:\r
850 if (ObjectNode != NULL) {\r
851 AmlDeleteTree ((AML_NODE_HEADER*)ObjectNode);\r
852 }\r
853\r
854error_handler1:\r
855 if (AmlNameString != NULL) {\r
856 FreePool (AmlNameString);\r
857 }\r
858\r
859 return Status;\r
860}\r
861\r
862/** AML code generation for a Scope object node.\r
863\r
864 AmlCodeGenScope ("_SB", ParentNode, NewObjectNode) is\r
865 equivalent of the following ASL code:\r
866 Scope(_SB) {}\r
867\r
868 @param [in] NameString The new Scope's name.\r
869 Must be a NULL-terminated ASL NameString\r
870 e.g.: "DEV0", "DV15.DEV0", etc.\r
871 The input string is copied.\r
872 @param [in] ParentNode If provided, set ParentNode as the parent\r
873 of the node created.\r
874 @param [out] NewObjectNode If success, contains the created node.\r
875\r
876 @retval EFI_SUCCESS Success.\r
877 @retval EFI_INVALID_PARAMETER Invalid parameter.\r
878 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
879**/\r
880EFI_STATUS\r
881EFIAPI\r
882AmlCodeGenScope (\r
883 IN CONST CHAR8 * NameString,\r
fe2d8189 884 IN AML_NODE_HEADER * ParentNode OPTIONAL,\r
3a681567
PG
885 OUT AML_OBJECT_NODE ** NewObjectNode OPTIONAL\r
886 )\r
887{\r
888 EFI_STATUS Status;\r
889 AML_OBJECT_NODE * ObjectNode;\r
890 AML_DATA_NODE * DataNode;\r
891 CHAR8 * AmlNameString;\r
892 UINT32 AmlNameStringSize;\r
893\r
894 if ((NameString == NULL) ||\r
895 ((ParentNode == NULL) && (NewObjectNode == NULL))) {\r
896 ASSERT (0);\r
897 return EFI_INVALID_PARAMETER;\r
898 }\r
899\r
900 ObjectNode = NULL;\r
901 DataNode = NULL;\r
902 AmlNameString = NULL;\r
903\r
904 Status = ConvertAslNameToAmlName (NameString, &AmlNameString);\r
905 if (EFI_ERROR (Status)) {\r
906 ASSERT (0);\r
907 return Status;\r
908 }\r
909\r
910 Status = AmlGetNameStringSize (AmlNameString, &AmlNameStringSize);\r
911 if (EFI_ERROR (Status)) {\r
912 ASSERT (0);\r
913 goto error_handler1;\r
914 }\r
915\r
916 Status = AmlCreateObjectNode (\r
917 AmlGetByteEncodingByOpCode (AML_SCOPE_OP, 0),\r
918 AmlNameStringSize + AmlComputePkgLengthWidth (AmlNameStringSize),\r
919 &ObjectNode\r
920 );\r
921 if (EFI_ERROR (Status)) {\r
922 ASSERT (0);\r
923 goto error_handler1;\r
924 }\r
925\r
926 Status = AmlCreateDataNode (\r
927 EAmlNodeDataTypeNameString,\r
928 (UINT8*)AmlNameString,\r
929 AmlNameStringSize,\r
930 &DataNode\r
931 );\r
932 if (EFI_ERROR (Status)) {\r
933 ASSERT (0);\r
934 goto error_handler2;\r
935 }\r
936\r
937 Status = AmlSetFixedArgument (\r
938 ObjectNode,\r
939 EAmlParseIndexTerm0,\r
940 (AML_NODE_HEADER*)DataNode\r
941 );\r
942 if (EFI_ERROR (Status)) {\r
943 ASSERT (0);\r
944 AmlDeleteTree ((AML_NODE_HEADER*)DataNode);\r
945 goto error_handler2;\r
946 }\r
947\r
948 Status = LinkNode (\r
949 ObjectNode,\r
950 ParentNode,\r
951 NewObjectNode\r
952 );\r
953 if (EFI_ERROR (Status)) {\r
954 ASSERT (0);\r
955 goto error_handler2;\r
956 }\r
957\r
958 // Free AmlNameString before returning as it is copied\r
959 // in the call to AmlCreateDataNode().\r
960 goto error_handler1;\r
961\r
962error_handler2:\r
963 if (ObjectNode != NULL) {\r
964 AmlDeleteTree ((AML_NODE_HEADER*)ObjectNode);\r
965 }\r
966\r
967error_handler1:\r
968 if (AmlNameString != NULL) {\r
969 FreePool (AmlNameString);\r
970 }\r
971\r
972 return Status;\r
973}\r
de62ccbf
PG
974\r
975/** AML code generation for a Method object node.\r
976\r
977 AmlCodeGenMethod ("MET0", 1, TRUE, 3, ParentNode, NewObjectNode) is\r
978 equivalent of the following ASL code:\r
979 Method(MET0, 1, Serialized, 3) {}\r
980\r
981 ACPI 6.4, s20.2.5.2 "Named Objects Encoding":\r
982 DefMethod := MethodOp PkgLength NameString MethodFlags TermList\r
983 MethodOp := 0x14\r
984\r
985 The ASL parameters "ReturnType" and "ParameterTypes" are not asked\r
986 in this function. They are optional parameters in ASL.\r
987\r
988 @param [in] NameString The new Method's name.\r
989 Must be a NULL-terminated ASL NameString\r
990 e.g.: "MET0", "_SB.MET0", etc.\r
991 The input string is copied.\r
992 @param [in] NumArgs Number of arguments.\r
993 Must be 0 <= NumArgs <= 6.\r
994 @param [in] IsSerialized TRUE is equivalent to Serialized.\r
995 FALSE is equivalent to NotSerialized.\r
996 Default is NotSerialized in ASL spec.\r
997 @param [in] SyncLevel Synchronization level for the method.\r
998 Must be 0 <= SyncLevel <= 15.\r
999 Default is 0 in ASL.\r
1000 @param [in] ParentNode If provided, set ParentNode as the parent\r
1001 of the node created.\r
1002 @param [out] NewObjectNode If success, contains the created node.\r
1003\r
1004 @retval EFI_SUCCESS Success.\r
1005 @retval EFI_INVALID_PARAMETER Invalid parameter.\r
1006 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
1007**/\r
1008STATIC\r
1009EFI_STATUS\r
1010EFIAPI\r
1011AmlCodeGenMethod (\r
1012 IN CONST CHAR8 * NameString,\r
1013 IN UINT8 NumArgs,\r
1014 IN BOOLEAN IsSerialized,\r
1015 IN UINT8 SyncLevel,\r
fe2d8189 1016 IN AML_NODE_HEADER * ParentNode OPTIONAL,\r
de62ccbf
PG
1017 OUT AML_OBJECT_NODE ** NewObjectNode OPTIONAL\r
1018 )\r
1019{\r
1020 EFI_STATUS Status;\r
1021 UINT32 PkgLen;\r
1022 UINT8 Flags;\r
1023 AML_OBJECT_NODE * ObjectNode;\r
1024 AML_DATA_NODE * DataNode;\r
1025 CHAR8 * AmlNameString;\r
1026 UINT32 AmlNameStringSize;\r
1027\r
1028 if ((NameString == NULL) ||\r
1029 (NumArgs > 6) ||\r
1030 (SyncLevel > 15) ||\r
1031 ((ParentNode == NULL) && (NewObjectNode == NULL))) {\r
1032 ASSERT (0);\r
1033 return EFI_INVALID_PARAMETER;\r
1034 }\r
1035\r
1036 ObjectNode = NULL;\r
1037 DataNode = NULL;\r
1038\r
1039 // ACPI 6.4, s20.2.5.2 "Named Objects Encoding":\r
1040 // DefMethod := MethodOp PkgLength NameString MethodFlags TermList\r
1041 // MethodOp := 0x14\r
1042 // So:\r
1043 // 1- Create the NameString\r
1044 // 2- Compute the size to write in the PkgLen\r
1045 // 3- Create nodes for the NameString and Method object node\r
1046 // 4- Set the NameString DataNode as a fixed argument\r
1047 // 5- Create and link the MethodFlags node\r
1048\r
1049 // 1- Create the NameString\r
1050 Status = ConvertAslNameToAmlName (NameString, &AmlNameString);\r
1051 if (EFI_ERROR (Status)) {\r
1052 ASSERT (0);\r
1053 return Status;\r
1054 }\r
1055\r
1056 Status = AmlGetNameStringSize (AmlNameString, &AmlNameStringSize);\r
1057 if (EFI_ERROR (Status)) {\r
1058 ASSERT (0);\r
1059 goto error_handler1;\r
1060 }\r
1061\r
1062 // 2- Compute the size to write in the PkgLen\r
1063 // Add 1 byte (ByteData) for MethodFlags.\r
1064 Status = AmlComputePkgLength (AmlNameStringSize + 1, &PkgLen);\r
1065 if (EFI_ERROR (Status)) {\r
1066 ASSERT (0);\r
1067 goto error_handler1;\r
1068 }\r
1069\r
1070 // 3- Create nodes for the NameString and Method object node\r
1071 Status = AmlCreateObjectNode (\r
1072 AmlGetByteEncodingByOpCode (AML_METHOD_OP, 0),\r
1073 PkgLen,\r
1074 &ObjectNode\r
1075 );\r
1076 if (EFI_ERROR (Status)) {\r
1077 ASSERT (0);\r
1078 goto error_handler1;\r
1079 }\r
1080\r
1081 Status = AmlCreateDataNode (\r
1082 EAmlNodeDataTypeNameString,\r
1083 (UINT8*)AmlNameString,\r
1084 AmlNameStringSize,\r
1085 &DataNode\r
1086 );\r
1087 if (EFI_ERROR (Status)) {\r
1088 ASSERT (0);\r
1089 goto error_handler2;\r
1090 }\r
1091\r
1092 // 4- Set the NameString DataNode as a fixed argument\r
1093 Status = AmlSetFixedArgument (\r
1094 ObjectNode,\r
1095 EAmlParseIndexTerm0,\r
1096 (AML_NODE_HEADER*)DataNode\r
1097 );\r
1098 if (EFI_ERROR (Status)) {\r
1099 ASSERT (0);\r
1100 goto error_handler2;\r
1101 }\r
1102\r
1103 DataNode = NULL;\r
1104\r
1105 // 5- Create and link the MethodFlags node\r
1106 Flags = NumArgs |\r
1107 (IsSerialized ? BIT3 : 0) |\r
1108 (SyncLevel << 4);\r
1109\r
1110 Status = AmlCreateDataNode (EAmlNodeDataTypeUInt, &Flags, 1, &DataNode);\r
1111 if (EFI_ERROR (Status)) {\r
1112 ASSERT (0);\r
1113 goto error_handler2;\r
1114 }\r
1115\r
1116 Status = AmlSetFixedArgument (\r
1117 ObjectNode,\r
1118 EAmlParseIndexTerm1,\r
1119 (AML_NODE_HEADER*)DataNode\r
1120 );\r
1121 if (EFI_ERROR (Status)) {\r
1122 ASSERT (0);\r
1123 goto error_handler2;\r
1124 }\r
1125\r
1126 // Data node is attached so set the pointer to\r
1127 // NULL to ensure correct error handling.\r
1128 DataNode = NULL;\r
1129\r
1130 Status = LinkNode (\r
1131 ObjectNode,\r
1132 ParentNode,\r
1133 NewObjectNode\r
1134 );\r
1135 if (EFI_ERROR (Status)) {\r
1136 ASSERT (0);\r
1137 goto error_handler2;\r
1138 }\r
1139\r
1140 // Free AmlNameString before returning as it is copied\r
1141 // in the call to AmlCreateDataNode().\r
1142 goto error_handler1;\r
1143\r
1144error_handler2:\r
1145 if (ObjectNode != NULL) {\r
1146 AmlDeleteTree ((AML_NODE_HEADER*)ObjectNode);\r
1147 }\r
1148 if (DataNode != NULL) {\r
1149 AmlDeleteTree ((AML_NODE_HEADER*)DataNode);\r
1150 }\r
1151\r
1152error_handler1:\r
1153 if (AmlNameString != NULL) {\r
1154 FreePool (AmlNameString);\r
1155 }\r
1156 return Status;\r
1157}\r
e2d7b495
PG
1158\r
1159/** AML code generation for a Return object node.\r
1160\r
1161 AmlCodeGenReturn (ReturnNode, ParentNode, NewObjectNode) is\r
1162 equivalent of the following ASL code:\r
1163 Return([Content of the ReturnNode])\r
1164\r
1165 The ACPI 6.3 specification, s20.2.5.3 "Type 1 Opcodes Encoding" states:\r
1166 DefReturn := ReturnOp ArgObject\r
1167 ReturnOp := 0xA4\r
1168 ArgObject := TermArg => DataRefObject\r
1169\r
1170 Thus, the ReturnNode must be evaluated as a DataRefObject. It can\r
1171 be a NameString referencing an object. As this CodeGen Api doesn't\r
1172 do semantic checking, it is strongly advised to check the AML bytecode\r
1173 generated by this function against an ASL compiler.\r
1174\r
1175 The ReturnNode must be generated inside a Method body scope.\r
1176\r
1177 @param [in] ReturnNode The object returned by the Return ASL statement.\r
1178 This node is deleted if an error occurs.\r
1179 @param [in] ParentNode If provided, set ParentNode as the parent\r
1180 of the node created.\r
1181 Must be a MethodOp node.\r
1182 @param [out] NewObjectNode If success, contains the created node.\r
1183\r
1184 @retval EFI_SUCCESS Success.\r
1185 @retval EFI_INVALID_PARAMETER Invalid parameter.\r
1186 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
1187**/\r
1188STATIC\r
1189EFI_STATUS\r
1190EFIAPI\r
1191AmlCodeGenReturn (\r
1192 IN AML_NODE_HEADER * ReturnNode,\r
fe2d8189 1193 IN AML_NODE_HEADER * ParentNode OPTIONAL,\r
e2d7b495
PG
1194 OUT AML_OBJECT_NODE ** NewObjectNode OPTIONAL\r
1195 )\r
1196{\r
1197 EFI_STATUS Status;\r
1198 AML_OBJECT_NODE * ObjectNode;\r
1199\r
1200 if ((ReturnNode == NULL) ||\r
1201 ((ParentNode == NULL) && (NewObjectNode == NULL)) ||\r
1202 ((ParentNode != NULL) &&\r
1203 !AmlNodeCompareOpCode (\r
1204 (AML_OBJECT_NODE*)ParentNode, AML_METHOD_OP, 0))) {\r
1205 ASSERT (0);\r
1206 return EFI_INVALID_PARAMETER;\r
1207 }\r
1208\r
1209 Status = AmlCreateObjectNode (\r
1210 AmlGetByteEncodingByOpCode (AML_RETURN_OP, 0),\r
1211 0,\r
1212 &ObjectNode\r
1213 );\r
1214 if (EFI_ERROR (Status)) {\r
1215 ASSERT (0);\r
1216 goto error_handler;\r
1217 }\r
1218\r
1219 Status = AmlSetFixedArgument (\r
1220 ObjectNode,\r
1221 EAmlParseIndexTerm0,\r
1222 (AML_NODE_HEADER*)ReturnNode\r
1223 );\r
1224 if (EFI_ERROR (Status)) {\r
1225 ASSERT (0);\r
1226 goto error_handler;\r
1227 }\r
1228\r
1229 ReturnNode = NULL;\r
1230\r
1231 Status = LinkNode (\r
1232 ObjectNode,\r
1233 ParentNode,\r
1234 NewObjectNode\r
1235 );\r
1236 if (EFI_ERROR (Status)) {\r
1237 ASSERT (0);\r
1238 goto error_handler;\r
1239 }\r
1240\r
1241 return Status;\r
1242\r
1243error_handler:\r
1244 if (ReturnNode != NULL) {\r
1245 AmlDeleteTree (ReturnNode);\r
1246 }\r
1247 if (ObjectNode != NULL) {\r
1248 AmlDeleteTree ((AML_NODE_HEADER*)ObjectNode);\r
1249 }\r
1250 return Status;\r
1251}\r
1252\r
1253/** AML code generation for a Return object node,\r
1254 returning the object as an input NameString.\r
1255\r
1256 AmlCodeGenReturn ("NAM1", ParentNode, NewObjectNode) is\r
1257 equivalent of the following ASL code:\r
1258 Return(NAM1)\r
1259\r
1260 The ACPI 6.3 specification, s20.2.5.3 "Type 1 Opcodes Encoding" states:\r
1261 DefReturn := ReturnOp ArgObject\r
1262 ReturnOp := 0xA4\r
1263 ArgObject := TermArg => DataRefObject\r
1264\r
1265 Thus, the ReturnNode must be evaluated as a DataRefObject. It can\r
1266 be a NameString referencing an object. As this CodeGen Api doesn't\r
1267 do semantic checking, it is strongly advised to check the AML bytecode\r
1268 generated by this function against an ASL compiler.\r
1269\r
1270 The ReturnNode must be generated inside a Method body scope.\r
1271\r
1272 @param [in] NameString The object referenced by this NameString\r
1273 is returned by the Return ASL statement.\r
1274 Must be a NULL-terminated ASL NameString\r
1275 e.g.: "NAM1", "_SB.NAM1", etc.\r
1276 The input string is copied.\r
1277 @param [in] ParentNode If provided, set ParentNode as the parent\r
1278 of the node created.\r
1279 Must be a MethodOp node.\r
1280 @param [out] NewObjectNode If success, contains the created node.\r
1281\r
1282 @retval EFI_SUCCESS Success.\r
1283 @retval EFI_INVALID_PARAMETER Invalid parameter.\r
1284 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
1285**/\r
1286STATIC\r
1287EFI_STATUS\r
1288EFIAPI\r
1289AmlCodeGenReturnNameString (\r
1290 IN CONST CHAR8 * NameString,\r
fe2d8189 1291 IN AML_NODE_HEADER * ParentNode OPTIONAL,\r
e2d7b495
PG
1292 OUT AML_OBJECT_NODE ** NewObjectNode OPTIONAL\r
1293 )\r
1294{\r
1295 EFI_STATUS Status;\r
1296 AML_DATA_NODE * DataNode;\r
1297 CHAR8 * AmlNameString;\r
1298 UINT32 AmlNameStringSize;\r
1299\r
1300 DataNode = NULL;\r
1301\r
1302 Status = ConvertAslNameToAmlName (NameString, &AmlNameString);\r
1303 if (EFI_ERROR (Status)) {\r
1304 ASSERT (0);\r
1305 return Status;\r
1306 }\r
1307\r
1308 Status = AmlGetNameStringSize (AmlNameString, &AmlNameStringSize);\r
1309 if (EFI_ERROR (Status)) {\r
1310 ASSERT (0);\r
1311 goto exit_handler;\r
1312 }\r
1313\r
1314 Status = AmlCreateDataNode (\r
1315 EAmlNodeDataTypeNameString,\r
1316 (UINT8*)AmlNameString,\r
1317 AmlNameStringSize,\r
1318 &DataNode\r
1319 );\r
1320 if (EFI_ERROR (Status)) {\r
1321 ASSERT (0);\r
1322 goto exit_handler;\r
1323 }\r
1324\r
1325 // AmlCodeGenReturn() deletes DataNode if error.\r
1326 Status = AmlCodeGenReturn (\r
1327 (AML_NODE_HEADER*)DataNode,\r
1328 ParentNode,\r
1329 NewObjectNode\r
1330 );\r
1331 ASSERT_EFI_ERROR (Status);\r
1332\r
1333exit_handler:\r
1334 if (AmlNameString != NULL) {\r
1335 FreePool (AmlNameString);\r
1336 }\r
1337 return Status;\r
1338}\r
3e958e93
PG
1339\r
1340/** AML code generation for a method returning a NameString.\r
1341\r
1342 AmlCodeGenMethodRetNameString (\r
1343 "MET0", "_CRS", 1, TRUE, 3, ParentNode, NewObjectNode\r
1344 );\r
1345 is equivalent of the following ASL code:\r
1346 Method(MET0, 1, Serialized, 3) {\r
1347 Return (_CRS)\r
1348 }\r
1349\r
1350 The ASL parameters "ReturnType" and "ParameterTypes" are not asked\r
1351 in this function. They are optional parameters in ASL.\r
1352\r
1353 @param [in] MethodNameString The new Method's name.\r
1354 Must be a NULL-terminated ASL NameString\r
1355 e.g.: "MET0", "_SB.MET0", etc.\r
1356 The input string is copied.\r
1357 @param [in] ReturnedNameString The name of the object returned by the\r
1358 method. Optional parameter, can be:\r
1359 - NULL (ignored).\r
1360 - A NULL-terminated ASL NameString.\r
1361 e.g.: "MET0", "_SB.MET0", etc.\r
1362 The input string is copied.\r
1363 @param [in] NumArgs Number of arguments.\r
1364 Must be 0 <= NumArgs <= 6.\r
1365 @param [in] IsSerialized TRUE is equivalent to Serialized.\r
1366 FALSE is equivalent to NotSerialized.\r
1367 Default is NotSerialized in ASL spec.\r
1368 @param [in] SyncLevel Synchronization level for the method.\r
1369 Must be 0 <= SyncLevel <= 15.\r
1370 Default is 0 in ASL.\r
1371 @param [in] ParentNode If provided, set ParentNode as the parent\r
1372 of the node created.\r
1373 @param [out] NewObjectNode If success, contains the created node.\r
1374\r
1375 @retval EFI_SUCCESS Success.\r
1376 @retval EFI_INVALID_PARAMETER Invalid parameter.\r
1377 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
1378**/\r
1379EFI_STATUS\r
1380EFIAPI\r
1381AmlCodeGenMethodRetNameString (\r
1382 IN CONST CHAR8 * MethodNameString,\r
fe2d8189 1383 IN CONST CHAR8 * ReturnedNameString OPTIONAL,\r
3e958e93
PG
1384 IN UINT8 NumArgs,\r
1385 IN BOOLEAN IsSerialized,\r
1386 IN UINT8 SyncLevel,\r
fe2d8189 1387 IN AML_NODE_HANDLE ParentNode OPTIONAL,\r
3e958e93
PG
1388 OUT AML_OBJECT_NODE_HANDLE * NewObjectNode OPTIONAL\r
1389 )\r
1390{\r
1391 EFI_STATUS Status;\r
1392 AML_OBJECT_NODE_HANDLE MethodNode;\r
1393\r
1394 if ((MethodNameString == NULL) ||\r
1395 ((ParentNode == NULL) && (NewObjectNode == NULL))) {\r
1396 ASSERT (0);\r
1397 return EFI_INVALID_PARAMETER;\r
1398 }\r
1399\r
1400 // Create a Method named MethodNameString.\r
1401 Status = AmlCodeGenMethod (\r
1402 MethodNameString,\r
1403 NumArgs,\r
1404 IsSerialized,\r
1405 SyncLevel,\r
1406 NULL,\r
1407 &MethodNode\r
1408 );\r
1409 if (EFI_ERROR (Status)) {\r
1410 ASSERT (0);\r
1411 return Status;\r
1412 }\r
1413\r
1414 // Return ReturnedNameString if provided.\r
1415 if (ReturnedNameString != NULL) {\r
1416 Status = AmlCodeGenReturnNameString (\r
1417 ReturnedNameString,\r
1418 (AML_NODE_HANDLE)MethodNode,\r
1419 NULL\r
1420 );\r
1421 if (EFI_ERROR (Status)) {\r
1422 ASSERT (0);\r
1423 goto error_handler;\r
1424 }\r
1425 }\r
1426\r
1427 Status = LinkNode (\r
1428 MethodNode,\r
1429 ParentNode,\r
1430 NewObjectNode\r
1431 );\r
1432 if (EFI_ERROR (Status)) {\r
1433 ASSERT (0);\r
1434 goto error_handler;\r
1435 }\r
1436\r
1437 return Status;\r
1438\r
1439error_handler:\r
1440 if (MethodNode != NULL) {\r
1441 AmlDeleteTree ((AML_NODE_HANDLE)MethodNode);\r
1442 }\r
1443 return Status;\r
1444}\r
018a962d
PG
1445\r
1446/** Create a _LPI name.\r
1447\r
1448 AmlCreateLpiNode ("_LPI", 0, 1, ParentNode, &LpiNode) is\r
1449 equivalent of the following ASL code:\r
1450 Name (_LPI, Package (\r
1451 0, // Revision\r
1452 1, // LevelId\r
1453 0 // Count\r
1454 ))\r
1455\r
1456 This function doesn't define any LPI state. As shown above, the count\r
1457 of _LPI state is set to 0.\r
1458 The AmlAddLpiState () function allows to add LPI states.\r
1459\r
1460 Cf ACPI 6.3 specification, s8.4.4 "Lower Power Idle States".\r
1461\r
1462 @param [in] LpiNameString The new LPI 's object name.\r
1463 Must be a NULL-terminated ASL NameString\r
1464 e.g.: "_LPI", "DEV0.PLPI", etc.\r
1465 The input string is copied.\r
1466 @param [in] Revision Revision number of the _LPI states.\r
1467 @param [in] LevelId A platform defined number that identifies the\r
1468 level of hierarchy of the processor node to\r
1469 which the LPI states apply.\r
1470 @param [in] ParentNode If provided, set ParentNode as the parent\r
1471 of the node created.\r
1472 @param [out] NewLpiNode If success, contains the created node.\r
1473\r
1474 @retval EFI_SUCCESS The function completed successfully.\r
1475 @retval EFI_INVALID_PARAMETER Invalid parameter.\r
1476 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
1477**/\r
1478EFI_STATUS\r
1479EFIAPI\r
1480AmlCreateLpiNode (\r
1481 IN CONST CHAR8 * LpiNameString,\r
1482 IN UINT16 Revision,\r
1483 IN UINT64 LevelId,\r
fe2d8189 1484 IN AML_NODE_HANDLE ParentNode OPTIONAL,\r
018a962d
PG
1485 OUT AML_OBJECT_NODE_HANDLE * NewLpiNode OPTIONAL\r
1486 )\r
1487{\r
1488 EFI_STATUS Status;\r
1489 AML_OBJECT_NODE_HANDLE PackageNode;\r
1490 AML_OBJECT_NODE_HANDLE IntegerNode;\r
1491\r
1492 if ((LpiNameString == NULL) ||\r
1493 ((ParentNode == NULL) && (NewLpiNode == NULL))) {\r
1494 ASSERT (0);\r
1495 return EFI_INVALID_PARAMETER;\r
1496 }\r
1497\r
1498 IntegerNode = NULL;\r
1499\r
1500 Status = AmlCodeGenPackage (&PackageNode);\r
1501 if (EFI_ERROR (Status)) {\r
1502 ASSERT (0);\r
1503 return Status;\r
1504 }\r
1505\r
1506 // Create and attach Revision\r
1507 Status = AmlCodeGenInteger (Revision, &IntegerNode);\r
1508 if (EFI_ERROR (Status)) {\r
1509 ASSERT (0);\r
1510 IntegerNode = NULL;\r
1511 goto error_handler;\r
1512 }\r
1513\r
1514 Status = AmlVarListAddTail (\r
1515 (AML_NODE_HANDLE)PackageNode,\r
1516 (AML_NODE_HANDLE)IntegerNode\r
1517 );\r
1518 if (EFI_ERROR (Status)) {\r
1519 ASSERT (0);\r
1520 goto error_handler;\r
1521 }\r
1522\r
1523 IntegerNode = NULL;\r
1524\r
1525 // Create and attach LevelId\r
1526 Status = AmlCodeGenInteger (LevelId, &IntegerNode);\r
1527 if (EFI_ERROR (Status)) {\r
1528 ASSERT (0);\r
1529 IntegerNode = NULL;\r
1530 goto error_handler;\r
1531 }\r
1532\r
1533 Status = AmlVarListAddTail (\r
1534 (AML_NODE_HANDLE)PackageNode,\r
1535 (AML_NODE_HANDLE)IntegerNode\r
1536 );\r
1537 if (EFI_ERROR (Status)) {\r
1538 ASSERT (0);\r
1539 goto error_handler;\r
1540 }\r
1541\r
1542 IntegerNode = NULL;\r
1543\r
1544 // Create and attach Count. No LPI state is added, so 0.\r
1545 Status = AmlCodeGenInteger (0, &IntegerNode);\r
1546 if (EFI_ERROR (Status)) {\r
1547 ASSERT (0);\r
1548 IntegerNode = NULL;\r
1549 goto error_handler;\r
1550 }\r
1551\r
1552 Status = AmlVarListAddTail (\r
1553 (AML_NODE_HANDLE)PackageNode,\r
1554 (AML_NODE_HANDLE)IntegerNode\r
1555 );\r
1556 if (EFI_ERROR (Status)) {\r
1557 ASSERT (0);\r
1558 goto error_handler;\r
1559 }\r
1560\r
1561 IntegerNode = NULL;\r
1562\r
1563 Status = AmlCodeGenName (LpiNameString, PackageNode, ParentNode, NewLpiNode);\r
1564 if (EFI_ERROR (Status)) {\r
1565 ASSERT (0);\r
1566 goto error_handler;\r
1567 }\r
1568\r
1569 return Status;\r
1570\r
1571error_handler:\r
1572 AmlDeleteTree ((AML_NODE_HANDLE)PackageNode);\r
1573 if (IntegerNode != NULL) {\r
1574 AmlDeleteTree ((AML_NODE_HANDLE)IntegerNode);\r
1575 }\r
1576 return Status;\r
1577}\r
a5e36ad9
PG
1578\r
1579/** Add an _LPI state to a LPI node created using AmlCreateLpiNode.\r
1580\r
1581 AmlAddLpiState increments the Count of LPI states in the LPI node by one,\r
1582 and adds the following package:\r
1583 Package() {\r
1584 MinResidency,\r
1585 WorstCaseWakeLatency,\r
1586 Flags,\r
1587 ArchFlags,\r
1588 ResCntFreq,\r
1589 EnableParentState,\r
1590 (GenericRegisterDescriptor != NULL) ? // Entry method. If a\r
1591 ResourceTemplate(GenericRegisterDescriptor) : // Register is given,\r
1592 Integer, // use it. Use the\r
1593 // Integer otherwise.\r
1594 ResourceTemplate() { // NULL Residency Counter\r
1595 Register (SystemMemory, 0, 0, 0, 0)\r
1596 },\r
1597 ResourceTemplate() { // NULL Usage Counter\r
1598 Register (SystemMemory, 0, 0, 0, 0)\r
1599 },\r
1600 "" // NULL State Name\r
1601 },\r
1602\r
1603 Cf ACPI 6.3 specification, s8.4.4 "Lower Power Idle States".\r
1604\r
1605 @param [in] MinResidency Minimum Residency.\r
1606 @param [in] WorstCaseWakeLatency Worst case wake-up latency.\r
1607 @param [in] Flags Flags.\r
1608 @param [in] ArchFlags Architectural flags.\r
1609 @param [in] ResCntFreq Residency Counter Frequency.\r
1610 @param [in] EnableParentState Enabled Parent State.\r
1611 @param [in] GenericRegisterDescriptor Entry Method.\r
1612 If not NULL, use this Register to\r
1613 describe the entry method address.\r
1614 @param [in] Integer Entry Method.\r
1615 If GenericRegisterDescriptor is NULL,\r
1616 take this value.\r
1617 @param [in] ResidencyCounterRegister If not NULL, use it to populate the\r
1618 residency counter register.\r
1619 @param [in] UsageCounterRegister If not NULL, use it to populate the\r
1620 usage counter register.\r
1621 @param [in] StateName If not NULL, use it to populate the\r
1622 state name.\r
1623 @param [in] LpiNode Lpi node created with the function\r
1624 AmlCreateLpiNode to which the new LPI\r
1625 state is appended.\r
1626\r
1627 @retval EFI_SUCCESS The function completed successfully.\r
1628 @retval EFI_INVALID_PARAMETER Invalid parameter.\r
1629 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
1630**/\r
1631EFI_STATUS\r
1632EFIAPI\r
1633AmlAddLpiState (\r
1634 IN UINT32 MinResidency,\r
1635 IN UINT32 WorstCaseWakeLatency,\r
1636 IN UINT32 Flags,\r
1637 IN UINT32 ArchFlags,\r
1638 IN UINT32 ResCntFreq,\r
1639 IN UINT32 EnableParentState,\r
fe2d8189
MK
1640 IN EFI_ACPI_6_3_GENERIC_ADDRESS_STRUCTURE * GenericRegisterDescriptor OPTIONAL,\r
1641 IN UINT64 Integer OPTIONAL,\r
1642 IN EFI_ACPI_6_3_GENERIC_ADDRESS_STRUCTURE * ResidencyCounterRegister OPTIONAL,\r
1643 IN EFI_ACPI_6_3_GENERIC_ADDRESS_STRUCTURE * UsageCounterRegister OPTIONAL,\r
1644 IN CHAR8 * StateName OPTIONAL,\r
a5e36ad9
PG
1645 IN AML_OBJECT_NODE_HANDLE LpiNode\r
1646 )\r
1647{\r
1648 EFI_STATUS Status;\r
1649 AML_DATA_NODE_HANDLE RdNode;\r
1650 AML_OBJECT_NODE_HANDLE PackageNode;\r
1651 AML_OBJECT_NODE_HANDLE IntegerNode;\r
1652 AML_OBJECT_NODE_HANDLE StringNode;\r
1653 AML_OBJECT_NODE_HANDLE NewLpiPackageNode;\r
1654 AML_OBJECT_NODE_HANDLE ResourceTemplateNode;\r
1655\r
1656 UINT32 Index;\r
1657 AML_OBJECT_NODE_HANDLE CountNode;\r
1658 UINT64 Count;\r
1659\r
1660 if ((LpiNode == NULL) ||\r
1661 (AmlGetNodeType ((AML_NODE_HANDLE)LpiNode) != EAmlNodeObject) ||\r
1662 (!AmlNodeHasOpCode (LpiNode, AML_NAME_OP, 0))) {\r
1663 ASSERT (0);\r
1664 return EFI_INVALID_PARAMETER;\r
1665 }\r
1666\r
1667 RdNode = 0;\r
1668 StringNode = NULL;\r
1669 IntegerNode = NULL;\r
1670 ResourceTemplateNode = NULL;\r
1671\r
1672 // AmlCreateLpiNode () created a LPI container such as:\r
1673 // Name (_LPI, Package (\r
1674 // 0, // Revision\r
1675 // 1, // LevelId\r
1676 // 0 // Count\r
1677 // ))\r
1678 // Get the LPI container, a PackageOp object node stored as the 2nd fixed\r
1679 // argument (i.e. index 1) of LpiNode.\r
1680 PackageNode = (AML_OBJECT_NODE_HANDLE)AmlGetFixedArgument (\r
1681 LpiNode,\r
1682 EAmlParseIndexTerm1\r
1683 );\r
1684 if ((PackageNode == NULL) ||\r
1685 (AmlGetNodeType ((AML_NODE_HANDLE)PackageNode) != EAmlNodeObject) ||\r
1686 (!AmlNodeHasOpCode (PackageNode, AML_PACKAGE_OP, 0))) {\r
1687 ASSERT (0);\r
1688 return EFI_INVALID_PARAMETER;\r
1689 }\r
1690\r
1691 CountNode = NULL;\r
1692 // The third variable argument is the LPI Count node.\r
1693 for (Index = 0; Index < 3; Index++) {\r
1694 CountNode = (AML_OBJECT_NODE_HANDLE)AmlGetNextVariableArgument (\r
1695 (AML_NODE_HANDLE)PackageNode,\r
1696 (AML_NODE_HANDLE)CountNode\r
1697 );\r
1698 if (CountNode == NULL) {\r
1699 ASSERT (0);\r
1700 return EFI_INVALID_PARAMETER;\r
1701 }\r
1702 }\r
1703\r
1704 Status = AmlNodeGetIntegerValue (CountNode, &Count);\r
1705 if (EFI_ERROR (Status)) {\r
1706 ASSERT (0);\r
1707 return Status;\r
1708 }\r
1709 Status = AmlUpdateInteger (CountNode, Count + 1);\r
1710 if (EFI_ERROR (Status)) {\r
1711 ASSERT (0);\r
1712 return Status;\r
1713 }\r
1714\r
1715 Status = AmlCodeGenPackage (&NewLpiPackageNode);\r
1716 if (EFI_ERROR (Status)) {\r
1717 ASSERT (0);\r
1718 return Status;\r
1719 }\r
1720\r
1721 // MinResidency\r
1722 Status = AmlCodeGenInteger (MinResidency, &IntegerNode);\r
1723 if (EFI_ERROR (Status)) {\r
1724 ASSERT (0);\r
1725 IntegerNode = NULL;\r
1726 goto error_handler;\r
1727 }\r
1728 Status = AmlVarListAddTail (\r
1729 (AML_NODE_HANDLE)NewLpiPackageNode,\r
1730 (AML_NODE_HANDLE)IntegerNode\r
1731 );\r
1732 if (EFI_ERROR (Status)) {\r
1733 ASSERT (0);\r
1734 goto error_handler;\r
1735 }\r
1736 IntegerNode = NULL;\r
1737\r
1738 // WorstCaseWakeLatency\r
1739 Status = AmlCodeGenInteger (WorstCaseWakeLatency, &IntegerNode);\r
1740 if (EFI_ERROR (Status)) {\r
1741 ASSERT (0);\r
1742 IntegerNode = NULL;\r
1743 goto error_handler;\r
1744 }\r
1745 Status = AmlVarListAddTail (\r
1746 (AML_NODE_HANDLE)NewLpiPackageNode,\r
1747 (AML_NODE_HANDLE)IntegerNode\r
1748 );\r
1749 if (EFI_ERROR (Status)) {\r
1750 ASSERT (0);\r
1751 goto error_handler;\r
1752 }\r
1753 IntegerNode = NULL;\r
1754\r
1755 // Flags\r
1756 Status = AmlCodeGenInteger (Flags, &IntegerNode);\r
1757 if (EFI_ERROR (Status)) {\r
1758 ASSERT (0);\r
1759 IntegerNode = NULL;\r
1760 goto error_handler;\r
1761 }\r
1762 Status = AmlVarListAddTail (\r
1763 (AML_NODE_HANDLE)NewLpiPackageNode,\r
1764 (AML_NODE_HANDLE)IntegerNode\r
1765 );\r
1766 if (EFI_ERROR (Status)) {\r
1767 ASSERT (0);\r
1768 goto error_handler;\r
1769 }\r
1770 IntegerNode = NULL;\r
1771\r
1772 // ArchFlags\r
1773 Status = AmlCodeGenInteger (ArchFlags, &IntegerNode);\r
1774 if (EFI_ERROR (Status)) {\r
1775 ASSERT (0);\r
1776 IntegerNode = NULL;\r
1777 goto error_handler;\r
1778 }\r
1779 Status = AmlVarListAddTail (\r
1780 (AML_NODE_HANDLE)NewLpiPackageNode,\r
1781 (AML_NODE_HANDLE)IntegerNode\r
1782 );\r
1783 if (EFI_ERROR (Status)) {\r
1784 ASSERT (0);\r
1785 goto error_handler;\r
1786 }\r
1787 IntegerNode = NULL;\r
1788\r
1789 // ResCntFreq\r
1790 Status = AmlCodeGenInteger (ResCntFreq, &IntegerNode);\r
1791 if (EFI_ERROR (Status)) {\r
1792 ASSERT (0);\r
1793 IntegerNode = NULL;\r
1794 goto error_handler;\r
1795 }\r
1796 Status = AmlVarListAddTail (\r
1797 (AML_NODE_HANDLE)NewLpiPackageNode,\r
1798 (AML_NODE_HANDLE)IntegerNode\r
1799 );\r
1800 if (EFI_ERROR (Status)) {\r
1801 ASSERT (0);\r
1802 goto error_handler;\r
1803 }\r
1804 IntegerNode = NULL;\r
1805\r
1806 // EnableParentState\r
1807 Status = AmlCodeGenInteger (EnableParentState, &IntegerNode);\r
1808 if (EFI_ERROR (Status)) {\r
1809 ASSERT (0);\r
1810 IntegerNode = NULL;\r
1811 goto error_handler;\r
1812 }\r
1813 Status = AmlVarListAddTail (\r
1814 (AML_NODE_HANDLE)NewLpiPackageNode,\r
1815 (AML_NODE_HANDLE)IntegerNode\r
1816 );\r
1817 if (EFI_ERROR (Status)) {\r
1818 ASSERT (0);\r
1819 goto error_handler;\r
1820 }\r
1821 IntegerNode = NULL;\r
1822\r
1823 // Entry Method\r
1824 if (GenericRegisterDescriptor != NULL) {\r
1825 // Entry Method: As a Register resource data\r
1826 Status = AmlCodeGenResourceTemplate (&ResourceTemplateNode);\r
1827 if (EFI_ERROR (Status)) {\r
1828 ASSERT (0);\r
1829 ResourceTemplateNode = NULL;\r
1830 goto error_handler;\r
1831 }\r
1832 Status = AmlCodeGenRdRegister (\r
1833 GenericRegisterDescriptor->AddressSpaceId,\r
1834 GenericRegisterDescriptor->RegisterBitWidth,\r
1835 GenericRegisterDescriptor->RegisterBitOffset,\r
1836 GenericRegisterDescriptor->Address,\r
1837 GenericRegisterDescriptor->AccessSize,\r
1838 NULL,\r
1839 &RdNode\r
1840 );\r
1841 if (EFI_ERROR (Status)) {\r
1842 ASSERT (0);\r
1843 RdNode = NULL;\r
1844 goto error_handler;\r
1845 }\r
1846\r
1847 Status = AmlAppendRdNode (ResourceTemplateNode, RdNode);\r
1848 if (EFI_ERROR (Status)) {\r
1849 ASSERT (0);\r
1850 goto error_handler;\r
1851 }\r
1852 RdNode = NULL;\r
1853\r
1854 Status = AmlVarListAddTail (\r
1855 (AML_NODE_HANDLE)NewLpiPackageNode,\r
1856 (AML_NODE_HANDLE)ResourceTemplateNode\r
1857 );\r
1858 if (EFI_ERROR (Status)) {\r
1859 ASSERT (0);\r
1860 goto error_handler;\r
1861 }\r
1862 ResourceTemplateNode = NULL;\r
1863 } else {\r
1864 // Entry Method: As an integer\r
1865 Status = AmlCodeGenInteger (Integer, &IntegerNode);\r
1866 if (EFI_ERROR (Status)) {\r
1867 ASSERT (0);\r
1868 IntegerNode = NULL;\r
1869 goto error_handler;\r
1870 }\r
1871 Status = AmlVarListAddTail (\r
1872 (AML_NODE_HANDLE)NewLpiPackageNode,\r
1873 (AML_NODE_HANDLE)IntegerNode\r
1874 );\r
1875 if (EFI_ERROR (Status)) {\r
1876 ASSERT (0);\r
1877 goto error_handler;\r
1878 }\r
1879 IntegerNode = NULL;\r
1880 }\r
1881\r
1882 // Residency Counter Register.\r
1883 Status = AmlCodeGenResourceTemplate (&ResourceTemplateNode);\r
1884 if (EFI_ERROR (Status)) {\r
1885 ASSERT (0);\r
1886 ResourceTemplateNode = NULL;\r
1887 goto error_handler;\r
1888 }\r
1889 if (ResidencyCounterRegister != NULL) {\r
1890 Status = AmlCodeGenRdRegister (\r
1891 ResidencyCounterRegister->AddressSpaceId,\r
1892 ResidencyCounterRegister->RegisterBitWidth,\r
1893 ResidencyCounterRegister->RegisterBitOffset,\r
1894 ResidencyCounterRegister->Address,\r
1895 ResidencyCounterRegister->AccessSize,\r
1896 NULL,\r
1897 &RdNode\r
1898 );\r
1899 } else {\r
1900 Status = AmlCodeGenRdRegister (\r
1901 EFI_ACPI_6_4_SYSTEM_MEMORY,\r
1902 0,\r
1903 0,\r
1904 0,\r
1905 0,\r
1906 NULL,\r
1907 &RdNode\r
1908 );\r
1909 }\r
1910 if (EFI_ERROR (Status)) {\r
1911 ASSERT (0);\r
1912 RdNode = NULL;\r
1913 goto error_handler;\r
1914 }\r
1915\r
1916 Status = AmlAppendRdNode (ResourceTemplateNode, RdNode);\r
1917 if (EFI_ERROR (Status)) {\r
1918 ASSERT (0);\r
1919 goto error_handler;\r
1920 }\r
1921 RdNode = NULL;\r
1922\r
1923 Status = AmlVarListAddTail (\r
1924 (AML_NODE_HANDLE)NewLpiPackageNode,\r
1925 (AML_NODE_HANDLE)ResourceTemplateNode\r
1926 );\r
1927 if (EFI_ERROR (Status)) {\r
1928 ASSERT (0);\r
1929 goto error_handler;\r
1930 }\r
1931 ResourceTemplateNode = NULL;\r
1932\r
1933 // Usage Counter Register.\r
1934 Status = AmlCodeGenResourceTemplate (&ResourceTemplateNode);\r
1935 if (EFI_ERROR (Status)) {\r
1936 ASSERT (0);\r
1937 ResourceTemplateNode = NULL;\r
1938 goto error_handler;\r
1939 }\r
1940 if (UsageCounterRegister != NULL) {\r
1941 Status = AmlCodeGenRdRegister (\r
1942 UsageCounterRegister->AddressSpaceId,\r
1943 UsageCounterRegister->RegisterBitWidth,\r
1944 UsageCounterRegister->RegisterBitOffset,\r
1945 UsageCounterRegister->Address,\r
1946 UsageCounterRegister->AccessSize,\r
1947 NULL,\r
1948 &RdNode\r
1949 );\r
1950 } else {\r
1951 Status = AmlCodeGenRdRegister (\r
1952 EFI_ACPI_6_4_SYSTEM_MEMORY,\r
1953 0,\r
1954 0,\r
1955 0,\r
1956 0,\r
1957 NULL,\r
1958 &RdNode\r
1959 );\r
1960 }\r
1961 if (EFI_ERROR (Status)) {\r
1962 ASSERT (0);\r
1963 RdNode = NULL;\r
1964 goto error_handler;\r
1965 }\r
1966\r
1967 Status = AmlAppendRdNode (ResourceTemplateNode, RdNode);\r
1968 if (EFI_ERROR (Status)) {\r
1969 ASSERT (0);\r
1970 goto error_handler;\r
1971 }\r
1972 RdNode = NULL;\r
1973\r
1974 Status = AmlVarListAddTail (\r
1975 (AML_NODE_HANDLE)NewLpiPackageNode,\r
1976 (AML_NODE_HANDLE)ResourceTemplateNode\r
1977 );\r
1978 if (EFI_ERROR (Status)) {\r
1979 ASSERT (0);\r
1980 goto error_handler;\r
1981 }\r
1982 ResourceTemplateNode = NULL;\r
1983\r
1984 // State name.\r
1985 if (UsageCounterRegister != NULL) {\r
1986 Status = AmlCodeGenString (StateName, &StringNode);\r
1987 } else {\r
1988 Status = AmlCodeGenString ("", &StringNode);\r
1989 }\r
1990 if (EFI_ERROR (Status)) {\r
1991 ASSERT (0);\r
1992 StringNode = NULL;\r
1993 goto error_handler;\r
1994 }\r
1995 Status = AmlVarListAddTail (\r
1996 (AML_NODE_HANDLE)NewLpiPackageNode,\r
1997 (AML_NODE_HANDLE)StringNode\r
1998 );\r
1999 if (EFI_ERROR (Status)) {\r
2000 ASSERT (0);\r
2001 goto error_handler;\r
2002 }\r
2003 StringNode = NULL;\r
2004\r
2005 // Add the new LPI state to the LpiNode.\r
2006 Status = AmlVarListAddTail (\r
2007 (AML_NODE_HANDLE)PackageNode,\r
2008 (AML_NODE_HANDLE)NewLpiPackageNode\r
2009 );\r
2010 if (EFI_ERROR (Status)) {\r
2011 ASSERT (0);\r
2012 goto error_handler;\r
2013 }\r
2014\r
2015 return Status;\r
2016\r
2017error_handler:\r
2018 if (RdNode != NULL) {\r
2019 AmlDeleteTree ((AML_NODE_HANDLE)RdNode);\r
2020 }\r
2021 if (NewLpiPackageNode != NULL) {\r
2022 AmlDeleteTree ((AML_NODE_HANDLE)NewLpiPackageNode);\r
2023 }\r
2024 if (StringNode != NULL) {\r
2025 AmlDeleteTree ((AML_NODE_HANDLE)StringNode);\r
2026 }\r
2027 if (IntegerNode != NULL) {\r
2028 AmlDeleteTree ((AML_NODE_HANDLE)IntegerNode);\r
2029 }\r
2030 if (ResourceTemplateNode != NULL) {\r
2031 AmlDeleteTree ((AML_NODE_HANDLE)ResourceTemplateNode);\r
2032 }\r
2033\r
2034 return Status;\r
2035}\r