VirtualBox

source: vbox/trunk/src/VBox/Runtime/common/acpi/acpi-ast.cpp@ 109128

Last change on this file since 109128 was 108235, checked in by vboxsync, 3 months ago

Runtime/RTAcpi*: Implement constant folding for ShiftLeft (used by vbox.dsl), bugref:10733 [build fix + memory leak fixes]

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 37.2 KB
Line 
1/* $Id: acpi-ast.cpp 108235 2025-02-16 14:24:41Z vboxsync $ */
2/** @file
3 * IPRT - Advanced Configuration and Power Interface (ACPI) AST handling.
4 */
5
6/*
7 * Copyright (C) 2025 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * The contents of this file may alternatively be used under the terms
26 * of the Common Development and Distribution License Version 1.0
27 * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
28 * in the VirtualBox distribution, in which case the provisions of the
29 * CDDL are applicable instead of those of the GPL.
30 *
31 * You may elect to license modified versions of this file under the
32 * terms and conditions of either the GPL or the CDDL or both.
33 *
34 * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
35 */
36
37
38/*********************************************************************************************************************************
39* Header Files *
40*********************************************************************************************************************************/
41#define LOG_GROUP RTLOGGROUP_ACPI
42#include <iprt/assert.h>
43#include <iprt/errcore.h>
44#include <iprt/list.h>
45#include <iprt/mem.h>
46
47#include <iprt/formats/acpi-aml.h>
48
49#include "internal/acpi.h"
50
51
52/*********************************************************************************************************************************
53* Defined Constants And Macros *
54*********************************************************************************************************************************/
55
56
57/*********************************************************************************************************************************
58* Structures and Typedefs *
59*********************************************************************************************************************************/
60
61
62/*********************************************************************************************************************************
63* Global Variables *
64*********************************************************************************************************************************/
65
66
67/*********************************************************************************************************************************
68* Internal Functions *
69*********************************************************************************************************************************/
70
71DECLHIDDEN(PRTACPIASTNODE) rtAcpiAstNodeAlloc(PCRTACPINSROOT pNs, RTACPIASTNODEOP enmOp, uint32_t fFlags, uint8_t cArgs)
72{
73 PRTACPIASTNODE pAstNd = (PRTACPIASTNODE)RTMemAllocZ(RT_UOFFSETOF_DYN(RTACPIASTNODE, aArgs[cArgs]));
74 if (pAstNd)
75 {
76 pAstNd->pNsEntry = rtAcpiNsGetCurrent(pNs);
77 pAstNd->enmOp = enmOp;
78 pAstNd->fFlags = fFlags;
79 pAstNd->cArgs = cArgs;
80 RTListInit(&pAstNd->LstScopeNodes);
81 }
82
83 return pAstNd;
84}
85
86
87DECLHIDDEN(void) rtAcpiAstNodeFree(PRTACPIASTNODE pAstNd)
88{
89 /* Free all the arguments first. */
90 for (uint8_t i = 0; i < pAstNd->cArgs; i++)
91 {
92 if ( pAstNd->aArgs[i].enmType == kAcpiAstArgType_AstNode
93 && pAstNd->aArgs[i].u.pAstNd)
94 rtAcpiAstNodeFree(pAstNd->aArgs[i].u.pAstNd);
95 }
96
97 if (pAstNd->fFlags & RTACPI_AST_NODE_F_NEW_SCOPE)
98 {
99 PRTACPIASTNODE pIt, pItNext;
100 /* Do transformations on the nodes first. */
101 RTListForEachSafe(&pAstNd->LstScopeNodes, pIt, pItNext, RTACPIASTNODE, NdAst)
102 {
103 RTListNodeRemove(&pIt->NdAst);
104 rtAcpiAstNodeFree(pIt);
105 }
106 }
107
108 pAstNd->enmOp = kAcpiAstNodeOp_Invalid;
109 pAstNd->cArgs = 0;
110 pAstNd->fFlags = 0;
111 RTMemFree(pAstNd);
112}
113
114
115/**
116 * Evaluates the given AST node to an integer if possible.
117 *
118 * @returns IPRT status code.
119 * @param pAstNd The AST node to evaluate.
120 * @param pNsRoot The namespace root this AST belongs to.
121 * @param fResolveIdentifiers Flag whether to try resolving identifiers to constant integers.
122 * @param pu64 Where to store the integer on success.
123 */
124static int rtAcpiAstNodeEvaluateToInteger(PCRTACPIASTNODE pAstNd, PRTACPINSROOT pNsRoot, bool fResolveIdentifiers, uint64_t *pu64)
125{
126 /* Easy way out?. */
127 if (pAstNd->enmOp == kAcpiAstNodeOp_Number)
128 {
129 *pu64 = pAstNd->u64;
130 return VINF_SUCCESS;
131 }
132
133 if (pAstNd->enmOp == kAcpiAstNodeOp_One)
134 {
135 *pu64 = 1;
136 return VINF_SUCCESS;
137 }
138
139 if (pAstNd->enmOp == kAcpiAstNodeOp_Zero)
140 {
141 *pu64 = 0;
142 return VINF_SUCCESS;
143 }
144
145 if ( pAstNd->enmOp == kAcpiAstNodeOp_Identifier
146 && fResolveIdentifiers)
147 {
148 /* Look it up in the namespace and use the result. */
149 PCRTACPINSENTRY pNsEntry = rtAcpiNsLookup(pNsRoot, pAstNd->pszIde);
150 if (!pNsEntry)
151 return VERR_NOT_FOUND;
152 if (pNsEntry->enmType != kAcpiNsEntryType_ResourceField)
153 return VERR_NOT_SUPPORTED;
154
155 *pu64 = pNsEntry->RsrcFld.offBits;
156 return VINF_SUCCESS;
157 }
158
159 /** @todo */
160 return VERR_NOT_IMPLEMENTED;
161}
162
163
164DECLHIDDEN(int) rtAcpiAstNodeTransform(PRTACPIASTNODE pAstNd, PRTACPINSROOT pNsRoot, PRTERRINFO pErrInfo)
165{
166 /* Walk all arguments containing AST nodes first. */
167 for (uint8_t i = 0; i < pAstNd->cArgs; i++)
168 {
169 if ( pAstNd->aArgs[i].enmType == kAcpiAstArgType_AstNode
170 && pAstNd->aArgs[i].u.pAstNd)
171 {
172 int rc = rtAcpiAstNodeTransform(pAstNd->aArgs[i].u.pAstNd, pNsRoot, pErrInfo);
173 if (RT_FAILURE(rc))
174 return rc;
175 }
176 }
177
178 if (pAstNd->fFlags & RTACPI_AST_NODE_F_NEW_SCOPE)
179 {
180 PRTACPIASTNODE pIt/*, pItPrev*/;
181 /* Do transformations on the nodes first. */
182 RTListForEach(&pAstNd->LstScopeNodes, pIt, RTACPIASTNODE, NdAst)
183 {
184 int rc = rtAcpiAstNodeTransform(pIt, pNsRoot, pErrInfo);
185 if (RT_FAILURE(rc))
186 return rc;
187 }
188 }
189
190 /* Now do optimizations we can do here. */
191 switch (pAstNd->enmOp)
192 {
193 case kAcpiAstNodeOp_ShiftLeft:
194 {
195 /*
196 * If both arguments evaluate to constant integers we can convert this
197 * to the final result.
198 */
199 /** @todo Skips the 3 operand variant (no target), check what iasl is doing here. */
200 if (!pAstNd->aArgs[2].u.pAstNd)
201 {
202 uint64_t u64ValToShift = 0;
203 uint64_t u64ValShift = 0;
204 int rc = rtAcpiAstNodeEvaluateToInteger(pAstNd->aArgs[0].u.pAstNd, pNsRoot, false /*fResolveIdentifiers*/, &u64ValToShift);
205 if (RT_SUCCESS(rc))
206 rc = rtAcpiAstNodeEvaluateToInteger(pAstNd->aArgs[1].u.pAstNd, pNsRoot, false /*fResolveIdentifiers*/, &u64ValShift);
207 if ( RT_SUCCESS(rc)
208 && u64ValShift <= 63)
209 {
210 /** @todo Check overflow handling. */
211 rtAcpiAstNodeFree(pAstNd->aArgs[0].u.pAstNd);
212 rtAcpiAstNodeFree(pAstNd->aArgs[1].u.pAstNd);
213
214 pAstNd->aArgs[0].u.pAstNd = NULL;
215 pAstNd->aArgs[1].u.pAstNd = NULL;
216 pAstNd->cArgs = 0;
217 pAstNd->enmOp = kAcpiAstNodeOp_Number;
218 pAstNd->u64 = u64ValToShift << u64ValShift;
219 }
220 }
221 break;
222 }
223 default:
224 break;
225 }
226
227 return VINF_SUCCESS;
228}
229
230
231static int rtAcpiAstDumpAstList(PCRTLISTANCHOR pLst, PRTACPINSROOT pNsRoot, RTACPITBL hAcpiTbl)
232{
233 PCRTACPIASTNODE pIt;
234 RTListForEach(pLst, pIt, RTACPIASTNODE, NdAst)
235 {
236 int rc = rtAcpiAstDumpToTbl(pIt, pNsRoot, hAcpiTbl);
237 if (RT_FAILURE(rc))
238 return rc;
239 }
240
241 return VINF_SUCCESS;
242}
243
244
245DECLHIDDEN(int) rtAcpiAstDumpToTbl(PCRTACPIASTNODE pAstNd, PRTACPINSROOT pNsRoot, RTACPITBL hAcpiTbl)
246{
247 int rc = VINF_SUCCESS;
248 char szNameString[_1K];
249
250 switch (pAstNd->enmOp)
251 {
252 case kAcpiAstNodeOp_Identifier:
253 {
254 rc = rtAcpiNsAbsoluteNameStringToRelative(pNsRoot, pAstNd->pNsEntry, pAstNd->pszIde, &szNameString[0], sizeof(szNameString));
255 AssertRC(rc);
256
257 rc = RTAcpiTblNameStringAppend(hAcpiTbl, szNameString);
258 if (RT_SUCCESS(rc))
259 {
260 for (uint8_t i = 0; i < pAstNd->cArgs; i++)
261 {
262 Assert(pAstNd->aArgs[i].enmType == kAcpiAstArgType_AstNode);
263 rc = rtAcpiAstDumpToTbl(pAstNd->aArgs[i].u.pAstNd, pNsRoot, hAcpiTbl);
264 if (RT_FAILURE(rc))
265 break;
266 }
267 }
268 break;
269 }
270 case kAcpiAstNodeOp_StringLiteral:
271 rc = RTAcpiTblStringAppend(hAcpiTbl, pAstNd->pszStrLit);
272 break;
273 case kAcpiAstNodeOp_Number:
274 rc = RTAcpiTblIntegerAppend(hAcpiTbl, pAstNd->u64);
275 break;
276 case kAcpiAstNodeOp_Scope:
277 {
278 AssertBreakStmt( pAstNd->cArgs == 1
279 && pAstNd->aArgs[0].enmType == kAcpiAstArgType_NameString,
280 rc = VERR_INTERNAL_ERROR);
281 rc = rtAcpiNsCompressNameString(pNsRoot, pAstNd->pNsEntry, pAstNd->aArgs[0].u.pszNameString,
282 &szNameString[0], sizeof(szNameString));
283 AssertRC(rc);
284
285 rc = RTAcpiTblScopeStart(hAcpiTbl, szNameString);
286 if (RT_SUCCESS(rc))
287 {
288 /* Walk all the other AST nodes. */
289 rc = rtAcpiAstDumpAstList(&pAstNd->LstScopeNodes, pNsRoot, hAcpiTbl);
290 if (RT_SUCCESS(rc))
291 rc = RTAcpiTblScopeFinalize(hAcpiTbl);
292 }
293 break;
294 }
295 case kAcpiAstNodeOp_Processor:
296 {
297 AssertBreakStmt( pAstNd->cArgs == 4
298 && pAstNd->aArgs[0].enmType == kAcpiAstArgType_NameString
299 && pAstNd->aArgs[1].enmType == kAcpiAstArgType_U8
300 && pAstNd->aArgs[2].enmType == kAcpiAstArgType_U32
301 && pAstNd->aArgs[3].enmType == kAcpiAstArgType_U8,
302 rc = VERR_INTERNAL_ERROR);
303 rc = RTAcpiTblProcessorStart(hAcpiTbl,
304 pAstNd->aArgs[0].u.pszNameString,
305 pAstNd->aArgs[1].u.u8,
306 pAstNd->aArgs[2].u.u32,
307 pAstNd->aArgs[3].u.u8);
308 if (RT_SUCCESS(rc))
309 {
310 /* Walk all the other AST nodes. */
311 rc = rtAcpiAstDumpAstList(&pAstNd->LstScopeNodes, pNsRoot, hAcpiTbl);
312 if (RT_SUCCESS(rc))
313 rc = RTAcpiTblProcessorFinalize(hAcpiTbl);
314 }
315 break;
316 }
317 case kAcpiAstNodeOp_Method:
318 {
319 AssertBreakStmt( pAstNd->cArgs == 4
320 && pAstNd->aArgs[0].enmType == kAcpiAstArgType_NameString
321 && pAstNd->aArgs[1].enmType == kAcpiAstArgType_U8
322 && pAstNd->aArgs[2].enmType == kAcpiAstArgType_Bool
323 && pAstNd->aArgs[3].enmType == kAcpiAstArgType_U8,
324 rc = VERR_INTERNAL_ERROR);
325 rc = rtAcpiNsCompressNameString(pNsRoot, pAstNd->pNsEntry, pAstNd->aArgs[0].u.pszNameString,
326 &szNameString[0], sizeof(szNameString));
327 AssertRC(rc);
328
329 rc = RTAcpiTblMethodStart(hAcpiTbl, szNameString,
330 pAstNd->aArgs[1].u.u8,
331 pAstNd->aArgs[2].u.f ? RTACPI_METHOD_F_SERIALIZED : RTACPI_METHOD_F_NOT_SERIALIZED,
332 pAstNd->aArgs[3].u.u8);
333 if (RT_SUCCESS(rc))
334 {
335 /* Walk all the other AST nodes. */
336 rc = rtAcpiAstDumpAstList(&pAstNd->LstScopeNodes, pNsRoot, hAcpiTbl);
337 if (RT_SUCCESS(rc))
338 rc = RTAcpiTblMethodFinalize(hAcpiTbl);
339 }
340 break;
341 }
342 case kAcpiAstNodeOp_Device:
343 {
344 AssertBreakStmt( pAstNd->cArgs == 1
345 && pAstNd->aArgs[0].enmType == kAcpiAstArgType_NameString,
346 rc = VERR_INTERNAL_ERROR);
347 rc = RTAcpiTblDeviceStart(hAcpiTbl, pAstNd->aArgs[0].u.pszNameString);
348 if (RT_SUCCESS(rc))
349 {
350 /* Walk all the other AST nodes. */
351 rc = rtAcpiAstDumpAstList(&pAstNd->LstScopeNodes, pNsRoot, hAcpiTbl);
352 if (RT_SUCCESS(rc))
353 rc = RTAcpiTblDeviceFinalize(hAcpiTbl);
354 }
355 break;
356 }
357 case kAcpiAstNodeOp_If:
358 {
359 AssertBreakStmt( pAstNd->cArgs == 1
360 && pAstNd->aArgs[0].enmType == kAcpiAstArgType_AstNode,
361 rc = VERR_INTERNAL_ERROR);
362 rc = RTAcpiTblIfStart(hAcpiTbl);
363 if (RT_SUCCESS(rc))
364 {
365 /* Predicate. */
366 rc = rtAcpiAstDumpToTbl(pAstNd->aArgs[0].u.pAstNd, pNsRoot, hAcpiTbl);
367 if (RT_SUCCESS(rc))
368 {
369 /* Walk all the other AST nodes. */
370 rc = rtAcpiAstDumpAstList(&pAstNd->LstScopeNodes, pNsRoot, hAcpiTbl);
371 if (RT_SUCCESS(rc))
372 rc = RTAcpiTblIfFinalize(hAcpiTbl);
373 }
374 }
375 break;
376 }
377 case kAcpiAstNodeOp_Else:
378 {
379 AssertBreakStmt(pAstNd->cArgs == 0, rc = VERR_INTERNAL_ERROR);
380 rc = RTAcpiTblElseStart(hAcpiTbl);
381 if (RT_SUCCESS(rc))
382 {
383 /* Walk all the other AST nodes. */
384 rc = rtAcpiAstDumpAstList(&pAstNd->LstScopeNodes, pNsRoot, hAcpiTbl);
385 if (RT_SUCCESS(rc))
386 rc = RTAcpiTblElseFinalize(hAcpiTbl);
387 }
388 break;
389 }
390 case kAcpiAstNodeOp_While:
391 {
392 AssertBreakStmt( pAstNd->cArgs == 1
393 && pAstNd->aArgs[0].enmType == kAcpiAstArgType_AstNode,
394 rc = VERR_INTERNAL_ERROR);
395 rc = RTAcpiTblWhileStart(hAcpiTbl);
396 if (RT_SUCCESS(rc))
397 {
398 /* Predicate. */
399 rc = rtAcpiAstDumpToTbl(pAstNd->aArgs[0].u.pAstNd, pNsRoot, hAcpiTbl);
400 if (RT_SUCCESS(rc))
401 {
402 /* Walk all the other AST nodes. */
403 rc = rtAcpiAstDumpAstList(&pAstNd->LstScopeNodes, pNsRoot, hAcpiTbl);
404 if (RT_SUCCESS(rc))
405 rc = RTAcpiTblWhileFinalize(hAcpiTbl);
406 }
407 }
408 break;
409 }
410 case kAcpiAstNodeOp_LAnd:
411 case kAcpiAstNodeOp_LOr:
412 case kAcpiAstNodeOp_LEqual:
413 case kAcpiAstNodeOp_LGreater:
414 case kAcpiAstNodeOp_LGreaterEqual:
415 case kAcpiAstNodeOp_LLess:
416 case kAcpiAstNodeOp_LLessEqual:
417 case kAcpiAstNodeOp_LNotEqual:
418 {
419 AssertBreakStmt( pAstNd->cArgs == 2
420 && pAstNd->aArgs[0].enmType == kAcpiAstArgType_AstNode
421 && pAstNd->aArgs[1].enmType == kAcpiAstArgType_AstNode,
422 rc = VERR_INTERNAL_ERROR);
423 RTACPIBINARYOP enmOp;
424 switch (pAstNd->enmOp)
425 {
426 case kAcpiAstNodeOp_LAnd: enmOp = kAcpiBinaryOp_LAnd; break;
427 case kAcpiAstNodeOp_LOr: enmOp = kAcpiBinaryOp_LOr; break;
428 case kAcpiAstNodeOp_LEqual: enmOp = kAcpiBinaryOp_LEqual; break;
429 case kAcpiAstNodeOp_LGreater: enmOp = kAcpiBinaryOp_LGreater; break;
430 case kAcpiAstNodeOp_LGreaterEqual: enmOp = kAcpiBinaryOp_LGreaterEqual; break;
431 case kAcpiAstNodeOp_LLess: enmOp = kAcpiBinaryOp_LLess; break;
432 case kAcpiAstNodeOp_LLessEqual: enmOp = kAcpiBinaryOp_LLessEqual; break;
433 case kAcpiAstNodeOp_LNotEqual: enmOp = kAcpiBinaryOp_LNotEqual; break;
434 default:
435 AssertReleaseFailed(); /* Impossible */
436 return VERR_INTERNAL_ERROR;
437 }
438
439 rc = RTAcpiTblBinaryOpAppend(hAcpiTbl, enmOp);
440 if (RT_SUCCESS(rc))
441 {
442 rc = rtAcpiAstDumpToTbl(pAstNd->aArgs[0].u.pAstNd, pNsRoot, hAcpiTbl);
443 if (RT_SUCCESS(rc))
444 rc = rtAcpiAstDumpToTbl(pAstNd->aArgs[1].u.pAstNd, pNsRoot, hAcpiTbl);
445 }
446 break;
447 }
448 case kAcpiAstNodeOp_LNot:
449 AssertBreakStmt( pAstNd->cArgs == 1
450 && pAstNd->aArgs[0].enmType == kAcpiAstArgType_AstNode,
451 rc = VERR_INTERNAL_ERROR);
452 rc = RTAcpiTblStmtSimpleAppend(hAcpiTbl, kAcpiStmt_LNot);
453 if (RT_SUCCESS(rc))
454 rc = rtAcpiAstDumpToTbl(pAstNd->aArgs[0].u.pAstNd, pNsRoot, hAcpiTbl);
455 break;
456 case kAcpiAstNodeOp_Zero:
457 {
458 AssertBreakStmt(pAstNd->cArgs == 0, rc = VERR_INTERNAL_ERROR);
459 rc = RTAcpiTblIntegerAppend(hAcpiTbl, 0);
460 break;
461 }
462 case kAcpiAstNodeOp_One:
463 {
464 AssertBreakStmt(pAstNd->cArgs == 0, rc = VERR_INTERNAL_ERROR);
465 rc = RTAcpiTblIntegerAppend(hAcpiTbl, 1);
466 break;
467 }
468 case kAcpiAstNodeOp_Ones:
469 {
470 AssertBreakStmt(pAstNd->cArgs == 0, rc = VERR_INTERNAL_ERROR);
471 rc = RTAcpiTblStmtSimpleAppend(hAcpiTbl, kAcpiStmt_Ones);
472 break;
473 }
474 case kAcpiAstNodeOp_Return:
475 {
476 AssertBreakStmt( pAstNd->cArgs == 1
477 && pAstNd->aArgs[0].enmType == kAcpiAstArgType_AstNode,
478 rc = VERR_INTERNAL_ERROR);
479 rc = RTAcpiTblStmtSimpleAppend(hAcpiTbl, kAcpiStmt_Return);
480 if (RT_SUCCESS(rc))
481 {
482 if (pAstNd->aArgs[0].u.pAstNd)
483 rc = rtAcpiAstDumpToTbl(pAstNd->aArgs[0].u.pAstNd, pNsRoot, hAcpiTbl);
484 else
485 rc = RTAcpiTblNullNameAppend(hAcpiTbl);
486 }
487 break;
488 }
489 case kAcpiAstNodeOp_Unicode:
490 {
491 AssertBreakStmt( pAstNd->cArgs == 1
492 && pAstNd->aArgs[0].enmType == kAcpiAstArgType_AstNode
493 && pAstNd->aArgs[0].u.pAstNd->enmOp == kAcpiAstNodeOp_StringLiteral,
494 rc = VERR_INTERNAL_ERROR);
495
496 rc = RTAcpiTblStringAppendAsUtf16(hAcpiTbl, pAstNd->aArgs[0].u.pAstNd->pszStrLit);
497 break;
498 }
499 case kAcpiAstNodeOp_OperationRegion:
500 {
501 AssertBreakStmt( pAstNd->cArgs == 4
502 && pAstNd->aArgs[0].enmType == kAcpiAstArgType_NameString
503 && pAstNd->aArgs[1].enmType == kAcpiAstArgType_RegionSpace
504 && pAstNd->aArgs[2].enmType == kAcpiAstArgType_AstNode
505 && pAstNd->aArgs[3].enmType == kAcpiAstArgType_AstNode,
506 rc = VERR_INTERNAL_ERROR);
507
508 rc = RTAcpiTblOpRegionAppendEx(hAcpiTbl, pAstNd->aArgs[0].u.pszNameString, pAstNd->aArgs[1].u.enmRegionSpace);
509 if (RT_SUCCESS(rc))
510 rc = rtAcpiAstDumpToTbl(pAstNd->aArgs[2].u.pAstNd, pNsRoot, hAcpiTbl);
511 if (RT_SUCCESS(rc))
512 rc = rtAcpiAstDumpToTbl(pAstNd->aArgs[3].u.pAstNd, pNsRoot, hAcpiTbl);
513 break;
514 }
515 case kAcpiAstNodeOp_Field:
516 {
517 AssertBreakStmt( pAstNd->cArgs == 4
518 && pAstNd->aArgs[0].enmType == kAcpiAstArgType_NameString
519 && pAstNd->aArgs[1].enmType == kAcpiAstArgType_FieldAcc
520 && pAstNd->aArgs[2].enmType == kAcpiAstArgType_Bool
521 && pAstNd->aArgs[3].enmType == kAcpiAstArgType_FieldUpdate,
522 rc = VERR_INTERNAL_ERROR);
523 rc = rtAcpiNsAbsoluteNameStringToRelative(pNsRoot, pAstNd->pNsEntry, pAstNd->aArgs[0].u.pszNameString, &szNameString[0], sizeof(szNameString));
524 AssertRC(rc);
525
526 rc = RTAcpiTblFieldAppend(hAcpiTbl, szNameString, pAstNd->aArgs[1].u.enmFieldAcc,
527 pAstNd->aArgs[2].u.f, pAstNd->aArgs[3].u.enmFieldUpdate, pAstNd->Fields.paFields,
528 pAstNd->Fields.cFields);
529 break;
530 }
531 case kAcpiAstNodeOp_IndexField:
532 {
533 AssertBreakStmt( pAstNd->cArgs == 5
534 && pAstNd->aArgs[0].enmType == kAcpiAstArgType_NameString
535 && pAstNd->aArgs[1].enmType == kAcpiAstArgType_NameString
536 && pAstNd->aArgs[2].enmType == kAcpiAstArgType_FieldAcc
537 && pAstNd->aArgs[3].enmType == kAcpiAstArgType_Bool
538 && pAstNd->aArgs[4].enmType == kAcpiAstArgType_FieldUpdate,
539 rc = VERR_INTERNAL_ERROR);
540
541 rc = RTAcpiTblIndexFieldAppend(hAcpiTbl, pAstNd->aArgs[0].u.pszNameString, pAstNd->aArgs[1].u.pszNameString,
542 pAstNd->aArgs[2].u.enmFieldAcc, pAstNd->aArgs[3].u.f, pAstNd->aArgs[4].u.enmFieldUpdate,
543 pAstNd->Fields.paFields, pAstNd->Fields.cFields);
544 break;
545 }
546 case kAcpiAstNodeOp_Name:
547 {
548 AssertBreakStmt( pAstNd->cArgs == 2
549 && pAstNd->aArgs[0].enmType == kAcpiAstArgType_NameString
550 && pAstNd->aArgs[1].enmType == kAcpiAstArgType_AstNode,
551 rc = VERR_INTERNAL_ERROR);
552
553 rc = RTAcpiTblNameAppend(hAcpiTbl, pAstNd->aArgs[0].u.pszNameString);
554 if (RT_SUCCESS(rc))
555 rc = rtAcpiAstDumpToTbl(pAstNd->aArgs[1].u.pAstNd, pNsRoot, hAcpiTbl);
556 break;
557 }
558 case kAcpiAstNodeOp_ResourceTemplate:
559 rc = RTAcpiTblResourceAppend(hAcpiTbl, pAstNd->hAcpiRes);
560 break;
561 case kAcpiAstNodeOp_Arg0:
562 case kAcpiAstNodeOp_Arg1:
563 case kAcpiAstNodeOp_Arg2:
564 case kAcpiAstNodeOp_Arg3:
565 case kAcpiAstNodeOp_Arg4:
566 case kAcpiAstNodeOp_Arg5:
567 case kAcpiAstNodeOp_Arg6:
568 rc = RTAcpiTblArgOpAppend(hAcpiTbl, pAstNd->enmOp - kAcpiAstNodeOp_Arg0);
569 break;
570 case kAcpiAstNodeOp_Local0:
571 case kAcpiAstNodeOp_Local1:
572 case kAcpiAstNodeOp_Local2:
573 case kAcpiAstNodeOp_Local3:
574 case kAcpiAstNodeOp_Local4:
575 case kAcpiAstNodeOp_Local5:
576 case kAcpiAstNodeOp_Local6:
577 case kAcpiAstNodeOp_Local7:
578 rc = RTAcpiTblLocalOpAppend(hAcpiTbl, pAstNd->enmOp - kAcpiAstNodeOp_Local0);
579 break;
580 case kAcpiAstNodeOp_Package:
581 {
582 AssertBreakStmt( pAstNd->cArgs == 1
583 && pAstNd->aArgs[0].enmType == kAcpiAstArgType_AstNode,
584 rc = VERR_INTERNAL_ERROR);
585
586 /* Try to gather the number of elements. */
587 uint64_t cElems = 0;
588 if (pAstNd->aArgs[0].u.pAstNd)
589 {
590 /* Try resolving to a constant expression. */
591 rc = rtAcpiAstNodeEvaluateToInteger(pAstNd->aArgs[0].u.pAstNd, pNsRoot, true /*fResolveIdentifiers*/, &cElems);
592 if (RT_FAILURE(rc))
593 break;
594 }
595 else
596 {
597 /* Count elements. */
598 PRTACPIASTNODE pIt;
599 RTListForEach(&pAstNd->LstScopeNodes, pIt, RTACPIASTNODE, NdAst)
600 {
601 cElems++;
602 }
603 }
604 if (RT_SUCCESS(rc))
605 {
606 if (cElems > 255)
607 {
608 rc = VERR_BUFFER_OVERFLOW;
609 break;
610 }
611
612 rc = RTAcpiTblPackageStart(hAcpiTbl, (uint8_t)cElems);
613 if (RT_SUCCESS(rc))
614 rc = rtAcpiAstDumpAstList(&pAstNd->LstScopeNodes, pNsRoot, hAcpiTbl);
615 if (RT_SUCCESS(rc))
616 rc = RTAcpiTblPackageFinalize(hAcpiTbl);
617 }
618 break;
619 }
620 case kAcpiAstNodeOp_Buffer:
621 {
622 AssertBreakStmt( pAstNd->cArgs == 1
623 && pAstNd->aArgs[0].enmType == kAcpiAstArgType_AstNode,
624 rc = VERR_INTERNAL_ERROR);
625
626 rc = RTAcpiTblBufferStart(hAcpiTbl);
627
628 /* Try to gather the number of elements. */
629 uint64_t cElems = 0;
630 /* Count elements. */
631 PRTACPIASTNODE pIt;
632 RTListForEach(&pAstNd->LstScopeNodes, pIt, RTACPIASTNODE, NdAst)
633 {
634 cElems++;
635 }
636
637 /*
638 * If the buffer size is empty (no AST node) the number of elements
639 * in the initializer serve as tehe buffer size.
640 */
641 /** @todo Strings. */
642 if (pAstNd->aArgs[0].u.pAstNd)
643 rc = rtAcpiAstDumpToTbl(pAstNd->aArgs[0].u.pAstNd, pNsRoot, hAcpiTbl);
644 else
645 rc = RTAcpiTblIntegerAppend(hAcpiTbl, cElems);
646
647 if ( RT_SUCCESS(rc)
648 && cElems)
649 {
650 uint8_t *pb = (uint8_t *)RTMemAlloc(cElems);
651 if (pb)
652 {
653 uint64_t i = 0;
654 RTListForEach(&pAstNd->LstScopeNodes, pIt, RTACPIASTNODE, NdAst)
655 {
656 /* Try resolving to a constant expression. */
657 uint64_t u64 = 0;
658 rc = rtAcpiAstNodeEvaluateToInteger(pIt, pNsRoot, true /*fResolveIdentifiers*/, &u64);
659 if (RT_FAILURE(rc))
660 break;
661 if (u64 > UINT8_MAX)
662 {
663 rc = VERR_BUFFER_OVERFLOW;
664 break;
665 }
666
667 pb[i++] = (uint8_t)u64;
668 }
669
670 if (RT_SUCCESS(rc))
671 rc = RTAcpiTblBufferAppendRawData(hAcpiTbl, pb, cElems);
672 RTMemFree(pb);
673 }
674 else
675 rc = VERR_NO_MEMORY;
676 }
677
678 rc = RTAcpiTblBufferFinalize(hAcpiTbl);
679 break;
680 }
681 case kAcpiAstNodeOp_ToUuid:
682 {
683 AssertBreakStmt( pAstNd->cArgs == 1
684 && pAstNd->aArgs[0].enmType == kAcpiAstArgType_AstNode
685 && pAstNd->aArgs[0].u.pAstNd->enmOp == kAcpiAstNodeOp_StringLiteral,
686 rc = VERR_INTERNAL_ERROR);
687 rc = RTAcpiTblUuidAppendFromStr(hAcpiTbl, pAstNd->aArgs[0].u.pAstNd->pszStrLit);
688 break;
689 }
690 case kAcpiAstNodeOp_Break:
691 {
692 AssertBreakStmt(pAstNd->cArgs == 0, rc = VERR_INTERNAL_ERROR);
693 rc = RTAcpiTblStmtSimpleAppend(hAcpiTbl, kAcpiStmt_Break);
694 break;
695 }
696 case kAcpiAstNodeOp_Continue:
697 {
698 AssertBreakStmt(pAstNd->cArgs == 0, rc = VERR_INTERNAL_ERROR);
699 rc = RTAcpiTblStmtSimpleAppend(hAcpiTbl, kAcpiStmt_Continue);
700 break;
701 }
702 case kAcpiAstNodeOp_DerefOf:
703 case kAcpiAstNodeOp_SizeOf:
704 case kAcpiAstNodeOp_Increment:
705 case kAcpiAstNodeOp_Decrement:
706 {
707 AssertBreakStmt( pAstNd->cArgs == 1
708 && pAstNd->aArgs[0].enmType == kAcpiAstArgType_AstNode,
709 rc = VERR_INTERNAL_ERROR);
710
711 RTACPISTMT enmStmt;
712 switch (pAstNd->enmOp)
713 {
714 case kAcpiAstNodeOp_DerefOf: enmStmt = kAcpiStmt_DerefOf; break;
715 case kAcpiAstNodeOp_SizeOf: enmStmt = kAcpiStmt_SizeOf; break;
716 case kAcpiAstNodeOp_Increment: enmStmt = kAcpiStmt_Increment; break;
717 case kAcpiAstNodeOp_Decrement: enmStmt = kAcpiStmt_Decrement; break;
718 default:
719 AssertReleaseFailed(); /* Impossible */
720 return VERR_INTERNAL_ERROR;
721 }
722
723
724 rc = RTAcpiTblStmtSimpleAppend(hAcpiTbl, enmStmt);
725 if (RT_SUCCESS(rc))
726 rc = rtAcpiAstDumpToTbl(pAstNd->aArgs[0].u.pAstNd, pNsRoot, hAcpiTbl);
727 break;
728 }
729 case kAcpiAstNodeOp_Store:
730 case kAcpiAstNodeOp_Notify:
731 {
732 AssertBreakStmt( pAstNd->cArgs == 2
733 && pAstNd->aArgs[0].enmType == kAcpiAstArgType_AstNode
734 && pAstNd->aArgs[1].enmType == kAcpiAstArgType_AstNode,
735 rc = VERR_INTERNAL_ERROR);
736 rc = RTAcpiTblStmtSimpleAppend(hAcpiTbl,
737 pAstNd->enmOp == kAcpiAstNodeOp_Store
738 ? kAcpiStmt_Store
739 : kAcpiStmt_Notify);
740 if (RT_SUCCESS(rc))
741 rc = rtAcpiAstDumpToTbl(pAstNd->aArgs[0].u.pAstNd, pNsRoot, hAcpiTbl);
742 if (RT_SUCCESS(rc))
743 rc = rtAcpiAstDumpToTbl(pAstNd->aArgs[1].u.pAstNd, pNsRoot, hAcpiTbl);
744 break;
745 }
746 case kAcpiAstNodeOp_Not:
747 case kAcpiAstNodeOp_CondRefOf:
748 case kAcpiAstNodeOp_FindSetLeftBit:
749 case kAcpiAstNodeOp_FindSetRightBit:
750 {
751 AssertBreakStmt( pAstNd->cArgs == 2
752 && pAstNd->aArgs[0].enmType == kAcpiAstArgType_AstNode
753 && pAstNd->aArgs[1].enmType == kAcpiAstArgType_AstNode,
754 rc = VERR_INTERNAL_ERROR);
755
756 RTACPISTMT enmStmt;
757 switch (pAstNd->enmOp)
758 {
759 case kAcpiAstNodeOp_Not: enmStmt = kAcpiStmt_Not; break;
760 case kAcpiAstNodeOp_CondRefOf: enmStmt = kAcpiStmt_CondRefOf; break;
761 case kAcpiAstNodeOp_FindSetLeftBit: enmStmt = kAcpiStmt_FindSetLeftBit; break;
762 case kAcpiAstNodeOp_FindSetRightBit: enmStmt = kAcpiStmt_FindSetRightBit; break;
763 default:
764 AssertReleaseFailed(); /* Impossible */
765 return VERR_INTERNAL_ERROR;
766 }
767
768 rc = RTAcpiTblStmtSimpleAppend(hAcpiTbl, enmStmt);
769 if (RT_SUCCESS(rc))
770 rc = rtAcpiAstDumpToTbl(pAstNd->aArgs[0].u.pAstNd, pNsRoot, hAcpiTbl);
771 if (RT_SUCCESS(rc))
772 {
773 if (pAstNd->aArgs[1].u.pAstNd)
774 rc = rtAcpiAstDumpToTbl(pAstNd->aArgs[1].u.pAstNd, pNsRoot, hAcpiTbl);
775 else
776 rc = RTAcpiTblNullNameAppend(hAcpiTbl);
777 }
778 break;
779 }
780 case kAcpiAstNodeOp_Index:
781 case kAcpiAstNodeOp_Add:
782 case kAcpiAstNodeOp_Subtract:
783 case kAcpiAstNodeOp_Multiply:
784 case kAcpiAstNodeOp_And:
785 case kAcpiAstNodeOp_Nand:
786 case kAcpiAstNodeOp_Or:
787 case kAcpiAstNodeOp_Xor:
788 case kAcpiAstNodeOp_ShiftLeft:
789 case kAcpiAstNodeOp_ShiftRight:
790 case kAcpiAstNodeOp_ConcatenateResTemplate:
791 {
792 AssertBreakStmt( pAstNd->cArgs == 3
793 && pAstNd->aArgs[0].enmType == kAcpiAstArgType_AstNode
794 && pAstNd->aArgs[1].enmType == kAcpiAstArgType_AstNode
795 && pAstNd->aArgs[2].enmType == kAcpiAstArgType_AstNode,
796 rc = VERR_INTERNAL_ERROR);
797
798 RTACPISTMT enmStmt;
799 switch (pAstNd->enmOp)
800 {
801 case kAcpiAstNodeOp_Index: enmStmt = kAcpiStmt_Index; break;
802 case kAcpiAstNodeOp_Add: enmStmt = kAcpiStmt_Add; break;
803 case kAcpiAstNodeOp_Subtract: enmStmt = kAcpiStmt_Subtract; break;
804 case kAcpiAstNodeOp_Multiply: enmStmt = kAcpiStmt_Multiply; break;
805 case kAcpiAstNodeOp_And: enmStmt = kAcpiStmt_And; break;
806 case kAcpiAstNodeOp_Nand: enmStmt = kAcpiStmt_Nand; break;
807 case kAcpiAstNodeOp_Or: enmStmt = kAcpiStmt_Or; break;
808 case kAcpiAstNodeOp_Xor: enmStmt = kAcpiStmt_Xor; break;
809 case kAcpiAstNodeOp_ShiftLeft: enmStmt = kAcpiStmt_ShiftLeft; break;
810 case kAcpiAstNodeOp_ShiftRight: enmStmt = kAcpiStmt_ShiftRight; break;
811 case kAcpiAstNodeOp_ConcatenateResTemplate: enmStmt = kAcpiStmt_ConcatenateResTemplate; break;
812 default:
813 AssertReleaseFailed(); /* Impossible */
814 return VERR_INTERNAL_ERROR;
815 }
816
817 rc = RTAcpiTblStmtSimpleAppend(hAcpiTbl, enmStmt);
818 if (RT_SUCCESS(rc))
819 rc = rtAcpiAstDumpToTbl(pAstNd->aArgs[0].u.pAstNd, pNsRoot, hAcpiTbl);
820 if (RT_SUCCESS(rc))
821 rc = rtAcpiAstDumpToTbl(pAstNd->aArgs[1].u.pAstNd, pNsRoot, hAcpiTbl);
822 if (RT_SUCCESS(rc))
823 {
824 if (pAstNd->aArgs[2].u.pAstNd)
825 rc = rtAcpiAstDumpToTbl(pAstNd->aArgs[2].u.pAstNd, pNsRoot, hAcpiTbl);
826 else
827 rc = RTAcpiTblNullNameAppend(hAcpiTbl);
828 }
829 break;
830 }
831 case kAcpiAstNodeOp_EisaId:
832 {
833 AssertBreakStmt( pAstNd->cArgs == 1
834 && pAstNd->aArgs[0].enmType == kAcpiAstArgType_StringLiteral,
835 rc = VERR_INTERNAL_ERROR);
836 rc = RTAcpiTblEisaIdAppend(hAcpiTbl, pAstNd->aArgs[0].u.pszStrLit);
837 break;
838 }
839 case kAcpiAstNodeOp_CreateBitField:
840 case kAcpiAstNodeOp_CreateByteField:
841 case kAcpiAstNodeOp_CreateWordField:
842 case kAcpiAstNodeOp_CreateDWordField:
843 case kAcpiAstNodeOp_CreateQWordField:
844 {
845 AssertBreakStmt( pAstNd->cArgs == 3
846 && pAstNd->aArgs[0].enmType == kAcpiAstArgType_AstNode
847 && pAstNd->aArgs[1].enmType == kAcpiAstArgType_AstNode
848 && pAstNd->aArgs[2].enmType == kAcpiAstArgType_NameString,
849 rc = VERR_INTERNAL_ERROR);
850
851 RTACPISTMT enmStmt;
852 switch (pAstNd->enmOp)
853 {
854 case kAcpiAstNodeOp_CreateBitField: enmStmt = kAcpiStmt_CreateBitField; break;
855 case kAcpiAstNodeOp_CreateByteField: enmStmt = kAcpiStmt_CreateByteField; break;
856 case kAcpiAstNodeOp_CreateWordField: enmStmt = kAcpiStmt_CreateWordField; break;
857 case kAcpiAstNodeOp_CreateDWordField: enmStmt = kAcpiStmt_CreateDWordField; break;
858 case kAcpiAstNodeOp_CreateQWordField: enmStmt = kAcpiStmt_CreateQWordField; break;
859 default:
860 AssertReleaseFailed(); /* Impossible */
861 return VERR_INTERNAL_ERROR;
862 }
863
864 rc = RTAcpiTblStmtSimpleAppend(hAcpiTbl, enmStmt);
865 if (RT_SUCCESS(rc))
866 rc = rtAcpiAstDumpToTbl(pAstNd->aArgs[0].u.pAstNd, pNsRoot, hAcpiTbl);
867 if (RT_SUCCESS(rc))
868 {
869 /* Try to resolve to an integer. */
870 uint64_t off = 0;
871 if (pAstNd->aArgs[1].u.pAstNd->enmOp == kAcpiAstNodeOp_Number)
872 off = pAstNd->aArgs[1].u.pAstNd->u64;
873 else
874 {
875 rc = rtAcpiAstNodeEvaluateToInteger(pAstNd->aArgs[1].u.pAstNd, pNsRoot, true /*fResolveIdentifiers*/, &off);
876 off = pAstNd->enmOp == kAcpiAstNodeOp_CreateBitField ? off : off / 8;
877 }
878 if (RT_SUCCESS(rc))
879 rc = RTAcpiTblIntegerAppend(hAcpiTbl, off);
880 else
881 rc = rtAcpiAstDumpToTbl(pAstNd->aArgs[1].u.pAstNd, pNsRoot, hAcpiTbl);
882 }
883 if (RT_SUCCESS(rc))
884 rc = RTAcpiTblNameStringAppend(hAcpiTbl, pAstNd->aArgs[2].u.pszNameString);
885 break;
886 }
887 case kAcpiAstNodeOp_External:
888 default:
889 AssertFailedStmt(rc = VERR_NOT_IMPLEMENTED);
890 }
891
892 AssertRC(rc);
893 return rc;
894}
Note: See TracBrowser for help on using the repository browser.

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