1 /** @file
2   ACPI table parser
3 
4   Copyright (c) 2016 - 2020, ARM Limited. All rights reserved.
5   SPDX-License-Identifier: BSD-2-Clause-Patent
6 
7   @par Glossary:
8     - Sbbr or SBBR   - Server Base Boot Requirements
9 
10   @par Reference(s):
11     - Arm Server Base Boot Requirements 1.2, September 2019
12 **/
13 
14 #include <Uefi.h>
15 #include <IndustryStandard/Acpi.h>
16 #include <Library/UefiLib.h>
17 #include "AcpiParser.h"
18 #include "AcpiTableParser.h"
19 #include "AcpiView.h"
20 #include "AcpiViewConfig.h"
21 
22 #if defined(MDE_CPU_ARM) || defined (MDE_CPU_AARCH64)
23 #include "Arm/SbbrValidator.h"
24 #endif
25 
26 /**
27   A list of registered ACPI table parsers.
28 **/
29 STATIC ACPI_TABLE_PARSER mTableParserList[MAX_ACPI_TABLE_PARSERS];
30 
31 /**
32   Register the ACPI table Parser
33 
34   This function registers the ACPI table parser.
35 
36   @param [in] Signature   The ACPI table signature.
37   @param [in] ParserProc  The ACPI table parser.
38 
39   @retval EFI_SUCCESS           The parser is registered.
40   @retval EFI_INVALID_PARAMETER A parameter is invalid.
41   @retval EFI_ALREADY_STARTED   The parser for the Table
42                                 was already registered.
43   @retval EFI_OUT_OF_RESOURCES  No space to register the
44                                 parser.
45 **/
46 EFI_STATUS
47 EFIAPI
RegisterParser(IN UINT32 Signature,IN PARSE_ACPI_TABLE_PROC ParserProc)48 RegisterParser (
49   IN  UINT32                  Signature,
50   IN  PARSE_ACPI_TABLE_PROC   ParserProc
51   )
52 {
53   UINT32 Index;
54 
55   if ((ParserProc == NULL) || (Signature == ACPI_PARSER_SIGNATURE_NULL)) {
56     return EFI_INVALID_PARAMETER;
57   }
58 
59   // Search if a parser is already installed
60   for (Index = 0;
61        Index < (sizeof (mTableParserList) / sizeof (mTableParserList[0]));
62        Index++)
63   {
64     if (Signature == mTableParserList[Index].Signature) {
65       if (mTableParserList[Index].Parser != NULL) {
66         return EFI_ALREADY_STARTED;
67       }
68     }
69   }
70 
71   // Find the first free slot and register the parser
72   for (Index = 0;
73       Index < (sizeof (mTableParserList) / sizeof (mTableParserList[0]));
74       Index++)
75   {
76     if (mTableParserList[Index].Signature == ACPI_PARSER_SIGNATURE_NULL) {
77       mTableParserList[Index].Signature = Signature;
78       mTableParserList[Index].Parser = ParserProc;
79       return EFI_SUCCESS;
80     }
81   }
82 
83   // No free slot found
84   return EFI_OUT_OF_RESOURCES;
85 }
86 
87 /**
88   Deregister the ACPI table Parser
89 
90   This function deregisters the ACPI table parser.
91 
92   @param [in] Signature   The ACPI table signature.
93 
94   @retval EFI_SUCCESS           The parser was deregistered.
95   @retval EFI_INVALID_PARAMETER A parameter is invalid.
96   @retval EFI_NOT_FOUND         A registered parser was not found.
97 **/
98 EFI_STATUS
99 EFIAPI
DeregisterParser(IN UINT32 Signature)100 DeregisterParser (
101   IN  UINT32                  Signature
102   )
103 {
104   UINT32 Index;
105 
106   if (Signature == ACPI_PARSER_SIGNATURE_NULL) {
107     return EFI_INVALID_PARAMETER;
108   }
109 
110   for (Index = 0;
111        Index < (sizeof (mTableParserList) / sizeof (mTableParserList[0]));
112        Index++)
113   {
114     if (Signature == mTableParserList[Index].Signature) {
115       mTableParserList[Index].Signature = ACPI_PARSER_SIGNATURE_NULL;
116       mTableParserList[Index].Parser = NULL;
117       return EFI_SUCCESS;
118     }
119   }
120 
121   // No matching registered parser found.
122   return EFI_NOT_FOUND;
123 }
124 
125 /**
126   Get the ACPI table Parser
127 
128   This function returns the ACPI table parser proc from the list of
129   registered parsers.
130 
131   @param [in]  Signature   The ACPI table signature.
132   @param [out] ParserProc  Pointer to a ACPI table parser proc.
133 
134   @retval EFI_SUCCESS           The parser was returned successfully.
135   @retval EFI_INVALID_PARAMETER A parameter is invalid.
136   @retval EFI_NOT_FOUND         A registered parser was not found.
137 **/
138 EFI_STATUS
139 EFIAPI
GetParser(IN UINT32 Signature,OUT PARSE_ACPI_TABLE_PROC * ParserProc)140 GetParser (
141   IN  UINT32                   Signature,
142   OUT PARSE_ACPI_TABLE_PROC *  ParserProc
143   )
144 {
145   UINT32 Index;
146 
147   if ((ParserProc == NULL) || (Signature == ACPI_PARSER_SIGNATURE_NULL)) {
148     return EFI_INVALID_PARAMETER;
149   }
150 
151   for (Index = 0;
152        Index < (sizeof (mTableParserList) / sizeof (mTableParserList[0]));
153        Index++)
154   {
155     if (Signature == mTableParserList[Index].Signature) {
156       *ParserProc = mTableParserList[Index].Parser;
157       return EFI_SUCCESS;
158     }
159   }
160 
161   // No matching registered parser found.
162   return EFI_NOT_FOUND;
163 }
164 
165 /**
166   This function processes the ACPI tables.
167   This function calls ProcessTableReportOptions() to list the ACPI
168   tables, perform binary dump of the tables and determine if the
169   ACPI fields should be traced.
170 
171   This function also invokes the parser for the ACPI tables.
172 
173   This function also performs a RAW dump of the ACPI table including
174   the unknown/unparsed ACPI tables and validates the checksum.
175 
176   @param [in] Ptr                Pointer to the start of the ACPI
177                                  table data buffer.
178 **/
179 VOID
180 EFIAPI
ProcessAcpiTable(IN UINT8 * Ptr)181 ProcessAcpiTable (
182   IN UINT8* Ptr
183   )
184 {
185   EFI_STATUS    Status;
186   BOOLEAN       Trace;
187   CONST UINT32* AcpiTableSignature;
188   CONST UINT32* AcpiTableLength;
189   CONST UINT8*  AcpiTableRevision;
190   CONST UINT8*  SignaturePtr;
191   PARSE_ACPI_TABLE_PROC ParserProc;
192 
193   ParseAcpiHeader (
194     Ptr,
195     &AcpiTableSignature,
196     &AcpiTableLength,
197     &AcpiTableRevision
198     );
199 
200   Trace = ProcessTableReportOptions (
201             *AcpiTableSignature,
202             Ptr,
203             *AcpiTableLength
204             );
205 
206   if (Trace) {
207     DumpRaw (Ptr, *AcpiTableLength);
208 
209     // Do not process the ACPI table any further if the table length read
210     // is invalid. The ACPI table should at least contain the table header.
211     if (*AcpiTableLength < sizeof (EFI_ACPI_DESCRIPTION_HEADER)) {
212       SignaturePtr = (CONST UINT8*)AcpiTableSignature;
213       IncrementErrorCount ();
214       Print (
215         L"ERROR: Invalid %c%c%c%c table length. Length = %d\n",
216         SignaturePtr[0],
217         SignaturePtr[1],
218         SignaturePtr[2],
219         SignaturePtr[3],
220         *AcpiTableLength
221         );
222       return;
223     }
224 
225     if (GetConsistencyChecking ()) {
226       VerifyChecksum (TRUE, Ptr, *AcpiTableLength);
227     }
228   }
229 
230 #if defined(MDE_CPU_ARM) || defined (MDE_CPU_AARCH64)
231   if (GetMandatoryTableValidate ()) {
232     ArmSbbrIncrementTableCount (*AcpiTableSignature);
233   }
234 #endif
235 
236   Status = GetParser (*AcpiTableSignature, &ParserProc);
237   if (EFI_ERROR (Status)) {
238     // No registered parser found, do default handling.
239     if (Trace) {
240       DumpAcpiHeader (Ptr);
241     }
242     return;
243   }
244 
245   ParserProc (
246     Trace,
247     Ptr,
248     *AcpiTableLength,
249     *AcpiTableRevision
250     );
251 }
252