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