1 | #ifndef HW_ACPI_AML_BUILD_H |
2 | #define HW_ACPI_AML_BUILD_H |
3 | |
4 | #include "hw/acpi/acpi-defs.h" |
5 | #include "hw/acpi/bios-linker-loader.h" |
6 | |
7 | /* Reserve RAM space for tables: add another order of magnitude. */ |
8 | #define ACPI_BUILD_TABLE_MAX_SIZE 0x200000 |
9 | |
10 | #define ACPI_BUILD_APPNAME6 "BOCHS " |
11 | #define ACPI_BUILD_APPNAME4 "BXPC" |
12 | |
13 | #define ACPI_BUILD_TABLE_FILE "etc/acpi/tables" |
14 | #define ACPI_BUILD_RSDP_FILE "etc/acpi/rsdp" |
15 | #define ACPI_BUILD_TPMLOG_FILE "etc/tpm/log" |
16 | |
17 | #define AML_NOTIFY_METHOD "NTFY" |
18 | |
19 | typedef enum { |
20 | AML_NO_OPCODE = 0,/* has only data */ |
21 | AML_OPCODE, /* has opcode optionally followed by data */ |
22 | AML_PACKAGE, /* has opcode and uses PkgLength for its length */ |
23 | AML_EXT_PACKAGE, /* Same as AML_PACKAGE but also has 'ExOpPrefix' */ |
24 | AML_BUFFER, /* data encoded as 'DefBuffer' */ |
25 | AML_RES_TEMPLATE, /* encoded as ResourceTemplate macro */ |
26 | } AmlBlockFlags; |
27 | |
28 | struct Aml { |
29 | GArray *buf; |
30 | |
31 | /*< private >*/ |
32 | uint8_t op; |
33 | AmlBlockFlags block_flags; |
34 | }; |
35 | typedef struct Aml Aml; |
36 | |
37 | typedef enum { |
38 | AML_COMPATIBILITY = 0, |
39 | AML_TYPEA = 1, |
40 | AML_TYPEB = 2, |
41 | AML_TYPEF = 3, |
42 | } AmlDmaType; |
43 | |
44 | typedef enum { |
45 | AML_NOTBUSMASTER = 0, |
46 | AML_BUSMASTER = 1, |
47 | } AmlDmaBusMaster; |
48 | |
49 | typedef enum { |
50 | AML_TRANSFER8 = 0, |
51 | AML_TRANSFER8_16 = 1, |
52 | AML_TRANSFER16 = 2, |
53 | } AmlTransferSize; |
54 | |
55 | typedef enum { |
56 | AML_DECODE10 = 0, |
57 | AML_DECODE16 = 1, |
58 | } AmlIODecode; |
59 | |
60 | typedef enum { |
61 | AML_ANY_ACC = 0, |
62 | AML_BYTE_ACC = 1, |
63 | AML_WORD_ACC = 2, |
64 | AML_DWORD_ACC = 3, |
65 | AML_QWORD_ACC = 4, |
66 | AML_BUFFER_ACC = 5, |
67 | } AmlAccessType; |
68 | |
69 | typedef enum { |
70 | AML_NOLOCK = 0, |
71 | AML_LOCK = 1, |
72 | } AmlLockRule; |
73 | |
74 | typedef enum { |
75 | AML_PRESERVE = 0, |
76 | AML_WRITE_AS_ONES = 1, |
77 | AML_WRITE_AS_ZEROS = 2, |
78 | } AmlUpdateRule; |
79 | |
80 | typedef enum { |
81 | AML_AS_SYSTEM_MEMORY = 0X00, |
82 | AML_AS_SYSTEM_IO = 0X01, |
83 | AML_AS_PCI_CONFIG = 0X02, |
84 | AML_AS_EMBEDDED_CTRL = 0X03, |
85 | AML_AS_SMBUS = 0X04, |
86 | AML_AS_FFH = 0X7F, |
87 | } AmlAddressSpace; |
88 | |
89 | typedef enum { |
90 | AML_SYSTEM_MEMORY = 0X00, |
91 | AML_SYSTEM_IO = 0X01, |
92 | AML_PCI_CONFIG = 0X02, |
93 | } AmlRegionSpace; |
94 | |
95 | typedef enum { |
96 | AML_MEMORY_RANGE = 0, |
97 | AML_IO_RANGE = 1, |
98 | AML_BUS_NUMBER_RANGE = 2, |
99 | } AmlResourceType; |
100 | |
101 | typedef enum { |
102 | AML_SUB_DECODE = 1 << 1, |
103 | AML_POS_DECODE = 0 |
104 | } AmlDecode; |
105 | |
106 | typedef enum { |
107 | AML_MAX_FIXED = 1 << 3, |
108 | AML_MAX_NOT_FIXED = 0, |
109 | } AmlMaxFixed; |
110 | |
111 | typedef enum { |
112 | AML_MIN_FIXED = 1 << 2, |
113 | AML_MIN_NOT_FIXED = 0 |
114 | } AmlMinFixed; |
115 | |
116 | /* |
117 | * ACPI 1.0b: Table 6-26 I/O Resource Flag (Resource Type = 1) Definitions |
118 | * _RNG field definition |
119 | */ |
120 | typedef enum { |
121 | AML_ISA_ONLY = 1, |
122 | AML_NON_ISA_ONLY = 2, |
123 | AML_ENTIRE_RANGE = 3, |
124 | } AmlISARanges; |
125 | |
126 | /* |
127 | * ACPI 1.0b: Table 6-25 Memory Resource Flag (Resource Type = 0) Definitions |
128 | * _MEM field definition |
129 | */ |
130 | typedef enum { |
131 | AML_NON_CACHEABLE = 0, |
132 | AML_CACHEABLE = 1, |
133 | AML_WRITE_COMBINING = 2, |
134 | AML_PREFETCHABLE = 3, |
135 | } AmlCacheable; |
136 | |
137 | /* |
138 | * ACPI 1.0b: Table 6-25 Memory Resource Flag (Resource Type = 0) Definitions |
139 | * _RW field definition |
140 | */ |
141 | typedef enum { |
142 | AML_READ_ONLY = 0, |
143 | AML_READ_WRITE = 1, |
144 | } AmlReadAndWrite; |
145 | |
146 | /* |
147 | * ACPI 5.0: Table 6-187 Extended Interrupt Descriptor Definition |
148 | * Interrupt Vector Flags Bits[0] Consumer/Producer |
149 | */ |
150 | typedef enum { |
151 | AML_CONSUMER_PRODUCER = 0, |
152 | AML_CONSUMER = 1, |
153 | } AmlConsumerAndProducer; |
154 | |
155 | /* |
156 | * ACPI 5.0: Table 6-187 Extended Interrupt Descriptor Definition |
157 | * _HE field definition |
158 | */ |
159 | typedef enum { |
160 | AML_LEVEL = 0, |
161 | AML_EDGE = 1, |
162 | } AmlLevelAndEdge; |
163 | |
164 | /* |
165 | * ACPI 5.0: Table 6-187 Extended Interrupt Descriptor Definition |
166 | * _LL field definition |
167 | */ |
168 | typedef enum { |
169 | AML_ACTIVE_HIGH = 0, |
170 | AML_ACTIVE_LOW = 1, |
171 | } AmlActiveHighAndLow; |
172 | |
173 | /* |
174 | * ACPI 5.0: Table 6-187 Extended Interrupt Descriptor Definition |
175 | * _SHR field definition |
176 | */ |
177 | typedef enum { |
178 | AML_EXCLUSIVE = 0, |
179 | AML_SHARED = 1, |
180 | AML_EXCLUSIVE_AND_WAKE = 2, |
181 | AML_SHARED_AND_WAKE = 3, |
182 | } AmlShared; |
183 | |
184 | /* ACPI 1.0b: 16.2.5.2 Named Objects Encoding: MethodFlags */ |
185 | typedef enum { |
186 | AML_NOTSERIALIZED = 0, |
187 | AML_SERIALIZED = 1, |
188 | } AmlSerializeFlag; |
189 | |
190 | /* |
191 | * ACPI 5.0: Table 6-189 GPIO Connection Descriptor Definition |
192 | * GPIO Connection Type |
193 | */ |
194 | typedef enum { |
195 | AML_INTERRUPT_CONNECTION = 0, |
196 | AML_IO_CONNECTION = 1, |
197 | } AmlGpioConnectionType; |
198 | |
199 | /* |
200 | * ACPI 5.0: Table 6-189 GPIO Connection Descriptor Definition |
201 | * _PPI field definition |
202 | */ |
203 | typedef enum { |
204 | AML_PULL_DEFAULT = 0, |
205 | AML_PULL_UP = 1, |
206 | AML_PULL_DOWN = 2, |
207 | AML_PULL_NONE = 3, |
208 | } AmlPinConfig; |
209 | |
210 | typedef enum { |
211 | MEM_AFFINITY_NOFLAGS = 0, |
212 | MEM_AFFINITY_ENABLED = (1 << 0), |
213 | MEM_AFFINITY_HOTPLUGGABLE = (1 << 1), |
214 | MEM_AFFINITY_NON_VOLATILE = (1 << 2), |
215 | } MemoryAffinityFlags; |
216 | |
217 | typedef |
218 | struct AcpiBuildTables { |
219 | GArray *table_data; |
220 | GArray *rsdp; |
221 | GArray *tcpalog; |
222 | GArray *vmgenid; |
223 | BIOSLinker *linker; |
224 | } AcpiBuildTables; |
225 | |
226 | /** |
227 | * init_aml_allocator: |
228 | * |
229 | * Called for initializing API allocator which allow to use |
230 | * AML API. |
231 | * Returns: toplevel container which accumulates all other |
232 | * AML elements for a table. |
233 | */ |
234 | Aml *init_aml_allocator(void); |
235 | |
236 | /** |
237 | * free_aml_allocator: |
238 | * |
239 | * Releases all elements used by AML API, frees associated memory |
240 | * and invalidates AML allocator. After this call @init_aml_allocator |
241 | * should be called again if AML API is to be used again. |
242 | */ |
243 | void free_aml_allocator(void); |
244 | |
245 | /** |
246 | * aml_append: |
247 | * @parent_ctx: context to which @child element is added |
248 | * @child: element that is copied into @parent_ctx context |
249 | * |
250 | * Joins Aml elements together and helps to construct AML tables |
251 | * Examle of usage: |
252 | * Aml *table = aml_def_block("SSDT", ...); |
253 | * Aml *sb = aml_scope("\\_SB"); |
254 | * Aml *dev = aml_device("PCI0"); |
255 | * |
256 | * aml_append(dev, aml_name_decl("HID", aml_eisaid("PNP0A03"))); |
257 | * aml_append(sb, dev); |
258 | * aml_append(table, sb); |
259 | */ |
260 | void aml_append(Aml *parent_ctx, Aml *child); |
261 | |
262 | /* non block AML object primitives */ |
263 | Aml *aml_name(const char *name_format, ...) GCC_FMT_ATTR(1, 2); |
264 | Aml *aml_name_decl(const char *name, Aml *val); |
265 | Aml *aml_debug(void); |
266 | Aml *aml_return(Aml *val); |
267 | Aml *aml_int(const uint64_t val); |
268 | Aml *aml_arg(int pos); |
269 | Aml *aml_to_integer(Aml *arg); |
270 | Aml *aml_to_hexstring(Aml *src, Aml *dst); |
271 | Aml *aml_to_buffer(Aml *src, Aml *dst); |
272 | Aml *aml_store(Aml *val, Aml *target); |
273 | Aml *aml_and(Aml *arg1, Aml *arg2, Aml *dst); |
274 | Aml *aml_or(Aml *arg1, Aml *arg2, Aml *dst); |
275 | Aml *aml_lor(Aml *arg1, Aml *arg2); |
276 | Aml *aml_shiftleft(Aml *arg1, Aml *count); |
277 | Aml *aml_shiftright(Aml *arg1, Aml *count, Aml *dst); |
278 | Aml *aml_lless(Aml *arg1, Aml *arg2); |
279 | Aml *aml_add(Aml *arg1, Aml *arg2, Aml *dst); |
280 | Aml *aml_subtract(Aml *arg1, Aml *arg2, Aml *dst); |
281 | Aml *aml_increment(Aml *arg); |
282 | Aml *aml_decrement(Aml *arg); |
283 | Aml *aml_index(Aml *arg1, Aml *idx); |
284 | Aml *aml_notify(Aml *arg1, Aml *arg2); |
285 | Aml *aml_call0(const char *method); |
286 | Aml *aml_call1(const char *method, Aml *arg1); |
287 | Aml *aml_call2(const char *method, Aml *arg1, Aml *arg2); |
288 | Aml *aml_call3(const char *method, Aml *arg1, Aml *arg2, Aml *arg3); |
289 | Aml *aml_call4(const char *method, Aml *arg1, Aml *arg2, Aml *arg3, Aml *arg4); |
290 | Aml *aml_call5(const char *method, Aml *arg1, Aml *arg2, Aml *arg3, Aml *arg4, |
291 | Aml *arg5); |
292 | Aml *aml_gpio_int(AmlConsumerAndProducer con_and_pro, |
293 | AmlLevelAndEdge edge_level, |
294 | AmlActiveHighAndLow active_level, AmlShared shared, |
295 | AmlPinConfig pin_config, uint16_t debounce_timeout, |
296 | const uint32_t pin_list[], uint32_t pin_count, |
297 | const char *resource_source_name, |
298 | const uint8_t *vendor_data, uint16_t vendor_data_len); |
299 | Aml *aml_memory32_fixed(uint32_t addr, uint32_t size, |
300 | AmlReadAndWrite read_and_write); |
301 | Aml *aml_interrupt(AmlConsumerAndProducer con_and_pro, |
302 | AmlLevelAndEdge level_and_edge, |
303 | AmlActiveHighAndLow high_and_low, AmlShared shared, |
304 | uint32_t *irq_list, uint8_t irq_count); |
305 | Aml *aml_io(AmlIODecode dec, uint16_t min_base, uint16_t max_base, |
306 | uint8_t aln, uint8_t len); |
307 | Aml *aml_operation_region(const char *name, AmlRegionSpace rs, |
308 | Aml *offset, uint32_t len); |
309 | Aml *aml_irq_no_flags(uint8_t irq); |
310 | Aml *aml_named_field(const char *name, unsigned length); |
311 | Aml *aml_reserved_field(unsigned length); |
312 | Aml *aml_local(int num); |
313 | Aml *aml_string(const char *name_format, ...) GCC_FMT_ATTR(1, 2); |
314 | Aml *aml_lnot(Aml *arg); |
315 | Aml *aml_equal(Aml *arg1, Aml *arg2); |
316 | Aml *aml_lgreater(Aml *arg1, Aml *arg2); |
317 | Aml *aml_lgreater_equal(Aml *arg1, Aml *arg2); |
318 | Aml *aml_processor(uint8_t proc_id, uint32_t pblk_addr, uint8_t pblk_len, |
319 | const char *name_format, ...) GCC_FMT_ATTR(4, 5); |
320 | Aml *aml_eisaid(const char *str); |
321 | Aml *aml_word_bus_number(AmlMinFixed min_fixed, AmlMaxFixed max_fixed, |
322 | AmlDecode dec, uint16_t addr_gran, |
323 | uint16_t addr_min, uint16_t addr_max, |
324 | uint16_t addr_trans, uint16_t len); |
325 | Aml *aml_word_io(AmlMinFixed min_fixed, AmlMaxFixed max_fixed, |
326 | AmlDecode dec, AmlISARanges isa_ranges, |
327 | uint16_t addr_gran, uint16_t addr_min, |
328 | uint16_t addr_max, uint16_t addr_trans, |
329 | uint16_t len); |
330 | Aml *aml_dword_io(AmlMinFixed min_fixed, AmlMaxFixed max_fixed, |
331 | AmlDecode dec, AmlISARanges isa_ranges, |
332 | uint32_t addr_gran, uint32_t addr_min, |
333 | uint32_t addr_max, uint32_t addr_trans, |
334 | uint32_t len); |
335 | Aml *aml_dword_memory(AmlDecode dec, AmlMinFixed min_fixed, |
336 | AmlMaxFixed max_fixed, AmlCacheable cacheable, |
337 | AmlReadAndWrite read_and_write, |
338 | uint32_t addr_gran, uint32_t addr_min, |
339 | uint32_t addr_max, uint32_t addr_trans, |
340 | uint32_t len); |
341 | Aml *aml_qword_memory(AmlDecode dec, AmlMinFixed min_fixed, |
342 | AmlMaxFixed max_fixed, AmlCacheable cacheable, |
343 | AmlReadAndWrite read_and_write, |
344 | uint64_t addr_gran, uint64_t addr_min, |
345 | uint64_t addr_max, uint64_t addr_trans, |
346 | uint64_t len); |
347 | Aml *aml_dma(AmlDmaType typ, AmlDmaBusMaster bm, AmlTransferSize sz, |
348 | uint8_t channel); |
349 | Aml *aml_sleep(uint64_t msec); |
350 | |
351 | /* Block AML object primitives */ |
352 | Aml *aml_scope(const char *name_format, ...) GCC_FMT_ATTR(1, 2); |
353 | Aml *aml_device(const char *name_format, ...) GCC_FMT_ATTR(1, 2); |
354 | Aml *aml_method(const char *name, int arg_count, AmlSerializeFlag sflag); |
355 | Aml *aml_if(Aml *predicate); |
356 | Aml *aml_else(void); |
357 | Aml *aml_while(Aml *predicate); |
358 | Aml *aml_package(uint8_t num_elements); |
359 | Aml *aml_buffer(int buffer_size, uint8_t *byte_list); |
360 | Aml *aml_resource_template(void); |
361 | Aml *aml_field(const char *name, AmlAccessType type, AmlLockRule lock, |
362 | AmlUpdateRule rule); |
363 | Aml *aml_mutex(const char *name, uint8_t sync_level); |
364 | Aml *aml_acquire(Aml *mutex, uint16_t timeout); |
365 | Aml *aml_release(Aml *mutex); |
366 | Aml *aml_alias(const char *source_object, const char *alias_object); |
367 | Aml *aml_create_field(Aml *srcbuf, Aml *bit_index, Aml *num_bits, |
368 | const char *name); |
369 | Aml *aml_create_dword_field(Aml *srcbuf, Aml *index, const char *name); |
370 | Aml *aml_create_qword_field(Aml *srcbuf, Aml *index, const char *name); |
371 | Aml *aml_varpackage(uint32_t num_elements); |
372 | Aml *aml_touuid(const char *uuid); |
373 | Aml *aml_unicode(const char *str); |
374 | Aml *aml_refof(Aml *arg); |
375 | Aml *aml_derefof(Aml *arg); |
376 | Aml *aml_sizeof(Aml *arg); |
377 | Aml *aml_concatenate(Aml *source1, Aml *source2, Aml *target); |
378 | Aml *aml_object_type(Aml *object); |
379 | |
380 | void build_append_int_noprefix(GArray *table, uint64_t value, int size); |
381 | void |
382 | (BIOSLinker *linker, GArray *table_data, |
383 | AcpiTableHeader *h, const char *sig, int len, uint8_t rev, |
384 | const char *oem_id, const char *oem_table_id); |
385 | void *acpi_data_push(GArray *table_data, unsigned size); |
386 | unsigned acpi_data_len(GArray *table); |
387 | void acpi_add_table(GArray *table_offsets, GArray *table_data); |
388 | void acpi_build_tables_init(AcpiBuildTables *tables); |
389 | void acpi_build_tables_cleanup(AcpiBuildTables *tables, bool mfre); |
390 | void |
391 | build_rsdp(GArray *tbl, BIOSLinker *linker, AcpiRsdpData *rsdp_data); |
392 | void |
393 | build_rsdt(GArray *table_data, BIOSLinker *linker, GArray *table_offsets, |
394 | const char *oem_id, const char *oem_table_id); |
395 | void |
396 | build_xsdt(GArray *table_data, BIOSLinker *linker, GArray *table_offsets, |
397 | const char *oem_id, const char *oem_table_id); |
398 | |
399 | int |
400 | build_append_named_dword(GArray *array, const char *name_format, ...) |
401 | GCC_FMT_ATTR(2, 3); |
402 | |
403 | void build_append_gas(GArray *table, AmlAddressSpace as, |
404 | uint8_t bit_width, uint8_t bit_offset, |
405 | uint8_t access_width, uint64_t address); |
406 | |
407 | static inline void |
408 | build_append_gas_from_struct(GArray *table, const struct AcpiGenericAddress *s) |
409 | { |
410 | build_append_gas(table, s->space_id, s->bit_width, s->bit_offset, |
411 | s->access_width, s->address); |
412 | } |
413 | |
414 | void build_srat_memory(AcpiSratMemoryAffinity *numamem, uint64_t base, |
415 | uint64_t len, int node, MemoryAffinityFlags flags); |
416 | |
417 | void build_slit(GArray *table_data, BIOSLinker *linker, MachineState *ms); |
418 | |
419 | void build_fadt(GArray *tbl, BIOSLinker *linker, const AcpiFadtData *f, |
420 | const char *oem_id, const char *oem_table_id); |
421 | #endif |
422 | |