1#pragma once
2
3#include <uacpi/types.h>
4#include <uacpi/resources.h>
5
6enum uacpi_aml_resource {
7 UACPI_AML_RESOURCE_TYPE_INVALID = 0,
8
9 // Small resources
10 UACPI_AML_RESOURCE_IRQ,
11 UACPI_AML_RESOURCE_DMA,
12 UACPI_AML_RESOURCE_START_DEPENDENT,
13 UACPI_AML_RESOURCE_END_DEPENDENT,
14 UACPI_AML_RESOURCE_IO,
15 UACPI_AML_RESOURCE_FIXED_IO,
16 UACPI_AML_RESOURCE_FIXED_DMA,
17 UACPI_AML_RESOURCE_VENDOR_TYPE0,
18 UACPI_AML_RESOURCE_END_TAG,
19
20 // Large resources
21 UACPI_AML_RESOURCE_MEMORY24,
22 UACPI_AML_RESOURCE_GENERIC_REGISTER,
23 UACPI_AML_RESOURCE_VENDOR_TYPE1,
24 UACPI_AML_RESOURCE_MEMORY32,
25 UACPI_AML_RESOURCE_FIXED_MEMORY32,
26 UACPI_AML_RESOURCE_ADDRESS32,
27 UACPI_AML_RESOURCE_ADDRESS16,
28 UACPI_AML_RESOURCE_EXTENDED_IRQ,
29 UACPI_AML_RESOURCE_ADDRESS64,
30 UACPI_AML_RESOURCE_ADDRESS64_EXTENDED,
31 UACPI_AML_RESOURCE_GPIO_CONNECTION,
32 UACPI_AML_RESOURCE_PIN_FUNCTION,
33 UACPI_AML_RESOURCE_SERIAL_CONNECTION,
34 UACPI_AML_RESOURCE_PIN_CONFIGURATION,
35 UACPI_AML_RESOURCE_PIN_GROUP,
36 UACPI_AML_RESOURCE_PIN_GROUP_FUNCTION,
37 UACPI_AML_RESOURCE_PIN_GROUP_CONFIGURATION,
38 UACPI_AML_RESOURCE_CLOCK_INPUT,
39 UACPI_AML_RESOURCE_MAX = UACPI_AML_RESOURCE_CLOCK_INPUT,
40};
41
42enum uacpi_aml_resource_size_kind {
43 UACPI_AML_RESOURCE_SIZE_KIND_FIXED,
44 UACPI_AML_RESOURCE_SIZE_KIND_FIXED_OR_ONE_LESS,
45 UACPI_AML_RESOURCE_SIZE_KIND_VARIABLE,
46};
47
48enum uacpi_aml_resource_kind {
49 UACPI_AML_RESOURCE_KIND_SMALL = 0,
50 UACPI_AML_RESOURCE_KIND_LARGE,
51};
52
53enum uacpi_resource_convert_opcode {
54 UACPI_RESOURCE_CONVERT_OPCODE_END = 0,
55
56 /*
57 * AML -> native:
58 * Take the mask at 'aml_offset' and convert to an array of uacpi_u8
59 * at 'native_offset' with the value corresponding to the bit index.
60 * The array size is written to the byte at offset 'arg2'.
61 *
62 * native -> AML:
63 * Walk each element of the array at 'native_offset' and set the
64 * corresponding bit in the mask at 'aml_offset' to 1. The array size is
65 * read from the byte at offset 'arg2'.
66 */
67 UACPI_RESOURCE_CONVERT_OPCODE_PACKED_ARRAY_8,
68 UACPI_RESOURCE_CONVERT_OPCODE_PACKED_ARRAY_16,
69
70 /*
71 * AML -> native:
72 * Grab the bits at the byte at 'aml_offset' + 'bit_index', and copy its
73 * value into the byte at 'native_offset'.
74 *
75 * native -> AML:
76 * Grab first N bits at 'native_offset' and copy to 'aml_offset' starting
77 * at the 'bit_index'.
78 *
79 * NOTE:
80 * These must be contiguous in this order.
81 */
82 UACPI_RESOURCE_CONVERT_OPCODE_BIT_FIELD_1,
83 UACPI_RESOURCE_CONVERT_OPCODE_BIT_FIELD_2,
84 UACPI_RESOURCE_CONVERT_OPCODE_BIT_FIELD_3,
85 UACPI_RESOURCE_CONVERT_OPCODE_BIT_FIELD_6 =
86 UACPI_RESOURCE_CONVERT_OPCODE_BIT_FIELD_3 + 3,
87
88 /*
89 * AML -> native:
90 * Copy N bytes at 'aml_offset' to 'native_offset'.
91 *
92 * native -> AML:
93 * Copy N bytes at 'native_offset' to 'aml_offset'.
94 *
95 * 'imm' is added to the accumulator.
96 *
97 * NOTE: These are affected by the current value in the accumulator. If it's
98 * set to 0 at the time of evalution, this is executed once, N times
99 * otherwise. 0xFF is considered a special value, which resets the
100 * accumulator to 0 unconditionally.
101 */
102 UACPI_RESOURCE_CONVERT_OPCODE_FIELD_8,
103 UACPI_RESOURCE_CONVERT_OPCODE_FIELD_16,
104 UACPI_RESOURCE_CONVERT_OPCODE_FIELD_32,
105 UACPI_RESOURCE_CONVERT_OPCODE_FIELD_64,
106
107 /*
108 * If the length of the current resource is less than 'arg0', then skip
109 * 'imm' instructions.
110 */
111 UACPI_RESOURCE_CONVERT_OPCODE_SKIP_IF_AML_SIZE_LESS_THAN,
112
113 /*
114 * Skip 'imm' instructions if 'arg0' is not equal to the value in the
115 * accumulator.
116 */
117 UACPI_RESOURCE_CONVERT_OPCODE_SKIP_IF_NOT_EQUALS,
118
119 /*
120 * AML -> native:
121 * Set the byte at 'native_offset' to 'imm'.
122 *
123 * native -> AML:
124 * Set the byte at 'aml_offset' to 'imm'.
125 */
126 UACPI_RESOURCE_CONVERT_OPCODE_SET_TO_IMM,
127
128 /*
129 * AML -> native:
130 * Load the AML resoruce length into the accumulator as well as the field at
131 * 'native_offset' of width N.
132 *
133 * native -> AML:
134 * Load the resource length into the accumulator.
135 */
136 UACPI_RESOURCE_CONVERT_OPCODE_LOAD_AML_SIZE_32,
137
138 /*
139 * AML -> native:
140 * Load the 8 bit field at 'aml_offset' into the accumulator and store at
141 * 'native_offset'.
142 *
143 * native -> AML:
144 * Load the 8 bit field at 'native_offset' into the accumulator and store
145 * at 'aml_offset'.
146 *
147 * The accumulator is multiplied by 'imm' unless it's set to zero.
148 */
149 UACPI_RESOURCE_CONVERT_OPCODE_LOAD_8_STORE,
150
151 /*
152 * Load the N bit field at 'native_offset' into the accumulator
153 */
154 UACPI_RESOURCE_CONVERT_OPCODE_LOAD_8_NATIVE,
155 UACPI_RESOURCE_CONVERT_OPCODE_LOAD_16_NATIVE,
156
157 /*
158 * Load 'imm' into the accumulator.
159 */
160 UACPI_RESOURCE_CONVERT_OPCODE_LOAD_IMM,
161
162 /*
163 * AML -> native:
164 * Load the resource source at offset = aml size + accumulator into the
165 * uacpi_resource_source struct at 'native_offset'. The string bytes are
166 * written to the offset at resource size + accumulator. The presence is
167 * detected by comparing the length of the resource to the offset,
168 * 'arg2' optionally specifies the offset to the upper bound of the string.
169 *
170 * native -> AML:
171 * Load the resource source from the uacpi_resource_source struct at
172 * 'native_offset' to aml_size + accumulator. aml_size + accumulator is
173 * optionally written to 'aml_offset' if it's specified.
174 */
175 UACPI_RESOURCE_CONVERT_OPCODE_RESOURCE_SOURCE,
176 UACPI_RESOURCE_CONVERT_OPCODE_RESOURCE_SOURCE_NO_INDEX,
177 UACPI_RESOURCE_CONVERT_OPCODE_RESOURCE_LABEL,
178
179 /*
180 * AML -> native:
181 * Load the pin table with upper bound specified at 'aml_offset'.
182 * The table length is calculated by subtracting the upper bound from
183 * aml_size and is written into the accumulator.
184 *
185 * native -> AML:
186 * Load the pin table length from 'native_offset' and multiply by 2, store
187 * the result in the accumulator.
188 */
189 UACPI_RESOURCE_CONVERT_OPCODE_LOAD_PIN_TABLE_LENGTH,
190
191 /*
192 * AML -> native:
193 * Store the accumulator divided by 2 at 'native_offset'.
194 * The table is copied to the offset at resource size from offset at
195 * aml_size with the pointer written to the offset at 'arg2'.
196 *
197 * native -> AML:
198 * Read the pin table from resource size offset, write aml_size to
199 * 'aml_offset'. Copy accumulator bytes to the offset at aml_size.
200 */
201 UACPI_RESOURCE_CONVERT_OPCODE_PIN_TABLE,
202
203 /*
204 * AML -> native:
205 * Load vendor data with offset stored at 'aml_offset'. The length is
206 * calculated as aml_size - aml_offset and is written to 'native_offset'.
207 * The data is written to offset - aml_size with the pointer written back
208 * to the offset at 'arg2'.
209 *
210 * native -> AML:
211 * Read vendor data from the pointer at offset 'arg2' and size at
212 * 'native_offset', the offset to write to is calculated as the difference
213 * between the data pointer and the native resource end pointer.
214 * offset + aml_size is written to 'aml_offset' and the data is copied
215 * there as well.
216 */
217 UACPI_RESOURCE_CONVERT_OPCODE_VENDOR_DATA,
218
219 /*
220 * AML -> native:
221 * Read the serial type from the byte at 'aml_offset' and write it to the
222 * type field of the uacpi_resource_serial_bus_common structure. Convert
223 * the serial type to native and set the resource type to it. Copy the
224 * vendor data to the offset at native size, the length is calculated
225 * as type_data_length - extra-type-specific-size, and is written to
226 * vendor_data_length, as well as the accumulator. The data pointer is
227 * written to vendor_data.
228 *
229 * native -> AML:
230 * Set the serial type at 'aml_offset' to the value stored at
231 * 'native_offset'. Load the vendor data to the offset at aml_size,
232 * the length is read from 'vendor_data_length', and the data is copied from
233 * 'vendor_data'.
234 */
235 UACPI_RESOURCE_CONVERT_OPCODE_SERIAL_TYPE_SPECIFIC,
236
237 /*
238 * Produces an error if encountered in the instruction stream.
239 * Used to trap invalid/unexpected code flow.
240 */
241 UACPI_RESOURCE_CONVERT_OPCODE_UNREACHABLE,
242};
243
244struct uacpi_resource_convert_instruction {
245 uacpi_u8 code;
246
247 union {
248 uacpi_u8 aml_offset;
249 uacpi_u8 arg0;
250 };
251
252 union {
253 uacpi_u8 native_offset;
254 uacpi_u8 arg1;
255 };
256
257 union {
258 uacpi_u8 imm;
259 uacpi_u8 bit_index;
260 uacpi_u8 arg2;
261 };
262};
263
264struct uacpi_resource_spec {
265 uacpi_u8 type : 5;
266 uacpi_u8 native_type : 5;
267 uacpi_u8 resource_kind : 1;
268 uacpi_u8 size_kind : 2;
269
270 /*
271 * Size of the resource as appears in the AML byte stream, for variable
272 * length resources this is the minimum.
273 */
274 uacpi_u16 aml_size;
275
276 /*
277 * Size of the native human-readable uacpi resource, for variable length
278 * resources this is the minimum. The final length is this field plus the
279 * result of extra_size_for_native().
280 */
281 uacpi_u16 native_size;
282
283 /*
284 * Calculate the amount of extra bytes that must be allocated for a specific
285 * native resource given the AML counterpart. This being NULL means no extra
286 * bytes are needed, aka native resources is always the same size.
287 */
288 uacpi_size (*extra_size_for_native)(
289 const struct uacpi_resource_spec*, void*, uacpi_size
290 );
291
292 /*
293 * Calculate the number of bytes needed to represent a native resource as
294 * AML. The 'aml_size' field is used if this is NULL.
295 */
296 uacpi_size (*size_for_aml)(
297 const struct uacpi_resource_spec*, uacpi_resource*
298 );
299
300 const struct uacpi_resource_convert_instruction *to_native;
301 const struct uacpi_resource_convert_instruction *to_aml;
302};
303
304typedef uacpi_resource_iteration_decision
305(*uacpi_aml_resource_iteration_callback) (
306 void*, uacpi_u8 *data, uacpi_u16 resource_size,
307 const struct uacpi_resource_spec*
308);
309
310uacpi_status uacpi_for_each_aml_resource(
311 uacpi_buffer *buffer, uacpi_aml_resource_iteration_callback cb, void *user
312);
313
314uacpi_status uacpi_find_aml_resource_end_tag(
315 uacpi_buffer *buffer, uacpi_size *out_offset
316);
317
318uacpi_status uacpi_native_resources_from_aml(
319 uacpi_buffer *aml_buffer, uacpi_resources **out_resources
320);
321
322uacpi_status uacpi_native_resources_to_aml(
323 uacpi_resources *resources, uacpi_object **out_template
324);
325