From 5880ec2182c9a1dd9c80c5e7cb1a59b9c7623d4d Mon Sep 17 00:00:00 2001 From: Vitaly Cheptsov <4348897+vit9696@users.noreply.github.com> Date: Mon, 15 Mar 2021 18:45:45 +0300 Subject: [PATCH] OcAcpiLib: Provide `Base` lookup for ACPI patches (#237) --- .gitignore | 1 + Docs/Configuration.tex | 24 + Docs/Sample.plist | 4 + Docs/SampleCustom.plist | 4 + Include/Acidanthera/Library/OcAcpiLib.h | 32 + .../Acidanthera/Library/OcConfigurationLib.h | 2 + Library/OcAcpiLib/AcpiParser.c | 2052 +++++++++++++++++ Library/OcAcpiLib/AcpiParser.h | 167 ++ Library/OcAcpiLib/OcAcpiLib.c | 70 +- Library/OcAcpiLib/OcAcpiLib.inf | 5 + .../OcConfigurationLib/OcConfigurationLib.c | 2 + Library/OcMainLib/OpenCoreAcpi.c | 7 +- Utilities/ACPIe/ACPIe.c | 244 ++ Utilities/ACPIe/Makefile | 15 + .../ACPIe/Tests/Correct/test100_output.txt | 1 + .../ACPIe/Tests/Correct/test10_output.txt | 1 + .../ACPIe/Tests/Correct/test11_output.txt | 1 + .../ACPIe/Tests/Correct/test12_output.txt | 1 + .../ACPIe/Tests/Correct/test13_output.txt | 1 + .../ACPIe/Tests/Correct/test14_output.txt | 1 + .../ACPIe/Tests/Correct/test15_output.txt | 1 + .../ACPIe/Tests/Correct/test16_output.txt | 1 + .../ACPIe/Tests/Correct/test17_output.txt | 1 + .../ACPIe/Tests/Correct/test18_output.txt | 1 + .../ACPIe/Tests/Correct/test19_output.txt | 1 + .../ACPIe/Tests/Correct/test1_output.txt | 1 + .../ACPIe/Tests/Correct/test20_output.txt | 1 + .../ACPIe/Tests/Correct/test2_output.txt | 1 + .../ACPIe/Tests/Correct/test3_output.txt | 1 + .../ACPIe/Tests/Correct/test4_output.txt | 1 + .../ACPIe/Tests/Correct/test5_output.txt | 1 + .../ACPIe/Tests/Correct/test6_output.txt | 1 + .../ACPIe/Tests/Correct/test7_output.txt | 1 + .../ACPIe/Tests/Correct/test8_output.txt | 1 + .../ACPIe/Tests/Correct/test9_output.txt | 1 + Utilities/ACPIe/Tests/Input/DSDT-legacy.bin | Bin 0 -> 41094 bytes Utilities/ACPIe/Tests/Input/DSDT.bin | Bin 0 -> 180054 bytes Utilities/ACPIe/Tests/Input/RSDT.bin | Bin 0 -> 132 bytes Utilities/ACPIe/Tests/Input/SSDT-0.bin | Bin 0 -> 857 bytes Utilities/ACPIe/Tests/Input/SSDT-1.bin | Bin 0 -> 27635 bytes Utilities/ACPIe/Tests/Input/SSDT-x4_0.bin | Bin 0 -> 1485 bytes Utilities/ACPIe/Tests/Input/broken3.bin | Bin 0 -> 13318 bytes Utilities/ACPIe/Tests/Input/corrupt1.bin | Bin 0 -> 14397 bytes Utilities/ACPIe/Tests/Input/nesting.bin | Bin 0 -> 120 bytes .../ACPIe/Tests/Output/test100_output.txt | 0 Utilities/ACPIe/testsuite.sh | 182 ++ build_oc.tool | 2 + 47 files changed, 2821 insertions(+), 13 deletions(-) create mode 100644 Library/OcAcpiLib/AcpiParser.c create mode 100644 Library/OcAcpiLib/AcpiParser.h create mode 100644 Utilities/ACPIe/ACPIe.c create mode 100644 Utilities/ACPIe/Makefile create mode 100644 Utilities/ACPIe/Tests/Correct/test100_output.txt create mode 100644 Utilities/ACPIe/Tests/Correct/test10_output.txt create mode 100644 Utilities/ACPIe/Tests/Correct/test11_output.txt create mode 100644 Utilities/ACPIe/Tests/Correct/test12_output.txt create mode 100644 Utilities/ACPIe/Tests/Correct/test13_output.txt create mode 100644 Utilities/ACPIe/Tests/Correct/test14_output.txt create mode 100644 Utilities/ACPIe/Tests/Correct/test15_output.txt create mode 100644 Utilities/ACPIe/Tests/Correct/test16_output.txt create mode 100644 Utilities/ACPIe/Tests/Correct/test17_output.txt create mode 100644 Utilities/ACPIe/Tests/Correct/test18_output.txt create mode 100644 Utilities/ACPIe/Tests/Correct/test19_output.txt create mode 100644 Utilities/ACPIe/Tests/Correct/test1_output.txt create mode 100644 Utilities/ACPIe/Tests/Correct/test20_output.txt create mode 100644 Utilities/ACPIe/Tests/Correct/test2_output.txt create mode 100644 Utilities/ACPIe/Tests/Correct/test3_output.txt create mode 100644 Utilities/ACPIe/Tests/Correct/test4_output.txt create mode 100644 Utilities/ACPIe/Tests/Correct/test5_output.txt create mode 100644 Utilities/ACPIe/Tests/Correct/test6_output.txt create mode 100644 Utilities/ACPIe/Tests/Correct/test7_output.txt create mode 100644 Utilities/ACPIe/Tests/Correct/test8_output.txt create mode 100644 Utilities/ACPIe/Tests/Correct/test9_output.txt create mode 100755 Utilities/ACPIe/Tests/Input/DSDT-legacy.bin create mode 100644 Utilities/ACPIe/Tests/Input/DSDT.bin create mode 100644 Utilities/ACPIe/Tests/Input/RSDT.bin create mode 100644 Utilities/ACPIe/Tests/Input/SSDT-0.bin create mode 100644 Utilities/ACPIe/Tests/Input/SSDT-1.bin create mode 100644 Utilities/ACPIe/Tests/Input/SSDT-x4_0.bin create mode 100644 Utilities/ACPIe/Tests/Input/broken3.bin create mode 100644 Utilities/ACPIe/Tests/Input/corrupt1.bin create mode 100644 Utilities/ACPIe/Tests/Input/nesting.bin create mode 100644 Utilities/ACPIe/Tests/Output/test100_output.txt create mode 100755 Utilities/ACPIe/testsuite.sh diff --git a/.gitignore b/.gitignore index ecce5a064e8..f720962df1a 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,7 @@ xcuserdata project.xcworkspace *.dSYM Utilities/AppleEfiSignTool/AppleEfiSignTool +Utilities/ACPIe/ACPIe Utilities/acdtinfo/acdtinfo Utilities/disklabel/disklabel Utilities/EfiResTool/EfiResTool diff --git a/Docs/Configuration.tex b/Docs/Configuration.tex index ccc2bcf264a..3ebf8a5e08b 100755 --- a/Docs/Configuration.tex +++ b/Docs/Configuration.tex @@ -967,6 +967,27 @@ \subsection{Patch Properties}\label{acpipropspatch} \begin{enumerate} +\item + \texttt{Base}\\ + \textbf{Type}: \texttt{plist\ string}\\ + \textbf{Failsafe}: Empty (Ignored)\\ + \textbf{Description}: Selects ACPI path base for patch lookup (or immediate + replacement) by obtaining the offset to the provided path. + + Only fully-qualified absolute paths are supported (e.g. \texttt{\textbackslash \_SB\_.PCI0.GFX0}). + Currently supported object types are: \texttt{Device}, \texttt{Field}, \texttt{Method}. + + \emph{Note}: Use with care, not all OEM tables can be parsed. Use \texttt{ACPIe} + utility to debug. \texttt{ACPIe} compiled with \texttt{DEBUG=1 make} command + produces helpful ACPI lookup tracing. + +\item + \texttt{BaseSkip}\\ + \textbf{Type}: \texttt{plist\ integer}\\ + \textbf{Failsafe}: \texttt{0} (Do not skip any occurrences)\\ + \textbf{Description}: Number of found \texttt{Base} occurrences to skip before + finds and replacements are applied. + \item \texttt{Comment}\\ \textbf{Type}: \texttt{plist\ string}\\ @@ -992,6 +1013,9 @@ \subsection{Patch Properties}\label{acpipropspatch} \textbf{Failsafe}: Empty\\ \textbf{Description}: Data to find. Must be equal to \texttt{Replace} in size if set. + \emph{Note}: Can be empty, when \texttt{Base} is specified, immediate replacement + after \texttt{Base} lookup happens in this case. + \item \texttt{Limit}\\ \textbf{Type}: \texttt{plist\ integer}\\ diff --git a/Docs/Sample.plist b/Docs/Sample.plist index 035790b3d1d..5ceccd526d7 100644 --- a/Docs/Sample.plist +++ b/Docs/Sample.plist @@ -185,6 +185,10 @@ Patch + Base + \_SB_.PCI0.GFX0 + BaseSkip + 0 Comment Replace one byte sequence with another Count diff --git a/Docs/SampleCustom.plist b/Docs/SampleCustom.plist index aeabd442258..7435e8b8e4e 100644 --- a/Docs/SampleCustom.plist +++ b/Docs/SampleCustom.plist @@ -185,6 +185,10 @@ Patch + Base + \_SB_.PCI0.GFX0 + BaseSkip + 0 Comment Replace one byte sequence with another Count diff --git a/Include/Acidanthera/Library/OcAcpiLib.h b/Include/Acidanthera/Library/OcAcpiLib.h index 527d68303f6..ecaa2a57f78 100755 --- a/Include/Acidanthera/Library/OcAcpiLib.h +++ b/Include/Acidanthera/Library/OcAcpiLib.h @@ -124,6 +124,14 @@ typedef struct { // CONST UINT8 *ReplaceMask; // + // Fully qualified name with ACPI path (e.g. \_SB_.PCI0.GFX0). + // + CONST CHAR8 *Base; + // + // Number of Base entries to skip before using. + // + UINT32 BaseSkip; + // // Patch size. // UINT32 Size; @@ -304,4 +312,28 @@ AcpiDumpTables ( IN EFI_FILE_PROTOCOL *Root ); +/** + Finds offset of required entry in ACPI table in case it exists. + + @param[in] Table Pointer to start of ACPI table. + @param[in] PathString Path to entry which must be found. + @param[in] Entry Number of entry which must be found. + @param[out] Offset Offset of the entry if it was found. + @param[out] TableLength Length of ACPI table. + + @retval EFI_SUCCESS Required entry was found. + @retval EFI_NOT_FOUND Required entry was not found. + @retval EFI_DEVICE_ERROR Error occured during parsing ACPI table. + @retval EFI_OUT_OF_RESOURCES Nesting limit has been reached. + @retval EFI_INVALID_PARAMETER Got wrong path to the entry. +**/ +EFI_STATUS +AcpiFindEntryInMemory ( + IN UINT8 *Table, + IN CONST CHAR8 *PathString, + IN UINT8 Entry, + OUT UINT32 *Offset, + IN UINT32 TableLength OPTIONAL + ); + #endif // OC_ACPI_LIB_H diff --git a/Include/Acidanthera/Library/OcConfigurationLib.h b/Include/Acidanthera/Library/OcConfigurationLib.h index 6c77e9ef2d8..eacd20171b0 100644 --- a/Include/Acidanthera/Library/OcConfigurationLib.h +++ b/Include/Acidanthera/Library/OcConfigurationLib.h @@ -60,6 +60,8 @@ _(BOOLEAN , Enabled , , FALSE , () ) \ _(OC_STRING , Comment , , OC_STRING_CONSTR ("", _, __), OC_DESTR (OC_STRING) ) \ _(OC_DATA , Find , , OC_EDATA_CONSTR (_, __) , OC_DESTR (OC_DATA) ) \ + _(OC_STRING , Base , , OC_STRING_CONSTR ("", _, __), OC_DESTR (OC_STRING) ) \ + _(UINT32 , BaseSkip , , 0 , () ) \ _(UINT32 , Limit , , 0 , () ) \ _(OC_DATA , Mask , , OC_EDATA_CONSTR (_, __) , OC_DESTR (OC_DATA) ) \ _(OC_DATA , Replace , , OC_EDATA_CONSTR (_, __) , OC_DESTR (OC_DATA) ) \ diff --git a/Library/OcAcpiLib/AcpiParser.c b/Library/OcAcpiLib/AcpiParser.c new file mode 100644 index 00000000000..68f6052cc46 --- /dev/null +++ b/Library/OcAcpiLib/AcpiParser.c @@ -0,0 +1,2052 @@ +/** @file + Copyright (c) 2020-2021, Ubsefor & koralexa. All rights reserved. + Copyright (c) 2021, vit9696. All rights reserved. + SPDX-License-Identifier: BSD-3-Clause +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "AcpiParser.h" + +/** + Parses identifier or path (several identifiers). Returns info about + the identifier / path if necessary. + + @param[in, out] Context Structure containing the parser context. + @param[in, out] NamePathStart Pointer to first opcode of identifier / path. + @param[in, out] PathLength Quantity of identifiers in path. + @param[in, out] IsRootPath 1 if parsed path was a root path, 0 otherwise. + + @retval EFI_SUCCESS Name was parsed successfuly. + @retval EFI_DEVICE_ERROR Error occured during parsing. + @retval EFI_OUT_OF_RESOURCES Nesting limit has been reached. +**/ +STATIC +EFI_STATUS +ParseNameString ( + IN OUT ACPI_PARSER_CONTEXT *Context, + IN OUT UINT8 **NamePathStart OPTIONAL, + IN OUT UINT8 *PathLength OPTIONAL, + IN OUT UINT8 *IsRootPath OPTIONAL + ) +{ + CONTEXT_ENTER (Context, "NameString"); + CONTEXT_HAS_WORK (Context); + CONTEXT_INCREASE_NESTING (Context); + + if (IsRootPath != NULL) { + *IsRootPath = 0; + } + + while (Context->CurrentOpcode[0] == AML_ROOT_CHAR || Context->CurrentOpcode[0] == AML_PARENT_PREFIX_CHAR) { + if (Context->CurrentOpcode[0] == AML_ROOT_CHAR && IsRootPath != NULL) { + *IsRootPath = 1; + } + + CONTEXT_ADVANCE_OPCODE (Context); + } + + switch (Context->CurrentOpcode[0]) { + case AML_ZERO_OP: + if (NamePathStart != NULL) { + *PathLength = 0; + *NamePathStart = NULL; + } + + Context->CurrentOpcode += 1; + break; + + case AML_DUAL_NAME_PREFIX: + CONTEXT_ADVANCE_OPCODE (Context); + CONTEXT_PEEK_BYTES (Context, 2 * IDENT_LEN); + + if (NamePathStart != NULL) { + *PathLength = 2; + *NamePathStart = Context->CurrentOpcode; + } + + Context->CurrentOpcode += 2 * IDENT_LEN; + break; + + case AML_MULTI_NAME_PREFIX: + CONTEXT_ADVANCE_OPCODE (Context); + CONTEXT_PEEK_BYTES (Context, 1 + Context->CurrentOpcode[0] * IDENT_LEN); + + if (NamePathStart != NULL) { + *PathLength = Context->CurrentOpcode[0]; + *NamePathStart = Context->CurrentOpcode + 1; + } + + Context->CurrentOpcode += 1 + Context->CurrentOpcode[0] * IDENT_LEN; + break; + + default: + CONTEXT_PEEK_BYTES (Context, IDENT_LEN); + + if (NamePathStart != NULL) { + *PathLength = 1; + *NamePathStart = Context->CurrentOpcode; + } + + Context->CurrentOpcode += IDENT_LEN; + } + + if (NamePathStart != NULL) { + PRINT_ACPI_NAME ("Read name", *NamePathStart, *PathLength); + } + + CONTEXT_DECREASE_NESTING (Context); + return EFI_SUCCESS; +} + +/** + Parses package length (length of current section). + + @param[in, out] Context Structure containing the parser context. + @param[out] PkgLength Total length of section. + + @retval EFI_SUCCESS Length was parsed successfuly. + @retval EFI_DEVICE_ERROR Error occured during parsing length. + @retval EFI_OUT_OF_RESOURCES Nesting limit has been reached. +**/ +STATIC +EFI_STATUS +ParsePkgLength ( + IN OUT ACPI_PARSER_CONTEXT *Context, + OUT UINT32 *PkgLength + ) +{ + UINT8 LeadByte; + UINT8 ByteCount; + UINT32 TotalSize; + UINT32 Index; + + CONTEXT_ENTER (Context, "PkgLength"); + CONTEXT_HAS_WORK (Context); + CONTEXT_INCREASE_NESTING (Context); + + LeadByte = Context->CurrentOpcode[0]; + TotalSize = 0; + ByteCount = (LeadByte & 0xC0) >> 6; + + CONTEXT_CONSUME_BYTES (Context, 1); + + if (ByteCount > 0) { + CONTEXT_PEEK_BYTES (Context, ByteCount); + + for (Index = 0; Index < ByteCount; Index++) { + TotalSize |= (UINT32) Context->CurrentOpcode[Index] << (Index * 8U + 4); + } + + TotalSize |= LeadByte & 0x0F; + *PkgLength = TotalSize; + CONTEXT_CONSUME_BYTES (Context, ByteCount); + } else { + *PkgLength = (UINT32) LeadByte; + } + + CONTEXT_DECREASE_NESTING (Context); + return EFI_SUCCESS; +} + +/** + Parses alias section to skip it correctly. + + @param[in, out] Context Structure containing the parser context. + + @retval EFI_NOT_FOUND Alias was parsed and skipped successfuly. + @retval EFI_DEVICE_ERROR Error occured during parsing alias. + @retval EFI_OUT_OF_RESOURCES Nesting limit has been reached. +**/ +STATIC +EFI_STATUS +ParseAlias ( + IN OUT ACPI_PARSER_CONTEXT *Context + ) +{ + CONTEXT_ENTER (Context, "Alias"); + CONTEXT_HAS_WORK (Context); + CONTEXT_INCREASE_NESTING (Context); + + if (ParseNameString ( + Context, + NULL, + NULL, + NULL + ) != EFI_SUCCESS) { + return EFI_DEVICE_ERROR; + } + + CONTEXT_PEEK_BYTES (Context, 1); + + if (ParseNameString ( + Context, + NULL, + NULL, + NULL + ) != EFI_SUCCESS) { + return EFI_DEVICE_ERROR; + } + + CONTEXT_DECREASE_NESTING (Context); + return EFI_NOT_FOUND; +} + +/** + Parses scope or device section. In case it's name is suitable parses + elements inside it, or returns pointer to it's opcode if this scope / device + was sought. Otherwise skips this section. + + @param[in, out] Context Structure containing the parser context. + @param[out] Result Pointer to sought opcode if required entry was found. + + @retval EFI_SUCCESS Required entry was found. + @retval EFI_NOT_FOUND Scope / device was parsed and skipped successfuly. + @retval EFI_DEVICE_ERROR Error occured during parsing scope / device. + @retval EFI_OUT_OF_RESOURCES Nesting limit has been reached. +**/ +STATIC +EFI_STATUS +ParseScopeOrDevice ( + IN OUT ACPI_PARSER_CONTEXT *Context, + OUT UINT8 **Result + ) +{ + UINT32 PkgLength; + UINT8 *ScopeStart; + UINT32 *CurrentPath; + UINT8 *ScopeEnd; + UINT8 *ScopeName; + UINT8 *ScopeNameStart; + UINT8 ScopeNameLength; + UINT8 IsRootPath; + EFI_STATUS Status; + UINT8 Index; + UINT8 Index2; + BOOLEAN Breakout; + + CONTEXT_ENTER (Context, "Scope / Device"); + CONTEXT_HAS_WORK (Context); + CONTEXT_INCREASE_NESTING (Context); + + ScopeStart = Context->CurrentOpcode; + CurrentPath = Context->CurrentIdentifier; + + if (ParsePkgLength ( + Context, + &PkgLength + ) != EFI_SUCCESS) { + return EFI_DEVICE_ERROR; + } + + if ((UINT32) (Context->TableEnd - ScopeStart) < PkgLength) { + return EFI_DEVICE_ERROR; + } + + ScopeEnd = ScopeStart + PkgLength; + + CONTEXT_PEEK_BYTES (Context, 1); + + if (ParseNameString ( + Context, + &ScopeName, + &ScopeNameLength, + &IsRootPath + ) != EFI_SUCCESS) { + return EFI_DEVICE_ERROR; + } + + ScopeNameStart = ScopeName; + + if (Context->CurrentOpcode > ScopeEnd) { + return EFI_DEVICE_ERROR; + } + + if (IsRootPath) { + Context->CurrentIdentifier = Context->PathStart; + } + + // + // Both exit conditions in these loops are for cases when there can be + // root-relative scopes within the current scope that does not match ours at all. + // + Breakout = FALSE; + + for (Index = 0; Index < ScopeNameLength; ++Index) { + if (Context->CurrentIdentifier == Context->PathEnd) { + Context->CurrentIdentifier = Context->PathStart; + break; + } + + for (Index2 = 0; Index2 < IDENT_LEN; ++Index2) { + if (*(ScopeName + Index2) != *((UINT8 *)Context->CurrentIdentifier + (IDENT_LEN - Index2 - 1))) { + Context->CurrentIdentifier = Context->PathStart; + Breakout = TRUE; + break; + } + } + + if (Breakout) { + break; + } + + Context->CurrentIdentifier += 1; + ScopeName += 4; + } + + if (Context->CurrentIdentifier == Context->PathEnd) { + Context->EntriesFound += 1; + if (Context->EntriesFound == Context->RequiredEntry) { + *Result = ScopeStart - 1; + return EFI_SUCCESS; + } + // + // Same issue with root-relative scopes. Retry search. + // + Context->CurrentIdentifier = Context->PathStart; + } + + PRINT_ACPI_NAME ("Entered scope", ScopeNameStart, ScopeNameLength); + + while (Context->CurrentOpcode < ScopeEnd) { + Status = InternalAcpiParseTerm ( + Context, + Result + ); + + if (Status != EFI_NOT_FOUND) { + return Status; + } + } + + PRINT_ACPI_NAME ("Left scope", ScopeNameStart, ScopeNameLength); + + Context->CurrentIdentifier = CurrentPath; + CONTEXT_DECREASE_NESTING (Context); + return EFI_NOT_FOUND; +} + +/** + Parses name section to correctly skip it. + + @param[in, out] Context Structure containing the parser context. + + @retval EFI_NOT_FOUND Name was parsed and skipped successfuly. + @retval EFI_DEVICE_ERROR Error occured during parsing name. + @retval EFI_OUT_OF_RESOURCES Nesting limit has been reached. +**/ +STATIC +EFI_STATUS +ParseName ( + IN OUT ACPI_PARSER_CONTEXT *Context + ) +{ + UINT32 PkgLength; + UINT8 *CurrentOpcode; + + CONTEXT_ENTER (Context, "Name"); + CONTEXT_HAS_WORK (Context); + CONTEXT_INCREASE_NESTING (Context); + + if (ParseNameString ( + Context, + NULL, + NULL, + NULL + ) != EFI_SUCCESS) { + return EFI_DEVICE_ERROR; + } + + CONTEXT_PEEK_BYTES (Context, 1); + + switch (Context->CurrentOpcode[0]) { + case AML_BYTE_PREFIX: + CONTEXT_CONSUME_BYTES (Context, 2); + break; + + case AML_WORD_PREFIX: + CONTEXT_CONSUME_BYTES (Context, 3); + break; + + case AML_DWORD_PREFIX: + CONTEXT_CONSUME_BYTES (Context, 5); + break; + + case AML_QWORD_PREFIX: + CONTEXT_CONSUME_BYTES (Context, 9); + break; + + case AML_STRING_PREFIX: + do { + CONTEXT_ADVANCE_OPCODE (Context); + } while (Context->CurrentOpcode[0] >= 0x01 && Context->CurrentOpcode[0] <= 0x7f); + + if (Context->CurrentOpcode[0] != AML_ZERO_OP) { + return EFI_DEVICE_ERROR; + } + + CONTEXT_CONSUME_BYTES (Context, 1); + break; + + case AML_ZERO_OP: + case AML_ONE_OP: + case AML_ONES_OP: + CONTEXT_CONSUME_BYTES (Context, 1); + break; + + case AML_EXT_OP: + CONTEXT_CONSUME_BYTES (Context, 2); + break; + + case AML_BUFFER_OP: + case AML_PACKAGE_OP: + case AML_VAR_PACKAGE_OP: + CONTEXT_ADVANCE_OPCODE (Context); + CurrentOpcode = Context->CurrentOpcode; + + if (ParsePkgLength ( + Context, + &PkgLength + ) != EFI_SUCCESS) { + return EFI_DEVICE_ERROR; + } + + Context->CurrentOpcode = CurrentOpcode; + CONTEXT_CONSUME_BYTES (Context, PkgLength); + break; + + default: + return EFI_DEVICE_ERROR; + } + + CONTEXT_DECREASE_NESTING (Context); + return EFI_NOT_FOUND; +} + +/** + Parses bank field section. In case it's name is suitable returns + pointer to it's opcode. Otherwise skips this section. + + @param[in, out] Context Structure containing the parser context. + @param[out] Result Pointer to sought opcode if required entry was found. + + @retval EFI_SUCCESS Required entry was found. + @retval EFI_NOT_FOUND Bank field was parsed and skipped successfuly. + @retval EFI_DEVICE_ERROR Error occured during parsing bank field. + @retval EFI_OUT_OF_RESOURCES Nesting limit has been reached. +**/ +STATIC +EFI_STATUS +ParseBankField ( + IN OUT ACPI_PARSER_CONTEXT *Context, + OUT UINT8 **Result + ) +{ + UINT32 PkgLength; + UINT8 *BankStart; + UINT8 *BankEnd; + UINT8 *Name; + UINT8 NameLength; + UINT8 Index; + + CONTEXT_ENTER (Context, "BankField"); + CONTEXT_HAS_WORK (Context); + CONTEXT_INCREASE_NESTING (Context); + + BankStart = Context->CurrentOpcode; + + if (ParsePkgLength ( + Context, + &PkgLength + ) != EFI_SUCCESS) { + return EFI_DEVICE_ERROR; + } + + if ((UINT32) (Context->TableEnd - BankStart) < PkgLength) { + return EFI_DEVICE_ERROR; + } + + BankEnd = BankStart + PkgLength; + + CONTEXT_PEEK_BYTES (Context, 1); + + if (ParseNameString ( + Context, + &Name, + &NameLength, + NULL + ) != EFI_SUCCESS) { + return EFI_DEVICE_ERROR; + } + + if (Context->CurrentOpcode >= BankEnd) { + return EFI_DEVICE_ERROR; + } + + if (NameLength != 1) { + return EFI_DEVICE_ERROR; + } + + for (Index = 0; Index < IDENT_LEN; ++Index) { + if (*(Name + Index) != *((UINT8 *)Context->CurrentIdentifier + (IDENT_LEN - Index - 1))) { + Context->CurrentOpcode = BankEnd; + CONTEXT_DECREASE_NESTING (Context); + return EFI_NOT_FOUND; + } + } + + Context->CurrentIdentifier += 1; + + CONTEXT_PEEK_BYTES (Context, 1); + + if (Context->CurrentIdentifier == Context->PathEnd) { + // + // FIXME: This looks weird. If it is a match, should not it return success? + // + Context->CurrentIdentifier -= 1; + if (ParseNameString ( + Context, + &Name, + &NameLength, + NULL + ) != EFI_SUCCESS) { + return EFI_DEVICE_ERROR; + } + Context->CurrentOpcode = BankEnd; + CONTEXT_DECREASE_NESTING (Context); + return EFI_NOT_FOUND; + } + + if (ParseNameString ( + Context, + &Name, + &NameLength, + NULL + ) != EFI_SUCCESS) { + return EFI_DEVICE_ERROR; + } + + if (Context->CurrentOpcode > BankEnd) { + return EFI_DEVICE_ERROR; + } + + if (NameLength != 1) { + return EFI_DEVICE_ERROR; + } + + for (Index = 0; Index < IDENT_LEN; ++Index) { + if (*(Name + Index) != *((UINT8 *)Context->CurrentIdentifier + (IDENT_LEN - Index - 1))) { + Context->CurrentOpcode = BankEnd; + Context->CurrentIdentifier -= 1; + CONTEXT_DECREASE_NESTING (Context); + return EFI_NOT_FOUND; + } + } + + if (Context->CurrentIdentifier + 1 != Context->PathEnd) { + Context->CurrentOpcode = BankEnd; + Context->CurrentIdentifier -= 1; + CONTEXT_DECREASE_NESTING (Context); + return EFI_NOT_FOUND; + } + + Context->EntriesFound += 1; + + if (Context->EntriesFound != Context->RequiredEntry) { + Context->CurrentOpcode = BankEnd; + Context->CurrentIdentifier -= 1; + CONTEXT_DECREASE_NESTING (Context); + return EFI_NOT_FOUND; + } + + *Result = BankStart - 1; + return EFI_SUCCESS; +} + +/** + Parses create field section (any of CreateDwordField, CreateWordField, + CreateByteField, CreateBitField, CreateQWordField, CreateField sections). + In case it's name is suitable returns pointer to it's opcode. + Otherwise skips this section. + + @param[in, out] Context Structure containing the parser context. + @param[out] Result Pointer to sought opcode if required entry was found. + + @retval EFI_SUCCESS Required entry was found. + @retval EFI_NOT_FOUND Field was parsed and skipped successfuly. + @retval EFI_DEVICE_ERROR Error occured during parsing field. + @retval EFI_OUT_OF_RESOURCES Nesting limit has been reached. +**/ +STATIC +EFI_STATUS +ParseCreateField ( + IN OUT ACPI_PARSER_CONTEXT *Context, + OUT UINT8 **Result + ) +{ + UINT8 *FieldStart; + UINT8 *FieldOpcode; + UINT8 *Name; + UINT8 NameLength; + UINT8 Index; + BOOLEAN Matched; + + CONTEXT_ENTER (Context, "CreateField"); + CONTEXT_HAS_WORK (Context); + CONTEXT_INCREASE_NESTING (Context); + + FieldStart = Context->CurrentOpcode; + FieldOpcode = Context->CurrentOpcode - 1; + + switch (Context->CurrentOpcode[0]) { + case AML_ARG0: + case AML_ARG1: + case AML_ARG2: + case AML_ARG3: + case AML_ARG4: + case AML_ARG5: + case AML_ARG6: + CONTEXT_CONSUME_BYTES (Context, 5); + + if (*FieldOpcode == AML_EXT_CREATE_FIELD_OP) { + CONTEXT_CONSUME_BYTES (Context, 4); + } + + CONTEXT_PEEK_BYTES (Context, 1); + + if (ParseNameString ( + Context, + NULL, + NULL, + NULL + ) != EFI_SUCCESS) { + return EFI_DEVICE_ERROR; + } + + CONTEXT_DECREASE_NESTING (Context); + return EFI_NOT_FOUND; + + default: + + if (ParseNameString ( + Context, + &Name, + &NameLength, + NULL + ) != EFI_SUCCESS) { + return EFI_DEVICE_ERROR; + } + + if (NameLength != 1) { + return EFI_DEVICE_ERROR; + } + + Matched = TRUE; + for (Index = 0; Index < IDENT_LEN; Index++) { + if (*(Name + Index) != *((UINT8 *)Context->CurrentIdentifier + (IDENT_LEN - Index - 1))) { + Matched = FALSE; + break; + } + } + + CONTEXT_PEEK_BYTES (Context, 1); + + switch (Context->CurrentOpcode[0]) { + case AML_ZERO_OP: + case AML_ONE_OP: + CONTEXT_CONSUME_BYTES (Context, 1); + break; + + case AML_BYTE_PREFIX: + CONTEXT_CONSUME_BYTES (Context, 2); + break; + + case AML_WORD_PREFIX: + CONTEXT_CONSUME_BYTES (Context, 3); + break; + + case AML_DWORD_PREFIX: + CONTEXT_CONSUME_BYTES (Context, 5); + break; + + case AML_QWORD_PREFIX: + CONTEXT_CONSUME_BYTES (Context, 9); + break; + } + + if (*FieldOpcode == AML_EXT_CREATE_FIELD_OP) { + CONTEXT_CONSUME_BYTES (Context, 1); + } + + CONTEXT_PEEK_BYTES (Context, 1); + + if (ParseNameString ( + Context, + &Name, + &NameLength, + NULL + ) != EFI_SUCCESS) { + return EFI_DEVICE_ERROR; + } + + if (NameLength != 1) { + return EFI_DEVICE_ERROR; + } + + if (!Matched) { + CONTEXT_DECREASE_NESTING (Context); + return EFI_NOT_FOUND; + } + + Context->CurrentIdentifier += 1; + + for (Index = 0; Index < IDENT_LEN; Index++) { + if (*(Name + Index) != *((UINT8 *)Context->CurrentIdentifier + (IDENT_LEN - Index - 1))) { + CONTEXT_DECREASE_NESTING (Context); + Context->CurrentIdentifier--; + return EFI_NOT_FOUND; + } + } + + Context->CurrentIdentifier += 1; + + if (Context->CurrentIdentifier != Context->PathEnd) { + CONTEXT_DECREASE_NESTING (Context); + Context->CurrentIdentifier -= 2; + return EFI_NOT_FOUND; + } + + Context->EntriesFound += 1; + + if (Context->EntriesFound != Context->RequiredEntry) { + CONTEXT_DECREASE_NESTING (Context); + Context->CurrentIdentifier -= 2; + return EFI_NOT_FOUND; + } + + *Result = FieldStart - 1; + return EFI_SUCCESS; + } +} + +/** + Parses external section to correctly skip it. + + @param[in, out] Context Structure containing the parser context. + + @retval EFI_NOT_FOUND External was parsed and skipped successfuly. + @retval EFI_DEVICE_ERROR Error occured during parsing external. + @retval EFI_OUT_OF_RESOURCES Nesting limit has been reached. +**/ +STATIC +EFI_STATUS +ParseExternal ( + IN OUT ACPI_PARSER_CONTEXT *Context + ) +{ + CONTEXT_ENTER (Context, "External"); + CONTEXT_HAS_WORK (Context); + CONTEXT_INCREASE_NESTING (Context); + + if (ParseNameString ( + Context, + NULL, + NULL, + NULL + ) != EFI_SUCCESS) { + return EFI_DEVICE_ERROR; + } + + CONTEXT_ADVANCE_OPCODE (Context); + + // + // FIXME: This looks suspicious. + // + while (Context->CurrentOpcode[0] != AML_ZERO_OP) { + CONTEXT_ADVANCE_OPCODE (Context); + } + + CONTEXT_CONSUME_BYTES (Context, 1); + CONTEXT_DECREASE_NESTING (Context); + return EFI_NOT_FOUND; +} + +/** + Parses operation region to skip it correctly. + + @param[in, out] Context Structure containing the parser context. + + @retval EFI_NOT_FOUND OpRegion was parsed and skipped successfuly. + @retval EFI_DEVICE_ERROR Error occured during parsing OpRegion. + @retval EFI_OUT_OF_RESOURCES Nesting limit has been reached. +**/ +STATIC +EFI_STATUS +ParseOpRegion ( + IN OUT ACPI_PARSER_CONTEXT *Context + ) +{ + CONTEXT_ENTER (Context, "OpRegion"); + CONTEXT_HAS_WORK (Context); + CONTEXT_INCREASE_NESTING (Context); + + if (ParseNameString ( + Context, + NULL, + NULL, + NULL + ) != EFI_SUCCESS) { + return EFI_DEVICE_ERROR; + } + + CONTEXT_ADVANCE_OPCODE (Context); + + switch (Context->CurrentOpcode[0]) { + case AML_ZERO_OP: + case AML_ONE_OP: + CONTEXT_CONSUME_BYTES (Context, 1); + break; + + case AML_BYTE_PREFIX: + CONTEXT_CONSUME_BYTES (Context, 2); + break; + + case AML_WORD_PREFIX: + CONTEXT_CONSUME_BYTES (Context, 3); + break; + + case AML_DWORD_PREFIX: + CONTEXT_CONSUME_BYTES (Context, 5); + break; + + case AML_QWORD_PREFIX: + CONTEXT_CONSUME_BYTES (Context, 9); + break; + + case AML_ADD_OP: + case AML_SUBTRACT_OP: + CONTEXT_ADVANCE_OPCODE (Context); + + switch (Context->CurrentOpcode[0]) { + case AML_ZERO_OP: + case AML_ONE_OP: + CONTEXT_CONSUME_BYTES (Context, 1); + break; + + case AML_BYTE_PREFIX: + CONTEXT_CONSUME_BYTES (Context, 2); + break; + + case AML_WORD_PREFIX: + CONTEXT_CONSUME_BYTES (Context, 3); + break; + + case AML_DWORD_PREFIX: + CONTEXT_CONSUME_BYTES (Context, 5); + break; + + case AML_QWORD_PREFIX: + CONTEXT_CONSUME_BYTES (Context, 9); + break; + + default: + if (ParseNameString ( + Context, + NULL, + NULL, + NULL + ) != EFI_SUCCESS) { + return EFI_DEVICE_ERROR; + } + break; + } + + CONTEXT_PEEK_BYTES (Context, 1); + + switch (Context->CurrentOpcode[0]) { + case AML_ZERO_OP: + case AML_ONE_OP: + CONTEXT_CONSUME_BYTES (Context, 1); + break; + + case AML_BYTE_PREFIX: + CONTEXT_CONSUME_BYTES (Context, 2); + break; + + case AML_WORD_PREFIX: + CONTEXT_CONSUME_BYTES (Context, 3); + break; + + case AML_DWORD_PREFIX: + CONTEXT_CONSUME_BYTES (Context, 5); + break; + + case AML_QWORD_PREFIX: + CONTEXT_CONSUME_BYTES (Context, 9); + break; + + default: + if (ParseNameString ( + Context, + NULL, + NULL, + NULL + ) != EFI_SUCCESS) { + return EFI_DEVICE_ERROR; + } + break; + } + + CONTEXT_PEEK_BYTES (Context, 1); + + /* Fallthrough */ + default: + if (ParseNameString ( + Context, + NULL, + NULL, + NULL + ) != EFI_SUCCESS) { + return EFI_DEVICE_ERROR; + } + break; + } + + CONTEXT_PEEK_BYTES (Context, 1); + + switch (Context->CurrentOpcode[0]) { + case AML_ZERO_OP: + case AML_ONE_OP: + CONTEXT_CONSUME_BYTES (Context, 1); + break; + + case AML_BYTE_PREFIX: + CONTEXT_CONSUME_BYTES (Context, 2); + break; + + case AML_WORD_PREFIX: + CONTEXT_CONSUME_BYTES (Context, 3); + break; + + case AML_DWORD_PREFIX: + CONTEXT_CONSUME_BYTES (Context, 5); + break; + + case AML_QWORD_PREFIX: + CONTEXT_CONSUME_BYTES (Context, 9); + break; + + case AML_ADD_OP: + case AML_SUBTRACT_OP: + CONTEXT_ADVANCE_OPCODE (Context); + + switch (Context->CurrentOpcode[0]) { + case AML_ZERO_OP: + case AML_ONE_OP: + CONTEXT_CONSUME_BYTES (Context, 1); + break; + + case AML_BYTE_PREFIX: + CONTEXT_CONSUME_BYTES (Context, 2); + break; + + case AML_WORD_PREFIX: + CONTEXT_CONSUME_BYTES (Context, 3); + break; + + case AML_DWORD_PREFIX: + CONTEXT_CONSUME_BYTES (Context, 5); + break; + + case AML_QWORD_PREFIX: + CONTEXT_CONSUME_BYTES (Context, 9); + break; + + default: + if (ParseNameString ( + Context, + NULL, + NULL, + NULL + ) != EFI_SUCCESS) { + return EFI_DEVICE_ERROR; + } + break; + } + + CONTEXT_PEEK_BYTES (Context, 1); + + switch (Context->CurrentOpcode[0]) { + case AML_ZERO_OP: + case AML_ONE_OP: + CONTEXT_CONSUME_BYTES (Context, 1); + break; + + case AML_BYTE_PREFIX: + CONTEXT_CONSUME_BYTES (Context, 2); + break; + + case AML_WORD_PREFIX: + CONTEXT_CONSUME_BYTES (Context, 3); + break; + + case AML_DWORD_PREFIX: + CONTEXT_CONSUME_BYTES (Context, 5); + break; + + case AML_QWORD_PREFIX: + CONTEXT_CONSUME_BYTES (Context, 9); + break; + + default: + if (ParseNameString ( + Context, + NULL, + NULL, + NULL + ) != EFI_SUCCESS) { + return EFI_DEVICE_ERROR; + } + break; + } + + CONTEXT_PEEK_BYTES (Context, 1); + /* Fallthrough */ + + default: + if (ParseNameString ( + Context, + NULL, + NULL, + NULL + ) != EFI_SUCCESS) { + return EFI_DEVICE_ERROR; + } + break; + } + + CONTEXT_DECREASE_NESTING (Context); + return EFI_NOT_FOUND; +} + +/** + Parses PowerRes to skip it correctly. + + @param[in, out] Context Structure containing the parser context. + + @retval EFI_NOT_FOUND PowerRes was parsed and skipped successfuly. + @retval EFI_DEVICE_ERROR Error occured during parsing PowerRes. + @retval EFI_OUT_OF_RESOURCES Nesting limit has been reached. +**/ +STATIC +EFI_STATUS +ParsePowerRes ( + IN OUT ACPI_PARSER_CONTEXT *Context + ) +{ + UINT32 PkgLength; + UINT8 *CurrentOpcode; + + CONTEXT_ENTER (Context, "PowerRes"); + CONTEXT_HAS_WORK (Context); + CONTEXT_INCREASE_NESTING (Context); + + CurrentOpcode = Context->CurrentOpcode; + + if (ParsePkgLength ( + Context, + &PkgLength + ) != EFI_SUCCESS) { + return EFI_DEVICE_ERROR; + } + + Context->CurrentOpcode = CurrentOpcode; + CONTEXT_CONSUME_BYTES (Context, PkgLength); + CONTEXT_DECREASE_NESTING (Context); + return EFI_NOT_FOUND; +} + +/** + Parses processor section to skip it correctly. + + @param[in, out] Context Structure containing the parser context. + + @retval EFI_NOT_FOUND Processor was parsed and skipped successfuly. + @retval EFI_DEVICE_ERROR Error occured during parsing processor. + @retval EFI_OUT_OF_RESOURCES Nesting limit has been reached. +**/ +STATIC +EFI_STATUS +ParseProcessor ( + IN OUT ACPI_PARSER_CONTEXT *Context + ) +{ + UINT8 *CurrentOpcode; + UINT32 PkgLength; + + CONTEXT_ENTER (Context, "Processor"); + CONTEXT_HAS_WORK (Context); + CONTEXT_INCREASE_NESTING (Context); + + CurrentOpcode = Context->CurrentOpcode; + + if (ParsePkgLength ( + Context, + &PkgLength + ) != EFI_SUCCESS) { + return EFI_DEVICE_ERROR; + } + + Context->CurrentOpcode = CurrentOpcode; + CONTEXT_CONSUME_BYTES (Context, PkgLength); + CONTEXT_DECREASE_NESTING (Context); + return EFI_NOT_FOUND; +} + +/** + Parses thermal zone to skip it correctly. + + @param[in, out] Context Structure containing the parser context. + + @retval EFI_NOT_FOUND Processor was parsed and skipped successfuly. + @retval EFI_DEVICE_ERROR Error occured during parsing processor. + @retval EFI_OUT_OF_RESOURCES Nesting limit has been reached. +**/ +STATIC +EFI_STATUS +ParseThermalZone ( + IN OUT ACPI_PARSER_CONTEXT *Context + ) +{ + UINT8 *CurrentOpcode; + UINT32 PkgLength; + + CONTEXT_ENTER (Context, "ThermalZone"); + CONTEXT_HAS_WORK (Context); + CONTEXT_INCREASE_NESTING (Context); + + CurrentOpcode = Context->CurrentOpcode; + + if (ParsePkgLength ( + Context, + &PkgLength + ) != EFI_SUCCESS) { + return EFI_DEVICE_ERROR; + } + + Context->CurrentOpcode = CurrentOpcode; + CONTEXT_CONSUME_BYTES (Context, PkgLength); + CONTEXT_DECREASE_NESTING (Context); + return EFI_NOT_FOUND; +} + +/** + Parses method section. + In case it's name is suitable returns pointer to it's opcode. + Otherwise skips this section. + + @param[in, out] Context Structure containing the parser context. + @param[out] Result Pointer to sought opcode if required entry was found. + + @retval EFI_SUCCESS Required entry was found. + @retval EFI_NOT_FOUND Method was parsed and skipped successfuly. + @retval EFI_DEVICE_ERROR Error occured during parsing method. + @retval EFI_OUT_OF_RESOURCES Nesting limit has been reached. +**/ +STATIC +EFI_STATUS +ParseMethod ( + IN OUT ACPI_PARSER_CONTEXT *Context, + OUT UINT8 **Result + ) +{ + UINT8 *MethodStart; + UINT32 *CurrentPath; + UINT32 PkgLength; + UINT8 *MethodEnd; + UINT8 *MethodName; + UINT8 MethodNameLength; + UINT8 Index; + UINT8 Index2; + + CONTEXT_ENTER (Context, "Method"); + CONTEXT_HAS_WORK (Context); + CONTEXT_INCREASE_NESTING (Context); + + MethodStart = Context->CurrentOpcode; + CurrentPath = Context->CurrentIdentifier; + + if (ParsePkgLength ( + Context, + &PkgLength + ) != EFI_SUCCESS) { + return EFI_DEVICE_ERROR; + } + + if ((UINT32) (Context->TableEnd - MethodStart) < PkgLength) { + return EFI_DEVICE_ERROR; + } + + MethodEnd = MethodStart + PkgLength; + + if (Context->CurrentOpcode >= MethodEnd) { + return EFI_DEVICE_ERROR; + } + + if (ParseNameString ( + Context, + &MethodName, + &MethodNameLength, + NULL + ) != EFI_SUCCESS) { + return EFI_DEVICE_ERROR; + } + + if (Context->CurrentOpcode > MethodEnd) { + return EFI_DEVICE_ERROR; + } + + for (Index = 0; Index < MethodNameLength; ++Index) { + // + // If the method is within our lookup path but not at it, this is not a match. + // + if (Context->CurrentIdentifier == Context->PathEnd) { + Context->CurrentOpcode = MethodEnd; + Context->CurrentIdentifier = CurrentPath; + CONTEXT_DECREASE_NESTING (Context); + return EFI_NOT_FOUND; + } + + for (Index2 = 0; Index2 < IDENT_LEN; Index2++) { + if (*(MethodName + Index2) != *((UINT8 *)Context->CurrentIdentifier + (IDENT_LEN - Index2 - 1))) { + Context->CurrentOpcode = MethodEnd; + Context->CurrentIdentifier = CurrentPath; + CONTEXT_DECREASE_NESTING (Context); + return EFI_NOT_FOUND; + } + } + + Context->CurrentIdentifier += 1; + MethodName += 4; + } + + if (Context->CurrentIdentifier != Context->PathEnd) { + Context->CurrentOpcode = MethodEnd; + Context->CurrentIdentifier = CurrentPath; + CONTEXT_DECREASE_NESTING (Context); + return EFI_NOT_FOUND; + } + + Context->EntriesFound += 1; + + if (Context->EntriesFound != Context->RequiredEntry) { + Context->CurrentOpcode = MethodEnd; + Context->CurrentIdentifier = CurrentPath; + CONTEXT_DECREASE_NESTING (Context); + return EFI_NOT_FOUND; + } + + *Result = MethodStart - 1; + return EFI_SUCCESS; +} + +/** + Parses if-else section. Looks for other sections inside it. + + @param[in, out] Context Structure containing the parser context. + @param[out] Result Pointer to sought opcode if required entry was found. + + @retval EFI_SUCCESS Required entry was found. + @retval EFI_NOT_FOUND If-else section was parsed and skipped successfuly. + @retval EFI_DEVICE_ERROR Error occured during parsing if-else section. + @retval EFI_OUT_OF_RESOURCES Nesting limit has been reached. +**/ +STATIC +EFI_STATUS +ParseIfElse ( + IN OUT ACPI_PARSER_CONTEXT *Context, + OUT UINT8 **Result + ) +{ + UINT32 PkgLength; + UINT8 *IfStart; + UINT32 *CurrentPath; + UINT8 *IfEnd; + EFI_STATUS Status; + + CONTEXT_ENTER (Context, "IfElse"); + CONTEXT_HAS_WORK (Context); + CONTEXT_INCREASE_NESTING (Context); + + IfStart = Context->CurrentOpcode; + CurrentPath = Context->CurrentIdentifier; + + if (ParsePkgLength ( + Context, + &PkgLength + ) != EFI_SUCCESS) { + return EFI_DEVICE_ERROR; + } + + if ((UINT32) (Context->TableEnd - IfStart) < PkgLength) { + return EFI_DEVICE_ERROR; + } + + IfEnd = IfStart + PkgLength; + + // + // FIXME: This is broken like hell. + // + Status = EFI_NOT_FOUND; + while (Status != EFI_SUCCESS && Context->CurrentOpcode < IfEnd) { + Status = InternalAcpiParseTerm (Context, Result); + if (Status == EFI_DEVICE_ERROR) { + Context->CurrentOpcode += 1; + } + } + + if (Context->CurrentOpcode > IfEnd || Status == EFI_DEVICE_ERROR) { + return EFI_DEVICE_ERROR; + } + + if (Status == EFI_SUCCESS) { + CONTEXT_DECREASE_NESTING (Context); + return EFI_SUCCESS; + } + + Context->CurrentIdentifier = CurrentPath; + + CONTEXT_PEEK_BYTES (Context, 1); + + if (Context->CurrentOpcode[0] == AML_ELSE_OP) { + CONTEXT_ADVANCE_OPCODE (Context); + IfStart = Context->CurrentOpcode; + + if (ParsePkgLength ( + Context, + &PkgLength + ) != EFI_SUCCESS) { + return EFI_DEVICE_ERROR; + } + + if ((UINT32) (Context->TableEnd - IfStart) < PkgLength) { + return EFI_DEVICE_ERROR; + } + + IfEnd = IfStart + PkgLength; + + // + // FIXME: This is broken like hell. + // + Status = EFI_NOT_FOUND; + while (Status != EFI_SUCCESS && Context->CurrentOpcode < IfEnd) { + Status = InternalAcpiParseTerm (Context, Result); + if (Status == EFI_DEVICE_ERROR) { + Context->CurrentOpcode += 1; + } + } + + if (Context->CurrentOpcode > IfEnd || Status == EFI_DEVICE_ERROR) { + return EFI_DEVICE_ERROR; + } + + if (Status == EFI_SUCCESS) { + CONTEXT_DECREASE_NESTING (Context); + return EFI_SUCCESS; + } + + Context->CurrentIdentifier = CurrentPath; + } + + CONTEXT_DECREASE_NESTING (Context); + return EFI_NOT_FOUND; +} + +/** + Parses event section to skip it correctly. + + @param[in, out] Context Structure containing the parser context. + + @retval EFI_NOT_FOUND Event was parsed and skipped successfuly. + @retval EFI_DEVICE_ERROR Error occured during parsing event. + @retval EFI_OUT_OF_RESOURCES Nesting limit has been reached. +**/ +STATIC +EFI_STATUS +ParseEvent ( + IN OUT ACPI_PARSER_CONTEXT *Context + ) +{ + CONTEXT_ENTER (Context, "Event"); + CONTEXT_HAS_WORK (Context); + CONTEXT_INCREASE_NESTING (Context); + + if (ParseNameString ( + Context, + NULL, + NULL, + NULL + ) != EFI_SUCCESS) { + return EFI_DEVICE_ERROR; + } + + CONTEXT_DECREASE_NESTING (Context); + return EFI_NOT_FOUND; +} + +/** + Parses field section. + In case it's name is suitable returns pointer to it's opcode. + Otherwise skips this section. + + @param[in, out] Context Structure containing the parser context. + @param[out] Result Pointer to sought opcode if required entry was found. + + @retval EFI_SUCCESS Required entry was found. + @retval EFI_NOT_FOUND Field was parsed and skipped successfuly. + @retval EFI_DEVICE_ERROR Error occured during parsing field. + @retval EFI_OUT_OF_RESOURCES Nesting limit has been reached. +**/ +STATIC +EFI_STATUS +ParseField ( + IN OUT ACPI_PARSER_CONTEXT *Context, + OUT UINT8 **Result + ) +{ + UINT8 *FieldStart; + UINT32 PkgLength; + UINT8 *FieldEnd; + UINT8 *FieldName; + UINT8 FieldNameLength; + UINT32 *CurrentPath; + UINT8 Index; + UINT8 Index2; + + CONTEXT_ENTER (Context, "Field"); + CONTEXT_HAS_WORK (Context); + CONTEXT_INCREASE_NESTING (Context); + + FieldStart = Context->CurrentOpcode; + + if (ParsePkgLength ( + Context, + &PkgLength + ) != EFI_SUCCESS) { + return EFI_DEVICE_ERROR; + } + + if ((UINT32) (Context->TableEnd - FieldStart) < PkgLength) { + return EFI_DEVICE_ERROR; + } + + FieldEnd = FieldStart + PkgLength; + + if (Context->CurrentOpcode >= FieldEnd) { + return EFI_DEVICE_ERROR; + } + + if (ParseNameString ( + Context, + &FieldName, + &FieldNameLength, + NULL + ) != EFI_SUCCESS) { + return EFI_DEVICE_ERROR; + } + + if (Context->CurrentOpcode > FieldEnd) { + return EFI_DEVICE_ERROR; + } + + CurrentPath = Context->CurrentIdentifier; + + for (Index = 0; Index < FieldNameLength; Index++) { + if (Context->CurrentIdentifier == Context->PathEnd) { + Context->CurrentOpcode = FieldEnd; + Context->CurrentIdentifier = CurrentPath; + CONTEXT_DECREASE_NESTING (Context); + return EFI_NOT_FOUND; + } + + for (Index2 = 0; Index2 < IDENT_LEN; Index2++) { + if (*(FieldName + Index2) != *((UINT8 *)Context->CurrentIdentifier + (IDENT_LEN - Index2 - 1))) { + Context->CurrentOpcode = FieldEnd; + Context->CurrentIdentifier = CurrentPath; + CONTEXT_DECREASE_NESTING (Context); + return EFI_NOT_FOUND; + } + } + + Context->CurrentIdentifier += 1; + FieldName += 4; + } + + if (Context->CurrentIdentifier != Context->PathEnd) { + Context->CurrentOpcode = FieldEnd; + Context->CurrentIdentifier = CurrentPath; + CONTEXT_DECREASE_NESTING (Context); + return EFI_NOT_FOUND; + } + + Context->EntriesFound += 1; + + if (Context->EntriesFound != Context->RequiredEntry) { + Context->CurrentOpcode = FieldEnd; + Context->CurrentIdentifier = CurrentPath; + CONTEXT_DECREASE_NESTING (Context); + return EFI_NOT_FOUND; + } + + *Result = FieldStart - 1; + return EFI_SUCCESS; +} + +/** + Parses mutex to correctly skip it. + + @param[in, out] Context Structure containing the parser context. + + @retval EFI_NOT_FOUND Mutex was parsed and skipped successfuly. + @retval EFI_DEVICE_ERROR Error occured during parsing mutex. + @retval EFI_OUT_OF_RESOURCES Nesting limit has been reached. +**/ +STATIC +EFI_STATUS +ParseMutex ( + IN OUT ACPI_PARSER_CONTEXT *Context + ) +{ + CONTEXT_ENTER (Context, "Mutex"); + CONTEXT_HAS_WORK (Context); + CONTEXT_INCREASE_NESTING (Context); + + if (ParseNameString ( + Context, + NULL, + NULL, + NULL + ) != EFI_SUCCESS) { + return EFI_DEVICE_ERROR; + } + + CONTEXT_CONSUME_BYTES (Context, 1); + CONTEXT_DECREASE_NESTING (Context); + return EFI_NOT_FOUND; +} + +/** + Parses index field section. + In case it's name is suitable returns pointer to it's opcode. + Otherwise skips this section. + + @param[in, out] Context Structure containing the parser context. + @param[out] Result Pointer to sought opcode if required entry was found. + + @retval EFI_SUCCESS Required entry was found. + @retval EFI_NOT_FOUND Index field was parsed and skipped successfuly. + @retval EFI_DEVICE_ERROR Error occured during parsing index field. + @retval EFI_OUT_OF_RESOURCES Nesting limit has been reached. +**/ +STATIC +EFI_STATUS +ParseIndexField ( + IN OUT ACPI_PARSER_CONTEXT *Context, + OUT UINT8 **Result + ) +{ + UINT8 *FieldStart; + UINT32 PkgLength; + UINT8 *FieldEnd; + UINT8 *FieldName; + UINT8 FieldNameLength; + UINT8 Index; + + CONTEXT_ENTER (Context, "IndexField"); + CONTEXT_HAS_WORK (Context); + CONTEXT_INCREASE_NESTING (Context); + + FieldStart = Context->CurrentOpcode; + + if (ParsePkgLength ( + Context, + &PkgLength + ) != EFI_SUCCESS) { + return EFI_DEVICE_ERROR; + } + + if ((UINT32) (Context->TableEnd - FieldStart) < PkgLength) { + return EFI_DEVICE_ERROR; + } + + FieldEnd = FieldStart + PkgLength; + + if (Context->CurrentOpcode >= FieldEnd) { + return EFI_DEVICE_ERROR; + } + + if (ParseNameString ( + Context, + &FieldName, + &FieldNameLength, + NULL + ) != EFI_SUCCESS) { + return EFI_DEVICE_ERROR; + } + + if (Context->CurrentOpcode >= FieldEnd) { + return EFI_DEVICE_ERROR; + } + + if (FieldNameLength != 1) { + return EFI_DEVICE_ERROR; + } + + for (Index = 0; Index < IDENT_LEN; ++Index) { + if (*(FieldName + Index) != *((UINT8 *)Context->CurrentIdentifier + (IDENT_LEN - Index - 1))) { + if (ParseNameString ( + Context, + &FieldName, + &FieldNameLength, + NULL + ) != EFI_SUCCESS) { + return EFI_DEVICE_ERROR; + } + + Context->CurrentOpcode = FieldEnd; + CONTEXT_DECREASE_NESTING (Context); + return EFI_NOT_FOUND; + } + } + + Context->CurrentIdentifier += 1; + + // + // FIXME: Not sure what to do. + // + if (Context->CurrentIdentifier == Context->PathEnd) { + return EFI_DEVICE_ERROR; + } + + CONTEXT_PEEK_BYTES (Context, 1); + + if (ParseNameString ( + Context, + &FieldName, + &FieldNameLength, + NULL + ) != EFI_SUCCESS) { + return EFI_DEVICE_ERROR; + } + + if (Context->CurrentOpcode >= FieldEnd) { + return EFI_DEVICE_ERROR; + } + + if (FieldNameLength != 1) { + return EFI_DEVICE_ERROR; + } + + for (Index = 0; Index < IDENT_LEN; Index++) { + if (*(FieldName + Index) != *((UINT8 *)Context->CurrentIdentifier + (IDENT_LEN - Index - 1))) { + Context->CurrentOpcode = FieldEnd; + Context->CurrentIdentifier -= 1; + CONTEXT_DECREASE_NESTING (Context); + return EFI_NOT_FOUND; + } + } + + if (Context->CurrentIdentifier + 1 != Context->PathEnd) { + Context->CurrentOpcode = FieldEnd; + Context->CurrentIdentifier -= 1; + CONTEXT_DECREASE_NESTING (Context); + return EFI_NOT_FOUND; + } + + Context->EntriesFound += 1; + + if (Context->EntriesFound != Context->RequiredEntry) { + Context->CurrentOpcode = FieldEnd; + Context->CurrentIdentifier -= 1; + CONTEXT_DECREASE_NESTING (Context); + return EFI_NOT_FOUND; + } + + *Result = FieldStart - 1; + return EFI_SUCCESS; +} + +EFI_STATUS +InternalAcpiParseTerm ( + IN OUT ACPI_PARSER_CONTEXT *Context, + OUT UINT8 **Result + ) +{ + EFI_STATUS Status; + + CONTEXT_ENTER (Context, "Term"); + CONTEXT_HAS_WORK (Context); + ASSERT (Result != NULL); + CONTEXT_INCREASE_NESTING (Context); + + DEBUG ((DEBUG_VERBOSE, "Opcode: %x\n", Context->CurrentOpcode[0])); + + switch (Context->CurrentOpcode[0]) { + case AML_ALIAS_OP: // Alias + CONTEXT_ADVANCE_OPCODE (Context); + Status = ParseAlias (Context); + break; + + case AML_SCOPE_OP: // Scope + CONTEXT_ADVANCE_OPCODE (Context); + Status = ParseScopeOrDevice (Context, Result); + break; + + case AML_NAME_OP: // Name + CONTEXT_ADVANCE_OPCODE (Context); + Status = ParseName (Context); + break; + + case AML_ZERO_OP: // ZeroOp + case AML_EXT_OP: // ExtOpPrefix + CONTEXT_ADVANCE_OPCODE (Context); + Status = EFI_NOT_FOUND; + break; + + case AML_EXT_BANK_FIELD_OP: // BankField + CONTEXT_ADVANCE_OPCODE (Context); + Status = ParseBankField (Context, Result); + break; + + case AML_CREATE_DWORD_FIELD_OP: // CreateDwordField + case AML_CREATE_WORD_FIELD_OP: // CreateWordField + case AML_CREATE_BYTE_FIELD_OP: // CreateByteField + case AML_CREATE_BIT_FIELD_OP: // CreateBitField + case AML_CREATE_QWORD_FIELD_OP: // CreateQWordField + case AML_EXT_CREATE_FIELD_OP: // CreateField + CONTEXT_ADVANCE_OPCODE (Context); + Status = ParseCreateField (Context, Result); + break; + + case AML_EXTERNAL_OP: // External + CONTEXT_ADVANCE_OPCODE (Context); + Status = ParseExternal (Context); + break; + + case AML_EXT_REGION_OP: // OpRegion + CONTEXT_ADVANCE_OPCODE (Context); + Status = ParseOpRegion (Context); + break; + + case AML_EXT_POWER_RES_OP: // PowerRes + CONTEXT_ADVANCE_OPCODE (Context); + Status = ParsePowerRes (Context); + break; + + case AML_EXT_PROCESSOR_OP: // Processor + CONTEXT_ADVANCE_OPCODE (Context); + Status = ParseProcessor (Context); + break; + + case AML_EXT_THERMAL_ZONE_OP: // ThermalZone + CONTEXT_ADVANCE_OPCODE (Context); + Status = ParseThermalZone (Context); + break; + + case AML_METHOD_OP: // Method + CONTEXT_ADVANCE_OPCODE (Context); + Status = ParseMethod (Context, Result); + break; + + case AML_IF_OP: // IfElse + CONTEXT_ADVANCE_OPCODE (Context); + Status = ParseIfElse (Context, Result); + break; + + case AML_EXT_DEVICE_OP: // Device + CONTEXT_ADVANCE_OPCODE (Context); + Status = ParseScopeOrDevice (Context, Result); + break; + + case AML_EXT_EVENT_OP: // Event + CONTEXT_ADVANCE_OPCODE (Context); + Status = ParseEvent (Context); + break; + + case AML_EXT_FIELD_OP: // Field + CONTEXT_ADVANCE_OPCODE (Context); + Status = ParseField (Context, Result); + break; + + case AML_EXT_INDEX_FIELD_OP: // IndexField + CONTEXT_ADVANCE_OPCODE (Context); + Status = ParseIndexField (Context, Result); + break; + + case AML_EXT_MUTEX_OP: // Mutex + CONTEXT_ADVANCE_OPCODE (Context); + Status = ParseMutex (Context); + break; + + default: + Status = EFI_DEVICE_ERROR; + break; + } + + CONTEXT_DECREASE_NESTING (Context); + return Status; +} + +/** + Translates one identifier to AML opcodes. Complements it with '_' + opcodes if identifier length is under 4. + + @param[in] Name Pointer to the start of the identifier. + @param[in] NameEnd Pointer to the end of the identifier. + @param[out] OpcodeName Identifier translated to opcodes. + + @retval EFI_SUCCESS Identifier was translated successfuly. + @retval EFI_INVALID_PARAMETER Identifier can't be translated to opcodes. +**/ +EFI_STATUS +TranslateNameToOpcodes ( + IN CONST CHAR8 *Name, + IN CONST CHAR8 *NameEnd, + OUT UINT32 *OpcodeName + ) +{ + UINT32 CurrentOpcode; + UINT8 NameLength; + UINT8 Index; + + CurrentOpcode = 0; + NameLength = (UINT8) (NameEnd - Name); + *OpcodeName = 0; + + if (NameLength > IDENT_LEN) { + return EFI_INVALID_PARAMETER; + } + + for (Index = 0; Index < IDENT_LEN; ++Index) { + if (Index < NameLength) { + if ((Name[Index] >= 'a') && (Name[Index] <= 'z')) { + CurrentOpcode = AML_NAME_CHAR_A + (Name[Index] - 'a'); + } else if ((Name[Index] >= 'A') && (Name[Index] <= 'Z')) { + CurrentOpcode = AML_NAME_CHAR_A + (Name[Index] - 'A'); + } else if ((Name[Index] >= '0') && (Name[Index] <= '9')) { + // AML_EXT_REVISION_OP == AML_NAME_INTEGER_0 + CurrentOpcode = AML_EXT_REVISION_OP + (Name[Index] - '0'); + } else if (Name[Index] == '_') { + CurrentOpcode = AML_NAME_CHAR__; + } else if (Name[Index] == '\\') { + *OpcodeName = 0; + return EFI_INVALID_PARAMETER; + } else { + *OpcodeName = 0; + return EFI_INVALID_PARAMETER; + } + } else { + CurrentOpcode = AML_NAME_CHAR__; + } + + *OpcodeName = *OpcodeName << OPCODE_LEN; + *OpcodeName |= CurrentOpcode; + } + + return EFI_SUCCESS; +} + +/** + Translates path (one or more identifiers) to AML opcodes. + + @param[in, out] Context Structure containing the parser context. + @param[in] PathString Original path. + + @retval EFI_SUCCESS Path was translated successfuly. + @retval EFI_INVALID_PARAMETER Path can't be translated to opcodes. +**/ +EFI_STATUS +GetOpcodeArray ( + IN OUT ACPI_PARSER_CONTEXT *Context, + IN CONST CHAR8 *PathString + ) +{ + EFI_STATUS Status; + UINT32 Index; + UINT32 PathLength; + CHAR8 *Walker; + CHAR8 *IdentifierStart; + CONST CHAR8 *PathStringEnd; + UINTN AsciiLength; + + ASSERT (Context != NULL); + ASSERT (PathString != NULL); + + if (PathString[0] == '\\') { + PathString += 1; + } + + AsciiLength = AsciiStrLen (PathString); + if (AsciiLength == 0) { + return EFI_INVALID_PARAMETER; + } + + PathLength = 0; + PathStringEnd = PathString + AsciiLength; + + for (Index = 0; Index < AsciiLength; Index++) { + if (PathString[Index] == '.') { + PathLength += 1; + } + } + + PathLength += 1; + Context->PathStart = (UINT32 *) AllocateZeroPool (sizeof (UINT32) * PathLength); + if (Context->PathStart == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Context->CurrentIdentifier = Context->PathStart; + Walker = (CHAR8 *) PathString; + IdentifierStart = (CHAR8 *) PathString; + + for (Index = 0; Index < PathLength; ++Index) { + while (*Walker != '.' && Walker < PathStringEnd) { + Walker++; + } + + if (Walker - IdentifierStart < 1) { + return EFI_INVALID_PARAMETER; + } + + Status = TranslateNameToOpcodes ( + IdentifierStart, + Walker, + (UINT32 *) (Context->CurrentIdentifier + Index) + ); + if (EFI_ERROR (Status)) { + return Status; + } + + ++Walker; + IdentifierStart = Walker; + } + + Context->PathEnd = Context->CurrentIdentifier + PathLength; + return EFI_SUCCESS; +} + + +/** + Initializes ACPI Context parser variable which stores ACPI header. + + @param[out] Context Address to a context structure, containing the parser context. +**/ +VOID +InitContext ( + OUT ACPI_PARSER_CONTEXT *Context + ) +{ + ASSERT (Context != NULL); + + ZeroMem (Context, sizeof (*Context)); +} + +/** + Deinitialises ACPI Context parser variable which stores ACPI header. + + @param[in,out] Context Address to a context structure, containing the parser context. +**/ +VOID +ClearContext ( + IN OUT ACPI_PARSER_CONTEXT *Context + ) +{ + if (Context->PathStart != NULL) { + FreePool (Context->PathStart); + Context->PathStart = NULL; + } + + ZeroMem (Context, sizeof (*Context)); +} + +EFI_STATUS +AcpiFindEntryInMemory ( + IN UINT8 *Table, + IN CONST CHAR8 *PathString, + IN UINT8 Entry, + OUT UINT32 *Offset, + IN UINT32 TableLength OPTIONAL + ) +{ + EFI_STATUS Status; + UINT8 *Result; + ACPI_PARSER_CONTEXT Context; + + ASSERT (Table != NULL); + ASSERT (PathString != NULL); + ASSERT (Offset != NULL); + + if (TableLength > 0) { + if (TableLength < sizeof (EFI_ACPI_COMMON_HEADER)) { + DEBUG ((DEBUG_VERBOSE, "OCA: Got bad table format which does not specify its length!\n")); + return EFI_LOAD_ERROR; + } + + // + // We do not check length here, mainly because TableLength > 0 is for fuzzing. + // + } else { + TableLength = ((EFI_ACPI_COMMON_HEADER *) Table)->Length; + } + + if (TableLength <= sizeof (EFI_ACPI_DESCRIPTION_HEADER)) { + DEBUG ((DEBUG_VERBOSE, "OCA: Bad or unsupported table header!\n")); + return EFI_DEVICE_ERROR; + } + + InitContext (&Context); + + Context.CurrentOpcode = Table; + Context.RequiredEntry = Entry; + Context.TableStart = Table; + Context.TableEnd = Table + TableLength; + Context.CurrentOpcode += sizeof (EFI_ACPI_DESCRIPTION_HEADER); + + Status = GetOpcodeArray ( + &Context, + PathString + ); + + if (EFI_ERROR (Status)) { + ClearContext (&Context); + return Status; + } + + while (Context.CurrentOpcode < Context.TableEnd) { + Status = InternalAcpiParseTerm (&Context, &Result); + + if (!EFI_ERROR (Status)) { + *Offset = (UINT32) (Result - Table); + ClearContext (&Context); + return EFI_SUCCESS; + } + + if (Status != EFI_NOT_FOUND) { + ClearContext (&Context); + return Status; + } + } + + ClearContext (&Context); + return EFI_NOT_FOUND; +} diff --git a/Library/OcAcpiLib/AcpiParser.h b/Library/OcAcpiLib/AcpiParser.h new file mode 100644 index 00000000000..d0c41df28ed --- /dev/null +++ b/Library/OcAcpiLib/AcpiParser.h @@ -0,0 +1,167 @@ +/** @file + Copyright (c) 2020-2021, Ubsefor & koralexa. All rights reserved. + SPDX-License-Identifier: BSD-3-Clause +**/ + +#ifndef ACPI_PARSER_H +#define ACPI_PARSER_H + +typedef struct { + /// + /// Currently processed opcode in ACPI table. + /// + UINT8 *CurrentOpcode; + /// + /// Pointer to the end of ACPI table. + /// + UINT8 *TableStart; + /// + /// Pointer to the end of ACPI table. + /// + UINT8 *TableEnd; + /// + /// Decoded lookup path allocated from pool. + /// Contains a sequence of parsed identifiers. + /// + UINT32 *PathStart; + /// + /// Identifier we need to match next. + /// Once it reaches PathEnd, matching is successful. + /// Requested number of matches is required to finish lookup. + /// + UINT32 *CurrentIdentifier; + /// + /// Pointer to the end of lookup path. + /// + UINT32 *PathEnd; + /// + /// Nesting level. Once it reaches MAX_NESTING the table is discarded. + /// + UINT32 Nesting; + /// + /// Number of entries to find. Generally 1 for first match success. + /// + UINT32 RequiredEntry; + /// + /// Number of entries already found. + /// + UINT32 EntriesFound; +} ACPI_PARSER_CONTEXT; + + +#define IDENT_LEN 4 +#define OPCODE_LEN 8 +#define MAX_NESTING 1024 + +/** + Print new entry name. +**/ +#define CONTEXT_ENTER(Context, Name) \ + DEBUG (( \ + DEBUG_VERBOSE, \ + "%a 0x%x (looking for %c%c%c%c)\n", \ + (Name), \ + (UINT32) ((Context)->CurrentOpcode - (Context)->TableStart), \ + ((CHAR8 *) (Context)->CurrentIdentifier)[3], \ + ((CHAR8 *) (Context)->CurrentIdentifier)[2], \ + ((CHAR8 *) (Context)->CurrentIdentifier)[1], \ + ((CHAR8 *) (Context)->CurrentIdentifier)[0] \ + )); + +#define PRINT_ACPI_NAME(Str, Name, Length) \ + DEBUG (( \ + DEBUG_VERBOSE, \ + "%a %u (%c%c%c%c)\n", \ + (Str), \ + (Length), \ + (Length) > 0 ? (Name)[((Length) - 1) * 4 + 0] : 'Z', \ + (Length) > 0 ? (Name)[((Length) - 1) * 4 + 1] : 'Z', \ + (Length) > 0 ? (Name)[((Length) - 1) * 4 + 2] : 'Z', \ + (Length) > 0 ? (Name)[((Length) - 1) * 4 + 3] : 'Z' \ + )); + +/** + Check that context is valid and has work to do. +**/ +#define CONTEXT_HAS_WORK(Context) do { \ + ASSERT ((Context) != NULL); \ + ASSERT ((Context)->CurrentOpcode != NULL); \ + ASSERT ((Context)->TableEnd != NULL); \ + ASSERT ((Context)->CurrentOpcode < (Context)->TableEnd); /* Must always have work to do. */ \ + ASSERT ((Context)->PathStart != NULL); \ + ASSERT ((Context)->PathEnd != NULL); \ + ASSERT ((Context)->CurrentIdentifier != NULL); \ + ASSERT ((Context)->CurrentIdentifier < (Context)->PathEnd); /* Must always have IDs to parse. */ \ + ASSERT ((Context)->RequiredEntry > 0); \ + ASSERT ((Context)->EntriesFound < (Context)->RequiredEntry); /* Must have entries to find. */ \ + } while (0) + +/** + Enter new nesting level. +**/ +#define CONTEXT_INCREASE_NESTING(Context) do { \ + ++(Context)->Nesting; \ + if ((Context)->Nesting > MAX_NESTING) { \ + return EFI_OUT_OF_RESOURCES; \ + } \ + } while (0) + +/** + Exit nesting level. + Does not need to be called on error-exit. +**/ +#define CONTEXT_DECREASE_NESTING(Context) do { \ + ASSERT ((Context)->Nesting > 0); \ + --(Context)->Nesting; \ + } while (0) + +/** + Check the specified amount of bytes exists. +**/ +#define CONTEXT_PEEK_BYTES(Context, Bytes) do { \ + if ((UINT32) ((Context)->TableEnd - (Context)->CurrentOpcode) < (UINT32) (Bytes)) { \ + return EFI_DEVICE_ERROR; \ + } \ + } while (0) + +/** + Consume the specified amount of bytes. +**/ +#define CONTEXT_CONSUME_BYTES(Context, Bytes) do { \ + if ((UINT32) ((Context)->TableEnd - (Context)->CurrentOpcode) < (UINT32) (Bytes)) { \ + return EFI_DEVICE_ERROR; \ + } \ + (Context)->CurrentOpcode += (Bytes); \ + } while (0) + +/** + Advance opcode to call the new parsing code. + This one will error as long as there is no new opcode, + i.e. one byte after the current one. +**/ +#define CONTEXT_ADVANCE_OPCODE(Context) do { \ + if ((UINT32) ((Context)->TableEnd - (Context)->CurrentOpcode) <= 1U) { \ + return EFI_DEVICE_ERROR; \ + } \ + ++(Context)->CurrentOpcode; \ + } while (0) + +/** + Determines which object to parse (depending on the opcode) + and calls the corresponding parser function. + + @param[in, out] Context Structure containing the parser context. + @param[out] Result Pointer to sought opcode if required entry was found. + + @retval EFI_SUCCESS Required entry was found (search complete). + @retval EFI_NOT_FOUND Required entry was not found (more terms need to be parsed). + @retval EFI_DEVICE_ERROR Error occured during parsing (must abort). + @retval EFI_OUT_OF_RESOURCES Nesting limit has been reached (must abort). + **/ +EFI_STATUS +InternalAcpiParseTerm ( + IN OUT ACPI_PARSER_CONTEXT *Context, + OUT UINT8 **Result + ); + +#endif // ACPI_PARSER_H diff --git a/Library/OcAcpiLib/OcAcpiLib.c b/Library/OcAcpiLib/OcAcpiLib.c index c242bbb3d8e..927f4b63345 100755 --- a/Library/OcAcpiLib/OcAcpiLib.c +++ b/Library/OcAcpiLib/OcAcpiLib.c @@ -1152,12 +1152,13 @@ AcpiApplyPatch ( ) { EFI_STATUS Status; + EFI_ACPI_COMMON_HEADER *NewTable; UINT32 Index; + UINT32 BaseOffset; UINT64 CurrOemTableId; UINT32 ReplaceCount; UINT32 ReplaceLimit; UINT32 TablePrintSignature; - EFI_ACPI_COMMON_HEADER *NewTable; DEBUG ((DEBUG_INFO, "OCA: Applying %u byte ACPI patch skip %u, count %u\n", Patch->Size, Patch->Skip, Patch->Count)); @@ -1165,9 +1166,32 @@ AcpiApplyPatch ( && (Patch->TableSignature == 0 || Patch->TableSignature == EFI_ACPI_6_2_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE) && (Patch->TableLength == 0 || Context->Dsdt->Length == Patch->TableLength) && (Patch->OemTableId == 0 || Context->Dsdt->OemTableId == Patch->OemTableId)) { - ReplaceLimit = Patch->Limit; - if (ReplaceLimit == 0) { - ReplaceLimit = Context->Dsdt->Length; + ReplaceLimit = Context->Dsdt->Length; + if (Patch->Limit > 0) { + ReplaceLimit = MIN (ReplaceLimit, Patch->Limit); + } + + BaseOffset = 0; + + if (Patch->Base != NULL && Patch->Base[0] != '\0') { + Status = AcpiFindEntryInMemory ( + (VOID *) Context->Dsdt, + Patch->Base, + (UINT8) (Patch->BaseSkip + 1), + &BaseOffset, + Context->Dsdt->Length + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_INFO, + "OCA: Patching DSDT of %u bytes failed to find base %a\n", + Context->Dsdt->Length, + Patch->Base + )); + return Status; + } + + ReplaceLimit = MIN (ReplaceLimit, Context->Dsdt->Length - BaseOffset); } if (!AcpiIsTableWritable ((EFI_ACPI_COMMON_HEADER *) Context->Dsdt)) { @@ -1183,7 +1207,7 @@ AcpiApplyPatch ( Patch->Size, Patch->Replace, Patch->ReplaceMask, - (UINT8 *) Context->Dsdt, + (UINT8 *) Context->Dsdt + BaseOffset, ReplaceLimit, Patch->Count, Patch->Skip @@ -1200,8 +1224,6 @@ AcpiApplyPatch ( if (ReplaceCount > 0) { AcpiRefreshTableChecksum (Context->Dsdt); - - } } @@ -1219,9 +1241,35 @@ AcpiApplyPatch ( continue; } - ReplaceLimit = Patch->Limit; - if (ReplaceLimit == 0) { - ReplaceLimit = Context->Tables[Index]->Length; + ReplaceLimit = Context->Tables[Index]->Length; + if (Patch->Limit > 0) { + ReplaceLimit = MIN (ReplaceLimit, Patch->Limit); + } + + BaseOffset = 0; + if (Patch->Base != NULL && Patch->Base[0] != '\0') { + Status = AcpiFindEntryInMemory ( + (VOID *) Context->Tables[Index], + Patch->Base, + (UINT8) (Patch->BaseSkip + 1), + &BaseOffset, + Context->Tables[Index]->Length + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_INFO, + "OCA: Patching %.4a (%08x) (OEM %016Lx) of %u bytes with %016Lx ID failed to find base %a\n", + (CHAR8 *) &TablePrintSignature, + Context->Tables[Index]->Signature, + AcpiReadOemTableId (Context->Tables[Index]), + Context->Tables[Index]->Length, + CurrOemTableId, + Patch->Base + )); + return Status; + } + + ReplaceLimit = MIN (ReplaceLimit, Context->Tables[Index]->Length - BaseOffset); } if (!AcpiIsTableWritable (Context->Tables[Index])) { @@ -1238,7 +1286,7 @@ AcpiApplyPatch ( Patch->Size, Patch->Replace, Patch->ReplaceMask, - (UINT8 *) Context->Tables[Index], + (UINT8 *) Context->Tables[Index] + BaseOffset, ReplaceLimit, Patch->Count, Patch->Skip diff --git a/Library/OcAcpiLib/OcAcpiLib.inf b/Library/OcAcpiLib/OcAcpiLib.inf index e1fa3e96a98..721cadfa193 100755 --- a/Library/OcAcpiLib/OcAcpiLib.inf +++ b/Library/OcAcpiLib/OcAcpiLib.inf @@ -33,6 +33,9 @@ [LibraryClasses] BaseLib + BaseMemoryLib + DebugLib + MemoryAllocationLib OcFileLib OcMemoryLib OcMiscLib @@ -44,4 +47,6 @@ [Sources] AcpiDump.c + AcpiParser.c + AcpiParser.h OcAcpiLib.c diff --git a/Library/OcConfigurationLib/OcConfigurationLib.c b/Library/OcConfigurationLib/OcConfigurationLib.c index d8874662e98..b4dbddf4211 100644 --- a/Library/OcConfigurationLib/OcConfigurationLib.c +++ b/Library/OcConfigurationLib/OcConfigurationLib.c @@ -118,6 +118,8 @@ mAcpiDeleteSchema = OC_SCHEMA_DICT (NULL, mAcpiDeleteSchemaEntry); STATIC OC_SCHEMA mAcpiPatchSchemaEntry[] = { + OC_SCHEMA_STRING_IN ("Base", OC_ACPI_PATCH_ENTRY, Base), + OC_SCHEMA_INTEGER_IN ("BaseSkip", OC_ACPI_PATCH_ENTRY, BaseSkip), OC_SCHEMA_STRING_IN ("Comment", OC_ACPI_PATCH_ENTRY, Comment), OC_SCHEMA_INTEGER_IN ("Count", OC_ACPI_PATCH_ENTRY, Count), OC_SCHEMA_BOOLEAN_IN ("Enabled", OC_ACPI_PATCH_ENTRY, Enabled), diff --git a/Library/OcMainLib/OpenCoreAcpi.c b/Library/OcMainLib/OpenCoreAcpi.c index f55c7ed4405..bed5183b55a 100644 --- a/Library/OcMainLib/OpenCoreAcpi.c +++ b/Library/OcMainLib/OpenCoreAcpi.c @@ -156,9 +156,10 @@ OcAcpiPatchTables ( // - Mask and ReplaceMask mismatch in size when are available. // if (UserPatch->Replace.Size == 0 - || UserPatch->Find.Size != UserPatch->Replace.Size + || (UserPatch->Find.Size > 0 && UserPatch->Find.Size != UserPatch->Replace.Size) + || (UserPatch->Find.Size == 0 && OC_BLOB_GET (&UserPatch->Base)[0] == '\0') || (UserPatch->Mask.Size > 0 && UserPatch->Find.Size != UserPatch->Mask.Size) - || (UserPatch->ReplaceMask.Size > 0 && UserPatch->Find.Size != UserPatch->ReplaceMask.Size)) { + || (UserPatch->ReplaceMask.Size > 0 && UserPatch->Replace.Size != UserPatch->ReplaceMask.Size)) { DEBUG ((DEBUG_ERROR, "OC: ACPI patch %u is borked\n", Index)); continue; } @@ -176,6 +177,8 @@ OcAcpiPatchTables ( Patch.ReplaceMask = OC_BLOB_GET (&UserPatch->ReplaceMask); } + Patch.Base = OC_BLOB_GET (&UserPatch->Base); + Patch.BaseSkip = UserPatch->BaseSkip; Patch.Size = UserPatch->Replace.Size; Patch.Count = UserPatch->Count; Patch.Skip = UserPatch->Skip; diff --git a/Utilities/ACPIe/ACPIe.c b/Utilities/ACPIe/ACPIe.c new file mode 100644 index 00000000000..f019974e234 --- /dev/null +++ b/Utilities/ACPIe/ACPIe.c @@ -0,0 +1,244 @@ +/** @file + Copyright (c) 2020-2021, Ubsefor & koralexa. All rights reserved. + SPDX-License-Identifier: BSD-3-Clause +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** + Prints description of error occured in the perser. + + @param[in] Status Error occured in the parser. +**/ +VOID +PrintParserError ( + IN EFI_STATUS Status + ) +{ + switch (Status) { + case EFI_SUCCESS: + break; + + case EFI_INVALID_PARAMETER: + printf ("EXIT: Invalid parameter!\n"); + break; + + case EFI_DEVICE_ERROR: + printf ("EXIT: ACPI table is incorrect or not supported by parser!\n"); + break; + + case EFI_NOT_FOUND: + printf ("EXIT: No entry found in the table.\n"); + break; + + case EFI_OUT_OF_RESOURCES: + printf ("EXIT: ACPI table has too much nesting!\n"); + break; + + case EFI_LOAD_ERROR: + printf ("EXIT: File error in table file!\n"); + break; + + default: + printf ("EXIT: Unknown error!\n"); + break; + } + + return; +} + +/** + Finds offset of required entry in ACPI table in case it exists. + + @param[in] FileName Path to file containing ACPI table. + @param[in] PathString Path to entry which must be found. + @param[in] Entry Number of entry which must be found. + @param[out] Offset Offset of the entry if it was found. + + @retval EFI_SUCCESS Required entry was found. + @retval EFI_NOT_FOUND Required entry was not found. + @retval EFI_DEVICE_ERROR Error occured during parsing ACPI table. + @retval EFI_OUT_OF_RESOURCES Nesting limit has been reached. + @retval EFI_INVALID_PARAMETER Got wrong path to the entry. + @retval EFI_LOAD_ERROR Wrong path to the file or the file can't + be opened. +**/ +EFI_STATUS +AcpiFindEntryInFile ( + IN CONST CHAR8 *FileName, + IN CONST CHAR8 *PathString, + IN UINT8 Entry, + OUT UINT32 *Offset + ) +{ + UINT8 *TableStart; + EFI_STATUS Status; + UINT32 TableLength; + + TableStart = UserReadFile (FileName, &TableLength); + if (TableStart == NULL) { + DEBUG ((DEBUG_INFO, "No file %a\n", FileName)); + return EFI_LOAD_ERROR; + } + + Status = AcpiFindEntryInMemory (TableStart, PathString, Entry, Offset, TableLength); + + FreePool(TableStart); + + return Status; +} + +// -[f|a] , CHAR8 ** memory_location , CHAR8 ** path , UINT8 occurance +/** + Finds sought entry in ACPI table. + Usage: + ./ACPIe -f FileName Path [Entry] + + @param[in] FileName Path to file with ACPI table. + @param[in] Path Path to required entry. + @param[in] Entry Number of required entry. + + **/ +INT32 +ENTRY_POINT ( + IN INT32 argc, + IN CONST CHAR8 *argv[] + ) // ENTRY_POINT + +{ + UINT32 ReturnedOffset; + EFI_STATUS Status; + +#if defined(VERBOSE) && !defined(FUZZING_TEST) + PcdGet32 (PcdFixedDebugPrintErrorLevel) |= DEBUG_VERBOSE | DEBUG_INFO; + PcdGet32 (PcdDebugPrintErrorLevel) |= DEBUG_VERBOSE | DEBUG_INFO; +#endif + + switch (argc) { + case 5: + + if ((argv[1][0] == '-' && argv[1][1] == 'f') || (argv[1][0] == '-' && argv[1][1] == 'a')) { + ReturnedOffset = 0; + + if (argv[1][0] == '-' && argv[1][1] == 'f') { + DEBUG ((DEBUG_VERBOSE, "Entered main (file)\n")); + Status = AcpiFindEntryInFile ( + argv[2], + argv[3], + atoi (argv[4]), + &ReturnedOffset + ); + + if (Status == EFI_SUCCESS) { + printf ("Returned offset: %d\n", ReturnedOffset); + } else { + PrintParserError (Status); + } + + return 0; + } else { + DEBUG ((DEBUG_VERBOSE, "Entered main (address)\n")); + Status = AcpiFindEntryInFile ( + argv[2], + argv[3], + atoi (argv[4]), + &ReturnedOffset + ); + + if (Status == EFI_SUCCESS) { + printf ("Returned offset: %d\n", ReturnedOffset); + } else { + PrintParserError (Status); + } + + return 0; + } + } else { + printf ("Usage: ACPIe -f *file* *search path* [number of occurance]\n"); + return 2; + } + + break; + + case 4: + + if ((argv[1][0] == '-' && argv[1][1] == 'f') || (argv[1][0] == '-' && argv[1][1] == 'a')) { + + if (argv[1][0] == '-' && argv[1][1] == 'f') { + DEBUG ((DEBUG_VERBOSE, "Entered main (file)\n")); + Status = AcpiFindEntryInFile ( + argv[2], + argv[3], + 1, + &ReturnedOffset + ); + + if (Status == EFI_SUCCESS) { + printf ("Returned offset: %d\n", ReturnedOffset); + } else { + PrintParserError (Status); + } + + return 0; + } else { + DEBUG ((DEBUG_VERBOSE, "Entered main (address)\n")); + Status = AcpiFindEntryInFile ( + argv[2], + argv[3], + 1, + &ReturnedOffset + ); + + if (Status == EFI_SUCCESS) { + printf ("Returned offset: %d\n", ReturnedOffset); + } else { + PrintParserError (Status); + } + + return 0; + } + } else { + printf ("Usage: ACPIe -f *file* *search path* [number of occurance]\n"); + return 2; + } + + break; + + default: + printf ("Usage: ACPIe -f *file* *search path* [number of occurance]\n"); + return 0; + + break; + } + + return 0; +} +INT32 +LLVMFuzzerTestOneInput ( + CONST UINT8 *Data, + UINTN Size + ) +{ + if (Size > 0) { + UINT32 offset = 0; + AcpiFindEntryInMemory ( + (UINT8 *)Data, "_SB.PCI0.GFX0", + 1, + &offset, + (UINT32) Size + ); + } + + return 0; +} diff --git a/Utilities/ACPIe/Makefile b/Utilities/ACPIe/Makefile new file mode 100644 index 00000000000..100d4a41222 --- /dev/null +++ b/Utilities/ACPIe/Makefile @@ -0,0 +1,15 @@ +## @file +# Copyright (c) 2020, Ubsefor, koralexa. All rights reserved. +# SPDX-License-Identifier: BSD-3-Clause +## + +PROJECT = ACPIe +PRODUCT = $(PROJECT)$(SUFFIX) +OBJS = $(PROJECT).o AcpiParser.o +VPATH = ../../Library/OcAcpiLib:$ + +include ../../User/Makefile + +ifeq ($(DEBUG),1) + CFLAGS += -DVERBOSE +endif diff --git a/Utilities/ACPIe/Tests/Correct/test100_output.txt b/Utilities/ACPIe/Tests/Correct/test100_output.txt new file mode 100644 index 00000000000..7e7dd698e3b --- /dev/null +++ b/Utilities/ACPIe/Tests/Correct/test100_output.txt @@ -0,0 +1 @@ +This one needs to be fixed, an assertion happens here. diff --git a/Utilities/ACPIe/Tests/Correct/test10_output.txt b/Utilities/ACPIe/Tests/Correct/test10_output.txt new file mode 100644 index 00000000000..5b3f0077900 --- /dev/null +++ b/Utilities/ACPIe/Tests/Correct/test10_output.txt @@ -0,0 +1 @@ +EXIT: File error in table file! diff --git a/Utilities/ACPIe/Tests/Correct/test11_output.txt b/Utilities/ACPIe/Tests/Correct/test11_output.txt new file mode 100644 index 00000000000..e06dd13dbb5 --- /dev/null +++ b/Utilities/ACPIe/Tests/Correct/test11_output.txt @@ -0,0 +1 @@ +EXIT: ACPI table is incorrect or not supported by parser! diff --git a/Utilities/ACPIe/Tests/Correct/test12_output.txt b/Utilities/ACPIe/Tests/Correct/test12_output.txt new file mode 100644 index 00000000000..527cc6cb08c --- /dev/null +++ b/Utilities/ACPIe/Tests/Correct/test12_output.txt @@ -0,0 +1 @@ +Returned offset: 71745 diff --git a/Utilities/ACPIe/Tests/Correct/test13_output.txt b/Utilities/ACPIe/Tests/Correct/test13_output.txt new file mode 100644 index 00000000000..8b4c99f0d67 --- /dev/null +++ b/Utilities/ACPIe/Tests/Correct/test13_output.txt @@ -0,0 +1 @@ +Returned offset: 179803 diff --git a/Utilities/ACPIe/Tests/Correct/test14_output.txt b/Utilities/ACPIe/Tests/Correct/test14_output.txt new file mode 100644 index 00000000000..4bcb8b9b17f --- /dev/null +++ b/Utilities/ACPIe/Tests/Correct/test14_output.txt @@ -0,0 +1 @@ +Returned offset: 15593 diff --git a/Utilities/ACPIe/Tests/Correct/test15_output.txt b/Utilities/ACPIe/Tests/Correct/test15_output.txt new file mode 100644 index 00000000000..e06dd13dbb5 --- /dev/null +++ b/Utilities/ACPIe/Tests/Correct/test15_output.txt @@ -0,0 +1 @@ +EXIT: ACPI table is incorrect or not supported by parser! diff --git a/Utilities/ACPIe/Tests/Correct/test16_output.txt b/Utilities/ACPIe/Tests/Correct/test16_output.txt new file mode 100644 index 00000000000..30a973d0f18 --- /dev/null +++ b/Utilities/ACPIe/Tests/Correct/test16_output.txt @@ -0,0 +1 @@ +Returned offset: 75 diff --git a/Utilities/ACPIe/Tests/Correct/test17_output.txt b/Utilities/ACPIe/Tests/Correct/test17_output.txt new file mode 100644 index 00000000000..3000e872764 --- /dev/null +++ b/Utilities/ACPIe/Tests/Correct/test17_output.txt @@ -0,0 +1 @@ +Returned offset: 5462 diff --git a/Utilities/ACPIe/Tests/Correct/test18_output.txt b/Utilities/ACPIe/Tests/Correct/test18_output.txt new file mode 100644 index 00000000000..6b185adeb82 --- /dev/null +++ b/Utilities/ACPIe/Tests/Correct/test18_output.txt @@ -0,0 +1 @@ +Returned offset: 22728 diff --git a/Utilities/ACPIe/Tests/Correct/test19_output.txt b/Utilities/ACPIe/Tests/Correct/test19_output.txt new file mode 100644 index 00000000000..b74decaa693 --- /dev/null +++ b/Utilities/ACPIe/Tests/Correct/test19_output.txt @@ -0,0 +1 @@ +Returned offset: 10009 diff --git a/Utilities/ACPIe/Tests/Correct/test1_output.txt b/Utilities/ACPIe/Tests/Correct/test1_output.txt new file mode 100644 index 00000000000..f9f42832b8f --- /dev/null +++ b/Utilities/ACPIe/Tests/Correct/test1_output.txt @@ -0,0 +1 @@ +Returned offset: 121 diff --git a/Utilities/ACPIe/Tests/Correct/test20_output.txt b/Utilities/ACPIe/Tests/Correct/test20_output.txt new file mode 100644 index 00000000000..e8c846b7b34 --- /dev/null +++ b/Utilities/ACPIe/Tests/Correct/test20_output.txt @@ -0,0 +1 @@ +EXIT: No entry found in the table. diff --git a/Utilities/ACPIe/Tests/Correct/test2_output.txt b/Utilities/ACPIe/Tests/Correct/test2_output.txt new file mode 100644 index 00000000000..e8c846b7b34 --- /dev/null +++ b/Utilities/ACPIe/Tests/Correct/test2_output.txt @@ -0,0 +1 @@ +EXIT: No entry found in the table. diff --git a/Utilities/ACPIe/Tests/Correct/test3_output.txt b/Utilities/ACPIe/Tests/Correct/test3_output.txt new file mode 100644 index 00000000000..4cae20303d8 --- /dev/null +++ b/Utilities/ACPIe/Tests/Correct/test3_output.txt @@ -0,0 +1 @@ +Returned offset: 3878 diff --git a/Utilities/ACPIe/Tests/Correct/test4_output.txt b/Utilities/ACPIe/Tests/Correct/test4_output.txt new file mode 100644 index 00000000000..199aa995865 --- /dev/null +++ b/Utilities/ACPIe/Tests/Correct/test4_output.txt @@ -0,0 +1 @@ +Returned offset: 385 diff --git a/Utilities/ACPIe/Tests/Correct/test5_output.txt b/Utilities/ACPIe/Tests/Correct/test5_output.txt new file mode 100644 index 00000000000..a6d05b1c5fa --- /dev/null +++ b/Utilities/ACPIe/Tests/Correct/test5_output.txt @@ -0,0 +1 @@ +Returned offset: 281 diff --git a/Utilities/ACPIe/Tests/Correct/test6_output.txt b/Utilities/ACPIe/Tests/Correct/test6_output.txt new file mode 100644 index 00000000000..a6d05b1c5fa --- /dev/null +++ b/Utilities/ACPIe/Tests/Correct/test6_output.txt @@ -0,0 +1 @@ +Returned offset: 281 diff --git a/Utilities/ACPIe/Tests/Correct/test7_output.txt b/Utilities/ACPIe/Tests/Correct/test7_output.txt new file mode 100644 index 00000000000..391c26f28e0 --- /dev/null +++ b/Utilities/ACPIe/Tests/Correct/test7_output.txt @@ -0,0 +1 @@ +Returned offset: 8797 diff --git a/Utilities/ACPIe/Tests/Correct/test8_output.txt b/Utilities/ACPIe/Tests/Correct/test8_output.txt new file mode 100644 index 00000000000..7f9679934d1 --- /dev/null +++ b/Utilities/ACPIe/Tests/Correct/test8_output.txt @@ -0,0 +1 @@ +EXIT: Invalid parameter! diff --git a/Utilities/ACPIe/Tests/Correct/test9_output.txt b/Utilities/ACPIe/Tests/Correct/test9_output.txt new file mode 100644 index 00000000000..7f9679934d1 --- /dev/null +++ b/Utilities/ACPIe/Tests/Correct/test9_output.txt @@ -0,0 +1 @@ +EXIT: Invalid parameter! diff --git a/Utilities/ACPIe/Tests/Input/DSDT-legacy.bin b/Utilities/ACPIe/Tests/Input/DSDT-legacy.bin new file mode 100755 index 0000000000000000000000000000000000000000..5ec1d590a4d83013d1c2fc228f59377881468058 GIT binary patch literal 41094 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 J@NKHY{}0Hje1-r3 literal 0 HcmV?d00001 diff --git a/Utilities/ACPIe/Tests/Input/DSDT.bin b/Utilities/ACPIe/Tests/Input/DSDT.bin new file mode 100644 index 0000000000000000000000000000000000000000..39ecb181229c8889f961225f1037073ab04b9f5f GIT binary patch literal 180054 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%0D$ZyS;eqPIfM%aZn3#Yn>3&6{oYCAA?#@J%Jnl@ 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 TKpY?`H!DL*Zq@=Iz5&Dlb2u*n literal 0 HcmV?d00001 diff --git a/Utilities/ACPIe/Tests/Input/SSDT-0.bin b/Utilities/ACPIe/Tests/Input/SSDT-0.bin new file mode 100644 index 0000000000000000000000000000000000000000..4087234a4fa14f694162d124c7ccd68f1f196172 GIT binary patch literal 857 zcmb`E%}T>S6oqd|Oyek$V&Ycu1x)$_UD{+iHPF=1nT0=vq=KN}B8Z|JUqD<4zCeY( zfREr4xpHq#lZ8m!C5z#lZ|0uKy(1-8ry5aXOV01+(@U&sesMzcqxz-Iaa zcAGY6;JRLRg{|xw`W{u*c=yk^OcilAzr%ippg25sSBmL88kEw^saMd=oR-oGjwZrx zCnFV6#vW0bF&kBd^9tuZ;T&7Ty2Kr}kw_J3R;c4)@}}|xK^fuy7Ol6{tD;W~iy7}5 fr5-W^3L_&3%!-!iwn*}7OX}2?)U7S4S3}YdpkdDe literal 0 HcmV?d00001 diff --git a/Utilities/ACPIe/Tests/Input/SSDT-1.bin b/Utilities/ACPIe/Tests/Input/SSDT-1.bin new file mode 100644 index 0000000000000000000000000000000000000000..62298b96b99001ea4931b1329bace1cf201682b5 GIT binary patch literal 27635 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 literal 0 HcmV?d00001 diff --git a/Utilities/ACPIe/Tests/Input/SSDT-x4_0.bin b/Utilities/ACPIe/Tests/Input/SSDT-x4_0.bin new file mode 100644 index 0000000000000000000000000000000000000000..51df5e3a1132f17447567ce20f308f3b728ec491 GIT binary patch literal 1485 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 literal 0 HcmV?d00001 diff --git a/Utilities/ACPIe/Tests/Output/test100_output.txt b/Utilities/ACPIe/Tests/Output/test100_output.txt new file mode 100644 index 00000000000..e69de29bb2d diff --git a/Utilities/ACPIe/testsuite.sh b/Utilities/ACPIe/testsuite.sh new file mode 100755 index 00000000000..024b61ccf38 --- /dev/null +++ b/Utilities/ACPIe/testsuite.sh @@ -0,0 +1,182 @@ +#!/bin/bash + +make clean; +echo "Silently recompiling" +SANITIZE=1 make -j8 > /dev/zero || exit 1; +echo "Done!" + +rm -rf Tests/Output || exit 1 +mkdir -p Tests/Output || exit 1 + +code=0 + +printf "%s" "Test_1(Tests/Input/SSDT-x4_0.bin, \\_PR.PR00._PPC, 1): " +./ACPIe -f Tests/Input/SSDT-x4_0.bin \\_PR.PR00._PPC 1 > Tests/Output/test1_output.txt +diff -q Tests/Output/test1_output.txt Tests/Correct/test1_output.txt +if (($? == 1)) +then echo FAIL && code=1 +else (echo OK; rm -f Tests/Output/test1_output.txt) +fi + +printf "%s" "Test_2(Tests/Input/SSDT-x4_0.bin, \\_PR.PR00._PPC, 2): " +./ACPIe -f Tests/Input/SSDT-x4_0.bin \\_PR.PR00._PPC 2 > Tests/Output/test2_output.txt +diff -q Tests/Output/test2_output.txt Tests/Correct/test2_output.txt +if (($? == 1)) +then echo FAIL && code=1 +else (echo OK; rm -f Tests/Output/test2_output.txt) +fi + +printf "%s" "Test_3(Tests/Input/SSDT-1.bin, \\_SB.IETM._STA, 1): " +./ACPIe -f Tests/Input/SSDT-1.bin \\_SB.IETM._STA 1 > Tests/Output/test3_output.txt +diff -q Tests/Output/test3_output.txt Tests/Correct/test3_output.txt +if (($? == 1)) +then echo FAIL && code=1 +else (echo OK; rm -f Tests/Output/test3_output.txt) +fi + +printf "%s" "Test_4(Tests/Input/SSDT-0.bin, \\_SB.PCI0.SAT0.TMD0.DMA0, 1): " +./ACPIe -f Tests/Input/SSDT-0.bin \\_SB.PCI0.SAT0.TMD0.DMA0 1 > Tests/Output/test4_output.txt +diff -q Tests/Output/test4_output.txt Tests/Correct/test4_output.txt +if (($? == 1)) +then echo FAIL && code=1 +else (echo OK; rm -f Tests/Output/test4_output.txt) +fi + +printf "%s" "Test_5(Tests/Input/SSDT-0.bin, GTFB, 1): " +./ACPIe -f Tests/Input/SSDT-0.bin GTFB 1 > Tests/Output/test5_output.txt +diff -q Tests/Output/test5_output.txt Tests/Correct/test5_output.txt +if (($? == 1)) +then echo FAIL && code=1 +else (echo OK; rm -f Tests/Output/test5_output.txt) +fi + +printf "%s" "Test_6(Tests/Input/SSDT-0.bin, \\GTFB, 1): " +./ACPIe -f Tests/Input/SSDT-0.bin \\GTFB 1 > Tests/Output/test6_output.txt +diff -q Tests/Output/test6_output.txt Tests/Correct/test6_output.txt +if (($? == 1)) +then echo FAIL && code=1 +else (echo OK; rm -f Tests/Output/test6_output.txt) +fi + +printf "%s" "Test_7(Tests/Input/DSDT.bin, \\PSM.DPLC, 1): " +./ACPIe -f Tests/Input/DSDT.bin \\PSM.DPLC 1 > Tests/Output/test7_output.txt +diff -q Tests/Output/test7_output.txt Tests/Correct/test7_output.txt +if (($? == 1)) +then echo FAIL && code=1 +else (echo OK; rm -f Tests/Output/test7_output.txt) +fi + +printf "%s" "Test_8(Tests/Input/DSDT.bin, \\_SB.ABC..AHJK, 1): " +./ACPIe -f Tests/Input/DSDT.bin \\_SB.ABC..AHJK 1 > Tests/Output/test8_output.txt +diff -q Tests/Output/test8_output.txt Tests/Correct/test8_output.txt +if (($? == 1)) +then echo FAIL && code=1 +else (echo OK; rm -f Tests/Output/test8_output.txt) +fi + +printf "%s" "Test_9(Tests/Input/DSDT.bin, ..\\.., 1): " +./ACPIe -f Tests/Input/DSDT.bin ..\\.. 1 > Tests/Output/test9_output.txt +diff -q Tests/Output/test9_output.txt Tests/Correct/test9_output.txt +if (($? == 1)) +then echo FAIL && code=1 +else (echo OK; rm -f Tests/Output/test9_output.txt) +fi + +printf "%s" "Test_10(Tests/Input/ABCD.bin, \\_SB.PCI0.SAT0.TMD0.DMA0, 1): " +./ACPIe -f Tests/Input/ABCD.bin \\_SB.PCI0.SAT0.TMD0.DMA0 1 > Tests/Output/test10_output.txt +diff -q Tests/Output/test10_output.txt Tests/Correct/test10_output.txt +if (($? == 1)) +then echo FAIL && code=1 +else (echo OK; rm -f Tests/Output/test10_output.txt) +fi + +printf "%s" "Test_11(Tests/Input/RSDT.bin, \\_SB.PCI0, 1): " +./ACPIe -f Tests/Input/RSDT.bin \\_SB.PCI0 1 > Tests/Output/test11_output.txt +diff -q Tests/Output/test11_output.txt Tests/Correct/test11_output.txt +if (($? == 1)) +then echo FAIL && code=1 +else (echo OK; rm -f Tests/Output/test11_output.txt) +fi + +printf "%s" "Test_12(Tests/Input/DSDT.bin, \\MBAR, 1): " +./ACPIe -f Tests/Input/DSDT.bin \\MBAR 1 > Tests/Output/test12_output.txt +diff -q Tests/Output/test12_output.txt Tests/Correct/test12_output.txt +if (($? == 1)) +then echo FAIL && code=1 +else (echo OK; rm -f Tests/Output/test12_output.txt) +fi + +printf "%s" "Test_13(Tests/Input/DSDT.bin, _SB.PCI0.I2C1.ETPD._HID, 1): " +./ACPIe -f Tests/Input/DSDT.bin _SB.PCI0.I2C1.ETPD._HID 1 > Tests/Output/test13_output.txt +diff -q Tests/Output/test13_output.txt Tests/Correct/test13_output.txt +if (($? == 1)) +then echo FAIL && code=1 +else (echo OK; rm -f Tests/Output/test13_output.txt) +fi + +printf "%s" "Test_14(Tests/Input/DSDT.bin, _SB_.PCI0.B0D4._DSM, 1): " +./ACPIe -f Tests/Input/DSDT.bin _SB_.PCI0.B0D4._DSM > Tests/Output/test14_output.txt +diff -q Tests/Output/test14_output.txt Tests/Correct/test14_output.txt +if (($? == 1)) +then echo FAIL && code=1 +else (echo OK; rm -f Tests/Output/test14_output.txt) +fi + +printf "%s" "Test_15(Tests/Input/corrupt1.bin, _SB.PCI0.GFX0, 1): " +./ACPIe -f Tests/Input/corrupt1.bin _SB.PCI0.GFX0 > Tests/Output/test15_output.txt +diff -q Tests/Output/test15_output.txt Tests/Correct/test15_output.txt +if (($? == 1)) +then echo FAIL && code=1 +else (echo OK; rm -f Tests/Output/test15_output.txt) +fi + +printf "%s" "Test_16(Tests/Input/nesting.bin, _SB.PCI0.GFX0, 1): " +./ACPIe -f Tests/Input/nesting.bin _SB.PCI0.GFX0 > Tests/Output/test16_output.txt +diff -q Tests/Output/test16_output.txt Tests/Correct/test16_output.txt +if (($? == 1)) +then echo FAIL && code=1 +else (echo OK; rm -f Tests/Output/test16_output.txt) +fi + +printf "%s" "Test_17(Tests/Input/DSDT-legacy.bin, _SB.PCI0.GFX0, 1): " +./ACPIe -f Tests/Input/DSDT-legacy.bin \\_SB.PCI0.SBRG > Tests/Output/test17_output.txt +diff -q Tests/Output/test17_output.txt Tests/Correct/test17_output.txt +if (($? == 1)) +then echo FAIL && code=1 +else (echo OK; rm -f Tests/Output/test17_output.txt) +fi + +printf "%s" "Test_18(Tests/Input/DSDT-legacy.bin, \\_SB.PCI0.P0P9, 1): " +./ACPIe -f Tests/Input/DSDT-legacy.bin \\_SB.PCI0.P0P9 > Tests/Output/test18_output.txt +diff -q Tests/Output/test18_output.txt Tests/Correct/test18_output.txt +if (($? == 1)) +then echo FAIL && code=1 +else (echo OK; rm -f Tests/Output/test18_output.txt) +fi + +printf "%s" "Test_19(Tests/Input/DSDT-legacy.bin, \\HPET, 1): " +./ACPIe -f Tests/Input/DSDT-legacy.bin \\HPET > Tests/Output/test19_output.txt +diff -q Tests/Output/test19_output.txt Tests/Correct/test19_output.txt +if (($? == 1)) +then echo FAIL && code=1 +else (echo OK; rm -f Tests/Output/test19_output.txt) +fi + +printf "%s" "Test_20(Tests/Input/DSDT-legacy.bin, \\_SB.PCI0.SBRG.HPET, 1): " +./ACPIe -f Tests/Input/DSDT-legacy.bin \\_SB.PCI0.SBRG.HPET > Tests/Output/test20_output.txt +diff -q Tests/Output/test20_output.txt Tests/Output/test20_output.txt +if (($? == 1)) +then echo FAIL && code=1 +else (echo OK; rm -f Tests/Output/test20_output.txt) +fi + +printf "%s" "Test_100(Tests/Input/broken3.bin, \\_SB.PCI0.GFX0, 1): " +./ACPIe -f Tests/Input/broken3.bin \\_SB.PCI0.GFX0 > Tests/Output/test100_output.txt +diff -q Tests/Output/test100_output.txt Tests/Correct/test100_output.txt +if (($? == 1)) +then echo FAIL && code=1 +else (echo OK; rm -f Tests/Output/test100_output.txt) +fi + + +exit $code diff --git a/build_oc.tool b/build_oc.tool index 96f247faa79..ec293f85588 100755 --- a/build_oc.tool +++ b/build_oc.tool @@ -3,6 +3,7 @@ buildutil() { UTILS=( "AppleEfiSignTool" + "ACPIe" "EfiResTool" "LogoutHook" "acdtinfo" @@ -219,6 +220,7 @@ package() { done utils=( + "ACPIe" "acdtinfo" "macserial" "ocpasswordgen"