summaryrefslogtreecommitdiffstats
path: root/DynamicTablesPkg/Library/Common/AmlLib/AmlEncoding/Aml.h
blob: 0c931dce9782989da6792a7a4787e806a133f2f9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
/** @file
  AML grammar definitions.

  Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved. <BR>
  Copyright (c) 2019 - 2021, Arm Limited. All rights reserved.<BR>

  SPDX-License-Identifier: BSD-2-Clause-Patent
**/

#ifndef AML_H_
#define AML_H_

#include <AmlDefines.h>
#include <AmlInclude.h>
#include <IndustryStandard/AcpiAml.h>

#if !defined (MDEPKG_NDEBUG)
#define AML_OPCODE_DEF(str, OpCode)  str, OpCode
#else
#define AML_OPCODE_DEF(str, OpCode)  OpCode
#endif // MDEPKG_NDEBUG

/** AML types.

  In the AML bytestream, data is represented using one of the following types.
  These types are used in the parsing logic to know what kind of data is
  expected next in the bytestream. This allows to parse data according
  to the AML_PARSE_FORMAT type.
  E.g.: A string will not be parsed in the same way as a UINT8.

  These are internal types.
*/
typedef enum EAmlParseFormat {
  EAmlNone = 0,       ///< No data expected.
  EAmlUInt8,          ///< One byte value evaluated as a UINT8.
  EAmlUInt16,         ///< Two byte value evaluated as a UINT16.
  EAmlUInt32,         ///< Four byte value evaluated as a UINT32.
  EAmlUInt64,         ///< Eight byte value evaluated as a UINT64.
  EAmlObject,         ///< AML object, starting with an OpCode/SubOpCode
                      ///  couple, potentially followed by package length.
                      ///  EAmlName is a subtype of an EAmlObject.
                      ///  Indeed, an EAmlName can also be evaluated as
                      ///  an EAmlObject in the parsing.
  EAmlName,           ///< Name corresponding to the NameString keyword
                      ///  in the ACPI specification. E.g.: "\_SB_.DEV0"
  EAmlString,         ///< NULL terminated string.
  EAmlFieldPkgLen,    ///< A field package length (PkgLen). A data node of this
                      ///  type can only be found in a field list, in a
                      ///  NamedField statement. The PkgLen is otherwise
                      /// part of the object node structure.
  EAmlParseFormatMax  ///< Max enum.
} AML_PARSE_FORMAT;

/** AML attributes

  To add some more information to the byte encoding, it is possible to add
  these attributes.
*/
typedef UINT32 AML_OP_ATTRIBUTE;

/** A PkgLength is expected between the OpCode/SubOpCode couple and the first
    fixed argument of the object.
*/
#define AML_HAS_PKG_LENGTH  0x00001U

/** The object's OpCode is actually a character. Encodings with this attribute
    don't describe objects. The dual/multi name prefix have this attribute,
    indicating the start of a longer NameString.
*/
#define AML_IS_NAME_CHAR  0x00002U

/** A variable list of arguments is following the last fixed argument. Each
    argument is evaluated as an EAmlObject.
*/
#define AML_HAS_CHILD_OBJ  0x00004U

/** This is a sub-type of a variable list of arguments. It can only be
    found in buffer objects. A ByteList is either a list of
    bytes or a list of resource data elements. Resource data elements
    have specific opcodes.
*/
#define AML_HAS_BYTE_LIST  0x00008U

/** This is a sub-type of a variable list of arguments. It can only be
    found in Fields, IndexFields and BankFields.
    A FieldList is made of FieldElements. FieldElements have specific opcodes.
*/
#define AML_HAS_FIELD_LIST  0x00010U

/** This object node is a field element. Its opcode is to be fetched from
    the field encoding table.
*/
#define AML_IS_FIELD_ELEMENT  0x00020U

/** The object has a name and which is part of the AML namespace. The name
    can be found in the fixed argument list at the NameIndex.
*/
#define AML_IN_NAMESPACE  0x10000U

/** Some OpCodes have been created in this library. They are called
    pseudo opcodes and must stay internal to this library.
*/
#define AML_IS_PSEUDO_OPCODE  0x20000U

