1 | #pragma once |
2 | |
3 | #include <uacpi/types.h> |
4 | #include <uacpi/resources.h> |
5 | |
6 | enum 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 | |
42 | enum 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 | |
48 | enum uacpi_aml_resource_kind { |
49 | UACPI_AML_RESOURCE_KIND_SMALL = 0, |
50 | UACPI_AML_RESOURCE_KIND_LARGE, |
51 | }; |
52 | |
53 | enum 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 | |
244 | struct 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 | |
264 | struct 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 (*)( |
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 | |
304 | typedef 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 | |
310 | uacpi_status uacpi_for_each_aml_resource( |
311 | uacpi_buffer *buffer, uacpi_aml_resource_iteration_callback cb, void *user |
312 | ); |
313 | |
314 | uacpi_status uacpi_find_aml_resource_end_tag( |
315 | uacpi_buffer *buffer, uacpi_size *out_offset |
316 | ); |
317 | |
318 | uacpi_status uacpi_native_resources_from_aml( |
319 | uacpi_buffer *aml_buffer, uacpi_resources **out_resources |
320 | ); |
321 | |
322 | uacpi_status uacpi_native_resources_to_aml( |
323 | uacpi_resources *resources, uacpi_object **out_template |
324 | ); |
325 | |