VirtualBox

source: vbox/trunk/src/VBox/Runtime/common/misc/acpi-decompiler.cpp@ 108008

Last change on this file since 108008 was 107971, checked in by vboxsync, 3 months ago

Runtime/common/misc/acpi-decompiler.cpp: Some updates, can decompile our CPU hotplug SSDT _mostly_ without error, bugref:10733

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 59.7 KB
Line 
1/* $Id: acpi-decompiler.cpp 107971 2025-01-28 15:48:44Z vboxsync $ */
2/** @file
3 * IPRT - Advanced Configuration and Power Interface (ACPI) Table generation API.
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/acpi.h>
43#include <iprt/asm.h>
44#include <iprt/ctype.h>
45#include <iprt/err.h>
46#include <iprt/file.h>
47#include <iprt/mem.h>
48#include <iprt/string.h>
49#include <iprt/uuid.h>
50
51#include <iprt/formats/acpi-aml.h>
52#include <iprt/formats/acpi-resources.h>
53
54
55/*********************************************************************************************************************************
56* Defined Constants And Macros *
57*********************************************************************************************************************************/
58
59
60
61/*********************************************************************************************************************************
62* Structures and Typedefs *
63*********************************************************************************************************************************/
64
65/**
66 * ACPI AML -> ASL decoder state.
67 */
68typedef struct RTACPITBLAMLDECODE
69{
70 /** Pointe to the raw table data. */
71 const uint8_t *pbTbl;
72 /** Size of the table. */
73 uint32_t cbTbl;
74 /** Offset into the table. */
75 uint32_t offTbl;
76 /** Current stack level. */
77 uint32_t iLvl;
78 /** Number of entries in the package stack. */
79 uint32_t cPkgStackMax;
80 /** Stack of package lengths. */
81 size_t *pacbPkgLeft;
82 /** Stack of original package lengths. */
83 size_t *pacbPkg;
84 /** Flag whether to indent. */
85 bool fIndent;
86} RTACPITBLAMLDECODE;
87/** Pointer to a ACPI AML -> ASL decoder state. */
88typedef RTACPITBLAMLDECODE *PRTACPITBLAMLDECODE;
89
90
91/**
92 * ACPI AML -> ASL decode callback
93 *
94 * @returns IPRT status code.
95 * @param pThis ACPI table decoder state.
96 * @param hVfsIosOut VFS I/O stream output handle.
97 * @param bOp The opcode.
98 * @param pErrInfo Where to return additional error information.
99 */
100typedef DECLCALLBACKTYPE(int, FNRTACPITBLAMLOPCDECODE,(PRTACPITBLAMLDECODE pThis, RTVFSIOSTREAM hVfsIosOut, uint8_t bOp, PRTERRINFO pErrInfo));
101/** Pointer to a ACPI AML -> ASL decode callback. */
102typedef FNRTACPITBLAMLOPCDECODE *PFNRTACPITBLAMLOPCDECODE;
103
104
105typedef enum ACPIAMLOPCTYPE
106{
107 kAcpiAmlOpcType_Invalid = 0,
108 kAcpiAmlOpcType_Byte,
109 kAcpiAmlOpcType_Word,
110 kAcpiAmlOpcType_DWord,
111 kAcpiAmlOpcType_NameString,
112 kAcpiAmlOpcType_TermArg,
113 kAcpiAmlOpcType_SuperName,
114 kAcpiAmlOpcType_32BitHack = 0x7fffffff
115} ACPIAMLOPCTYPE;
116
117
118typedef struct RTACPIAMLOPC
119{
120 /** Name of the opcode. */
121 const char *pszOpc;
122 /** Flags for the opcode. */
123 uint32_t fFlags;
124 /** Opcode type for the fields following. */
125 ACPIAMLOPCTYPE aenmTypes[5];
126 /** Optional decoder callback. */
127 PFNRTACPITBLAMLOPCDECODE pfnDecode;
128} RTACPIAMLOPC;
129typedef RTACPIAMLOPC *PRTACPIAMLOPC;
130typedef const RTACPIAMLOPC *PCRTACPIAMLOPC;
131
132#define RTACPI_AML_OPC_F_NONE 0
133#define RTACPI_AML_OPC_F_HAS_PKG_LENGTH RT_BIT_32(0)
134
135
136/*********************************************************************************************************************************
137* Global Variables *
138*********************************************************************************************************************************/
139
140
141/*********************************************************************************************************************************
142* Internal Functions *
143*********************************************************************************************************************************/
144
145static int rtAcpiTblAmlDecodeTerminal(PRTACPITBLAMLDECODE pThis, RTVFSIOSTREAM hVfsIosOut, PRTERRINFO pErrInfo);
146
147
148DECLINLINE(int) rtAcpiTblAmlDecodeReadU8(PRTACPITBLAMLDECODE pThis, uint8_t *pb, PRTERRINFO pErrInfo)
149{
150 if (pThis->offTbl < pThis->cbTbl)
151 { /* probable */ }
152 else
153 return RTErrInfoSetF(pErrInfo, VERR_EOF, "AML stream ended prematurely at offset '%#x' trying to read a byte", pThis->offTbl);
154
155 if (!pThis->pacbPkgLeft[pThis->iLvl])
156 return RTErrInfoSetF(pErrInfo, VERR_INVALID_STATE, "Data overflows current package limitation");
157
158 pThis->pacbPkgLeft[pThis->iLvl]--;
159
160 *pb = pThis->pbTbl[pThis->offTbl++];
161 return VINF_SUCCESS;
162}
163
164
165#if 0
166DECLINLINE(int) rtAcpiTblAmlDecodeSkipU8IfEqual(PRTACPITBLAMLDECODE pThis, uint8_t ch, bool *fSkipped, PRTERRINFO pErrInfo)
167{
168 if (pThis->offTbl < pThis->cbTbl)
169 { /* probable */ }
170 else
171 return RTErrInfoSetF(pErrInfo, VERR_EOF, "AML stream ended prematurely at offset '%#x' trying to read a byte", pThis->offTbl);
172
173 if (pThis->pbTbl[pThis->offTbl] == ch)
174 {
175 pThis->offTbl++;
176 *pfSkipped = true;
177 }
178 else
179 *pfSkipped = false;
180 return VINF_SUCCESS;
181}
182#endif
183
184
185DECLINLINE(int) rtAcpiTblAmlDecodeReadU16(PRTACPITBLAMLDECODE pThis, uint16_t *pu16, PRTERRINFO pErrInfo)
186{
187 if (pThis->offTbl <= pThis->cbTbl + sizeof(uint16_t))
188 { /* probable */ }
189 else
190 return RTErrInfoSetF(pErrInfo, VERR_EOF, "AML stream ended prematurely at offset '%#x' trying to read two bytes", pThis->offTbl);
191
192 if (pThis->pacbPkgLeft[pThis->iLvl] < sizeof(uint16_t))
193 return RTErrInfoSetF(pErrInfo, VERR_INVALID_STATE, "Data overflows current package limitation");
194
195 pThis->pacbPkgLeft[pThis->iLvl] -= sizeof(uint16_t);
196
197 *pu16 = pThis->pbTbl[pThis->offTbl++];
198 *pu16 |= (uint16_t)pThis->pbTbl[pThis->offTbl++] << 8;
199 return VINF_SUCCESS;
200}
201
202
203DECLINLINE(int) rtAcpiTblAmlDecodeReadU32(PRTACPITBLAMLDECODE pThis, uint32_t *pu32, PRTERRINFO pErrInfo)
204{
205 if (pThis->offTbl <= pThis->cbTbl + sizeof(uint32_t))
206 { /* probable */ }
207 else
208 return RTErrInfoSetF(pErrInfo, VERR_EOF, "AML stream ended prematurely at offset '%#x' trying to read four bytes", pThis->offTbl);
209
210 if (pThis->pacbPkgLeft[pThis->iLvl] < sizeof(uint32_t))
211 return RTErrInfoSetF(pErrInfo, VERR_INVALID_STATE, "Data overflows current package limitation");
212
213 pThis->pacbPkgLeft[pThis->iLvl] -= sizeof(uint32_t);
214
215 *pu32 = pThis->pbTbl[pThis->offTbl++];
216 *pu32 |= (uint32_t)pThis->pbTbl[pThis->offTbl++] << 8;
217 *pu32 |= (uint32_t)pThis->pbTbl[pThis->offTbl++] << 16;
218 *pu32 |= (uint32_t)pThis->pbTbl[pThis->offTbl++] << 24;
219 return VINF_SUCCESS;
220}
221
222
223DECLINLINE(int) rtAcpiTblAmlDecodeReadU64(PRTACPITBLAMLDECODE pThis, uint64_t *pu64, PRTERRINFO pErrInfo)
224{
225 if (pThis->offTbl <= pThis->cbTbl + sizeof(uint64_t))
226 { /* probable */ }
227 else
228 return RTErrInfoSetF(pErrInfo, VERR_EOF, "AML stream ended prematurely at offset '%#x' trying to read eight bytes", pThis->offTbl);
229
230 if (pThis->pacbPkgLeft[pThis->iLvl] < sizeof(uint64_t))
231 return RTErrInfoSetF(pErrInfo, VERR_INVALID_STATE, "Data overflows current package limitation");
232
233 pThis->pacbPkgLeft[pThis->iLvl] -= sizeof(uint64_t);
234
235 *pu64 = pThis->pbTbl[pThis->offTbl++];
236 *pu64 |= (uint64_t)pThis->pbTbl[pThis->offTbl++] << 8;
237 *pu64 |= (uint64_t)pThis->pbTbl[pThis->offTbl++] << 16;
238 *pu64 |= (uint64_t)pThis->pbTbl[pThis->offTbl++] << 24;
239 *pu64 |= (uint64_t)pThis->pbTbl[pThis->offTbl++] << 32;
240 *pu64 |= (uint64_t)pThis->pbTbl[pThis->offTbl++] << 40;
241 *pu64 |= (uint64_t)pThis->pbTbl[pThis->offTbl++] << 48;
242 *pu64 |= (uint64_t)pThis->pbTbl[pThis->offTbl++] << 54;
243 return VINF_SUCCESS;
244}
245
246
247static int rtAcpiTblAmlDecodeNameSeg(PRTACPITBLAMLDECODE pThis, char *pszNameString, PRTERRINFO pErrInfo)
248{
249 uint8_t abNameSeg[4];
250 for (uint8_t i = 0; i < sizeof(abNameSeg); i++)
251 {
252 int rc = rtAcpiTblAmlDecodeReadU8(pThis, &abNameSeg[i], pErrInfo);
253 if (RT_FAILURE(rc)) return rc;
254 }
255
256 /* LeadNameChar */
257 if ( abNameSeg[0] != '_'
258 && !RTLocCIsUpper(abNameSeg[0]))
259 return RTErrInfoSetF(pErrInfo, VERR_INVALID_PARAMETER, "AML stream contains invalid lead name character '%#02RX8'", abNameSeg[0]);
260
261 for (uint8_t i = 1; i < sizeof(abNameSeg); i++)
262 {
263 if ( abNameSeg[i] != '_'
264 && !RTLocCIsUpper(abNameSeg[i])
265 && !RTLocCIsDigit(abNameSeg[i]))
266 return RTErrInfoSetF(pErrInfo, VERR_INVALID_PARAMETER, "AML stream contains invalid name character '%#02RX8", abNameSeg[i]);
267 }
268
269 pszNameString[0] = (char)abNameSeg[0];
270 pszNameString[1] = (char)abNameSeg[1];
271 pszNameString[2] = (char)abNameSeg[2];
272 pszNameString[3] = (char)abNameSeg[3];
273 return VINF_SUCCESS;
274}
275
276
277static int rtAcpiTblAmlDecodeNameSegWithoutLeadChar(PRTACPITBLAMLDECODE pThis, uint8_t bLeadChar, char *pszNameString, PRTERRINFO pErrInfo)
278{
279 uint8_t abNameSeg[3];
280 for (uint8_t i = 0; i < sizeof(abNameSeg); i++)
281 {
282 int rc = rtAcpiTblAmlDecodeReadU8(pThis, &abNameSeg[i], pErrInfo);
283 if (RT_FAILURE(rc)) return rc;
284 }
285
286 /* LeadNameChar */
287 if ( bLeadChar != '_'
288 && !RTLocCIsUpper(bLeadChar))
289 return RTErrInfoSetF(pErrInfo, VERR_INVALID_PARAMETER, "AML stream contains invalid lead name character '%#02RX8'", bLeadChar);
290
291 for (uint8_t i = 1; i < sizeof(abNameSeg); i++)
292 {
293 if ( abNameSeg[i] != '_'
294 && !RTLocCIsUpper(abNameSeg[i])
295 && !RTLocCIsDigit(abNameSeg[i]))
296 return RTErrInfoSetF(pErrInfo, VERR_INVALID_PARAMETER, "AML stream contains invalid name character '%#02RX8'", abNameSeg[i]);
297 }
298
299 pszNameString[0] = (char)bLeadChar;
300 pszNameString[1] = (char)abNameSeg[0];
301 pszNameString[2] = (char)abNameSeg[1];
302 pszNameString[3] = (char)abNameSeg[2];
303 return VINF_SUCCESS;
304}
305
306
307static int rtAcpiTblAmlDecodeNameStringWithLead(PRTACPITBLAMLDECODE pThis, uint8_t bLeadChar, char *pszNameString, size_t cchNameString, size_t *pcbNameString, PRTERRINFO pErrInfo)
308{
309 AssertReturn(cchNameString >= 5, VERR_INVALID_PARAMETER); /* One name segment is at least 4 bytes (+ terminator). */
310
311 /* Check for a root path. */
312 int rc = VINF_SUCCESS;
313 uint8_t bTmp = bLeadChar;
314 size_t idxName = 0;
315 if (bTmp == '\\')
316 {
317 pszNameString[idxName++] = '\\';
318
319 rc = rtAcpiTblAmlDecodeReadU8(pThis, &bTmp, pErrInfo);
320 if (RT_FAILURE(rc)) return rc;
321 }
322 else if (bTmp == '^')
323 {
324 /* Prefix path, can have multiple ^ prefixes. */
325 pszNameString[idxName++] = '^';
326
327 for (;;)
328 {
329 rc = rtAcpiTblAmlDecodeReadU8(pThis, &bTmp, pErrInfo);
330 if (RT_FAILURE(rc)) return rc;
331
332 if (bTmp != '^')
333 break;
334
335 if (idxName == cchNameString - 1)
336 return RTErrInfoSetF(pErrInfo, VERR_BUFFER_OVERFLOW, "PrefixPath in AML byte stream is too long to fit into a %zu byte buffer",
337 cchNameString - 1);
338
339 pszNameString[idxName++] = '^';
340 }
341 }
342
343 if (bTmp == ACPI_AML_BYTE_CODE_PREFIX_DUAL_NAME)
344 {
345 if (idxName + 8 < cchNameString)
346 {
347 rc = rtAcpiTblAmlDecodeNameSeg(pThis, &pszNameString[idxName], pErrInfo);
348 if (RT_FAILURE(rc)) return rc;
349
350 rc = rtAcpiTblAmlDecodeNameSeg(pThis, &pszNameString[idxName + 4], pErrInfo);
351 if (RT_FAILURE(rc)) return rc;
352
353 idxName += 8;
354 pszNameString[idxName] = '\0';
355 }
356 else
357 rc = RTErrInfoSetF(pErrInfo, VERR_BUFFER_OVERFLOW, "DualNamePrefix string in AML byte stream is too long to fit into a %zu byte buffer",
358 cchNameString - 1);
359 }
360 else if (bTmp == ACPI_AML_BYTE_CODE_PREFIX_MULTI_NAME)
361 {
362 uint8_t cSegs = 0;
363 rc = rtAcpiTblAmlDecodeReadU8(pThis, &cSegs, pErrInfo);
364 if (RT_FAILURE(rc)) return rc;
365
366 if (idxName + cSegs * 4 < cchNameString)
367 {
368 for (uint8_t i = 0; i < cSegs; i++)
369 {
370 rc = rtAcpiTblAmlDecodeNameSeg(pThis, &pszNameString[idxName + i * 4], pErrInfo);
371 if (RT_FAILURE(rc)) return rc;
372 }
373
374 idxName += cSegs * 4;
375 pszNameString[idxName] = '\0';
376 }
377 else
378 rc = RTErrInfoSetF(pErrInfo, VERR_BUFFER_OVERFLOW, "MultiNamePrefix string in AML byte stream is too long to fit into a %zu byte buffer",
379 cchNameString - 1);
380 }
381 else if (bTmp == ACPI_AML_BYTE_CODE_PREFIX_NULL_NAME)
382 pszNameString[idxName] = '\0';
383 else
384 {
385 if (idxName + 4 < cchNameString)
386 {
387 rc = rtAcpiTblAmlDecodeNameSegWithoutLeadChar(pThis, bTmp, &pszNameString[idxName], pErrInfo);
388 if (RT_FAILURE(rc)) return rc;
389
390 idxName += 4;
391 pszNameString[idxName] = '\0';
392 }
393 else
394 rc = RTErrInfoSetF(pErrInfo, VERR_BUFFER_OVERFLOW, "Name string in AML byte stream is too long to fit into a %zu byte buffer",
395 cchNameString - 1);
396 }
397
398 *pcbNameString = idxName;
399 return rc;
400}
401
402
403static int rtAcpiTblAmlDecodeNameString(PRTACPITBLAMLDECODE pThis, char *pszNameString, size_t cchNameString, size_t *pcbNameString, PRTERRINFO pErrInfo)
404{
405 AssertReturn(cchNameString >= 5, VERR_INVALID_PARAMETER); /* One name segment is at least 4 bytes (+ terminator). */
406
407 uint8_t bLead = 0; /* shut up gcc */
408 int rc = rtAcpiTblAmlDecodeReadU8(pThis, &bLead, pErrInfo);
409 if (RT_FAILURE(rc)) return rc;
410
411 return rtAcpiTblAmlDecodeNameStringWithLead( pThis, bLead, pszNameString, cchNameString, pcbNameString, pErrInfo);
412}
413
414
415/**
416 * Adds the proper indentation before a new line.
417 *
418 * @returns IPRT status code.
419 * @param hVfsIos The VFS I/O stream handle to dump the ASL to.
420 * @param uIndentLvl The level of indentation.
421 */
422static int rtAcpiTblAmlDecodeIndent(RTVFSIOSTREAM hVfsIos, uint32_t uIndentLvl)
423{
424 while (uIndentLvl--)
425 {
426 ssize_t cch = RTVfsIoStrmPrintf(hVfsIos, " ");
427 if (cch != 4)
428 return cch < 0 ? (int)cch : VERR_BUFFER_UNDERFLOW;
429 }
430
431 return VINF_SUCCESS;
432}
433
434
435static int rtAcpiTblAmlDecodeFormat(PRTACPITBLAMLDECODE pThis, RTVFSIOSTREAM hVfsIos, const char *pszFmt, ...)
436{
437 int rc = VINF_SUCCESS;
438 if (pThis->fIndent)
439 rc = rtAcpiTblAmlDecodeIndent(hVfsIos, pThis->iLvl);
440 if (RT_SUCCESS(rc))
441 {
442 va_list VaArgs;
443 va_start(VaArgs, pszFmt);
444 ssize_t cch = RTVfsIoStrmPrintfV(hVfsIos, pszFmt, VaArgs);
445 va_end(VaArgs);
446 if (cch <= 0)
447 rc = cch < 0 ? (int)cch : VERR_NO_MEMORY;
448 }
449
450 return rc;
451}
452
453
454static int rtAcpiTblAmlDecodePkgLength(PRTACPITBLAMLDECODE pThis, size_t *pcbPkg, size_t *pcbPkgLength, PRTERRINFO pErrInfo)
455{
456 uint8_t bTmp = 0; /* shut up gcc */
457 int rc = rtAcpiTblAmlDecodeReadU8(pThis, &bTmp, pErrInfo);
458 if (RT_FAILURE(rc))
459 return rc;
460
461 /* High 2 bits give the remaining bytes following to form the final package length. */
462 uint8_t cBytesRemaining = (bTmp >> 6) & 0x3;
463 *pcbPkgLength = 1 + cBytesRemaining;
464
465 if (cBytesRemaining)
466 {
467 size_t cbPkg = bTmp & 0xf;
468 for (uint8_t i = 0; i < cBytesRemaining; i++)
469 {
470 rc = rtAcpiTblAmlDecodeReadU8(pThis, &bTmp, pErrInfo);
471 if (RT_FAILURE(rc))
472 return rc;
473
474 cbPkg |= (size_t)bTmp << (i * 8 + 4);
475 *pcbPkg = cbPkg;
476 }
477 }
478 else
479 *pcbPkg = bTmp & 0x3f;
480
481 return VINF_SUCCESS;
482}
483
484
485static int rtAcpiTblAmlDecodePkgPush(PRTACPITBLAMLDECODE pThis, RTVFSIOSTREAM hVfsIosOut, size_t cbPkg, PRTERRINFO pErrInfo)
486{
487 /* Get a new stack element. */
488 if (pThis->iLvl == pThis->cPkgStackMax)
489 {
490 uint32_t const cPkgElemsNew = pThis->cPkgStackMax + 8;
491 size_t *pacbPkgLeftNew = (size_t *)RTMemRealloc(pThis->pacbPkgLeft, 2 * cPkgElemsNew * sizeof(*pacbPkgLeftNew));
492 if (!pacbPkgLeftNew)
493 return RTErrInfoSetF(pErrInfo, VERR_NO_MEMORY, "Out of memory pushing a new package onto the stack");
494
495 pThis->pacbPkgLeft = pacbPkgLeftNew;
496 pThis->pacbPkg = pacbPkgLeftNew + cPkgElemsNew;
497 pThis->cPkgStackMax = cPkgElemsNew;
498 }
499
500 uint32_t const iLvlNew = pThis->iLvl + 1;
501 pThis->pacbPkgLeft[iLvlNew] = cbPkg;
502 pThis->pacbPkg[iLvlNew] = cbPkg;
503 int rc = rtAcpiTblAmlDecodeFormat(pThis, hVfsIosOut, "{\n");
504 pThis->iLvl = iLvlNew;
505 return rc;
506}
507
508
509DECLINLINE(int) rtAcpiTblAmlDecodePkgPop(PRTACPITBLAMLDECODE pThis, RTVFSIOSTREAM hVfsIosOut, PRTERRINFO pErrInfo)
510{
511 while (!pThis->pacbPkgLeft[pThis->iLvl])
512 {
513 size_t cbPkg = pThis->pacbPkg[pThis->iLvl];
514 pThis->iLvl--;
515
516 if (pThis->pacbPkgLeft[pThis->iLvl] < cbPkg)
517 return RTErrInfoSetF(pErrInfo, VERR_INVALID_STATE, "AML contains invalid package length encoding");
518
519 pThis->pacbPkgLeft[pThis->iLvl] -= cbPkg;
520 int rc = rtAcpiTblAmlDecodeFormat(pThis, hVfsIosOut, "}\n");
521 if (RT_FAILURE(rc))
522 return rc;
523 }
524
525 return VINF_SUCCESS;
526}
527
528
529static int rtAcpiTblAmlDecodeIntegerFromPrefix(PRTACPITBLAMLDECODE pThis, uint8_t bPrefix, uint64_t *pu64, size_t cbDecodeMax, size_t *pcbDecoded, PRTERRINFO pErrInfo)
530{
531 switch (bPrefix)
532 {
533 case ACPI_AML_BYTE_CODE_PREFIX_BYTE:
534 {
535 if (!cbDecodeMax)
536 return RTErrInfoSetF(pErrInfo, VERR_INVALID_STATE, "Not enough data left to decode byte integer in AML stream");
537
538 uint8_t bInt = 0;
539 int rc = rtAcpiTblAmlDecodeReadU8(pThis, &bInt, pErrInfo);
540 if (RT_FAILURE(rc))
541 return rc;
542
543 *pu64 = bInt;
544 *pcbDecoded = 2;
545 break;
546 }
547 case ACPI_AML_BYTE_CODE_PREFIX_WORD:
548 {
549 if (cbDecodeMax < 2)
550 return RTErrInfoSetF(pErrInfo, VERR_INVALID_STATE, "Not enough data left to decode word integer in AML stream");
551
552 uint16_t u16 = 0;
553 int rc = rtAcpiTblAmlDecodeReadU16(pThis, &u16, pErrInfo);
554 if (RT_FAILURE(rc))
555 return rc;
556
557 *pu64 = u16;
558 *pcbDecoded = 3;
559 break;
560 }
561 case ACPI_AML_BYTE_CODE_PREFIX_DWORD:
562 {
563 if (cbDecodeMax < 4)
564 return RTErrInfoSetF(pErrInfo, VERR_INVALID_STATE, "Not enough data left to decode double word integer in AML stream");
565
566 uint32_t u32 = 0;
567 int rc = rtAcpiTblAmlDecodeReadU32(pThis, &u32, pErrInfo);
568 if (RT_FAILURE(rc))
569 return rc;
570
571 *pu64 = u32;
572 *pcbDecoded = 5;
573 break;
574 }
575 case ACPI_AML_BYTE_CODE_PREFIX_QWORD:
576 {
577 if (cbDecodeMax < 8)
578 return RTErrInfoSetF(pErrInfo, VERR_INVALID_STATE, "Not enough data left to decode quad word integer in AML stream");
579
580 uint64_t u64 = 0;
581 int rc = rtAcpiTblAmlDecodeReadU64(pThis, &u64, pErrInfo);
582 if (RT_FAILURE(rc))
583 return rc;
584
585 *pu64 = u64;
586 *pcbDecoded = 9;
587 break;
588 }
589 default:
590 return RTErrInfoSetF(pErrInfo, VERR_INVALID_STATE, "Invalid integer prefix '%#02RX8'", bPrefix);
591 }
592
593 return VINF_SUCCESS;
594}
595
596
597static int rtAcpiTblAmlDecodeIntegerWorker(PRTACPITBLAMLDECODE pThis, uint64_t *pu64, size_t cbDecodeMax, size_t *pcbDecoded, PRTERRINFO pErrInfo)
598{
599 AssertReturn(cbDecodeMax >= 1, VERR_INVALID_PARAMETER);
600
601 uint8_t bPrefix = 0; /* shut up gcc */
602 int rc = rtAcpiTblAmlDecodeReadU8(pThis, &bPrefix, pErrInfo);
603 if (RT_FAILURE(rc))
604 return rc;
605
606 cbDecodeMax--;
607 return rtAcpiTblAmlDecodeIntegerFromPrefix(pThis, bPrefix, pu64, cbDecodeMax, pcbDecoded, pErrInfo);
608}
609
610
611static DECLCALLBACK(int) rtAcpiTblAmlDecodeNameObject(PRTACPITBLAMLDECODE pThis, RTVFSIOSTREAM hVfsIosOut, uint8_t bOp, PRTERRINFO pErrInfo)
612{
613 char szName[512];
614 size_t cbName = 0;
615
616 int rc = rtAcpiTblAmlDecodeNameStringWithLead(pThis, bOp, &szName[0], sizeof(szName), &cbName, pErrInfo);
617 if (RT_FAILURE(rc)) return rc;
618
619 return rtAcpiTblAmlDecodeFormat(pThis, hVfsIosOut, "%s", szName);
620}
621
622
623static DECLCALLBACK(int) rtAcpiTblAmlDecodeString(PRTACPITBLAMLDECODE pThis, RTVFSIOSTREAM hVfsIosOut, uint8_t bOp, PRTERRINFO pErrInfo)
624{
625 RT_NOREF(bOp);
626
627 char szStr[512];
628 uint32_t i = 0;
629 for (;;)
630 {
631 uint8_t bTmp = 0; /* shut up gcc */
632 int rc = rtAcpiTblAmlDecodeReadU8(pThis, &bTmp, pErrInfo);
633 if (RT_FAILURE(rc))
634 return rc;
635
636 if (bTmp >= 0x1 && bTmp <= 0x7f)
637 szStr[i++] = (char)bTmp;
638 else if (bTmp == 0x00)
639 {
640 szStr[i++] = '\0';
641 break;
642 }
643 else
644 return RTErrInfoSetF(pErrInfo, VERR_INVALID_STATE, "Invalid ASCII string character %#x in string", bTmp);
645
646 if (i == sizeof(szStr))
647 return RTErrInfoSetF(pErrInfo, VERR_BUFFER_OVERFLOW, "ASCII string is out of bounds");
648 }
649
650 return rtAcpiTblAmlDecodeFormat(pThis, hVfsIosOut, "\"%s\"", szStr);
651}
652
653
654static DECLCALLBACK(int) rtAcpiTblAmlDecodeBuffer(PRTACPITBLAMLDECODE pThis, RTVFSIOSTREAM hVfsIosOut, uint8_t bOp, PRTERRINFO pErrInfo)
655{
656 RT_NOREF(bOp);
657
658 size_t cbPkg = 0;
659 size_t cbPkgLength = 0;
660 int rc = rtAcpiTblAmlDecodePkgLength(pThis, &cbPkg, &cbPkgLength, pErrInfo);
661 if (RT_FAILURE(rc))
662 return rc;
663
664 cbPkg -= cbPkgLength;
665 uint64_t u64 = 0;
666 size_t cbInt = 0;
667 rc = rtAcpiTblAmlDecodeIntegerWorker(pThis, &u64, cbPkg, &cbInt, pErrInfo);
668 if (RT_FAILURE(rc))
669 return rc;
670
671 cbPkg -= cbInt;
672
673 rc = rtAcpiTblAmlDecodeFormat(pThis, hVfsIosOut, "Buffer (%RU64) {", u64);
674 if (RT_FAILURE(rc))
675 return rc;
676
677 /* Decode remaining bytes. */
678 while (cbPkg--)
679 {
680 uint8_t bTmp = 0;
681 rc = rtAcpiTblAmlDecodeReadU8(pThis, &bTmp, pErrInfo);
682 if (RT_FAILURE(rc))
683 return rc;
684
685 rc = rtAcpiTblAmlDecodeFormat(pThis, hVfsIosOut, "%#02RX8%s", bTmp, cbPkg ? "," : "");
686 if (RT_FAILURE(rc))
687 return rc;
688 }
689
690 return rtAcpiTblAmlDecodeFormat(pThis, hVfsIosOut, "}");
691}
692
693
694static DECLCALLBACK(int) rtAcpiTblAmlDecodeInteger(PRTACPITBLAMLDECODE pThis, RTVFSIOSTREAM hVfsIosOut, uint8_t bOp, PRTERRINFO pErrInfo)
695{
696 uint64_t u64 = 0;
697 size_t cbDecoded = 0;
698 int rc = rtAcpiTblAmlDecodeIntegerFromPrefix(pThis, bOp, &u64, sizeof(uint64_t), &cbDecoded, pErrInfo);
699 if (RT_FAILURE(rc))
700 return rc;
701
702 return rtAcpiTblAmlDecodeFormat(pThis, hVfsIosOut, "%#RX64", u64);
703}
704
705
706/**
707 * AML Opcode -> ASL decoder array.
708 */
709static const RTACPIAMLOPC g_aAmlOpcodeDecode[] =
710{
711#define RTACPI_AML_OPC_INVALID \
712 { NULL, 0, { kAcpiAmlOpcType_Invalid, kAcpiAmlOpcType_Invalid, kAcpiAmlOpcType_Invalid, kAcpiAmlOpcType_Invalid, kAcpiAmlOpcType_Invalid }, NULL }
713#define RTACPI_AML_OPC_SIMPLE_0(a_pszOpc, a_fFlags) \
714 { a_pszOpc, a_fFlags, { kAcpiAmlOpcType_Invalid, kAcpiAmlOpcType_Invalid, kAcpiAmlOpcType_Invalid, kAcpiAmlOpcType_Invalid, kAcpiAmlOpcType_Invalid }, NULL }
715#define RTACPI_AML_OPC_SIMPLE_1(a_pszOpc, a_fFlags, a_enmType0) \
716 { a_pszOpc, a_fFlags, { a_enmType0, kAcpiAmlOpcType_Invalid, kAcpiAmlOpcType_Invalid, kAcpiAmlOpcType_Invalid, kAcpiAmlOpcType_Invalid }, NULL }
717#define RTACPI_AML_OPC_SIMPLE_2(a_pszOpc, a_fFlags, a_enmType0, a_enmType1) \
718 { a_pszOpc, a_fFlags, { a_enmType0, a_enmType1, kAcpiAmlOpcType_Invalid, kAcpiAmlOpcType_Invalid, kAcpiAmlOpcType_Invalid }, NULL }
719#define RTACPI_AML_OPC_SIMPLE_3(a_pszOpc, a_fFlags, a_enmType0, a_enmType1, a_enmType2) \
720 { a_pszOpc, a_fFlags, { a_enmType0, a_enmType1, a_enmType2, kAcpiAmlOpcType_Invalid, kAcpiAmlOpcType_Invalid }, NULL }
721#define RTACPI_AML_OPC_SIMPLE_4(a_pszOpc, a_fFlags, a_enmType0, a_enmType1, a_enmType2, a_enmType3) \
722 { a_pszOpc, a_fFlags, { a_enmType0, a_enmType1, a_enmType2, a_enmType3, kAcpiAmlOpcType_Invalid }, NULL }
723#define RTACPI_AML_OPC_SIMPLE_5(a_pszOpc, a_fFlags, a_enmType0, a_enmType1, a_enmType2, a_enmType3, a_enmType4) \
724 { a_pszOpc, a_fFlags, { a_enmType0, a_enmType1, a_enmType2, a_enmType3, a_enmType4 }, NULL }
725#define RTACPI_AML_OPC_HANDLER(a_pszOpc, a_pfnHandler) \
726 { a_pszOpc, 0, { kAcpiAmlOpcType_Invalid, kAcpiAmlOpcType_Invalid, kAcpiAmlOpcType_Invalid, kAcpiAmlOpcType_Invalid, kAcpiAmlOpcType_Invalid }, a_pfnHandler }
727
728 /* 0x00 */ RTACPI_AML_OPC_SIMPLE_0("Zero", RTACPI_AML_OPC_F_NONE),
729 /* 0x01 */ RTACPI_AML_OPC_SIMPLE_0("One", RTACPI_AML_OPC_F_NONE),
730 /* 0x02 */ RTACPI_AML_OPC_INVALID,
731 /* 0x03 */ RTACPI_AML_OPC_INVALID,
732 /* 0x04 */ RTACPI_AML_OPC_INVALID,
733 /* 0x05 */ RTACPI_AML_OPC_INVALID,
734 /* 0x06 */ RTACPI_AML_OPC_INVALID,
735 /* 0x07 */ RTACPI_AML_OPC_INVALID,
736 /* 0x08 */ RTACPI_AML_OPC_SIMPLE_2("Name", 0, kAcpiAmlOpcType_NameString, kAcpiAmlOpcType_TermArg),
737 /* 0x09 */ RTACPI_AML_OPC_INVALID,
738 /* 0x0a */ RTACPI_AML_OPC_HANDLER( "ByteInteger", rtAcpiTblAmlDecodeInteger),
739 /* 0x0b */ RTACPI_AML_OPC_HANDLER( "WordInteger", rtAcpiTblAmlDecodeInteger),
740 /* 0x0c */ RTACPI_AML_OPC_HANDLER( "DWordInteger", rtAcpiTblAmlDecodeInteger),
741 /* 0x0d */ RTACPI_AML_OPC_HANDLER( "StringPrefix", rtAcpiTblAmlDecodeString),
742 /* 0x0e */ RTACPI_AML_OPC_HANDLER( "QWordInteger", rtAcpiTblAmlDecodeInteger),
743 /* 0x0f */ RTACPI_AML_OPC_INVALID,
744
745 /* 0x10 */ RTACPI_AML_OPC_SIMPLE_1("Scope", RTACPI_AML_OPC_F_HAS_PKG_LENGTH, kAcpiAmlOpcType_NameString),
746 /* 0x11 */ RTACPI_AML_OPC_HANDLER( "Buffer", rtAcpiTblAmlDecodeBuffer),
747 /* 0x12 */ RTACPI_AML_OPC_INVALID,
748 /* 0x13 */ RTACPI_AML_OPC_INVALID,
749 /* 0x14 */ RTACPI_AML_OPC_SIMPLE_2("Method", RTACPI_AML_OPC_F_HAS_PKG_LENGTH, kAcpiAmlOpcType_NameString, kAcpiAmlOpcType_Byte),
750 /* 0x15 */ RTACPI_AML_OPC_SIMPLE_3("External", RTACPI_AML_OPC_F_NONE, kAcpiAmlOpcType_NameString, kAcpiAmlOpcType_Byte, kAcpiAmlOpcType_Byte),
751 /* 0x16 */ RTACPI_AML_OPC_INVALID,
752 /* 0x17 */ RTACPI_AML_OPC_INVALID,
753 /* 0x18 */ RTACPI_AML_OPC_INVALID,
754 /* 0x19 */ RTACPI_AML_OPC_INVALID,
755 /* 0x1a */ RTACPI_AML_OPC_INVALID,
756 /* 0x1b */ RTACPI_AML_OPC_INVALID,
757 /* 0x1c */ RTACPI_AML_OPC_INVALID,
758 /* 0x1d */ RTACPI_AML_OPC_INVALID,
759 /* 0x1e */ RTACPI_AML_OPC_INVALID,
760 /* 0x1f */ RTACPI_AML_OPC_INVALID,
761
762 /* 0x20 */ RTACPI_AML_OPC_INVALID,
763 /* 0x21 */ RTACPI_AML_OPC_INVALID,
764 /* 0x22 */ RTACPI_AML_OPC_INVALID,
765 /* 0x23 */ RTACPI_AML_OPC_INVALID,
766 /* 0x24 */ RTACPI_AML_OPC_INVALID,
767 /* 0x25 */ RTACPI_AML_OPC_INVALID,
768 /* 0x26 */ RTACPI_AML_OPC_INVALID,
769 /* 0x27 */ RTACPI_AML_OPC_INVALID,
770 /* 0x28 */ RTACPI_AML_OPC_INVALID,
771 /* 0x29 */ RTACPI_AML_OPC_INVALID,
772 /* 0x2a */ RTACPI_AML_OPC_INVALID,
773 /* 0x2b */ RTACPI_AML_OPC_INVALID,
774 /* 0x2c */ RTACPI_AML_OPC_INVALID,
775 /* 0x2d */ RTACPI_AML_OPC_INVALID,
776 /* 0x2e */ RTACPI_AML_OPC_INVALID,
777 /* 0x2f */ RTACPI_AML_OPC_INVALID,
778
779 /* 0x30 */ RTACPI_AML_OPC_INVALID,
780 /* 0x31 */ RTACPI_AML_OPC_INVALID,
781 /* 0x32 */ RTACPI_AML_OPC_INVALID,
782 /* 0x33 */ RTACPI_AML_OPC_INVALID,
783 /* 0x34 */ RTACPI_AML_OPC_INVALID,
784 /* 0x35 */ RTACPI_AML_OPC_INVALID,
785 /* 0x36 */ RTACPI_AML_OPC_INVALID,
786 /* 0x37 */ RTACPI_AML_OPC_INVALID,
787 /* 0x38 */ RTACPI_AML_OPC_INVALID,
788 /* 0x39 */ RTACPI_AML_OPC_INVALID,
789 /* 0x3a */ RTACPI_AML_OPC_INVALID,
790 /* 0x3b */ RTACPI_AML_OPC_INVALID,
791 /* 0x3c */ RTACPI_AML_OPC_INVALID,
792 /* 0x3d */ RTACPI_AML_OPC_INVALID,
793 /* 0x3e */ RTACPI_AML_OPC_INVALID,
794 /* 0x3f */ RTACPI_AML_OPC_INVALID,
795
796 /* 0x40 */ RTACPI_AML_OPC_INVALID,
797 /* 0x41 */ RTACPI_AML_OPC_HANDLER("NameChar", rtAcpiTblAmlDecodeNameObject),
798 /* 0x42 */ RTACPI_AML_OPC_HANDLER("NameChar", rtAcpiTblAmlDecodeNameObject),
799 /* 0x43 */ RTACPI_AML_OPC_HANDLER("NameChar", rtAcpiTblAmlDecodeNameObject),
800 /* 0x44 */ RTACPI_AML_OPC_HANDLER("NameChar", rtAcpiTblAmlDecodeNameObject),
801 /* 0x45 */ RTACPI_AML_OPC_HANDLER("NameChar", rtAcpiTblAmlDecodeNameObject),
802 /* 0x46 */ RTACPI_AML_OPC_HANDLER("NameChar", rtAcpiTblAmlDecodeNameObject),
803 /* 0x47 */ RTACPI_AML_OPC_HANDLER("NameChar", rtAcpiTblAmlDecodeNameObject),
804 /* 0x48 */ RTACPI_AML_OPC_HANDLER("NameChar", rtAcpiTblAmlDecodeNameObject),
805 /* 0x49 */ RTACPI_AML_OPC_HANDLER("NameChar", rtAcpiTblAmlDecodeNameObject),
806 /* 0x4a */ RTACPI_AML_OPC_HANDLER("NameChar", rtAcpiTblAmlDecodeNameObject),
807 /* 0x4b */ RTACPI_AML_OPC_HANDLER("NameChar", rtAcpiTblAmlDecodeNameObject),
808 /* 0x4c */ RTACPI_AML_OPC_HANDLER("NameChar", rtAcpiTblAmlDecodeNameObject),
809 /* 0x4d */ RTACPI_AML_OPC_HANDLER("NameChar", rtAcpiTblAmlDecodeNameObject),
810 /* 0x4e */ RTACPI_AML_OPC_HANDLER("NameChar", rtAcpiTblAmlDecodeNameObject),
811 /* 0x4f */ RTACPI_AML_OPC_HANDLER("NameChar", rtAcpiTblAmlDecodeNameObject),
812
813 /* 0x50 */ RTACPI_AML_OPC_HANDLER("NameChar", rtAcpiTblAmlDecodeNameObject),
814 /* 0x51 */ RTACPI_AML_OPC_HANDLER("NameChar", rtAcpiTblAmlDecodeNameObject),
815 /* 0x52 */ RTACPI_AML_OPC_HANDLER("NameChar", rtAcpiTblAmlDecodeNameObject),
816 /* 0x53 */ RTACPI_AML_OPC_HANDLER("NameChar", rtAcpiTblAmlDecodeNameObject),
817 /* 0x54 */ RTACPI_AML_OPC_HANDLER("NameChar", rtAcpiTblAmlDecodeNameObject),
818 /* 0x55 */ RTACPI_AML_OPC_HANDLER("NameChar", rtAcpiTblAmlDecodeNameObject),
819 /* 0x56 */ RTACPI_AML_OPC_HANDLER("NameChar", rtAcpiTblAmlDecodeNameObject),
820 /* 0x57 */ RTACPI_AML_OPC_HANDLER("NameChar", rtAcpiTblAmlDecodeNameObject),
821 /* 0x58 */ RTACPI_AML_OPC_HANDLER("NameChar", rtAcpiTblAmlDecodeNameObject),
822 /* 0x59 */ RTACPI_AML_OPC_HANDLER("NameChar", rtAcpiTblAmlDecodeNameObject),
823 /* 0x5a */ RTACPI_AML_OPC_HANDLER("NameChar", rtAcpiTblAmlDecodeNameObject),
824 /* 0x5b */ RTACPI_AML_OPC_INVALID,
825 /* 0x5c */ RTACPI_AML_OPC_HANDLER("RootChar", rtAcpiTblAmlDecodeNameObject),
826 /* 0x5d */ RTACPI_AML_OPC_INVALID,
827 /* 0x5e */ RTACPI_AML_OPC_HANDLER("ParentPrefixChar", rtAcpiTblAmlDecodeNameObject),
828 /* 0x5f */ RTACPI_AML_OPC_HANDLER("NameChar", rtAcpiTblAmlDecodeNameObject),
829
830 /* 0x60 */ RTACPI_AML_OPC_SIMPLE_0("Local0", RTACPI_AML_OPC_F_NONE),
831 /* 0x61 */ RTACPI_AML_OPC_SIMPLE_0("Local1", RTACPI_AML_OPC_F_NONE),
832 /* 0x62 */ RTACPI_AML_OPC_SIMPLE_0("Local2", RTACPI_AML_OPC_F_NONE),
833 /* 0x63 */ RTACPI_AML_OPC_SIMPLE_0("Local3", RTACPI_AML_OPC_F_NONE),
834 /* 0x64 */ RTACPI_AML_OPC_SIMPLE_0("Local4", RTACPI_AML_OPC_F_NONE),
835 /* 0x65 */ RTACPI_AML_OPC_SIMPLE_0("Local5", RTACPI_AML_OPC_F_NONE),
836 /* 0x66 */ RTACPI_AML_OPC_SIMPLE_0("Local6", RTACPI_AML_OPC_F_NONE),
837 /* 0x67 */ RTACPI_AML_OPC_SIMPLE_0("Local7", RTACPI_AML_OPC_F_NONE),
838 /* 0x68 */ RTACPI_AML_OPC_SIMPLE_0("Arg0", RTACPI_AML_OPC_F_NONE),
839 /* 0x69 */ RTACPI_AML_OPC_SIMPLE_0("Arg1", RTACPI_AML_OPC_F_NONE),
840 /* 0x6a */ RTACPI_AML_OPC_SIMPLE_0("Arg2", RTACPI_AML_OPC_F_NONE),
841 /* 0x6b */ RTACPI_AML_OPC_SIMPLE_0("Arg3", RTACPI_AML_OPC_F_NONE),
842 /* 0x6c */ RTACPI_AML_OPC_SIMPLE_0("Arg4", RTACPI_AML_OPC_F_NONE),
843 /* 0x6d */ RTACPI_AML_OPC_SIMPLE_0("Arg5", RTACPI_AML_OPC_F_NONE),
844 /* 0x6e */ RTACPI_AML_OPC_SIMPLE_0("Arg6", RTACPI_AML_OPC_F_NONE),
845 /* 0x6f */ RTACPI_AML_OPC_INVALID,
846
847 /* 0x70 */ RTACPI_AML_OPC_SIMPLE_2("Store", 0, kAcpiAmlOpcType_TermArg, kAcpiAmlOpcType_SuperName),
848 /* 0x71 */ RTACPI_AML_OPC_INVALID,
849 /* 0x72 */ RTACPI_AML_OPC_INVALID,
850 /* 0x73 */ RTACPI_AML_OPC_INVALID,
851 /* 0x74 */ RTACPI_AML_OPC_INVALID,
852 /* 0x75 */ RTACPI_AML_OPC_INVALID,
853 /* 0x76 */ RTACPI_AML_OPC_INVALID,
854 /* 0x77 */ RTACPI_AML_OPC_INVALID,
855 /* 0x78 */ RTACPI_AML_OPC_INVALID,
856 /* 0x79 */ RTACPI_AML_OPC_INVALID,
857 /* 0x7a */ RTACPI_AML_OPC_INVALID,
858 /* 0x7b */ RTACPI_AML_OPC_INVALID,
859 /* 0x7c */ RTACPI_AML_OPC_INVALID,
860 /* 0x7d */ RTACPI_AML_OPC_INVALID,
861 /* 0x7e */ RTACPI_AML_OPC_INVALID,
862 /* 0x7f */ RTACPI_AML_OPC_INVALID,
863
864 /* 0x80 */ RTACPI_AML_OPC_INVALID,
865 /* 0x81 */ RTACPI_AML_OPC_INVALID,
866 /* 0x82 */ RTACPI_AML_OPC_INVALID,
867 /* 0x83 */ RTACPI_AML_OPC_INVALID,
868 /* 0x84 */ RTACPI_AML_OPC_INVALID,
869 /* 0x85 */ RTACPI_AML_OPC_INVALID,
870 /* 0x86 */ RTACPI_AML_OPC_SIMPLE_2("Notify", 0, kAcpiAmlOpcType_SuperName, kAcpiAmlOpcType_TermArg),
871 /* 0x87 */ RTACPI_AML_OPC_INVALID,
872 /* 0x88 */ RTACPI_AML_OPC_SIMPLE_3("Index", 0, kAcpiAmlOpcType_TermArg, kAcpiAmlOpcType_TermArg, kAcpiAmlOpcType_SuperName),
873 /* 0x89 */ RTACPI_AML_OPC_INVALID,
874 /* 0x8a */ RTACPI_AML_OPC_INVALID,
875 /* 0x8b */ RTACPI_AML_OPC_INVALID,
876 /* 0x8c */ RTACPI_AML_OPC_INVALID,
877 /* 0x8d */ RTACPI_AML_OPC_INVALID,
878 /* 0x8e */ RTACPI_AML_OPC_INVALID,
879 /* 0x8f */ RTACPI_AML_OPC_INVALID,
880
881 /* 0x90 */ RTACPI_AML_OPC_INVALID,
882 /* 0x91 */ RTACPI_AML_OPC_INVALID,
883 /* 0x92 */ RTACPI_AML_OPC_INVALID,
884 /* 0x93 */ RTACPI_AML_OPC_SIMPLE_2("LEqual", 0, kAcpiAmlOpcType_TermArg, kAcpiAmlOpcType_TermArg),
885 /* 0x94 */ RTACPI_AML_OPC_INVALID,
886 /* 0x95 */ RTACPI_AML_OPC_INVALID,
887 /* 0x96 */ RTACPI_AML_OPC_INVALID,
888 /* 0x97 */ RTACPI_AML_OPC_INVALID,
889 /* 0x98 */ RTACPI_AML_OPC_INVALID,
890 /* 0x99 */ RTACPI_AML_OPC_INVALID,
891 /* 0x9a */ RTACPI_AML_OPC_INVALID,
892 /* 0x9b */ RTACPI_AML_OPC_INVALID,
893 /* 0x9c */ RTACPI_AML_OPC_INVALID,
894 /* 0x9d */ RTACPI_AML_OPC_INVALID,
895 /* 0x9e */ RTACPI_AML_OPC_INVALID,
896 /* 0x9f */ RTACPI_AML_OPC_INVALID,
897
898 /* 0xa0 */ RTACPI_AML_OPC_SIMPLE_1("If", RTACPI_AML_OPC_F_HAS_PKG_LENGTH, kAcpiAmlOpcType_TermArg),
899 /* 0xa1 */ RTACPI_AML_OPC_SIMPLE_0("Else", RTACPI_AML_OPC_F_HAS_PKG_LENGTH),
900 /* 0xa2 */ RTACPI_AML_OPC_INVALID,
901 /* 0xa3 */ RTACPI_AML_OPC_INVALID,
902 /* 0xa4 */ RTACPI_AML_OPC_SIMPLE_1("Return", 0, kAcpiAmlOpcType_TermArg),
903 /* 0xa5 */ RTACPI_AML_OPC_INVALID,
904 /* 0xa6 */ RTACPI_AML_OPC_INVALID,
905 /* 0xa7 */ RTACPI_AML_OPC_INVALID,
906 /* 0xa8 */ RTACPI_AML_OPC_INVALID,
907 /* 0xa9 */ RTACPI_AML_OPC_INVALID,
908 /* 0xaa */ RTACPI_AML_OPC_INVALID,
909 /* 0xab */ RTACPI_AML_OPC_INVALID,
910 /* 0xac */ RTACPI_AML_OPC_INVALID,
911 /* 0xad */ RTACPI_AML_OPC_INVALID,
912 /* 0xae */ RTACPI_AML_OPC_INVALID,
913 /* 0xaf */ RTACPI_AML_OPC_INVALID,
914
915 /* 0xb0 */ RTACPI_AML_OPC_INVALID,
916 /* 0xb1 */ RTACPI_AML_OPC_INVALID,
917 /* 0xb2 */ RTACPI_AML_OPC_INVALID,
918 /* 0xb3 */ RTACPI_AML_OPC_INVALID,
919 /* 0xb4 */ RTACPI_AML_OPC_INVALID,
920 /* 0xb5 */ RTACPI_AML_OPC_INVALID,
921 /* 0xb6 */ RTACPI_AML_OPC_INVALID,
922 /* 0xb7 */ RTACPI_AML_OPC_INVALID,
923 /* 0xb8 */ RTACPI_AML_OPC_INVALID,
924 /* 0xb9 */ RTACPI_AML_OPC_INVALID,
925 /* 0xba */ RTACPI_AML_OPC_INVALID,
926 /* 0xbb */ RTACPI_AML_OPC_INVALID,
927 /* 0xbc */ RTACPI_AML_OPC_INVALID,
928 /* 0xbd */ RTACPI_AML_OPC_INVALID,
929 /* 0xbe */ RTACPI_AML_OPC_INVALID,
930 /* 0xbf */ RTACPI_AML_OPC_INVALID,
931
932 /* 0xc0 */ RTACPI_AML_OPC_INVALID,
933 /* 0xc1 */ RTACPI_AML_OPC_INVALID,
934 /* 0xc2 */ RTACPI_AML_OPC_INVALID,
935 /* 0xc3 */ RTACPI_AML_OPC_INVALID,
936 /* 0xc4 */ RTACPI_AML_OPC_INVALID,
937 /* 0xc5 */ RTACPI_AML_OPC_INVALID,
938 /* 0xc6 */ RTACPI_AML_OPC_INVALID,
939 /* 0xc7 */ RTACPI_AML_OPC_INVALID,
940 /* 0xc8 */ RTACPI_AML_OPC_INVALID,
941 /* 0xc9 */ RTACPI_AML_OPC_INVALID,
942 /* 0xca */ RTACPI_AML_OPC_INVALID,
943 /* 0xcb */ RTACPI_AML_OPC_INVALID,
944 /* 0xcc */ RTACPI_AML_OPC_INVALID,
945 /* 0xcd */ RTACPI_AML_OPC_INVALID,
946 /* 0xce */ RTACPI_AML_OPC_INVALID,
947 /* 0xcf */ RTACPI_AML_OPC_INVALID,
948
949 /* 0xd0 */ RTACPI_AML_OPC_INVALID,
950 /* 0xd1 */ RTACPI_AML_OPC_INVALID,
951 /* 0xd2 */ RTACPI_AML_OPC_INVALID,
952 /* 0xd3 */ RTACPI_AML_OPC_INVALID,
953 /* 0xd4 */ RTACPI_AML_OPC_INVALID,
954 /* 0xd5 */ RTACPI_AML_OPC_INVALID,
955 /* 0xd6 */ RTACPI_AML_OPC_INVALID,
956 /* 0xd7 */ RTACPI_AML_OPC_INVALID,
957 /* 0xd8 */ RTACPI_AML_OPC_INVALID,
958 /* 0xd9 */ RTACPI_AML_OPC_INVALID,
959 /* 0xda */ RTACPI_AML_OPC_INVALID,
960 /* 0xdb */ RTACPI_AML_OPC_INVALID,
961 /* 0xdc */ RTACPI_AML_OPC_INVALID,
962 /* 0xdd */ RTACPI_AML_OPC_INVALID,
963 /* 0xde */ RTACPI_AML_OPC_INVALID,
964 /* 0xdf */ RTACPI_AML_OPC_INVALID,
965
966 /* 0xe0 */ RTACPI_AML_OPC_INVALID,
967 /* 0xe1 */ RTACPI_AML_OPC_INVALID,
968 /* 0xe2 */ RTACPI_AML_OPC_INVALID,
969 /* 0xe3 */ RTACPI_AML_OPC_INVALID,
970 /* 0xe4 */ RTACPI_AML_OPC_INVALID,
971 /* 0xe5 */ RTACPI_AML_OPC_INVALID,
972 /* 0xe6 */ RTACPI_AML_OPC_INVALID,
973 /* 0xe7 */ RTACPI_AML_OPC_INVALID,
974 /* 0xe8 */ RTACPI_AML_OPC_INVALID,
975 /* 0xe9 */ RTACPI_AML_OPC_INVALID,
976 /* 0xea */ RTACPI_AML_OPC_INVALID,
977 /* 0xeb */ RTACPI_AML_OPC_INVALID,
978 /* 0xec */ RTACPI_AML_OPC_INVALID,
979 /* 0xed */ RTACPI_AML_OPC_INVALID,
980 /* 0xee */ RTACPI_AML_OPC_INVALID,
981 /* 0xef */ RTACPI_AML_OPC_INVALID,
982
983 /* 0xf0 */ RTACPI_AML_OPC_INVALID,
984 /* 0xf1 */ RTACPI_AML_OPC_INVALID,
985 /* 0xf2 */ RTACPI_AML_OPC_INVALID,
986 /* 0xf3 */ RTACPI_AML_OPC_INVALID,
987 /* 0xf4 */ RTACPI_AML_OPC_INVALID,
988 /* 0xf5 */ RTACPI_AML_OPC_INVALID,
989 /* 0xf6 */ RTACPI_AML_OPC_INVALID,
990 /* 0xf7 */ RTACPI_AML_OPC_INVALID,
991 /* 0xf8 */ RTACPI_AML_OPC_INVALID,
992 /* 0xf9 */ RTACPI_AML_OPC_INVALID,
993 /* 0xfa */ RTACPI_AML_OPC_INVALID,
994 /* 0xfb */ RTACPI_AML_OPC_INVALID,
995 /* 0xfc */ RTACPI_AML_OPC_INVALID,
996 /* 0xfd */ RTACPI_AML_OPC_INVALID,
997 /* 0xfe */ RTACPI_AML_OPC_INVALID,
998 /* 0xff */ RTACPI_AML_OPC_INVALID
999};
1000
1001
1002/**
1003 * AML extended opcode -> ASL decoder array.
1004 */
1005static const RTACPIAMLOPC g_aAmlExtOpcodeDecode[] =
1006{
1007 /* 0x00 */ RTACPI_AML_OPC_INVALID,
1008 /* 0x01 */ RTACPI_AML_OPC_INVALID,
1009 /* 0x02 */ RTACPI_AML_OPC_INVALID,
1010 /* 0x03 */ RTACPI_AML_OPC_INVALID,
1011 /* 0x04 */ RTACPI_AML_OPC_INVALID,
1012 /* 0x05 */ RTACPI_AML_OPC_INVALID,
1013 /* 0x06 */ RTACPI_AML_OPC_INVALID,
1014 /* 0x07 */ RTACPI_AML_OPC_INVALID,
1015 /* 0x08 */ RTACPI_AML_OPC_INVALID,
1016 /* 0x09 */ RTACPI_AML_OPC_INVALID,
1017 /* 0x0a */ RTACPI_AML_OPC_INVALID,
1018 /* 0x0b */ RTACPI_AML_OPC_INVALID,
1019 /* 0x0c */ RTACPI_AML_OPC_INVALID,
1020 /* 0x0d */ RTACPI_AML_OPC_INVALID,
1021 /* 0x0e */ RTACPI_AML_OPC_INVALID,
1022 /* 0x0f */ RTACPI_AML_OPC_INVALID,
1023
1024 /* 0x10 */ RTACPI_AML_OPC_INVALID,
1025 /* 0x11 */ RTACPI_AML_OPC_INVALID,
1026 /* 0x12 */ RTACPI_AML_OPC_INVALID,
1027 /* 0x13 */ RTACPI_AML_OPC_INVALID,
1028 /* 0x14 */ RTACPI_AML_OPC_INVALID,
1029 /* 0x15 */ RTACPI_AML_OPC_INVALID,
1030 /* 0x16 */ RTACPI_AML_OPC_INVALID,
1031 /* 0x17 */ RTACPI_AML_OPC_INVALID,
1032 /* 0x18 */ RTACPI_AML_OPC_INVALID,
1033 /* 0x19 */ RTACPI_AML_OPC_INVALID,
1034 /* 0x1a */ RTACPI_AML_OPC_INVALID,
1035 /* 0x1b */ RTACPI_AML_OPC_INVALID,
1036 /* 0x1c */ RTACPI_AML_OPC_INVALID,
1037 /* 0x1d */ RTACPI_AML_OPC_INVALID,
1038 /* 0x1e */ RTACPI_AML_OPC_INVALID,
1039 /* 0x1f */ RTACPI_AML_OPC_INVALID,
1040
1041 /* 0x20 */ RTACPI_AML_OPC_INVALID,
1042 /* 0x21 */ RTACPI_AML_OPC_INVALID,
1043 /* 0x22 */ RTACPI_AML_OPC_INVALID,
1044 /* 0x23 */ RTACPI_AML_OPC_INVALID,
1045 /* 0x24 */ RTACPI_AML_OPC_INVALID,
1046 /* 0x25 */ RTACPI_AML_OPC_INVALID,
1047 /* 0x26 */ RTACPI_AML_OPC_INVALID,
1048 /* 0x27 */ RTACPI_AML_OPC_INVALID,
1049 /* 0x28 */ RTACPI_AML_OPC_INVALID,
1050 /* 0x29 */ RTACPI_AML_OPC_INVALID,
1051 /* 0x2a */ RTACPI_AML_OPC_INVALID,
1052 /* 0x2b */ RTACPI_AML_OPC_INVALID,
1053 /* 0x2c */ RTACPI_AML_OPC_INVALID,
1054 /* 0x2d */ RTACPI_AML_OPC_INVALID,
1055 /* 0x2e */ RTACPI_AML_OPC_INVALID,
1056 /* 0x2f */ RTACPI_AML_OPC_INVALID,
1057
1058 /* 0x30 */ RTACPI_AML_OPC_INVALID,
1059 /* 0x31 */ RTACPI_AML_OPC_SIMPLE_0("Debug", RTACPI_AML_OPC_F_NONE),
1060 /* 0x32 */ RTACPI_AML_OPC_INVALID,
1061 /* 0x33 */ RTACPI_AML_OPC_INVALID,
1062 /* 0x34 */ RTACPI_AML_OPC_INVALID,
1063 /* 0x35 */ RTACPI_AML_OPC_INVALID,
1064 /* 0x36 */ RTACPI_AML_OPC_INVALID,
1065 /* 0x37 */ RTACPI_AML_OPC_INVALID,
1066 /* 0x38 */ RTACPI_AML_OPC_INVALID,
1067 /* 0x39 */ RTACPI_AML_OPC_INVALID,
1068 /* 0x3a */ RTACPI_AML_OPC_INVALID,
1069 /* 0x3b */ RTACPI_AML_OPC_INVALID,
1070 /* 0x3c */ RTACPI_AML_OPC_INVALID,
1071 /* 0x3d */ RTACPI_AML_OPC_INVALID,
1072 /* 0x3e */ RTACPI_AML_OPC_INVALID,
1073 /* 0x3f */ RTACPI_AML_OPC_INVALID,
1074
1075 /* 0x40 */ RTACPI_AML_OPC_INVALID,
1076 /* 0x41 */ RTACPI_AML_OPC_INVALID,
1077 /* 0x42 */ RTACPI_AML_OPC_INVALID,
1078 /* 0x43 */ RTACPI_AML_OPC_INVALID,
1079 /* 0x44 */ RTACPI_AML_OPC_INVALID,
1080 /* 0x45 */ RTACPI_AML_OPC_INVALID,
1081 /* 0x46 */ RTACPI_AML_OPC_INVALID,
1082 /* 0x47 */ RTACPI_AML_OPC_INVALID,
1083 /* 0x48 */ RTACPI_AML_OPC_INVALID,
1084 /* 0x49 */ RTACPI_AML_OPC_INVALID,
1085 /* 0x4a */ RTACPI_AML_OPC_INVALID,
1086 /* 0x4b */ RTACPI_AML_OPC_INVALID,
1087 /* 0x4c */ RTACPI_AML_OPC_INVALID,
1088 /* 0x4d */ RTACPI_AML_OPC_INVALID,
1089 /* 0x4e */ RTACPI_AML_OPC_INVALID,
1090 /* 0x4f */ RTACPI_AML_OPC_INVALID,
1091
1092 /* 0x50 */ RTACPI_AML_OPC_INVALID,
1093 /* 0x51 */ RTACPI_AML_OPC_INVALID,
1094 /* 0x52 */ RTACPI_AML_OPC_INVALID,
1095 /* 0x53 */ RTACPI_AML_OPC_INVALID,
1096 /* 0x54 */ RTACPI_AML_OPC_INVALID,
1097 /* 0x55 */ RTACPI_AML_OPC_INVALID,
1098 /* 0x56 */ RTACPI_AML_OPC_INVALID,
1099 /* 0x57 */ RTACPI_AML_OPC_INVALID,
1100 /* 0x58 */ RTACPI_AML_OPC_INVALID,
1101 /* 0x59 */ RTACPI_AML_OPC_INVALID,
1102 /* 0x5a */ RTACPI_AML_OPC_INVALID,
1103 /* 0x5b */ RTACPI_AML_OPC_INVALID,
1104 /* 0x5c */ RTACPI_AML_OPC_INVALID,
1105 /* 0x5d */ RTACPI_AML_OPC_INVALID,
1106 /* 0x5e */ RTACPI_AML_OPC_INVALID,
1107 /* 0x5f */ RTACPI_AML_OPC_INVALID,
1108
1109 /* 0x60 */ RTACPI_AML_OPC_INVALID,
1110 /* 0x61 */ RTACPI_AML_OPC_INVALID,
1111 /* 0x62 */ RTACPI_AML_OPC_INVALID,
1112 /* 0x63 */ RTACPI_AML_OPC_INVALID,
1113 /* 0x64 */ RTACPI_AML_OPC_INVALID,
1114 /* 0x65 */ RTACPI_AML_OPC_INVALID,
1115 /* 0x66 */ RTACPI_AML_OPC_INVALID,
1116 /* 0x67 */ RTACPI_AML_OPC_INVALID,
1117 /* 0x68 */ RTACPI_AML_OPC_INVALID,
1118 /* 0x69 */ RTACPI_AML_OPC_INVALID,
1119 /* 0x6a */ RTACPI_AML_OPC_INVALID,
1120 /* 0x6b */ RTACPI_AML_OPC_INVALID,
1121 /* 0x6c */ RTACPI_AML_OPC_INVALID,
1122 /* 0x6d */ RTACPI_AML_OPC_INVALID,
1123 /* 0x6e */ RTACPI_AML_OPC_INVALID,
1124 /* 0x6f */ RTACPI_AML_OPC_INVALID,
1125
1126 /* 0x70 */ RTACPI_AML_OPC_INVALID,
1127 /* 0x71 */ RTACPI_AML_OPC_INVALID,
1128 /* 0x72 */ RTACPI_AML_OPC_INVALID,
1129 /* 0x73 */ RTACPI_AML_OPC_INVALID,
1130 /* 0x74 */ RTACPI_AML_OPC_INVALID,
1131 /* 0x75 */ RTACPI_AML_OPC_INVALID,
1132 /* 0x76 */ RTACPI_AML_OPC_INVALID,
1133 /* 0x77 */ RTACPI_AML_OPC_INVALID,
1134 /* 0x78 */ RTACPI_AML_OPC_INVALID,
1135 /* 0x79 */ RTACPI_AML_OPC_INVALID,
1136 /* 0x7a */ RTACPI_AML_OPC_INVALID,
1137 /* 0x7b */ RTACPI_AML_OPC_INVALID,
1138 /* 0x7c */ RTACPI_AML_OPC_INVALID,
1139 /* 0x7d */ RTACPI_AML_OPC_INVALID,
1140 /* 0x7e */ RTACPI_AML_OPC_INVALID,
1141 /* 0x7f */ RTACPI_AML_OPC_INVALID,
1142
1143 /* 0x80 */ RTACPI_AML_OPC_SIMPLE_4("OpRegion", 0, kAcpiAmlOpcType_NameString, kAcpiAmlOpcType_Byte, kAcpiAmlOpcType_TermArg, kAcpiAmlOpcType_TermArg),
1144 /* 0x81 */ RTACPI_AML_OPC_INVALID,
1145 /* 0x82 */ RTACPI_AML_OPC_SIMPLE_1("Device", RTACPI_AML_OPC_F_HAS_PKG_LENGTH, kAcpiAmlOpcType_NameString),
1146 /* 0x83 */ RTACPI_AML_OPC_SIMPLE_4("Processor", RTACPI_AML_OPC_F_HAS_PKG_LENGTH, kAcpiAmlOpcType_NameString, kAcpiAmlOpcType_Byte, kAcpiAmlOpcType_DWord, kAcpiAmlOpcType_Byte),
1147 /* 0x84 */ RTACPI_AML_OPC_INVALID,
1148 /* 0x85 */ RTACPI_AML_OPC_INVALID,
1149 /* 0x86 */ RTACPI_AML_OPC_INVALID,
1150 /* 0x87 */ RTACPI_AML_OPC_INVALID,
1151 /* 0x88 */ RTACPI_AML_OPC_INVALID,
1152 /* 0x89 */ RTACPI_AML_OPC_INVALID,
1153 /* 0x8a */ RTACPI_AML_OPC_INVALID,
1154 /* 0x8b */ RTACPI_AML_OPC_INVALID,
1155 /* 0x8c */ RTACPI_AML_OPC_INVALID,
1156 /* 0x8d */ RTACPI_AML_OPC_INVALID,
1157 /* 0x8e */ RTACPI_AML_OPC_INVALID,
1158 /* 0x8f */ RTACPI_AML_OPC_INVALID,
1159
1160 /* 0x90 */ RTACPI_AML_OPC_INVALID,
1161 /* 0x91 */ RTACPI_AML_OPC_INVALID,
1162 /* 0x92 */ RTACPI_AML_OPC_INVALID,
1163 /* 0x93 */ RTACPI_AML_OPC_INVALID,
1164 /* 0x94 */ RTACPI_AML_OPC_INVALID,
1165 /* 0x95 */ RTACPI_AML_OPC_INVALID,
1166 /* 0x96 */ RTACPI_AML_OPC_INVALID,
1167 /* 0x97 */ RTACPI_AML_OPC_INVALID,
1168 /* 0x98 */ RTACPI_AML_OPC_INVALID,
1169 /* 0x99 */ RTACPI_AML_OPC_INVALID,
1170 /* 0x9a */ RTACPI_AML_OPC_INVALID,
1171 /* 0x9b */ RTACPI_AML_OPC_INVALID,
1172 /* 0x9c */ RTACPI_AML_OPC_INVALID,
1173 /* 0x9d */ RTACPI_AML_OPC_INVALID,
1174 /* 0x9e */ RTACPI_AML_OPC_INVALID,
1175 /* 0x9f */ RTACPI_AML_OPC_INVALID,
1176
1177 /* 0xa0 */ RTACPI_AML_OPC_INVALID,
1178 /* 0xa1 */ RTACPI_AML_OPC_INVALID,
1179 /* 0xa2 */ RTACPI_AML_OPC_INVALID,
1180 /* 0xa3 */ RTACPI_AML_OPC_INVALID,
1181 /* 0xa4 */ RTACPI_AML_OPC_INVALID,
1182 /* 0xa5 */ RTACPI_AML_OPC_INVALID,
1183 /* 0xa6 */ RTACPI_AML_OPC_INVALID,
1184 /* 0xa7 */ RTACPI_AML_OPC_INVALID,
1185 /* 0xa8 */ RTACPI_AML_OPC_INVALID,
1186 /* 0xa9 */ RTACPI_AML_OPC_INVALID,
1187 /* 0xaa */ RTACPI_AML_OPC_INVALID,
1188 /* 0xab */ RTACPI_AML_OPC_INVALID,
1189 /* 0xac */ RTACPI_AML_OPC_INVALID,
1190 /* 0xad */ RTACPI_AML_OPC_INVALID,
1191 /* 0xae */ RTACPI_AML_OPC_INVALID,
1192 /* 0xaf */ RTACPI_AML_OPC_INVALID,
1193
1194 /* 0xb0 */ RTACPI_AML_OPC_INVALID,
1195 /* 0xb1 */ RTACPI_AML_OPC_INVALID,
1196 /* 0xb2 */ RTACPI_AML_OPC_INVALID,
1197 /* 0xb3 */ RTACPI_AML_OPC_INVALID,
1198 /* 0xb4 */ RTACPI_AML_OPC_INVALID,
1199 /* 0xb5 */ RTACPI_AML_OPC_INVALID,
1200 /* 0xb6 */ RTACPI_AML_OPC_INVALID,
1201 /* 0xb7 */ RTACPI_AML_OPC_INVALID,
1202 /* 0xb8 */ RTACPI_AML_OPC_INVALID,
1203 /* 0xb9 */ RTACPI_AML_OPC_INVALID,
1204 /* 0xba */ RTACPI_AML_OPC_INVALID,
1205 /* 0xbb */ RTACPI_AML_OPC_INVALID,
1206 /* 0xbc */ RTACPI_AML_OPC_INVALID,
1207 /* 0xbd */ RTACPI_AML_OPC_INVALID,
1208 /* 0xbe */ RTACPI_AML_OPC_INVALID,
1209 /* 0xbf */ RTACPI_AML_OPC_INVALID,
1210
1211 /* 0xc0 */ RTACPI_AML_OPC_INVALID,
1212 /* 0xc1 */ RTACPI_AML_OPC_INVALID,
1213 /* 0xc2 */ RTACPI_AML_OPC_INVALID,
1214 /* 0xc3 */ RTACPI_AML_OPC_INVALID,
1215 /* 0xc4 */ RTACPI_AML_OPC_INVALID,
1216 /* 0xc5 */ RTACPI_AML_OPC_INVALID,
1217 /* 0xc6 */ RTACPI_AML_OPC_INVALID,
1218 /* 0xc7 */ RTACPI_AML_OPC_INVALID,
1219 /* 0xc8 */ RTACPI_AML_OPC_INVALID,
1220 /* 0xc9 */ RTACPI_AML_OPC_INVALID,
1221 /* 0xca */ RTACPI_AML_OPC_INVALID,
1222 /* 0xcb */ RTACPI_AML_OPC_INVALID,
1223 /* 0xcc */ RTACPI_AML_OPC_INVALID,
1224 /* 0xcd */ RTACPI_AML_OPC_INVALID,
1225 /* 0xce */ RTACPI_AML_OPC_INVALID,
1226 /* 0xcf */ RTACPI_AML_OPC_INVALID,
1227
1228 /* 0xd0 */ RTACPI_AML_OPC_INVALID,
1229 /* 0xd1 */ RTACPI_AML_OPC_INVALID,
1230 /* 0xd2 */ RTACPI_AML_OPC_INVALID,
1231 /* 0xd3 */ RTACPI_AML_OPC_INVALID,
1232 /* 0xd4 */ RTACPI_AML_OPC_INVALID,
1233 /* 0xd5 */ RTACPI_AML_OPC_INVALID,
1234 /* 0xd6 */ RTACPI_AML_OPC_INVALID,
1235 /* 0xd7 */ RTACPI_AML_OPC_INVALID,
1236 /* 0xd8 */ RTACPI_AML_OPC_INVALID,
1237 /* 0xd9 */ RTACPI_AML_OPC_INVALID,
1238 /* 0xda */ RTACPI_AML_OPC_INVALID,
1239 /* 0xdb */ RTACPI_AML_OPC_INVALID,
1240 /* 0xdc */ RTACPI_AML_OPC_INVALID,
1241 /* 0xdd */ RTACPI_AML_OPC_INVALID,
1242 /* 0xde */ RTACPI_AML_OPC_INVALID,
1243 /* 0xdf */ RTACPI_AML_OPC_INVALID,
1244
1245 /* 0xe0 */ RTACPI_AML_OPC_INVALID,
1246 /* 0xe1 */ RTACPI_AML_OPC_INVALID,
1247 /* 0xe2 */ RTACPI_AML_OPC_INVALID,
1248 /* 0xe3 */ RTACPI_AML_OPC_INVALID,
1249 /* 0xe4 */ RTACPI_AML_OPC_INVALID,
1250 /* 0xe5 */ RTACPI_AML_OPC_INVALID,
1251 /* 0xe6 */ RTACPI_AML_OPC_INVALID,
1252 /* 0xe7 */ RTACPI_AML_OPC_INVALID,
1253 /* 0xe8 */ RTACPI_AML_OPC_INVALID,
1254 /* 0xe9 */ RTACPI_AML_OPC_INVALID,
1255 /* 0xea */ RTACPI_AML_OPC_INVALID,
1256 /* 0xeb */ RTACPI_AML_OPC_INVALID,
1257 /* 0xec */ RTACPI_AML_OPC_INVALID,
1258 /* 0xed */ RTACPI_AML_OPC_INVALID,
1259 /* 0xee */ RTACPI_AML_OPC_INVALID,
1260 /* 0xef */ RTACPI_AML_OPC_INVALID,
1261
1262 /* 0xf0 */ RTACPI_AML_OPC_INVALID,
1263 /* 0xf1 */ RTACPI_AML_OPC_INVALID,
1264 /* 0xf2 */ RTACPI_AML_OPC_INVALID,
1265 /* 0xf3 */ RTACPI_AML_OPC_INVALID,
1266 /* 0xf4 */ RTACPI_AML_OPC_INVALID,
1267 /* 0xf5 */ RTACPI_AML_OPC_INVALID,
1268 /* 0xf6 */ RTACPI_AML_OPC_INVALID,
1269 /* 0xf7 */ RTACPI_AML_OPC_INVALID,
1270 /* 0xf8 */ RTACPI_AML_OPC_INVALID,
1271 /* 0xf9 */ RTACPI_AML_OPC_INVALID,
1272 /* 0xfa */ RTACPI_AML_OPC_INVALID,
1273 /* 0xfb */ RTACPI_AML_OPC_INVALID,
1274 /* 0xfc */ RTACPI_AML_OPC_INVALID,
1275 /* 0xfd */ RTACPI_AML_OPC_INVALID,
1276 /* 0xfe */ RTACPI_AML_OPC_INVALID,
1277 /* 0xff */ RTACPI_AML_OPC_INVALID
1278};
1279
1280
1281static int rtAcpiTblAmlDecodeSimple(PRTACPITBLAMLDECODE pThis, PCRTACPIAMLOPC pAmlOpc, uint8_t bOpc, RTVFSIOSTREAM hVfsIosOut, PRTERRINFO pErrInfo)
1282{
1283 RT_NOREF(bOpc);
1284
1285 int rc;
1286
1287 /* Decode any package length field first. */
1288 size_t cbPkg = 0;
1289 size_t cbPkgLength = 0;
1290 size_t cbPkgConsumed = 0;
1291 if (pAmlOpc->fFlags & RTACPI_AML_OPC_F_HAS_PKG_LENGTH)
1292 {
1293 rc = rtAcpiTblAmlDecodePkgLength(pThis, &cbPkg, &cbPkgLength, pErrInfo);
1294 if (RT_FAILURE(rc)) return rc;
1295
1296 cbPkgConsumed += cbPkgLength;
1297 }
1298
1299 rc = rtAcpiTblAmlDecodeFormat(pThis, hVfsIosOut, "%s", pAmlOpc->pszOpc);
1300 if (RT_FAILURE(rc)) return rc;
1301
1302 /* Any arguments? */
1303 if (pAmlOpc->aenmTypes[0] != kAcpiAmlOpcType_Invalid)
1304 {
1305 pThis->fIndent = false;
1306
1307 rc = rtAcpiTblAmlDecodeFormat(pThis, hVfsIosOut, "(");
1308 if (RT_FAILURE(rc)) return rc;
1309
1310 for (uint32_t i = 0; i < RT_ELEMENTS(pAmlOpc->aenmTypes); i++)
1311 {
1312 if (pAmlOpc->aenmTypes[i] == kAcpiAmlOpcType_Invalid)
1313 break; /* End of arguments. */
1314
1315 if (i > 0)
1316 {
1317 rc = rtAcpiTblAmlDecodeFormat(pThis, hVfsIosOut, ", ");
1318 if (RT_FAILURE(rc)) return rc;
1319 }
1320
1321 switch (pAmlOpc->aenmTypes[i])
1322 {
1323 case kAcpiAmlOpcType_Byte:
1324 {
1325 uint8_t bVal = 0; /* shut up gcc */
1326 rc = rtAcpiTblAmlDecodeReadU8(pThis, &bVal, pErrInfo);
1327 if (RT_FAILURE(rc)) return rc;
1328
1329 rc = rtAcpiTblAmlDecodeFormat(pThis, hVfsIosOut, "%RU8", bVal);
1330 if (RT_FAILURE(rc)) return rc;
1331
1332 cbPkgConsumed++;
1333 break;
1334 }
1335 case kAcpiAmlOpcType_Word:
1336 {
1337 uint16_t u16Val = 0; /* shut up gcc */
1338 rc = rtAcpiTblAmlDecodeReadU16(pThis, &u16Val, pErrInfo);
1339 if (RT_FAILURE(rc)) return rc;
1340
1341 rc = rtAcpiTblAmlDecodeFormat(pThis, hVfsIosOut, "%RX16", u16Val);
1342 if (RT_FAILURE(rc)) return rc;
1343
1344 cbPkgConsumed += sizeof(uint16_t);
1345 break;
1346 }
1347 case kAcpiAmlOpcType_DWord:
1348 {
1349 uint32_t u32Val = 0; /* shut up gcc */
1350 rc = rtAcpiTblAmlDecodeReadU32(pThis, &u32Val, pErrInfo);
1351 if (RT_FAILURE(rc)) return rc;
1352
1353 rc = rtAcpiTblAmlDecodeFormat(pThis, hVfsIosOut, "%RX32", u32Val);
1354 if (RT_FAILURE(rc)) return rc;
1355
1356 cbPkgConsumed += sizeof(uint32_t);
1357 break;
1358 }
1359 case kAcpiAmlOpcType_NameString:
1360 {
1361 char szName[512];
1362 size_t cbName = 0;
1363 rc = rtAcpiTblAmlDecodeNameString(pThis, &szName[0], sizeof(szName), &cbName, pErrInfo);
1364 if (RT_FAILURE(rc)) return rc;
1365
1366 rc = rtAcpiTblAmlDecodeFormat(pThis, hVfsIosOut, "%s", szName);
1367 if (RT_FAILURE(rc)) return rc;
1368
1369 cbPkgConsumed += cbName;
1370 break;
1371 }
1372 case kAcpiAmlOpcType_SuperName:
1373 case kAcpiAmlOpcType_TermArg:
1374 {
1375 /** @todo SuperName has limited allowed arguments. */
1376 size_t offTblOrig = pThis->offTbl;
1377
1378 rc = rtAcpiTblAmlDecodeTerminal(pThis, hVfsIosOut, pErrInfo);
1379 if (RT_FAILURE(rc)) return rc;
1380
1381 cbPkgConsumed += pThis->offTbl - offTblOrig;
1382 break;
1383 }
1384 case kAcpiAmlOpcType_Invalid:
1385 default:
1386 AssertReleaseFailed();
1387 }
1388 }
1389
1390 rc = rtAcpiTblAmlDecodeFormat(pThis, hVfsIosOut, ")\n");
1391 if (RT_FAILURE(rc)) return rc;
1392
1393 pThis->fIndent = true;
1394 }
1395 else if (pThis->fIndent)
1396 {
1397 rc = rtAcpiTblAmlDecodeFormat(pThis, hVfsIosOut, "\n");
1398 if (RT_FAILURE(rc)) return rc;
1399 }
1400
1401 if (pAmlOpc->fFlags & RTACPI_AML_OPC_F_HAS_PKG_LENGTH)
1402 {
1403 if (cbPkg < cbPkgConsumed)
1404 return RTErrInfoSetF(pErrInfo, VERR_BUFFER_OVERFLOW, "Opcode arguments consumed more than the package length indicated (%zu vs %zu)", cbPkg, cbPkgConsumed);
1405 rc = rtAcpiTblAmlDecodePkgPush(pThis, hVfsIosOut, cbPkg - cbPkgConsumed, pErrInfo);
1406 }
1407
1408 return rc;
1409}
1410
1411static int rtAcpiTblAmlDecode(PRTACPITBLAMLDECODE pThis, PCRTACPIAMLOPC pAmlOpc, uint8_t bOpc, RTVFSIOSTREAM hVfsIosOut, PRTERRINFO pErrInfo)
1412{
1413 if (pAmlOpc->pszOpc)
1414 {
1415 if (pAmlOpc->pfnDecode)
1416 return pAmlOpc->pfnDecode(pThis, hVfsIosOut, bOpc, pErrInfo);
1417 return rtAcpiTblAmlDecodeSimple(pThis, pAmlOpc, bOpc, hVfsIosOut, pErrInfo);
1418 }
1419
1420 return RTErrInfoSetF(pErrInfo, VERR_INVALID_STATE, "Invalid opcode %#x in ACPI table at offset %u", bOpc, pThis->offTbl);
1421}
1422
1423
1424static int rtAcpiTblAmlDecodeTerminal(PRTACPITBLAMLDECODE pThis, RTVFSIOSTREAM hVfsIosOut, PRTERRINFO pErrInfo)
1425{
1426 PCRTACPIAMLOPC pAmlOpc = NULL;
1427 uint8_t bOpc = 0; /* shut up gcc */
1428 int rc = rtAcpiTblAmlDecodeReadU8(pThis, &bOpc, pErrInfo);
1429 if (RT_SUCCESS(rc))
1430 {
1431 if (bOpc == ACPI_AML_BYTE_CODE_PREFIX_EXT_OP)
1432 {
1433 rc = rtAcpiTblAmlDecodeReadU8(pThis, &bOpc, pErrInfo);
1434 if (RT_FAILURE(rc))
1435 return rc;
1436
1437 pAmlOpc = &g_aAmlExtOpcodeDecode[bOpc];
1438 }
1439 else
1440 pAmlOpc = &g_aAmlOpcodeDecode[bOpc];
1441
1442 return rtAcpiTblAmlDecode(pThis, pAmlOpc, bOpc, hVfsIosOut, pErrInfo);
1443 }
1444
1445 return rc;
1446}
1447
1448
1449RTDECL(int) RTAcpiTblCreateFromVfsIoStrm(PRTACPITBL phAcpiTbl, RTVFSIOSTREAM hVfsIos, RTACPITBLTYPE enmInType, PRTERRINFO pErrInfo)
1450{
1451 AssertPtrReturn(phAcpiTbl, VERR_INVALID_POINTER);
1452 AssertReturn(hVfsIos != NIL_RTVFSIOSTREAM, VERR_INVALID_HANDLE);
1453
1454 RT_NOREF(pErrInfo, enmInType);
1455#if 0
1456 if (enmInType == RTACPITBLTYPE_AML)
1457 return rtAcpiTblLoadAml(phAcpiTbl, hVfsIos, pErrInfo);
1458#endif
1459
1460 return VERR_NOT_IMPLEMENTED;
1461}
1462
1463
1464RTDECL(int) RTAcpiTblConvertFromVfsIoStrm(RTVFSIOSTREAM hVfsIosOut, RTACPITBLTYPE enmOutType,
1465 RTVFSIOSTREAM hVfsIosIn, RTACPITBLTYPE enmInType, PRTERRINFO pErrInfo)
1466{
1467 AssertReturn(hVfsIosOut != NIL_RTVFSIOSTREAM, VERR_INVALID_HANDLE);
1468 AssertReturn(hVfsIosIn != NIL_RTVFSIOSTREAM, VERR_INVALID_HANDLE);
1469 AssertReturn(enmInType == RTACPITBLTYPE_AML, VERR_NOT_SUPPORTED);
1470 AssertReturn(enmOutType == RTACPITBLTYPE_ASL, VERR_NOT_SUPPORTED);
1471
1472 ACPITBLHDR Hdr;
1473 int rc = RTVfsIoStrmRead(hVfsIosIn, &Hdr, sizeof(Hdr), true /*fBlocking*/, NULL /*pcbRead*/);
1474 if (RT_SUCCESS(rc))
1475 {
1476 Hdr.u32Signature = RT_LE2H_U32(Hdr.u32Signature);
1477 Hdr.cbTbl = RT_LE2H_U32(Hdr.cbTbl);
1478 Hdr.u32OemRevision = RT_LE2H_U32(Hdr.u32OemRevision);
1479 Hdr.u32CreatorRevision = RT_LE2H_U32(Hdr.u32CreatorRevision);
1480
1481 if ( Hdr.u32Signature == ACPI_TABLE_HDR_SIGNATURE_SSDT
1482 || Hdr.u32Signature == ACPI_TABLE_HDR_SIGNATURE_DSDT)
1483 {
1484 uint8_t *pbTbl = (uint8_t *)RTMemAlloc(Hdr.cbTbl);
1485 if (pbTbl)
1486 {
1487 rc = RTVfsIoStrmRead(hVfsIosIn, pbTbl, Hdr.cbTbl - sizeof(Hdr), true /*fBlocking*/, NULL /*pcbRead*/);
1488 if (RT_SUCCESS(rc))
1489 {
1490 /** @todo Verify checksum */
1491 ssize_t cch = RTVfsIoStrmPrintf(hVfsIosOut, "DefinitionBlock(\"\", \"%s\", %u, \"%.6s\", \"%.8s\", %u)\n",
1492 Hdr.u32Signature == ACPI_TABLE_HDR_SIGNATURE_SSDT ? "SSDT" : "DSDT",
1493 1, &Hdr.abOemId[0], &Hdr.abOemTblId[0], Hdr.u32OemRevision);
1494 if (cch > 0)
1495 {
1496 RTACPITBLAMLDECODE AmlDecode;
1497 AmlDecode.pbTbl = pbTbl;
1498 AmlDecode.cbTbl = Hdr.cbTbl - sizeof(Hdr);
1499 AmlDecode.offTbl = 0;
1500 AmlDecode.iLvl = 0;
1501 AmlDecode.cPkgStackMax = 0;
1502 AmlDecode.pacbPkgLeft = NULL;
1503 AmlDecode.fIndent = true;
1504 rc = rtAcpiTblAmlDecodePkgPush(&AmlDecode, hVfsIosOut, AmlDecode.cbTbl, pErrInfo);
1505 while ( RT_SUCCESS(rc)
1506 && AmlDecode.offTbl < Hdr.cbTbl - sizeof(Hdr))
1507 {
1508 rc = rtAcpiTblAmlDecodeTerminal(&AmlDecode, hVfsIosOut, pErrInfo);
1509 if (RT_SUCCESS(rc))
1510 rc = rtAcpiTblAmlDecodePkgPop(&AmlDecode, hVfsIosOut, pErrInfo);
1511 }
1512 if (AmlDecode.pacbPkgLeft)
1513 RTMemFree(AmlDecode.pacbPkgLeft);
1514
1515 if (RT_SUCCESS(rc))
1516 {
1517 cch = RTVfsIoStrmPrintf(hVfsIosOut, "}\n");
1518 if (cch <= 0)
1519 rc = RTErrInfoSetF(pErrInfo, cch == 0 ? VERR_NO_MEMORY : (int)cch, "Failed to emit closing definition block");
1520 }
1521 }
1522 else
1523 rc = RTErrInfoSetF(pErrInfo, cch == 0 ? VERR_NO_MEMORY : (int)cch, "Failed to emit DefinitionBlock()");
1524 }
1525 else
1526 rc = RTErrInfoSetF(pErrInfo, rc, "Reading %u bytes of the ACPI table failed", Hdr.cbTbl);
1527
1528 RTMemFree(pbTbl);
1529 pbTbl = NULL;
1530 }
1531 else
1532 rc = RTErrInfoSetF(pErrInfo, VERR_NO_MEMORY, "Allocating memory for the ACPI table failed");
1533 }
1534 else
1535 rc = RTErrInfoSetF(pErrInfo, VERR_NOT_SUPPORTED, "Only DSDT and SSDT ACPI tables are supported");
1536 }
1537 else
1538 rc = RTErrInfoSetF(pErrInfo, rc, "Reading the ACPI table header failed with %Rrc", rc);
1539
1540 return rc;
1541}
1542
1543
1544RTDECL(int) RTAcpiTblCreateFromFile(PRTACPITBL phAcpiTbl, const char *pszFilename, RTACPITBLTYPE enmInType, PRTERRINFO pErrInfo)
1545{
1546 RTVFSIOSTREAM hVfsIos = NIL_RTVFSIOSTREAM;
1547 int rc = RTVfsChainOpenIoStream(pszFilename, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_NONE,
1548 &hVfsIos, NULL /*poffError*/, pErrInfo);
1549 if (RT_FAILURE(rc))
1550 return rc;
1551
1552 rc = RTAcpiTblCreateFromVfsIoStrm(phAcpiTbl, hVfsIos, enmInType, pErrInfo);
1553 RTVfsIoStrmRelease(hVfsIos);
1554 return rc;
1555}
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