| 1 | #pragma once |
| 2 | |
| 3 | #include <uacpi/internal/types.h> |
| 4 | #include <uacpi/resources.h> |
| 5 | |
| 6 | #ifndef UACPI_BAREBONES_MODE |
| 7 | |
| 8 | enum 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 | |
| 44 | enum 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 | |
| 50 | enum uacpi_aml_resource_kind { |
| 51 | UACPI_AML_RESOURCE_KIND_SMALL = 0, |
| 52 | UACPI_AML_RESOURCE_KIND_LARGE, |
| 53 | }; |
| 54 | |
| 55 | enum 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 | |
| 246 | struct 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 | |
| 266 | struct 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 (*)( |
| 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 | |
| 306 | typedef 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 | |
| 311 | uacpi_status uacpi_for_each_aml_resource( |
| 312 | uacpi_data_view, uacpi_aml_resource_iteration_callback cb, void *user |
| 313 | ); |
| 314 | |
| 315 | uacpi_status uacpi_find_aml_resource_end_tag( |
| 316 | uacpi_data_view, uacpi_size *out_offset |
| 317 | ); |
| 318 | |
| 319 | uacpi_status uacpi_native_resources_from_aml( |
| 320 | uacpi_data_view, uacpi_resources **out_resources |
| 321 | ); |
| 322 | |
| 323 | uacpi_status uacpi_native_resources_to_aml( |
| 324 | uacpi_resources *resources, uacpi_object **out_template |
| 325 | ); |
| 326 | |
| 327 | #endif // !UACPI_BAREBONES_MODE |
| 328 | |