/** Encoding of an AML object.

  Every AML object has a specific encoding. This encoding information
  is used to parse AML objects. A table of AML_BYTE_ENCODING entries
  allows to parse an AML bytestream.
  This structure is also used to describe field objects.

  Cf. ACPI 6.3 specification, s20.2.
*/
typedef struct _AML_BYTE_ENCODING {
  // Enable this field for debug.
 #if !defined (MDEPKG_NDEBUG)
  /// String field allowing to print the AML object.
  CONST CHAR8         *Str;
 #endif // MDEPKG_NDEBUG

  /// OpCode of the AML object.
  UINT8               OpCode;

  /// SubOpCode of the AML object.
  /// The SubOpcode field has a valid value when the OpCode is 0x5B,
  /// otherwise this field must be zero.
  /// For field objects, the SubOpCode is not used.
  UINT8               SubOpCode;

  /// Number of fixed arguments for the AML statement represented
  /// by the OpCode & SubOpcode.
  /// Maximum is 6 for AML objects.
  /// Maximum is 3 for field objects.
  EAML_PARSE_INDEX    MaxIndex;

  /// If the encoding has the AML_IN_NAMESPACE attribute (cf Attribute
  /// field below), indicate where to find the name in the fixed list
  /// of arguments.
  EAML_PARSE_INDEX    NameIndex;

  /// Type of each fixed argument.
  AML_PARSE_FORMAT    Format[EAmlParseIndexMax];

  /// Additional information on the AML object.
  AML_OP_ATTRIBUTE    Attribute;
} AML_BYTE_ENCODING;

/** Get the AML_BYTE_ENCODING entry in the AML encoding table.

  Note: For Pseudo OpCodes this function returns NULL.

  @param  [in]  Buffer    Pointer to an OpCode/SubOpCode couple.
                          If *Buffer = 0x5b (extended OpCode),
                          Buffer must be at least two bytes long.

  @return The corresponding AML_BYTE_ENCODING entry.
          NULL if not found.
**/
CONST
AML_BYTE_ENCODING *
EFIAPI
AmlGetByteEncoding (
  IN  CONST UINT8  *Buffer
  );

/** Get the AML_BYTE_ENCODING entry in the AML encoding table
    by providing an OpCode/SubOpCode couple.

  @param  [in]  OpCode     OpCode.
  @param  [in]  SubOpCode  SubOpCode.

  @return The corresponding AML_BYTE_ENCODING entry.
          NULL if not found.
**/
CONST
AML_BYTE_ENCODING *
EFIAPI
AmlGetByteEncodingByOpCode (
  IN  UINT8  OpCode,
  IN  UINT8  SubOpCode
  );

/** Get the AML_BYTE_ENCODING entry in the field encoding table.

  Note: For Pseudo OpCodes this function returns NULL.

  @param  [in]  Buffer  Pointer to a field OpCode.
                        No SubOpCode is expected.

  @return The corresponding AML_BYTE_ENCODING entry
          in the field encoding table.
          NULL if not found.
**/
CONST
AML_BYTE_ENCODING *
EFIAPI
AmlGetFieldEncoding (
  IN  CONST UINT8  *Buffer
  );

/** Get the AML_BYTE_ENCODING entry in the field encoding table
    by providing an OpCode/SubOpCode couple.

  @param  [in]  OpCode     OpCode.
  @param  [in]  SubOpCode  SubOpCode.

  @return The corresponding AML_BYTE_ENCODING entry
          in the field encoding table.
          NULL if not found.
**/
CONST
AML_BYTE_ENCODING *
EFIAPI
AmlGetFieldEncodingByOpCode (
  IN  UINT8  OpCode,
  IN  UINT8  SubOpCode
  );

// Enable this function for debug.
#if !defined (MDEPKG_NDEBUG)

/** Look for an OpCode/SubOpCode couple in the AML grammar,
    and return a corresponding string.

  @param  [in]  OpCode      The OpCode.
  @param  [in]  SubOpCode   The SubOpCode.

  @return A string describing the OpCode/SubOpCode couple.
          NULL if not found.
**/
CONST
CHAR8 *
AmlGetOpCodeStr (
  IN  UINT8  OpCode,
  IN  UINT8  SubOpCode
  );

/** Look for an OpCode/SubOpCode couple in the AML field element grammar,
    and return a corresponding string.

  @param  [in]  OpCode      The OpCode.
  @param  [in]  SubOpCode   The SubOpCode. Must be zero.

  @return A string describing the OpCode/SubOpCode couple.
          NULL if not found.
**/
CONST
CHAR8 *
AmlGetFieldOpCodeStr (
  IN  UINT8  OpCode,
  IN  UINT8  SubOpCode
  );

#endif // MDEPKG_NDEBUG

/** Check whether the OpCode/SubOpcode couple is a valid entry
    in the AML grammar encoding table.

  @param  [in]  OpCode     OpCode to check.
  @param  [in]  SubOpCode  SubOpCode to check.

  @retval TRUE    The OpCode/SubOpCode couple is valid.
  @retval FALSE   Otherwise.
**/
BOOLEAN
EFIAPI
AmlIsOpCodeValid (
  IN  UINT8  OpCode,
  IN  UINT8  SubOpCode
  );

/** Convert an AML_PARSE_FORMAT to its corresponding EAML_NODE_DATA_TYPE.

  @param  [in]  AmlType   Input AML Type.

  @return The corresponding EAML_NODE_DATA_TYPE.
          EAmlNodeDataTypeNone if not found.
**/
EAML_NODE_DATA_TYPE
EFIAPI
AmlTypeToNodeDataType (
  IN  AML_PARSE_FORMAT  AmlType
  );

/** Get the package length from the buffer.

  @param  [in]  Buffer      AML buffer.
  @param  [out] PkgLength   The interpreted PkgLen value.
                            Length cannot exceed 2^28.

  @return The number of bytes to represent the package length.
          0 if an issue occurred.
**/
UINT32
EFIAPI
AmlGetPkgLength (
  IN  CONST UINT8   *Buffer,
  OUT       UINT32  *PkgLength
  );

/** Convert the Length to the AML PkgLen encoding,
    then and write it in the Buffer.

  @param  [in]    Length  Length to convert.
                          Length cannot exceed 2^28.
  @param  [out]   Buffer  Write the result in this Buffer.

  @return The number of bytes used to write the Length.
**/
UINT8
EFIAPI
AmlSetPkgLength (
  IN  UINT32  Length,
  OUT UINT8   *Buffer
  );

/** Compute the number of bytes required to write a package length.

  @param  [in]  Length  The length to convert in the AML package length
                        encoding style.
                        Length cannot exceed 2^28.

  @return The number of bytes required to write the Length.
**/
UINT8
EFIAPI
AmlComputePkgLengthWidth (
  IN  UINT32  Length
  );

/** Given a length, compute the value of a PkgLen.

  In AML, some object have a PkgLen, telling the size of the AML object.
  It can be encoded in 1 to 4 bytes. The bytes used to encode the PkgLen is
  itself counted in the PkgLen value.
  This means that if an AML object sees its size increment/decrement,
  the number of bytes used to encode the PkgLen value can itself
  increment/decrement.

  For instance, the AML encoding of a DeviceOp is:
    DefDevice := DeviceOp PkgLength NameString TermList
  If:
   - sizeof (NameString) = 4 (the name is "DEV0" for instance);
   - sizeof (TermList) = (2^6-6)
  then the PkgLen is encoded on 1 byte. Indeed, its value is:
    sizeof (PkgLen) + sizeof (NameString) + sizeof (TermList) =
    sizeof (PkgLen) + 4 + (2^6-6)
  So:
    PkgLen = sizeof (PkgLen) + (2^6-2)

  The input arguments Length and PkgLen represent, for the DefDevice:
    DefDevice := DeviceOp PkgLength NameString TermList
                                    |------Length-----|
                          |--------*PgkLength---------|

  @param  [in]  Length  The length to encode as a PkgLen.
                        Length cannot exceed 2^28 - 4 (4 bytes for the
                        PkgLen encoding).
                        The size of the PkgLen encoding bytes should not be
                        counted in this length value.
  @param  [out] PkgLen  If success, contains the value of the PkgLen,
                        ready to encode in the PkgLen format.
                        This value takes into account the size of PkgLen
                        encoding.

  @retval EFI_SUCCESS             The function completed successfully.
  @retval EFI_INVALID_PARAMETER   Invalid parameter.
**/
EFI_STATUS
EFIAPI
AmlComputePkgLength (
  IN  UINT32  Length,
  OUT UINT32  *PkgLen
  );

#endif // AML_H_