xref: /openbmc/qemu/hw/acpi/aml-build.c (revision e452053097371880910c744a5d42ae2df058a4a7)
1 /* Support for generating ACPI tables and passing them to Guests
2  *
3  * Copyright (C) 2015 Red Hat Inc
4  *
5  * Author: Michael S. Tsirkin <mst@redhat.com>
6  * Author: Igor Mammedov <imammedo@redhat.com>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12 
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17 
18  * You should have received a copy of the GNU General Public License along
19  * with this program; if not, see <http://www.gnu.org/licenses/>.
20  */
21 
22 #include "qemu/osdep.h"
23 #include <glib/gprintf.h>
24 #include "hw/acpi/aml-build.h"
25 #include "qemu/bswap.h"
26 #include "qemu/bitops.h"
27 #include "system/numa.h"
28 #include "hw/boards.h"
29 #include "hw/acpi/tpm.h"
30 #include "hw/pci/pci_host.h"
31 #include "hw/pci/pci_bus.h"
32 #include "hw/pci/pci_bridge.h"
33 #include "qemu/cutils.h"
34 
build_alloc_array(void)35 static GArray *build_alloc_array(void)
36 {
37     return g_array_new(false, true /* clear */, 1);
38 }
39 
build_free_array(GArray * array)40 static void build_free_array(GArray *array)
41 {
42     g_array_free(array, true);
43 }
44 
build_prepend_byte(GArray * array,uint8_t val)45 static void build_prepend_byte(GArray *array, uint8_t val)
46 {
47     g_array_prepend_val(array, val);
48 }
49 
build_append_byte(GArray * array,uint8_t val)50 static void build_append_byte(GArray *array, uint8_t val)
51 {
52     g_array_append_val(array, val);
53 }
54 
build_append_padded_str(GArray * array,const char * str,size_t maxlen,char pad)55 static void build_append_padded_str(GArray *array, const char *str,
56                                     size_t maxlen, char pad)
57 {
58     size_t i;
59     size_t len = strlen(str);
60 
61     g_assert(len <= maxlen);
62     g_array_append_vals(array, str, len);
63     for (i = maxlen - len; i > 0; i--) {
64         g_array_append_val(array, pad);
65     }
66 }
67 
build_append_array(GArray * array,GArray * val)68 static void build_append_array(GArray *array, GArray *val)
69 {
70     g_array_append_vals(array, val->data, val->len);
71 }
72 
73 #define ACPI_NAMESEG_LEN 4
74 
crs_range_insert(GPtrArray * ranges,uint64_t base,uint64_t limit)75 void crs_range_insert(GPtrArray *ranges, uint64_t base, uint64_t limit)
76 {
77     CrsRangeEntry *entry;
78 
79     entry = g_malloc(sizeof(*entry));
80     entry->base = base;
81     entry->limit = limit;
82 
83     g_ptr_array_add(ranges, entry);
84 }
85 
crs_range_free(gpointer data)86 static void crs_range_free(gpointer data)
87 {
88     CrsRangeEntry *entry = (CrsRangeEntry *)data;
89     g_free(entry);
90 }
91 
crs_range_set_init(CrsRangeSet * range_set)92 void crs_range_set_init(CrsRangeSet *range_set)
93 {
94     range_set->io_ranges = g_ptr_array_new_with_free_func(crs_range_free);
95     range_set->mem_ranges = g_ptr_array_new_with_free_func(crs_range_free);
96     range_set->mem_64bit_ranges =
97             g_ptr_array_new_with_free_func(crs_range_free);
98 }
99 
crs_range_set_free(CrsRangeSet * range_set)100 void crs_range_set_free(CrsRangeSet *range_set)
101 {
102     g_ptr_array_free(range_set->io_ranges, true);
103     g_ptr_array_free(range_set->mem_ranges, true);
104     g_ptr_array_free(range_set->mem_64bit_ranges, true);
105 }
106 
crs_range_compare(gconstpointer a,gconstpointer b)107 static gint crs_range_compare(gconstpointer a, gconstpointer b)
108 {
109     CrsRangeEntry *entry_a = *(CrsRangeEntry **)a;
110     CrsRangeEntry *entry_b = *(CrsRangeEntry **)b;
111 
112     if (entry_a->base < entry_b->base) {
113         return -1;
114     } else if (entry_a->base > entry_b->base) {
115         return 1;
116     } else {
117         return 0;
118     }
119 }
120 
121 /*
122  * crs_replace_with_free_ranges - given the 'used' ranges within [start - end]
123  * interval, computes the 'free' ranges from the same interval.
124  * Example: If the input array is { [a1 - a2],[b1 - b2] }, the function
125  * will return { [base - a1], [a2 - b1], [b2 - limit] }.
126  */
crs_replace_with_free_ranges(GPtrArray * ranges,uint64_t start,uint64_t end)127 void crs_replace_with_free_ranges(GPtrArray *ranges,
128                                   uint64_t start, uint64_t end)
129 {
130     GPtrArray *free_ranges = g_ptr_array_new();
131     uint64_t free_base = start;
132     int i;
133 
134     g_ptr_array_sort(ranges, crs_range_compare);
135     for (i = 0; i < ranges->len; i++) {
136         CrsRangeEntry *used = g_ptr_array_index(ranges, i);
137 
138         if (free_base < used->base) {
139             crs_range_insert(free_ranges, free_base, used->base - 1);
140         }
141 
142         free_base = used->limit + 1;
143     }
144 
145     if (free_base < end) {
146         crs_range_insert(free_ranges, free_base, end);
147     }
148 
149     g_ptr_array_set_size(ranges, 0);
150     for (i = 0; i < free_ranges->len; i++) {
151         g_ptr_array_add(ranges, g_ptr_array_index(free_ranges, i));
152     }
153 
154     g_ptr_array_free(free_ranges, true);
155 }
156 
157 /*
158  * crs_range_merge - merges adjacent ranges in the given array.
159  * Array elements are deleted and replaced with the merged ranges.
160  */
crs_range_merge(GPtrArray * range)161 static void crs_range_merge(GPtrArray *range)
162 {
163     g_autoptr(GPtrArray) tmp = g_ptr_array_new_with_free_func(crs_range_free);
164     CrsRangeEntry *entry;
165     uint64_t range_base, range_limit;
166     int i;
167 
168     if (!range->len) {
169         return;
170     }
171 
172     g_ptr_array_sort(range, crs_range_compare);
173 
174     entry = g_ptr_array_index(range, 0);
175     range_base = entry->base;
176     range_limit = entry->limit;
177     for (i = 1; i < range->len; i++) {
178         entry = g_ptr_array_index(range, i);
179         if (entry->base - 1 == range_limit) {
180             range_limit = entry->limit;
181         } else {
182             crs_range_insert(tmp, range_base, range_limit);
183             range_base = entry->base;
184             range_limit = entry->limit;
185         }
186     }
187     crs_range_insert(tmp, range_base, range_limit);
188 
189     g_ptr_array_set_size(range, 0);
190     for (i = 0; i < tmp->len; i++) {
191         entry = g_ptr_array_index(tmp, i);
192         crs_range_insert(range, entry->base, entry->limit);
193     }
194 }
195 
196 static void
build_append_nameseg(GArray * array,const char * seg)197 build_append_nameseg(GArray *array, const char *seg)
198 {
199     int len;
200 
201     len = strlen(seg);
202     assert(len <= ACPI_NAMESEG_LEN);
203 
204     g_array_append_vals(array, seg, len);
205     /* Pad up to ACPI_NAMESEG_LEN characters if necessary. */
206     g_array_append_vals(array, "____", ACPI_NAMESEG_LEN - len);
207 }
208 
209 static void G_GNUC_PRINTF(2, 0)
build_append_namestringv(GArray * array,const char * format,va_list ap)210 build_append_namestringv(GArray *array, const char *format, va_list ap)
211 {
212     char *s;
213     char **segs;
214     char **segs_iter;
215     int seg_count = 0;
216 
217     s = g_strdup_vprintf(format, ap);
218     segs = g_strsplit(s, ".", 0);
219     g_free(s);
220 
221     /* count segments */
222     segs_iter = segs;
223     while (*segs_iter) {
224         ++segs_iter;
225         ++seg_count;
226     }
227     /*
228      * ACPI 5.0 spec: 20.2.2 Name Objects Encoding:
229      * "SegCount can be from 1 to 255"
230      */
231     assert(seg_count > 0 && seg_count <= 255);
232 
233     /* handle RootPath || PrefixPath */
234     s = *segs;
235     while (*s == '\\' || *s == '^') {
236         build_append_byte(array, *s);
237         ++s;
238     }
239 
240     switch (seg_count) {
241     case 1:
242         if (!*s) {
243             build_append_byte(array, 0x00); /* NullName */
244         } else {
245             build_append_nameseg(array, s);
246         }
247         break;
248 
249     case 2:
250         build_append_byte(array, 0x2E); /* DualNamePrefix */
251         build_append_nameseg(array, s);
252         build_append_nameseg(array, segs[1]);
253         break;
254     default:
255         build_append_byte(array, 0x2F); /* MultiNamePrefix */
256         build_append_byte(array, seg_count);
257 
258         /* handle the 1st segment manually due to prefix/root path */
259         build_append_nameseg(array, s);
260 
261         /* add the rest of segments */
262         segs_iter = segs + 1;
263         while (*segs_iter) {
264             build_append_nameseg(array, *segs_iter);
265             ++segs_iter;
266         }
267         break;
268     }
269     g_strfreev(segs);
270 }
271 
272 G_GNUC_PRINTF(2, 3)
build_append_namestring(GArray * array,const char * format,...)273 static void build_append_namestring(GArray *array, const char *format, ...)
274 {
275     va_list ap;
276 
277     va_start(ap, format);
278     build_append_namestringv(array, format, ap);
279     va_end(ap);
280 }
281 
282 /* 5.4 Definition Block Encoding */
283 enum {
284     PACKAGE_LENGTH_1BYTE_SHIFT = 6, /* Up to 63 - use extra 2 bits. */
285     PACKAGE_LENGTH_2BYTE_SHIFT = 4,
286     PACKAGE_LENGTH_3BYTE_SHIFT = 12,
287     PACKAGE_LENGTH_4BYTE_SHIFT = 20,
288 };
289 
290 static void
build_prepend_package_length(GArray * package,unsigned length,bool incl_self)291 build_prepend_package_length(GArray *package, unsigned length, bool incl_self)
292 {
293     uint8_t byte;
294     unsigned length_bytes;
295 
296     if (length + 1 < (1 << PACKAGE_LENGTH_1BYTE_SHIFT)) {
297         length_bytes = 1;
298     } else if (length + 2 < (1 << PACKAGE_LENGTH_3BYTE_SHIFT)) {
299         length_bytes = 2;
300     } else if (length + 3 < (1 << PACKAGE_LENGTH_4BYTE_SHIFT)) {
301         length_bytes = 3;
302     } else {
303         length_bytes = 4;
304     }
305 
306     /*
307      * NamedField uses PkgLength encoding but it doesn't include length
308      * of PkgLength itself.
309      */
310     if (incl_self) {
311         /*
312          * PkgLength is the length of the inclusive length of the data
313          * and PkgLength's length itself when used for terms with
314          * explicit length.
315          */
316         length += length_bytes;
317     }
318 
319     switch (length_bytes) {
320     case 1:
321         byte = length;
322         build_prepend_byte(package, byte);
323         return;
324     case 4:
325         byte = length >> PACKAGE_LENGTH_4BYTE_SHIFT;
326         build_prepend_byte(package, byte);
327         length &= (1 << PACKAGE_LENGTH_4BYTE_SHIFT) - 1;
328         /* fall through */
329     case 3:
330         byte = length >> PACKAGE_LENGTH_3BYTE_SHIFT;
331         build_prepend_byte(package, byte);
332         length &= (1 << PACKAGE_LENGTH_3BYTE_SHIFT) - 1;
333         /* fall through */
334     case 2:
335         byte = length >> PACKAGE_LENGTH_2BYTE_SHIFT;
336         build_prepend_byte(package, byte);
337         length &= (1 << PACKAGE_LENGTH_2BYTE_SHIFT) - 1;
338         /* fall through */
339     }
340     /*
341      * Most significant two bits of byte zero indicate how many following bytes
342      * are in PkgLength encoding.
343      */
344     byte = ((length_bytes - 1) << PACKAGE_LENGTH_1BYTE_SHIFT) | length;
345     build_prepend_byte(package, byte);
346 }
347 
348 static void
build_append_pkg_length(GArray * array,unsigned length,bool incl_self)349 build_append_pkg_length(GArray *array, unsigned length, bool incl_self)
350 {
351     GArray *tmp = build_alloc_array();
352 
353     build_prepend_package_length(tmp, length, incl_self);
354     build_append_array(array, tmp);
355     build_free_array(tmp);
356 }
357 
build_package(GArray * package,uint8_t op)358 static void build_package(GArray *package, uint8_t op)
359 {
360     build_prepend_package_length(package, package->len, true);
361     build_prepend_byte(package, op);
362 }
363 
build_extop_package(GArray * package,uint8_t op)364 static void build_extop_package(GArray *package, uint8_t op)
365 {
366     build_package(package, op);
367     build_prepend_byte(package, 0x5B); /* ExtOpPrefix */
368 }
369 
build_append_int_noprefix(GArray * table,uint64_t value,int size)370 void build_append_int_noprefix(GArray *table, uint64_t value, int size)
371 {
372     int i;
373 
374     for (i = 0; i < size; ++i) {
375         build_append_byte(table, value & 0xFF);
376         value = value >> 8;
377     }
378 }
379 
build_append_int(GArray * table,uint64_t value)380 static void build_append_int(GArray *table, uint64_t value)
381 {
382     if (value == 0x00) {
383         build_append_byte(table, 0x00); /* ZeroOp */
384     } else if (value == 0x01) {
385         build_append_byte(table, 0x01); /* OneOp */
386     } else if (value <= 0xFF) {
387         build_append_byte(table, 0x0A); /* BytePrefix */
388         build_append_int_noprefix(table, value, 1);
389     } else if (value <= 0xFFFF) {
390         build_append_byte(table, 0x0B); /* WordPrefix */
391         build_append_int_noprefix(table, value, 2);
392     } else if (value <= 0xFFFFFFFF) {
393         build_append_byte(table, 0x0C); /* DWordPrefix */
394         build_append_int_noprefix(table, value, 4);
395     } else {
396         build_append_byte(table, 0x0E); /* QWordPrefix */
397         build_append_int_noprefix(table, value, 8);
398     }
399 }
400 
401 /* Generic Address Structure (GAS)
402  * ACPI 2.0/3.0: 5.2.3.1 Generic Address Structure
403  * 2.0 compat note:
404  *    @access_width must be 0, see ACPI 2.0:Table 5-1
405  */
build_append_gas(GArray * table,AmlAddressSpace as,uint8_t bit_width,uint8_t bit_offset,uint8_t access_width,uint64_t address)406 void build_append_gas(GArray *table, AmlAddressSpace as,
407                       uint8_t bit_width, uint8_t bit_offset,
408                       uint8_t access_width, uint64_t address)
409 {
410     build_append_int_noprefix(table, as, 1);
411     build_append_int_noprefix(table, bit_width, 1);
412     build_append_int_noprefix(table, bit_offset, 1);
413     build_append_int_noprefix(table, access_width, 1);
414     build_append_int_noprefix(table, address, 8);
415 }
416 
417 /*
418  * Build NAME(XXXX, 0x00000000) where 0x00000000 is encoded as a dword,
419  * and return the offset to 0x00000000 for runtime patching.
420  *
421  * Warning: runtime patching is best avoided. Only use this as
422  * a replacement for DataTableRegion (for guests that don't
423  * support it).
424  */
425 int
build_append_named_dword(GArray * array,const char * name_format,...)426 build_append_named_dword(GArray *array, const char *name_format, ...)
427 {
428     int offset;
429     va_list ap;
430 
431     build_append_byte(array, 0x08); /* NameOp */
432     va_start(ap, name_format);
433     build_append_namestringv(array, name_format, ap);
434     va_end(ap);
435 
436     build_append_byte(array, 0x0C); /* DWordPrefix */
437 
438     offset = array->len;
439     build_append_int_noprefix(array, 0x00000000, 4);
440     assert(array->len == offset + 4);
441 
442     return offset;
443 }
444 
445 static GPtrArray *alloc_list;
446 
aml_alloc(void)447 static Aml *aml_alloc(void)
448 {
449     Aml *var = g_new0(typeof(*var), 1);
450 
451     g_ptr_array_add(alloc_list, var);
452     var->block_flags = AML_NO_OPCODE;
453     var->buf = build_alloc_array();
454     return var;
455 }
456 
aml_opcode(uint8_t op)457 static Aml *aml_opcode(uint8_t op)
458 {
459     Aml *var = aml_alloc();
460 
461     var->op  = op;
462     var->block_flags = AML_OPCODE;
463     return var;
464 }
465 
aml_bundle(uint8_t op,AmlBlockFlags flags)466 static Aml *aml_bundle(uint8_t op, AmlBlockFlags flags)
467 {
468     Aml *var = aml_alloc();
469 
470     var->op  = op;
471     var->block_flags = flags;
472     return var;
473 }
474 
aml_free(gpointer data,gpointer user_data)475 static void aml_free(gpointer data, gpointer user_data)
476 {
477     Aml *var = data;
478     build_free_array(var->buf);
479     g_free(var);
480 }
481 
init_aml_allocator(void)482 Aml *init_aml_allocator(void)
483 {
484     assert(!alloc_list);
485     alloc_list = g_ptr_array_new();
486     return aml_alloc();
487 }
488 
free_aml_allocator(void)489 void free_aml_allocator(void)
490 {
491     g_ptr_array_foreach(alloc_list, aml_free, NULL);
492     g_ptr_array_free(alloc_list, true);
493     alloc_list = 0;
494 }
495 
496 /* pack data with DefBuffer encoding */
build_buffer(GArray * array,uint8_t op)497 static void build_buffer(GArray *array, uint8_t op)
498 {
499     GArray *data = build_alloc_array();
500 
501     build_append_int(data, array->len);
502     g_array_prepend_vals(array, data->data, data->len);
503     build_free_array(data);
504     build_package(array, op);
505 }
506 
aml_append(Aml * parent_ctx,Aml * child)507 void aml_append(Aml *parent_ctx, Aml *child)
508 {
509     GArray *buf = build_alloc_array();
510     build_append_array(buf, child->buf);
511 
512     switch (child->block_flags) {
513     case AML_OPCODE:
514         build_append_byte(parent_ctx->buf, child->op);
515         break;
516     case AML_EXT_PACKAGE:
517         build_extop_package(buf, child->op);
518         break;
519     case AML_PACKAGE:
520         build_package(buf, child->op);
521         break;
522     case AML_RES_TEMPLATE:
523         build_append_byte(buf, 0x79); /* EndTag */
524         /*
525          * checksum operations are treated as succeeded if checksum
526          * field is zero. [ACPI Spec 1.0b, 6.4.2.8 End Tag]
527          */
528         build_append_byte(buf, 0);
529         /* fall through, to pack resources in buffer */
530     case AML_BUFFER:
531         build_buffer(buf, child->op);
532         break;
533     case AML_NO_OPCODE:
534         break;
535     default:
536         g_assert_not_reached();
537     }
538     build_append_array(parent_ctx->buf, buf);
539     build_free_array(buf);
540 }
541 
542 /* ACPI 1.0b: 16.2.5.1 Namespace Modifier Objects Encoding: DefScope */
aml_scope(const char * name_format,...)543 Aml *aml_scope(const char *name_format, ...)
544 {
545     va_list ap;
546     Aml *var = aml_bundle(0x10 /* ScopeOp */, AML_PACKAGE);
547     va_start(ap, name_format);
548     build_append_namestringv(var->buf, name_format, ap);
549     va_end(ap);
550     return var;
551 }
552 
553 /* ACPI 1.0b: 16.2.5.3 Type 1 Opcodes Encoding: DefReturn */
aml_return(Aml * val)554 Aml *aml_return(Aml *val)
555 {
556     Aml *var = aml_opcode(0xA4 /* ReturnOp */);
557     aml_append(var, val);
558     return var;
559 }
560 
561 /* ACPI 1.0b: 16.2.6.3 Debug Objects Encoding: DebugObj */
aml_debug(void)562 Aml *aml_debug(void)
563 {
564     Aml *var = aml_alloc();
565     build_append_byte(var->buf, 0x5B); /* ExtOpPrefix */
566     build_append_byte(var->buf, 0x31); /* DebugOp */
567     return var;
568 }
569 
570 /*
571  * ACPI 1.0b: 16.2.3 Data Objects Encoding:
572  * encodes: ByteConst, WordConst, DWordConst, QWordConst, ZeroOp, OneOp
573  */
aml_int(const uint64_t val)574 Aml *aml_int(const uint64_t val)
575 {
576     Aml *var = aml_alloc();
577     build_append_int(var->buf, val);
578     return var;
579 }
580 
581 /*
582  * helper to construct NameString, which returns Aml object
583  * for using with aml_append or other aml_* terms
584  */
aml_name(const char * name_format,...)585 Aml *aml_name(const char *name_format, ...)
586 {
587     va_list ap;
588     Aml *var = aml_alloc();
589     va_start(ap, name_format);
590     build_append_namestringv(var->buf, name_format, ap);
591     va_end(ap);
592     return var;
593 }
594 
595 /* ACPI 1.0b: 16.2.5.1 Namespace Modifier Objects Encoding: DefName */
aml_name_decl(const char * name,Aml * val)596 Aml *aml_name_decl(const char *name, Aml *val)
597 {
598     Aml *var = aml_opcode(0x08 /* NameOp */);
599     build_append_namestring(var->buf, "%s", name);
600     aml_append(var, val);
601     return var;
602 }
603 
604 /* ACPI 1.0b: 16.2.6.1 Arg Objects Encoding */
aml_arg(int pos)605 Aml *aml_arg(int pos)
606 {
607     uint8_t op = 0x68 /* ARG0 op */ + pos;
608 
609     assert(pos <= 6);
610     return aml_opcode(op);
611 }
612 
613 /* ACPI 2.0a: 17.2.4.4 Type 2 Opcodes Encoding: DefToInteger */
aml_to_integer(Aml * arg)614 Aml *aml_to_integer(Aml *arg)
615 {
616     Aml *var = aml_opcode(0x99 /* ToIntegerOp */);
617     aml_append(var, arg);
618     build_append_byte(var->buf, 0x00 /* NullNameOp */);
619     return var;
620 }
621 
622 /* ACPI 2.0a: 17.2.4.4 Type 2 Opcodes Encoding: DefToHexString */
aml_to_hexstring(Aml * src,Aml * dst)623 Aml *aml_to_hexstring(Aml *src, Aml *dst)
624 {
625     Aml *var = aml_opcode(0x98 /* ToHexStringOp */);
626     aml_append(var, src);
627     if (dst) {
628         aml_append(var, dst);
629     } else {
630         build_append_byte(var->buf, 0x00 /* NullNameOp */);
631     }
632     return var;
633 }
634 
635 /* ACPI 2.0a: 17.2.4.4 Type 2 Opcodes Encoding: DefToBuffer */
aml_to_buffer(Aml * src,Aml * dst)636 Aml *aml_to_buffer(Aml *src, Aml *dst)
637 {
638     Aml *var = aml_opcode(0x96 /* ToBufferOp */);
639     aml_append(var, src);
640     if (dst) {
641         aml_append(var, dst);
642     } else {
643         build_append_byte(var->buf, 0x00 /* NullNameOp */);
644     }
645     return var;
646 }
647 
648 /* ACPI 2.0a: 17.2.4.4 Type 2 Opcodes Encoding: DefToDecimalString */
aml_to_decimalstring(Aml * src,Aml * dst)649 Aml *aml_to_decimalstring(Aml *src, Aml *dst)
650 {
651     Aml *var = aml_opcode(0x97 /* ToDecimalStringOp */);
652     aml_append(var, src);
653     if (dst) {
654         aml_append(var, dst);
655     } else {
656         build_append_byte(var->buf, 0x00 /* NullNameOp */);
657     }
658     return var;
659 }
660 
661 /* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefStore */
aml_store(Aml * val,Aml * target)662 Aml *aml_store(Aml *val, Aml *target)
663 {
664     Aml *var = aml_opcode(0x70 /* StoreOp */);
665     aml_append(var, val);
666     aml_append(var, target);
667     return var;
668 }
669 
670 /**
671  * build_opcode_2arg_dst:
672  * @op: 1-byte opcode
673  * @arg1: 1st operand
674  * @arg2: 2nd operand
675  * @dst: optional target to store to, set to NULL if it's not required
676  *
677  * An internal helper to compose AML terms that have
678  *   "Op Operand Operand Target"
679  * pattern.
680  *
681  * Returns: The newly allocated and composed according to pattern Aml object.
682  */
683 static Aml *
build_opcode_2arg_dst(uint8_t op,Aml * arg1,Aml * arg2,Aml * dst)684 build_opcode_2arg_dst(uint8_t op, Aml *arg1, Aml *arg2, Aml *dst)
685 {
686     Aml *var = aml_opcode(op);
687     aml_append(var, arg1);
688     aml_append(var, arg2);
689     if (dst) {
690         aml_append(var, dst);
691     } else {
692         build_append_byte(var->buf, 0x00 /* NullNameOp */);
693     }
694     return var;
695 }
696 
697 /* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefAnd */
aml_and(Aml * arg1,Aml * arg2,Aml * dst)698 Aml *aml_and(Aml *arg1, Aml *arg2, Aml *dst)
699 {
700     return build_opcode_2arg_dst(0x7B /* AndOp */, arg1, arg2, dst);
701 }
702 
703 /* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefOr */
aml_or(Aml * arg1,Aml * arg2,Aml * dst)704 Aml *aml_or(Aml *arg1, Aml *arg2, Aml *dst)
705 {
706     return build_opcode_2arg_dst(0x7D /* OrOp */, arg1, arg2, dst);
707 }
708 
709 /* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefLAnd */
aml_land(Aml * arg1,Aml * arg2)710 Aml *aml_land(Aml *arg1, Aml *arg2)
711 {
712     Aml *var = aml_opcode(0x90 /* LAndOp */);
713     aml_append(var, arg1);
714     aml_append(var, arg2);
715     return var;
716 }
717 
718 /* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefLOr */
aml_lor(Aml * arg1,Aml * arg2)719 Aml *aml_lor(Aml *arg1, Aml *arg2)
720 {
721     Aml *var = aml_opcode(0x91 /* LOrOp */);
722     aml_append(var, arg1);
723     aml_append(var, arg2);
724     return var;
725 }
726 
727 /* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefShiftLeft */
aml_shiftleft(Aml * arg1,Aml * count)728 Aml *aml_shiftleft(Aml *arg1, Aml *count)
729 {
730     return build_opcode_2arg_dst(0x79 /* ShiftLeftOp */, arg1, count, NULL);
731 }
732 
733 /* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefShiftRight */
aml_shiftright(Aml * arg1,Aml * count,Aml * dst)734 Aml *aml_shiftright(Aml *arg1, Aml *count, Aml *dst)
735 {
736     return build_opcode_2arg_dst(0x7A /* ShiftRightOp */, arg1, count, dst);
737 }
738 
739 /* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefLLess */
aml_lless(Aml * arg1,Aml * arg2)740 Aml *aml_lless(Aml *arg1, Aml *arg2)
741 {
742     Aml *var = aml_opcode(0x95 /* LLessOp */);
743     aml_append(var, arg1);
744     aml_append(var, arg2);
745     return var;
746 }
747 
748 /* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefAdd */
aml_add(Aml * arg1,Aml * arg2,Aml * dst)749 Aml *aml_add(Aml *arg1, Aml *arg2, Aml *dst)
750 {
751     return build_opcode_2arg_dst(0x72 /* AddOp */, arg1, arg2, dst);
752 }
753 
754 /* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefSubtract */
aml_subtract(Aml * arg1,Aml * arg2,Aml * dst)755 Aml *aml_subtract(Aml *arg1, Aml *arg2, Aml *dst)
756 {
757     return build_opcode_2arg_dst(0x74 /* SubtractOp */, arg1, arg2, dst);
758 }
759 
760 /* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefIncrement */
aml_increment(Aml * arg)761 Aml *aml_increment(Aml *arg)
762 {
763     Aml *var = aml_opcode(0x75 /* IncrementOp */);
764     aml_append(var, arg);
765     return var;
766 }
767 
768 /* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefDecrement */
aml_decrement(Aml * arg)769 Aml *aml_decrement(Aml *arg)
770 {
771     Aml *var = aml_opcode(0x76 /* DecrementOp */);
772     aml_append(var, arg);
773     return var;
774 }
775 
776 /* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefIndex */
aml_index(Aml * arg1,Aml * idx)777 Aml *aml_index(Aml *arg1, Aml *idx)
778 {
779     return build_opcode_2arg_dst(0x88 /* IndexOp */, arg1, idx, NULL);
780 }
781 
782 /* ACPI 1.0b: 16.2.5.3 Type 1 Opcodes Encoding: DefNotify */
aml_notify(Aml * arg1,Aml * arg2)783 Aml *aml_notify(Aml *arg1, Aml *arg2)
784 {
785     Aml *var = aml_opcode(0x86 /* NotifyOp */);
786     aml_append(var, arg1);
787     aml_append(var, arg2);
788     return var;
789 }
790 
791 /* ACPI 1.0b: 16.2.5.3 Type 1 Opcodes Encoding: DefBreak */
aml_break(void)792 Aml *aml_break(void)
793 {
794     Aml *var = aml_opcode(0xa5 /* BreakOp */);
795     return var;
796 }
797 
798 /* helper to call method without argument */
aml_call0(const char * method)799 Aml *aml_call0(const char *method)
800 {
801     Aml *var = aml_alloc();
802     build_append_namestring(var->buf, "%s", method);
803     return var;
804 }
805 
806 /* helper to call method with 1 argument */
aml_call1(const char * method,Aml * arg1)807 Aml *aml_call1(const char *method, Aml *arg1)
808 {
809     Aml *var = aml_alloc();
810     build_append_namestring(var->buf, "%s", method);
811     aml_append(var, arg1);
812     return var;
813 }
814 
815 /* helper to call method with 2 arguments */
aml_call2(const char * method,Aml * arg1,Aml * arg2)816 Aml *aml_call2(const char *method, Aml *arg1, Aml *arg2)
817 {
818     Aml *var = aml_alloc();
819     build_append_namestring(var->buf, "%s", method);
820     aml_append(var, arg1);
821     aml_append(var, arg2);
822     return var;
823 }
824 
825 /* helper to call method with 3 arguments */
aml_call3(const char * method,Aml * arg1,Aml * arg2,Aml * arg3)826 Aml *aml_call3(const char *method, Aml *arg1, Aml *arg2, Aml *arg3)
827 {
828     Aml *var = aml_alloc();
829     build_append_namestring(var->buf, "%s", method);
830     aml_append(var, arg1);
831     aml_append(var, arg2);
832     aml_append(var, arg3);
833     return var;
834 }
835 
836 /* helper to call method with 4 arguments */
aml_call4(const char * method,Aml * arg1,Aml * arg2,Aml * arg3,Aml * arg4)837 Aml *aml_call4(const char *method, Aml *arg1, Aml *arg2, Aml *arg3, Aml *arg4)
838 {
839     Aml *var = aml_alloc();
840     build_append_namestring(var->buf, "%s", method);
841     aml_append(var, arg1);
842     aml_append(var, arg2);
843     aml_append(var, arg3);
844     aml_append(var, arg4);
845     return var;
846 }
847 
848 /* helper to call method with 5 arguments */
aml_call5(const char * method,Aml * arg1,Aml * arg2,Aml * arg3,Aml * arg4,Aml * arg5)849 Aml *aml_call5(const char *method, Aml *arg1, Aml *arg2, Aml *arg3, Aml *arg4,
850                Aml *arg5)
851 {
852     Aml *var = aml_alloc();
853     build_append_namestring(var->buf, "%s", method);
854     aml_append(var, arg1);
855     aml_append(var, arg2);
856     aml_append(var, arg3);
857     aml_append(var, arg4);
858     aml_append(var, arg5);
859     return var;
860 }
861 
862 /* helper to call method with 5 arguments */
aml_call6(const char * method,Aml * arg1,Aml * arg2,Aml * arg3,Aml * arg4,Aml * arg5,Aml * arg6)863 Aml *aml_call6(const char *method, Aml *arg1, Aml *arg2, Aml *arg3, Aml *arg4,
864                Aml *arg5, Aml *arg6)
865 {
866     Aml *var = aml_alloc();
867     build_append_namestring(var->buf, "%s", method);
868     aml_append(var, arg1);
869     aml_append(var, arg2);
870     aml_append(var, arg3);
871     aml_append(var, arg4);
872     aml_append(var, arg5);
873     aml_append(var, arg6);
874     return var;
875 }
876 
877 /*
878  * ACPI 5.0: 6.4.3.8.1 GPIO Connection Descriptor
879  * Type 1, Large Item Name 0xC
880  */
881 
aml_gpio_connection(AmlGpioConnectionType type,AmlConsumerAndProducer con_and_pro,uint8_t flags,AmlPinConfig pin_config,uint16_t output_drive,uint16_t debounce_timeout,const uint32_t pin_list[],uint32_t pin_count,const char * resource_source_name,const uint8_t * vendor_data,uint16_t vendor_data_len)882 static Aml *aml_gpio_connection(AmlGpioConnectionType type,
883                                 AmlConsumerAndProducer con_and_pro,
884                                 uint8_t flags, AmlPinConfig pin_config,
885                                 uint16_t output_drive,
886                                 uint16_t debounce_timeout,
887                                 const uint32_t pin_list[], uint32_t pin_count,
888                                 const char *resource_source_name,
889                                 const uint8_t *vendor_data,
890                                 uint16_t vendor_data_len)
891 {
892     Aml *var = aml_alloc();
893     const uint16_t min_desc_len = 0x16;
894     uint16_t resource_source_name_len, length;
895     uint16_t pin_table_offset, resource_source_name_offset, vendor_data_offset;
896     uint32_t i;
897 
898     assert(resource_source_name);
899     resource_source_name_len = strlen(resource_source_name) + 1;
900     length = min_desc_len + resource_source_name_len + vendor_data_len;
901     pin_table_offset = min_desc_len + 1;
902     resource_source_name_offset = pin_table_offset + pin_count * 2;
903     vendor_data_offset = resource_source_name_offset + resource_source_name_len;
904 
905     build_append_byte(var->buf, 0x8C);  /* GPIO Connection Descriptor */
906     build_append_int_noprefix(var->buf, length, 2); /* Length */
907     build_append_byte(var->buf, 1);     /* Revision ID */
908     build_append_byte(var->buf, type);  /* GPIO Connection Type */
909     /* General Flags (2 bytes) */
910     build_append_int_noprefix(var->buf, con_and_pro, 2);
911     /* Interrupt and IO Flags (2 bytes) */
912     build_append_int_noprefix(var->buf, flags, 2);
913     /* Pin Configuration 0 = Default 1 = Pull-up 2 = Pull-down 3 = No Pull */
914     build_append_byte(var->buf, pin_config);
915     /* Output Drive Strength (2 bytes) */
916     build_append_int_noprefix(var->buf, output_drive, 2);
917     /* Debounce Timeout (2 bytes) */
918     build_append_int_noprefix(var->buf, debounce_timeout, 2);
919     /* Pin Table Offset (2 bytes) */
920     build_append_int_noprefix(var->buf, pin_table_offset, 2);
921     build_append_byte(var->buf, 0);     /* Resource Source Index */
922     /* Resource Source Name Offset (2 bytes) */
923     build_append_int_noprefix(var->buf, resource_source_name_offset, 2);
924     /* Vendor Data Offset (2 bytes) */
925     build_append_int_noprefix(var->buf, vendor_data_offset, 2);
926     /* Vendor Data Length (2 bytes) */
927     build_append_int_noprefix(var->buf, vendor_data_len, 2);
928     /* Pin Number (2n bytes)*/
929     for (i = 0; i < pin_count; i++) {
930         build_append_int_noprefix(var->buf, pin_list[i], 2);
931     }
932 
933     /* Resource Source Name */
934     build_append_namestring(var->buf, "%s", resource_source_name);
935     build_append_byte(var->buf, '\0');
936 
937     /* Vendor-defined Data */
938     if (vendor_data != NULL) {
939         g_array_append_vals(var->buf, vendor_data, vendor_data_len);
940     }
941 
942     return var;
943 }
944 
945 /*
946  * ACPI 5.0: 19.5.53
947  * GpioInt(GPIO Interrupt Connection Resource Descriptor Macro)
948  */
aml_gpio_int(AmlConsumerAndProducer con_and_pro,AmlLevelAndEdge edge_level,AmlActiveHighAndLow active_level,AmlShared shared,AmlPinConfig pin_config,uint16_t debounce_timeout,const uint32_t pin_list[],uint32_t pin_count,const char * resource_source_name,const uint8_t * vendor_data,uint16_t vendor_data_len)949 Aml *aml_gpio_int(AmlConsumerAndProducer con_and_pro,
950                   AmlLevelAndEdge edge_level,
951                   AmlActiveHighAndLow active_level, AmlShared shared,
952                   AmlPinConfig pin_config, uint16_t debounce_timeout,
953                   const uint32_t pin_list[], uint32_t pin_count,
954                   const char *resource_source_name,
955                   const uint8_t *vendor_data, uint16_t vendor_data_len)
956 {
957     uint8_t flags = edge_level | (active_level << 1) | (shared << 3);
958 
959     return aml_gpio_connection(AML_INTERRUPT_CONNECTION, con_and_pro, flags,
960                                pin_config, 0, debounce_timeout, pin_list,
961                                pin_count, resource_source_name, vendor_data,
962                                vendor_data_len);
963 }
964 
965 /*
966  * ACPI 1.0b: 6.4.3.4 32-Bit Fixed Location Memory Range Descriptor
967  * (Type 1, Large Item Name 0x6)
968  */
aml_memory32_fixed(uint32_t addr,uint32_t size,AmlReadAndWrite read_and_write)969 Aml *aml_memory32_fixed(uint32_t addr, uint32_t size,
970                         AmlReadAndWrite read_and_write)
971 {
972     Aml *var = aml_alloc();
973     build_append_byte(var->buf, 0x86); /* Memory32Fixed Resource Descriptor */
974     build_append_byte(var->buf, 9);    /* Length, bits[7:0] value = 9 */
975     build_append_byte(var->buf, 0);    /* Length, bits[15:8] value = 0 */
976     build_append_byte(var->buf, read_and_write); /* Write status, 1 rw 0 ro */
977 
978     /* Range base address */
979     build_append_byte(var->buf, extract32(addr, 0, 8));  /* bits[7:0] */
980     build_append_byte(var->buf, extract32(addr, 8, 8));  /* bits[15:8] */
981     build_append_byte(var->buf, extract32(addr, 16, 8)); /* bits[23:16] */
982     build_append_byte(var->buf, extract32(addr, 24, 8)); /* bits[31:24] */
983 
984     /* Range length */
985     build_append_byte(var->buf, extract32(size, 0, 8));  /* bits[7:0] */
986     build_append_byte(var->buf, extract32(size, 8, 8));  /* bits[15:8] */
987     build_append_byte(var->buf, extract32(size, 16, 8)); /* bits[23:16] */
988     build_append_byte(var->buf, extract32(size, 24, 8)); /* bits[31:24] */
989     return var;
990 }
991 
992 /*
993  * ACPI 5.0: 6.4.3.6 Extended Interrupt Descriptor
994  * Type 1, Large Item Name 0x9
995  */
aml_interrupt(AmlConsumerAndProducer con_and_pro,AmlLevelAndEdge level_and_edge,AmlActiveHighAndLow high_and_low,AmlShared shared,uint32_t * irq_list,uint8_t irq_count)996 Aml *aml_interrupt(AmlConsumerAndProducer con_and_pro,
997                    AmlLevelAndEdge level_and_edge,
998                    AmlActiveHighAndLow high_and_low, AmlShared shared,
999                    uint32_t *irq_list, uint8_t irq_count)
1000 {
1001     int i;
1002     Aml *var = aml_alloc();
1003     uint8_t irq_flags = con_and_pro | (level_and_edge << 1)
1004                         | (high_and_low << 2) | (shared << 3);
1005     const int header_bytes_in_len = 2;
1006     uint16_t len = header_bytes_in_len + irq_count * sizeof(uint32_t);
1007 
1008     assert(irq_count > 0);
1009 
1010     build_append_byte(var->buf, 0x89); /* Extended irq descriptor */
1011     build_append_byte(var->buf, len & 0xFF); /* Length, bits[7:0] */
1012     build_append_byte(var->buf, len >> 8); /* Length, bits[15:8] */
1013     build_append_byte(var->buf, irq_flags); /* Interrupt Vector Information. */
1014     build_append_byte(var->buf, irq_count);   /* Interrupt table length */
1015 
1016     /* Interrupt Number List */
1017     for (i = 0; i < irq_count; i++) {
1018         build_append_int_noprefix(var->buf, irq_list[i], 4);
1019     }
1020     return var;
1021 }
1022 
1023 /* ACPI 1.0b: 6.4.2.5 I/O Port Descriptor */
aml_io(AmlIODecode dec,uint16_t min_base,uint16_t max_base,uint8_t aln,uint8_t len)1024 Aml *aml_io(AmlIODecode dec, uint16_t min_base, uint16_t max_base,
1025             uint8_t aln, uint8_t len)
1026 {
1027     Aml *var = aml_alloc();
1028     build_append_byte(var->buf, 0x47); /* IO port descriptor */
1029     build_append_byte(var->buf, dec);
1030     build_append_byte(var->buf, min_base & 0xff);
1031     build_append_byte(var->buf, (min_base >> 8) & 0xff);
1032     build_append_byte(var->buf, max_base & 0xff);
1033     build_append_byte(var->buf, (max_base >> 8) & 0xff);
1034     build_append_byte(var->buf, aln);
1035     build_append_byte(var->buf, len);
1036     return var;
1037 }
1038 
1039 /*
1040  * ACPI 1.0b: 6.4.2.1.1 ASL Macro for IRQ Descriptor
1041  *
1042  * More verbose description at:
1043  * ACPI 5.0: 19.5.64 IRQNoFlags (Interrupt Resource Descriptor Macro)
1044  *           6.4.2.1 IRQ Descriptor
1045  */
aml_irq_no_flags(uint8_t irq)1046 Aml *aml_irq_no_flags(uint8_t irq)
1047 {
1048     uint16_t irq_mask;
1049     Aml *var = aml_alloc();
1050 
1051     assert(irq < 16);
1052     build_append_byte(var->buf, 0x22); /* IRQ descriptor 2 byte form */
1053 
1054     irq_mask = 1U << irq;
1055     build_append_byte(var->buf, irq_mask & 0xFF); /* IRQ mask bits[7:0] */
1056     build_append_byte(var->buf, irq_mask >> 8); /* IRQ mask bits[15:8] */
1057     return var;
1058 }
1059 
1060 /* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefLNot */
aml_lnot(Aml * arg)1061 Aml *aml_lnot(Aml *arg)
1062 {
1063     Aml *var = aml_opcode(0x92 /* LNotOp */);
1064     aml_append(var, arg);
1065     return var;
1066 }
1067 
1068 /* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefLEqual */
aml_equal(Aml * arg1,Aml * arg2)1069 Aml *aml_equal(Aml *arg1, Aml *arg2)
1070 {
1071     Aml *var = aml_opcode(0x93 /* LequalOp */);
1072     aml_append(var, arg1);
1073     aml_append(var, arg2);
1074     return var;
1075 }
1076 
1077 /* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefLGreater */
aml_lgreater(Aml * arg1,Aml * arg2)1078 Aml *aml_lgreater(Aml *arg1, Aml *arg2)
1079 {
1080     Aml *var = aml_opcode(0x94 /* LGreaterOp */);
1081     aml_append(var, arg1);
1082     aml_append(var, arg2);
1083     return var;
1084 }
1085 
1086 /* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefLGreaterEqual */
aml_lgreater_equal(Aml * arg1,Aml * arg2)1087 Aml *aml_lgreater_equal(Aml *arg1, Aml *arg2)
1088 {
1089     /* LGreaterEqualOp := LNotOp LLessOp */
1090     Aml *var = aml_opcode(0x92 /* LNotOp */);
1091     build_append_byte(var->buf, 0x95 /* LLessOp */);
1092     aml_append(var, arg1);
1093     aml_append(var, arg2);
1094     return var;
1095 }
1096 
1097 /* ACPI 1.0b: 16.2.5.3 Type 1 Opcodes Encoding: DefIfElse */
aml_if(Aml * predicate)1098 Aml *aml_if(Aml *predicate)
1099 {
1100     Aml *var = aml_bundle(0xA0 /* IfOp */, AML_PACKAGE);
1101     aml_append(var, predicate);
1102     return var;
1103 }
1104 
1105 /* ACPI 1.0b: 16.2.5.3 Type 1 Opcodes Encoding: DefElse */
aml_else(void)1106 Aml *aml_else(void)
1107 {
1108     Aml *var = aml_bundle(0xA1 /* ElseOp */, AML_PACKAGE);
1109     return var;
1110 }
1111 
1112 /* ACPI 1.0b: 16.2.5.3 Type 1 Opcodes Encoding: DefWhile */
aml_while(Aml * predicate)1113 Aml *aml_while(Aml *predicate)
1114 {
1115     Aml *var = aml_bundle(0xA2 /* WhileOp */, AML_PACKAGE);
1116     aml_append(var, predicate);
1117     return var;
1118 }
1119 
1120 /* ACPI 1.0b: 16.2.5.2 Named Objects Encoding: DefMethod */
aml_method(const char * name,int arg_count,AmlSerializeFlag sflag)1121 Aml *aml_method(const char *name, int arg_count, AmlSerializeFlag sflag)
1122 {
1123     Aml *var = aml_bundle(0x14 /* MethodOp */, AML_PACKAGE);
1124     int methodflags;
1125 
1126     /*
1127      * MethodFlags:
1128      *   bit 0-2: ArgCount (0-7)
1129      *   bit 3: SerializeFlag
1130      *     0: NotSerialized
1131      *     1: Serialized
1132      *   bit 4-7: reserved (must be 0)
1133      */
1134     assert(arg_count < 8);
1135     methodflags = arg_count | (sflag << 3);
1136 
1137     build_append_namestring(var->buf, "%s", name);
1138     build_append_byte(var->buf, methodflags); /* MethodFlags: ArgCount */
1139     return var;
1140 }
1141 
1142 /* ACPI 1.0b: 16.2.5.2 Named Objects Encoding: DefDevice */
aml_device(const char * name_format,...)1143 Aml *aml_device(const char *name_format, ...)
1144 {
1145     va_list ap;
1146     Aml *var = aml_bundle(0x82 /* DeviceOp */, AML_EXT_PACKAGE);
1147     va_start(ap, name_format);
1148     build_append_namestringv(var->buf, name_format, ap);
1149     va_end(ap);
1150     return var;
1151 }
1152 
1153 /* ACPI 1.0b: 6.4.1 ASL Macros for Resource Descriptors */
aml_resource_template(void)1154 Aml *aml_resource_template(void)
1155 {
1156     /* ResourceTemplate is a buffer of Resources with EndTag at the end */
1157     Aml *var = aml_bundle(0x11 /* BufferOp */, AML_RES_TEMPLATE);
1158     return var;
1159 }
1160 
1161 /* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefBuffer
1162  * Pass byte_list as NULL to request uninitialized buffer to reserve space.
1163  */
aml_buffer(int buffer_size,uint8_t * byte_list)1164 Aml *aml_buffer(int buffer_size, uint8_t *byte_list)
1165 {
1166     int i;
1167     Aml *var = aml_bundle(0x11 /* BufferOp */, AML_BUFFER);
1168 
1169     for (i = 0; i < buffer_size; i++) {
1170         if (byte_list == NULL) {
1171             build_append_byte(var->buf, 0x0);
1172         } else {
1173             build_append_byte(var->buf, byte_list[i]);
1174         }
1175     }
1176 
1177     return var;
1178 }
1179 
1180 /* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefPackage */
aml_package(uint8_t num_elements)1181 Aml *aml_package(uint8_t num_elements)
1182 {
1183     Aml *var = aml_bundle(0x12 /* PackageOp */, AML_PACKAGE);
1184     build_append_byte(var->buf, num_elements);
1185     return var;
1186 }
1187 
1188 /* ACPI 1.0b: 16.2.5.2 Named Objects Encoding: DefOpRegion */
aml_operation_region(const char * name,AmlRegionSpace rs,Aml * offset,uint32_t len)1189 Aml *aml_operation_region(const char *name, AmlRegionSpace rs,
1190                           Aml *offset, uint32_t len)
1191 {
1192     Aml *var = aml_alloc();
1193     build_append_byte(var->buf, 0x5B); /* ExtOpPrefix */
1194     build_append_byte(var->buf, 0x80); /* OpRegionOp */
1195     build_append_namestring(var->buf, "%s", name);
1196     build_append_byte(var->buf, rs);
1197     aml_append(var, offset);
1198     build_append_int(var->buf, len);
1199     return var;
1200 }
1201 
1202 /* ACPI 1.0b: 16.2.5.2 Named Objects Encoding: NamedField */
aml_named_field(const char * name,unsigned length)1203 Aml *aml_named_field(const char *name, unsigned length)
1204 {
1205     Aml *var = aml_alloc();
1206     build_append_nameseg(var->buf, name);
1207     build_append_pkg_length(var->buf, length, false);
1208     return var;
1209 }
1210 
1211 /* ACPI 1.0b: 16.2.5.2 Named Objects Encoding: ReservedField */
aml_reserved_field(unsigned length)1212 Aml *aml_reserved_field(unsigned length)
1213 {
1214     Aml *var = aml_alloc();
1215     /* ReservedField  := 0x00 PkgLength */
1216     build_append_byte(var->buf, 0x00);
1217     build_append_pkg_length(var->buf, length, false);
1218     return var;
1219 }
1220 
1221 /* ACPI 1.0b: 16.2.5.2 Named Objects Encoding: DefField */
aml_field(const char * name,AmlAccessType type,AmlLockRule lock,AmlUpdateRule rule)1222 Aml *aml_field(const char *name, AmlAccessType type, AmlLockRule lock,
1223                AmlUpdateRule rule)
1224 {
1225     Aml *var = aml_bundle(0x81 /* FieldOp */, AML_EXT_PACKAGE);
1226     uint8_t flags = rule << 5 | type;
1227 
1228     flags |= lock << 4; /* LockRule at 4 bit offset */
1229 
1230     build_append_namestring(var->buf, "%s", name);
1231     build_append_byte(var->buf, flags);
1232     return var;
1233 }
1234 
1235 static
create_field_common(int opcode,Aml * srcbuf,Aml * index,const char * name)1236 Aml *create_field_common(int opcode, Aml *srcbuf, Aml *index, const char *name)
1237 {
1238     Aml *var = aml_opcode(opcode);
1239     aml_append(var, srcbuf);
1240     aml_append(var, index);
1241     build_append_namestring(var->buf, "%s", name);
1242     return var;
1243 }
1244 
1245 /* ACPI 1.0b: 16.2.5.2 Named Objects Encoding: DefCreateField */
aml_create_field(Aml * srcbuf,Aml * bit_index,Aml * num_bits,const char * name)1246 Aml *aml_create_field(Aml *srcbuf, Aml *bit_index, Aml *num_bits,
1247                       const char *name)
1248 {
1249     Aml *var = aml_alloc();
1250     build_append_byte(var->buf, 0x5B); /* ExtOpPrefix */
1251     build_append_byte(var->buf, 0x13); /* CreateFieldOp */
1252     aml_append(var, srcbuf);
1253     aml_append(var, bit_index);
1254     aml_append(var, num_bits);
1255     build_append_namestring(var->buf, "%s", name);
1256     return var;
1257 }
1258 
1259 /* ACPI 1.0b: 16.2.5.2 Named Objects Encoding: DefCreateDWordField */
aml_create_dword_field(Aml * srcbuf,Aml * index,const char * name)1260 Aml *aml_create_dword_field(Aml *srcbuf, Aml *index, const char *name)
1261 {
1262     return create_field_common(0x8A /* CreateDWordFieldOp */,
1263                                srcbuf, index, name);
1264 }
1265 
1266 /* ACPI 2.0a: 17.2.4.2 Named Objects Encoding: DefCreateQWordField */
aml_create_qword_field(Aml * srcbuf,Aml * index,const char * name)1267 Aml *aml_create_qword_field(Aml *srcbuf, Aml *index, const char *name)
1268 {
1269     return create_field_common(0x8F /* CreateQWordFieldOp */,
1270                                srcbuf, index, name);
1271 }
1272 
1273 /* ACPI 1.0b: 16.2.3 Data Objects Encoding: String */
aml_string(const char * name_format,...)1274 Aml *aml_string(const char *name_format, ...)
1275 {
1276     Aml *var = aml_opcode(0x0D /* StringPrefix */);
1277     va_list ap;
1278     char *s;
1279     int len;
1280 
1281     va_start(ap, name_format);
1282     len = g_vasprintf(&s, name_format, ap);
1283     va_end(ap);
1284 
1285     g_array_append_vals(var->buf, s, len + 1);
1286     g_free(s);
1287 
1288     return var;
1289 }
1290 
1291 /* ACPI 1.0b: 16.2.6.2 Local Objects Encoding */
aml_local(int num)1292 Aml *aml_local(int num)
1293 {
1294     uint8_t op = 0x60 /* Local0Op */ + num;
1295 
1296     assert(num <= 7);
1297     return aml_opcode(op);
1298 }
1299 
1300 /* ACPI 2.0a: 17.2.2 Data Objects Encoding: DefVarPackage */
aml_varpackage(uint32_t num_elements)1301 Aml *aml_varpackage(uint32_t num_elements)
1302 {
1303     Aml *var = aml_bundle(0x13 /* VarPackageOp */, AML_PACKAGE);
1304     build_append_int(var->buf, num_elements);
1305     return var;
1306 }
1307 
1308 /* ACPI 1.0b: 16.2.5.2 Named Objects Encoding: DefProcessor */
aml_processor(uint8_t proc_id,uint32_t pblk_addr,uint8_t pblk_len,const char * name_format,...)1309 Aml *aml_processor(uint8_t proc_id, uint32_t pblk_addr, uint8_t pblk_len,
1310                    const char *name_format, ...)
1311 {
1312     va_list ap;
1313     Aml *var = aml_bundle(0x83 /* ProcessorOp */, AML_EXT_PACKAGE);
1314     va_start(ap, name_format);
1315     build_append_namestringv(var->buf, name_format, ap);
1316     va_end(ap);
1317     build_append_byte(var->buf, proc_id); /* ProcID */
1318     build_append_int_noprefix(var->buf, pblk_addr, sizeof(pblk_addr));
1319     build_append_byte(var->buf, pblk_len); /* PblkLen */
1320     return var;
1321 }
1322 
Hex2Digit(char c)1323 static uint8_t Hex2Digit(char c)
1324 {
1325     if (c >= 'A') {
1326         return c - 'A' + 10;
1327     }
1328 
1329     return c - '0';
1330 }
1331 
1332 /* ACPI 1.0b: 15.2.3.6.4.1 EISAID Macro - Convert EISA ID String To Integer */
aml_eisaid(const char * str)1333 Aml *aml_eisaid(const char *str)
1334 {
1335     Aml *var = aml_alloc();
1336     uint32_t id;
1337 
1338     g_assert(strlen(str) == 7);
1339     id = (str[0] - 0x40) << 26 |
1340     (str[1] - 0x40) << 21 |
1341     (str[2] - 0x40) << 16 |
1342     Hex2Digit(str[3]) << 12 |
1343     Hex2Digit(str[4]) << 8 |
1344     Hex2Digit(str[5]) << 4 |
1345     Hex2Digit(str[6]);
1346 
1347     build_append_byte(var->buf, 0x0C); /* DWordPrefix */
1348     build_append_int_noprefix(var->buf, bswap32(id), sizeof(id));
1349     return var;
1350 }
1351 
1352 /* ACPI 1.0b: 6.4.3.5.5 Word Address Space Descriptor: bytes 3-5 */
aml_as_desc_header(AmlResourceType type,AmlMinFixed min_fixed,AmlMaxFixed max_fixed,AmlDecode dec,uint8_t type_flags)1353 static Aml *aml_as_desc_header(AmlResourceType type, AmlMinFixed min_fixed,
1354                                AmlMaxFixed max_fixed, AmlDecode dec,
1355                                uint8_t type_flags)
1356 {
1357     uint8_t flags = max_fixed | min_fixed | dec;
1358     Aml *var = aml_alloc();
1359 
1360     build_append_byte(var->buf, type);
1361     build_append_byte(var->buf, flags);
1362     build_append_byte(var->buf, type_flags); /* Type Specific Flags */
1363     return var;
1364 }
1365 
1366 /* ACPI 1.0b: 6.4.3.5.5 Word Address Space Descriptor */
aml_word_as_desc(AmlResourceType type,AmlMinFixed min_fixed,AmlMaxFixed max_fixed,AmlDecode dec,uint16_t addr_gran,uint16_t addr_min,uint16_t addr_max,uint16_t addr_trans,uint16_t len,uint8_t type_flags)1367 static Aml *aml_word_as_desc(AmlResourceType type, AmlMinFixed min_fixed,
1368                              AmlMaxFixed max_fixed, AmlDecode dec,
1369                              uint16_t addr_gran, uint16_t addr_min,
1370                              uint16_t addr_max, uint16_t addr_trans,
1371                              uint16_t len, uint8_t type_flags)
1372 {
1373     Aml *var = aml_alloc();
1374 
1375     build_append_byte(var->buf, 0x88); /* Word Address Space Descriptor */
1376     /* minimum length since we do not encode optional fields */
1377     build_append_byte(var->buf, 0x0D);
1378     build_append_byte(var->buf, 0x0);
1379 
1380     aml_append(var,
1381         aml_as_desc_header(type, min_fixed, max_fixed, dec, type_flags));
1382     build_append_int_noprefix(var->buf, addr_gran, sizeof(addr_gran));
1383     build_append_int_noprefix(var->buf, addr_min, sizeof(addr_min));
1384     build_append_int_noprefix(var->buf, addr_max, sizeof(addr_max));
1385     build_append_int_noprefix(var->buf, addr_trans, sizeof(addr_trans));
1386     build_append_int_noprefix(var->buf, len, sizeof(len));
1387     return var;
1388 }
1389 
1390 /* ACPI 1.0b: 6.4.3.5.3 DWord Address Space Descriptor */
aml_dword_as_desc(AmlResourceType type,AmlMinFixed min_fixed,AmlMaxFixed max_fixed,AmlDecode dec,uint32_t addr_gran,uint32_t addr_min,uint32_t addr_max,uint32_t addr_trans,uint32_t len,uint8_t type_flags)1391 static Aml *aml_dword_as_desc(AmlResourceType type, AmlMinFixed min_fixed,
1392                               AmlMaxFixed max_fixed, AmlDecode dec,
1393                               uint32_t addr_gran, uint32_t addr_min,
1394                               uint32_t addr_max, uint32_t addr_trans,
1395                               uint32_t len, uint8_t type_flags)
1396 {
1397     Aml *var = aml_alloc();
1398 
1399     build_append_byte(var->buf, 0x87); /* DWord Address Space Descriptor */
1400     /* minimum length since we do not encode optional fields */
1401     build_append_byte(var->buf, 23);
1402     build_append_byte(var->buf, 0x0);
1403 
1404 
1405     aml_append(var,
1406         aml_as_desc_header(type, min_fixed, max_fixed, dec, type_flags));
1407     build_append_int_noprefix(var->buf, addr_gran, sizeof(addr_gran));
1408     build_append_int_noprefix(var->buf, addr_min, sizeof(addr_min));
1409     build_append_int_noprefix(var->buf, addr_max, sizeof(addr_max));
1410     build_append_int_noprefix(var->buf, addr_trans, sizeof(addr_trans));
1411     build_append_int_noprefix(var->buf, len, sizeof(len));
1412     return var;
1413 }
1414 
1415 /* ACPI 1.0b: 6.4.3.5.1 QWord Address Space Descriptor */
aml_qword_as_desc(AmlResourceType type,AmlMinFixed min_fixed,AmlMaxFixed max_fixed,AmlDecode dec,uint64_t addr_gran,uint64_t addr_min,uint64_t addr_max,uint64_t addr_trans,uint64_t len,uint8_t type_flags)1416 static Aml *aml_qword_as_desc(AmlResourceType type, AmlMinFixed min_fixed,
1417                               AmlMaxFixed max_fixed, AmlDecode dec,
1418                               uint64_t addr_gran, uint64_t addr_min,
1419                               uint64_t addr_max, uint64_t addr_trans,
1420                               uint64_t len, uint8_t type_flags)
1421 {
1422     Aml *var = aml_alloc();
1423 
1424     build_append_byte(var->buf, 0x8A); /* QWord Address Space Descriptor */
1425     /* minimum length since we do not encode optional fields */
1426     build_append_byte(var->buf, 0x2B);
1427     build_append_byte(var->buf, 0x0);
1428 
1429     aml_append(var,
1430         aml_as_desc_header(type, min_fixed, max_fixed, dec, type_flags));
1431     build_append_int_noprefix(var->buf, addr_gran, sizeof(addr_gran));
1432     build_append_int_noprefix(var->buf, addr_min, sizeof(addr_min));
1433     build_append_int_noprefix(var->buf, addr_max, sizeof(addr_max));
1434     build_append_int_noprefix(var->buf, addr_trans, sizeof(addr_trans));
1435     build_append_int_noprefix(var->buf, len, sizeof(len));
1436     return var;
1437 }
1438 
1439 /*
1440  * ACPI 1.0b: 6.4.3.5.6 ASL Macros for WORD Address Descriptor
1441  *
1442  * More verbose description at:
1443  * ACPI 5.0: 19.5.141 WordBusNumber (Word Bus Number Resource Descriptor Macro)
1444  */
aml_word_bus_number(AmlMinFixed min_fixed,AmlMaxFixed max_fixed,AmlDecode dec,uint16_t addr_gran,uint16_t addr_min,uint16_t addr_max,uint16_t addr_trans,uint16_t len)1445 Aml *aml_word_bus_number(AmlMinFixed min_fixed, AmlMaxFixed max_fixed,
1446                          AmlDecode dec, uint16_t addr_gran,
1447                          uint16_t addr_min, uint16_t addr_max,
1448                          uint16_t addr_trans, uint16_t len)
1449 
1450 {
1451     return aml_word_as_desc(AML_BUS_NUMBER_RANGE, min_fixed, max_fixed, dec,
1452                             addr_gran, addr_min, addr_max, addr_trans, len, 0);
1453 }
1454 
1455 /*
1456  * ACPI 1.0b: 6.4.3.5.6 ASL Macros for WORD Address Descriptor
1457  *
1458  * More verbose description at:
1459  * ACPI 5.0: 19.5.142 WordIO (Word IO Resource Descriptor Macro)
1460  */
aml_word_io(AmlMinFixed min_fixed,AmlMaxFixed max_fixed,AmlDecode dec,AmlISARanges isa_ranges,uint16_t addr_gran,uint16_t addr_min,uint16_t addr_max,uint16_t addr_trans,uint16_t len)1461 Aml *aml_word_io(AmlMinFixed min_fixed, AmlMaxFixed max_fixed,
1462                  AmlDecode dec, AmlISARanges isa_ranges,
1463                  uint16_t addr_gran, uint16_t addr_min,
1464                  uint16_t addr_max, uint16_t addr_trans,
1465                  uint16_t len)
1466 
1467 {
1468     return aml_word_as_desc(AML_IO_RANGE, min_fixed, max_fixed, dec,
1469                             addr_gran, addr_min, addr_max, addr_trans, len,
1470                             isa_ranges);
1471 }
1472 
1473 /*
1474  * ACPI 1.0b: 6.4.3.5.4 ASL Macros for DWORD Address Descriptor
1475  *
1476  * More verbose description at:
1477  * ACPI 5.0: 19.5.33 DWordIO (DWord IO Resource Descriptor Macro)
1478  */
aml_dword_io(AmlMinFixed min_fixed,AmlMaxFixed max_fixed,AmlDecode dec,AmlISARanges isa_ranges,uint32_t addr_gran,uint32_t addr_min,uint32_t addr_max,uint32_t addr_trans,uint32_t len)1479 Aml *aml_dword_io(AmlMinFixed min_fixed, AmlMaxFixed max_fixed,
1480                  AmlDecode dec, AmlISARanges isa_ranges,
1481                  uint32_t addr_gran, uint32_t addr_min,
1482                  uint32_t addr_max, uint32_t addr_trans,
1483                  uint32_t len)
1484 
1485 {
1486     return aml_dword_as_desc(AML_IO_RANGE, min_fixed, max_fixed, dec,
1487                             addr_gran, addr_min, addr_max, addr_trans, len,
1488                             isa_ranges);
1489 }
1490 
1491 /*
1492  * ACPI 1.0b: 6.4.3.5.4 ASL Macros for DWORD Address Space Descriptor
1493  *
1494  * More verbose description at:
1495  * ACPI 5.0: 19.5.34 DWordMemory (DWord Memory Resource Descriptor Macro)
1496  */
aml_dword_memory(AmlDecode dec,AmlMinFixed min_fixed,AmlMaxFixed max_fixed,AmlCacheable cacheable,AmlReadAndWrite read_and_write,uint32_t addr_gran,uint32_t addr_min,uint32_t addr_max,uint32_t addr_trans,uint32_t len)1497 Aml *aml_dword_memory(AmlDecode dec, AmlMinFixed min_fixed,
1498                       AmlMaxFixed max_fixed, AmlCacheable cacheable,
1499                       AmlReadAndWrite read_and_write,
1500                       uint32_t addr_gran, uint32_t addr_min,
1501                       uint32_t addr_max, uint32_t addr_trans,
1502                       uint32_t len)
1503 {
1504     uint8_t flags = read_and_write | (cacheable << 1);
1505 
1506     return aml_dword_as_desc(AML_MEMORY_RANGE, min_fixed, max_fixed,
1507                              dec, addr_gran, addr_min, addr_max,
1508                              addr_trans, len, flags);
1509 }
1510 
1511 /*
1512  * ACPI 1.0b: 6.4.3.5.2 ASL Macros for QWORD Address Space Descriptor
1513  *
1514  * More verbose description at:
1515  * ACPI 5.0: 19.5.102 QWordMemory (QWord Memory Resource Descriptor Macro)
1516  */
aml_qword_memory(AmlDecode dec,AmlMinFixed min_fixed,AmlMaxFixed max_fixed,AmlCacheable cacheable,AmlReadAndWrite read_and_write,uint64_t addr_gran,uint64_t addr_min,uint64_t addr_max,uint64_t addr_trans,uint64_t len)1517 Aml *aml_qword_memory(AmlDecode dec, AmlMinFixed min_fixed,
1518                       AmlMaxFixed max_fixed, AmlCacheable cacheable,
1519                       AmlReadAndWrite read_and_write,
1520                       uint64_t addr_gran, uint64_t addr_min,
1521                       uint64_t addr_max, uint64_t addr_trans,
1522                       uint64_t len)
1523 {
1524     uint8_t flags = read_and_write | (cacheable << 1);
1525 
1526     return aml_qword_as_desc(AML_MEMORY_RANGE, min_fixed, max_fixed,
1527                              dec, addr_gran, addr_min, addr_max,
1528                              addr_trans, len, flags);
1529 }
1530 
1531 /* ACPI 1.0b: 6.4.2.2 DMA Format/6.4.2.2.1 ASL Macro for DMA Descriptor */
aml_dma(AmlDmaType typ,AmlDmaBusMaster bm,AmlTransferSize sz,uint8_t channel)1532 Aml *aml_dma(AmlDmaType typ, AmlDmaBusMaster bm, AmlTransferSize sz,
1533              uint8_t channel)
1534 {
1535     Aml *var = aml_alloc();
1536     uint8_t flags = sz | bm << 2 | typ << 5;
1537 
1538     assert(channel < 8);
1539     build_append_byte(var->buf, 0x2A);    /* Byte 0: DMA Descriptor */
1540     build_append_byte(var->buf, 1U << channel); /* Byte 1: _DMA - DmaChannel */
1541     build_append_byte(var->buf, flags);   /* Byte 2 */
1542     return var;
1543 }
1544 
1545 /* ACPI 1.0b: 16.2.5.3 Type 1 Opcodes Encoding: DefSleep */
aml_sleep(uint64_t msec)1546 Aml *aml_sleep(uint64_t msec)
1547 {
1548     Aml *var = aml_alloc();
1549     build_append_byte(var->buf, 0x5B); /* ExtOpPrefix */
1550     build_append_byte(var->buf, 0x22); /* SleepOp */
1551     aml_append(var, aml_int(msec));
1552     return var;
1553 }
1554 
Hex2Byte(const char * src)1555 static uint8_t Hex2Byte(const char *src)
1556 {
1557     int hi, lo;
1558 
1559     hi = Hex2Digit(src[0]);
1560     assert(hi >= 0);
1561     assert(hi <= 15);
1562 
1563     lo = Hex2Digit(src[1]);
1564     assert(lo >= 0);
1565     assert(lo <= 15);
1566     return (hi << 4) | lo;
1567 }
1568 
1569 /*
1570  * ACPI 3.0: 17.5.124 ToUUID (Convert String to UUID Macro)
1571  * e.g. UUID: aabbccdd-eeff-gghh-iijj-kkllmmnnoopp
1572  * call aml_touuid("aabbccdd-eeff-gghh-iijj-kkllmmnnoopp");
1573  */
aml_touuid(const char * uuid)1574 Aml *aml_touuid(const char *uuid)
1575 {
1576     Aml *var = aml_bundle(0x11 /* BufferOp */, AML_BUFFER);
1577 
1578     assert(strlen(uuid) == 36);
1579     assert(uuid[8] == '-');
1580     assert(uuid[13] == '-');
1581     assert(uuid[18] == '-');
1582     assert(uuid[23] == '-');
1583 
1584     build_append_byte(var->buf, Hex2Byte(uuid + 6));  /* dd - at offset 00 */
1585     build_append_byte(var->buf, Hex2Byte(uuid + 4));  /* cc - at offset 01 */
1586     build_append_byte(var->buf, Hex2Byte(uuid + 2));  /* bb - at offset 02 */
1587     build_append_byte(var->buf, Hex2Byte(uuid + 0));  /* aa - at offset 03 */
1588 
1589     build_append_byte(var->buf, Hex2Byte(uuid + 11)); /* ff - at offset 04 */
1590     build_append_byte(var->buf, Hex2Byte(uuid + 9));  /* ee - at offset 05 */
1591 
1592     build_append_byte(var->buf, Hex2Byte(uuid + 16)); /* hh - at offset 06 */
1593     build_append_byte(var->buf, Hex2Byte(uuid + 14)); /* gg - at offset 07 */
1594 
1595     build_append_byte(var->buf, Hex2Byte(uuid + 19)); /* ii - at offset 08 */
1596     build_append_byte(var->buf, Hex2Byte(uuid + 21)); /* jj - at offset 09 */
1597 
1598     build_append_byte(var->buf, Hex2Byte(uuid + 24)); /* kk - at offset 10 */
1599     build_append_byte(var->buf, Hex2Byte(uuid + 26)); /* ll - at offset 11 */
1600     build_append_byte(var->buf, Hex2Byte(uuid + 28)); /* mm - at offset 12 */
1601     build_append_byte(var->buf, Hex2Byte(uuid + 30)); /* nn - at offset 13 */
1602     build_append_byte(var->buf, Hex2Byte(uuid + 32)); /* oo - at offset 14 */
1603     build_append_byte(var->buf, Hex2Byte(uuid + 34)); /* pp - at offset 15 */
1604 
1605     return var;
1606 }
1607 
1608 /*
1609  * ACPI 2.0b: 16.2.3.6.4.3  Unicode Macro (Convert Ascii String To Unicode)
1610  */
aml_unicode(const char * str)1611 Aml *aml_unicode(const char *str)
1612 {
1613     int i = 0;
1614     Aml *var = aml_bundle(0x11 /* BufferOp */, AML_BUFFER);
1615 
1616     do {
1617         build_append_byte(var->buf, str[i]);
1618         build_append_byte(var->buf, 0);
1619         i++;
1620     } while (i <= strlen(str));
1621 
1622     return var;
1623 }
1624 
1625 /* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefRefOf */
aml_refof(Aml * arg)1626 Aml *aml_refof(Aml *arg)
1627 {
1628     Aml *var = aml_opcode(0x71 /* RefOfOp */);
1629     aml_append(var, arg);
1630     return var;
1631 }
1632 
1633 /* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefDerefOf */
aml_derefof(Aml * arg)1634 Aml *aml_derefof(Aml *arg)
1635 {
1636     Aml *var = aml_opcode(0x83 /* DerefOfOp */);
1637     aml_append(var, arg);
1638     return var;
1639 }
1640 
1641 /* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefSizeOf */
aml_sizeof(Aml * arg)1642 Aml *aml_sizeof(Aml *arg)
1643 {
1644     Aml *var = aml_opcode(0x87 /* SizeOfOp */);
1645     aml_append(var, arg);
1646     return var;
1647 }
1648 
1649 /* ACPI 1.0b: 16.2.5.2 Named Objects Encoding: DefMutex */
aml_mutex(const char * name,uint8_t sync_level)1650 Aml *aml_mutex(const char *name, uint8_t sync_level)
1651 {
1652     Aml *var = aml_alloc();
1653     build_append_byte(var->buf, 0x5B); /* ExtOpPrefix */
1654     build_append_byte(var->buf, 0x01); /* MutexOp */
1655     build_append_namestring(var->buf, "%s", name);
1656     assert(!(sync_level & 0xF0));
1657     build_append_byte(var->buf, sync_level);
1658     return var;
1659 }
1660 
1661 /* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefAcquire */
aml_acquire(Aml * mutex,uint16_t timeout)1662 Aml *aml_acquire(Aml *mutex, uint16_t timeout)
1663 {
1664     Aml *var = aml_alloc();
1665     build_append_byte(var->buf, 0x5B); /* ExtOpPrefix */
1666     build_append_byte(var->buf, 0x23); /* AcquireOp */
1667     aml_append(var, mutex);
1668     build_append_int_noprefix(var->buf, timeout, sizeof(timeout));
1669     return var;
1670 }
1671 
1672 /* ACPI 1.0b: 16.2.5.3 Type 1 Opcodes Encoding: DefRelease */
aml_release(Aml * mutex)1673 Aml *aml_release(Aml *mutex)
1674 {
1675     Aml *var = aml_alloc();
1676     build_append_byte(var->buf, 0x5B); /* ExtOpPrefix */
1677     build_append_byte(var->buf, 0x27); /* ReleaseOp */
1678     aml_append(var, mutex);
1679     return var;
1680 }
1681 
1682 /* ACPI 1.0b: 16.2.5.1 Name Space Modifier Objects Encoding: DefAlias */
aml_alias(const char * source_object,const char * alias_object)1683 Aml *aml_alias(const char *source_object, const char *alias_object)
1684 {
1685     Aml *var = aml_opcode(0x06 /* AliasOp */);
1686     aml_append(var, aml_name("%s", source_object));
1687     aml_append(var, aml_name("%s", alias_object));
1688     return var;
1689 }
1690 
1691 /* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefConcat */
aml_concatenate(Aml * source1,Aml * source2,Aml * target)1692 Aml *aml_concatenate(Aml *source1, Aml *source2, Aml *target)
1693 {
1694     return build_opcode_2arg_dst(0x73 /* ConcatOp */, source1, source2,
1695                                  target);
1696 }
1697 
1698 /* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefObjectType */
aml_object_type(Aml * object)1699 Aml *aml_object_type(Aml *object)
1700 {
1701     Aml *var = aml_opcode(0x8E /* ObjectTypeOp */);
1702     aml_append(var, object);
1703     return var;
1704 }
1705 
acpi_table_begin(AcpiTable * desc,GArray * array)1706 void acpi_table_begin(AcpiTable *desc, GArray *array)
1707 {
1708 
1709     desc->array = array;
1710     desc->table_offset = array->len;
1711 
1712     /*
1713      * ACPI spec 1.0b
1714      * 5.2.3 System Description Table Header
1715      */
1716     g_assert(strlen(desc->sig) == 4);
1717     g_array_append_vals(array, desc->sig, 4); /* Signature */
1718     /*
1719      * reserve space for Length field, which will be patched by
1720      * acpi_table_end() when the table creation is finished.
1721      */
1722     build_append_int_noprefix(array, 0, 4); /* Length */
1723     build_append_int_noprefix(array, desc->rev, 1); /* Revision */
1724     build_append_int_noprefix(array, 0, 1); /* Checksum */
1725     build_append_padded_str(array, desc->oem_id, 6, '\0'); /* OEMID */
1726     /* OEM Table ID */
1727     build_append_padded_str(array, desc->oem_table_id, 8, '\0');
1728     build_append_int_noprefix(array, 1, 4); /* OEM Revision */
1729     g_array_append_vals(array, ACPI_BUILD_APPNAME8, 4); /* Creator ID */
1730     build_append_int_noprefix(array, 1, 4); /* Creator Revision */
1731 }
1732 
acpi_table_end(BIOSLinker * linker,AcpiTable * desc)1733 void acpi_table_end(BIOSLinker *linker, AcpiTable *desc)
1734 {
1735     /*
1736      * ACPI spec 1.0b
1737      * 5.2.3 System Description Table Header
1738      * Table 5-2 DESCRIPTION_HEADER Fields
1739      */
1740     const unsigned checksum_offset = 9;
1741     uint32_t table_len = desc->array->len - desc->table_offset;
1742     uint32_t table_len_le = cpu_to_le32(table_len);
1743     gchar *len_ptr = &desc->array->data[desc->table_offset + 4];
1744 
1745     /* patch "Length" field that has been reserved by acpi_table_begin()
1746      * to the actual length, i.e. accumulated table length from
1747      * acpi_table_begin() till acpi_table_end()
1748      */
1749     memcpy(len_ptr, &table_len_le, sizeof table_len_le);
1750 
1751     bios_linker_loader_add_checksum(linker, ACPI_BUILD_TABLE_FILE,
1752         desc->table_offset, table_len, desc->table_offset + checksum_offset);
1753 }
1754 
acpi_data_push(GArray * table_data,unsigned size)1755 void *acpi_data_push(GArray *table_data, unsigned size)
1756 {
1757     unsigned off = table_data->len;
1758     g_array_set_size(table_data, off + size);
1759     return table_data->data + off;
1760 }
1761 
acpi_data_len(GArray * table)1762 unsigned acpi_data_len(GArray *table)
1763 {
1764     assert(g_array_get_element_size(table) == 1);
1765     return table->len;
1766 }
1767 
acpi_add_table(GArray * table_offsets,GArray * table_data)1768 void acpi_add_table(GArray *table_offsets, GArray *table_data)
1769 {
1770     uint32_t offset = table_data->len;
1771     g_array_append_val(table_offsets, offset);
1772 }
1773 
acpi_build_tables_init(AcpiBuildTables * tables)1774 void acpi_build_tables_init(AcpiBuildTables *tables)
1775 {
1776     tables->rsdp = g_array_new(false, true /* clear */, 1);
1777     tables->table_data = g_array_new(false, true /* clear */, 1);
1778     tables->tcpalog = g_array_new(false, true /* clear */, 1);
1779     tables->vmgenid = g_array_new(false, true /* clear */, 1);
1780     tables->hardware_errors = g_array_new(false, true /* clear */, 1);
1781     tables->linker = bios_linker_loader_init();
1782 }
1783 
acpi_build_tables_cleanup(AcpiBuildTables * tables,bool mfre)1784 void acpi_build_tables_cleanup(AcpiBuildTables *tables, bool mfre)
1785 {
1786     bios_linker_loader_cleanup(tables->linker);
1787     g_array_free(tables->rsdp, true);
1788     g_array_free(tables->table_data, true);
1789     g_array_free(tables->tcpalog, mfre);
1790     g_array_free(tables->vmgenid, mfre);
1791     g_array_free(tables->hardware_errors, mfre);
1792 }
1793 
1794 /*
1795  * ACPI spec 5.2.5.3 Root System Description Pointer (RSDP).
1796  * (Revision 1.0 or later)
1797  */
1798 void
build_rsdp(GArray * tbl,BIOSLinker * linker,AcpiRsdpData * rsdp_data)1799 build_rsdp(GArray *tbl, BIOSLinker *linker, AcpiRsdpData *rsdp_data)
1800 {
1801     int tbl_off = tbl->len; /* Table offset in the RSDP file */
1802 
1803     switch (rsdp_data->revision) {
1804     case 0:
1805         /* With ACPI 1.0, we must have an RSDT pointer */
1806         g_assert(rsdp_data->rsdt_tbl_offset);
1807         break;
1808     case 2:
1809         /* With ACPI 2.0+, we must have an XSDT pointer */
1810         g_assert(rsdp_data->xsdt_tbl_offset);
1811         break;
1812     default:
1813         /* Only revisions 0 (ACPI 1.0) and 2 (ACPI 2.0+) are valid for RSDP */
1814         g_assert_not_reached();
1815     }
1816 
1817     bios_linker_loader_alloc(linker, ACPI_BUILD_RSDP_FILE, tbl, 16,
1818                              true /* fseg memory */);
1819 
1820     g_array_append_vals(tbl, "RSD PTR ", 8); /* Signature */
1821     build_append_int_noprefix(tbl, 0, 1); /* Checksum */
1822     g_array_append_vals(tbl, rsdp_data->oem_id, 6); /* OEMID */
1823     build_append_int_noprefix(tbl, rsdp_data->revision, 1); /* Revision */
1824     build_append_int_noprefix(tbl, 0, 4); /* RsdtAddress */
1825     if (rsdp_data->rsdt_tbl_offset) {
1826         /* RSDT address to be filled by guest linker */
1827         bios_linker_loader_add_pointer(linker, ACPI_BUILD_RSDP_FILE,
1828                                        tbl_off + 16, 4,
1829                                        ACPI_BUILD_TABLE_FILE,
1830                                        *rsdp_data->rsdt_tbl_offset);
1831     }
1832 
1833     /* Checksum to be filled by guest linker */
1834     bios_linker_loader_add_checksum(linker, ACPI_BUILD_RSDP_FILE,
1835                                     tbl_off, 20, /* ACPI rev 1.0 RSDP size */
1836                                     8);
1837 
1838     if (rsdp_data->revision == 0) {
1839         /* ACPI 1.0 RSDP, we're done */
1840         return;
1841     }
1842 
1843     build_append_int_noprefix(tbl, 36, 4); /* Length */
1844 
1845     /* XSDT address to be filled by guest linker */
1846     build_append_int_noprefix(tbl, 0, 8); /* XsdtAddress */
1847     /* We already validated our xsdt pointer */
1848     bios_linker_loader_add_pointer(linker, ACPI_BUILD_RSDP_FILE,
1849                                    tbl_off + 24, 8,
1850                                    ACPI_BUILD_TABLE_FILE,
1851                                    *rsdp_data->xsdt_tbl_offset);
1852 
1853     build_append_int_noprefix(tbl, 0, 1); /* Extended Checksum */
1854     build_append_int_noprefix(tbl, 0, 3); /* Reserved */
1855 
1856     /* Extended checksum to be filled by Guest linker */
1857     bios_linker_loader_add_checksum(linker, ACPI_BUILD_RSDP_FILE,
1858                                     tbl_off, 36, /* ACPI rev 2.0 RSDP size */
1859                                     32);
1860 }
1861 
1862 /*
1863  * ACPI 1.0 Root System Description Table (RSDT)
1864  */
1865 void
build_rsdt(GArray * table_data,BIOSLinker * linker,GArray * table_offsets,const char * oem_id,const char * oem_table_id)1866 build_rsdt(GArray *table_data, BIOSLinker *linker, GArray *table_offsets,
1867            const char *oem_id, const char *oem_table_id)
1868 {
1869     int i;
1870     AcpiTable table = { .sig = "RSDT", .rev = 1,
1871                         .oem_id = oem_id, .oem_table_id = oem_table_id };
1872 
1873     acpi_table_begin(&table, table_data);
1874     for (i = 0; i < table_offsets->len; ++i) {
1875         uint32_t ref_tbl_offset = g_array_index(table_offsets, uint32_t, i);
1876         uint32_t rsdt_entry_offset = table.array->len;
1877 
1878         /* reserve space for entry */
1879         build_append_int_noprefix(table.array, 0, 4);
1880 
1881         /* mark position of RSDT entry to be filled by Guest linker */
1882         bios_linker_loader_add_pointer(linker,
1883             ACPI_BUILD_TABLE_FILE, rsdt_entry_offset, 4,
1884             ACPI_BUILD_TABLE_FILE, ref_tbl_offset);
1885 
1886     }
1887     acpi_table_end(linker, &table);
1888 }
1889 
1890 /*
1891  * ACPI 2.0 eXtended System Description Table (XSDT)
1892  */
1893 void
build_xsdt(GArray * table_data,BIOSLinker * linker,GArray * table_offsets,const char * oem_id,const char * oem_table_id)1894 build_xsdt(GArray *table_data, BIOSLinker *linker, GArray *table_offsets,
1895            const char *oem_id, const char *oem_table_id)
1896 {
1897     int i;
1898     AcpiTable table = { .sig = "XSDT", .rev = 1,
1899                         .oem_id = oem_id, .oem_table_id = oem_table_id };
1900 
1901     acpi_table_begin(&table, table_data);
1902 
1903     for (i = 0; i < table_offsets->len; ++i) {
1904         uint64_t ref_tbl_offset = g_array_index(table_offsets, uint32_t, i);
1905         uint64_t xsdt_entry_offset = table.array->len;
1906 
1907         /* reserve space for entry */
1908         build_append_int_noprefix(table.array, 0, 8);
1909 
1910         /* mark position of RSDT entry to be filled by Guest linker */
1911         bios_linker_loader_add_pointer(linker,
1912             ACPI_BUILD_TABLE_FILE, xsdt_entry_offset, 8,
1913             ACPI_BUILD_TABLE_FILE, ref_tbl_offset);
1914     }
1915     acpi_table_end(linker, &table);
1916 }
1917 
1918 /*
1919  * ACPI spec, Revision 4.0
1920  * 5.2.16.2 Memory Affinity Structure
1921  */
build_srat_memory(GArray * table_data,uint64_t base,uint64_t len,int node,MemoryAffinityFlags flags)1922 void build_srat_memory(GArray *table_data, uint64_t base,
1923                        uint64_t len, int node, MemoryAffinityFlags flags)
1924 {
1925     build_append_int_noprefix(table_data, 1, 1); /* Type */
1926     build_append_int_noprefix(table_data, 40, 1); /* Length */
1927     build_append_int_noprefix(table_data, node, 4); /* Proximity Domain */
1928     build_append_int_noprefix(table_data, 0, 2); /* Reserved */
1929     build_append_int_noprefix(table_data, base, 4); /* Base Address Low */
1930     /* Base Address High */
1931     build_append_int_noprefix(table_data, base >> 32, 4);
1932     build_append_int_noprefix(table_data, len, 4); /* Length Low */
1933     build_append_int_noprefix(table_data, len >> 32, 4); /* Length High */
1934     build_append_int_noprefix(table_data, 0, 4); /* Reserved */
1935     build_append_int_noprefix(table_data, flags, 4); /* Flags */
1936     build_append_int_noprefix(table_data, 0, 8); /* Reserved */
1937 }
1938 
1939 /*
1940  * ACPI Spec Revision 6.3
1941  * Table 5-80 Device Handle - PCI
1942  */
build_append_srat_pci_device_handle(GArray * table_data,uint16_t segment,uint8_t bus,uint8_t devfn)1943 static void build_append_srat_pci_device_handle(GArray *table_data,
1944                                                 uint16_t segment,
1945                                                 uint8_t bus, uint8_t devfn)
1946 {
1947     /* PCI segment number */
1948     build_append_int_noprefix(table_data, segment, 2);
1949     /* PCI Bus Device Function */
1950     build_append_int_noprefix(table_data, bus, 1);
1951     build_append_int_noprefix(table_data, devfn, 1);
1952     /* Reserved */
1953     build_append_int_noprefix(table_data, 0, 12);
1954 }
1955 
build_append_srat_acpi_device_handle(GArray * table_data,const char * hid,uint32_t uid)1956 static void build_append_srat_acpi_device_handle(GArray *table_data,
1957                                                  const char *hid,
1958                                                  uint32_t uid)
1959 {
1960     assert(strlen(hid) == 8);
1961     /* Device Handle - ACPI */
1962     for (int i = 0; i < 8; i++) {
1963         build_append_int_noprefix(table_data, hid[i], 1);
1964     }
1965     build_append_int_noprefix(table_data, uid, 4);
1966     build_append_int_noprefix(table_data, 0, 4);
1967 }
1968 
1969 /*
1970  * ACPI spec, Revision 6.3
1971  * 5.2.16.6 Generic Initiator Affinity Structure
1972  *    With PCI Device Handle.
1973  */
build_srat_pci_generic_initiator(GArray * table_data,uint32_t node,uint16_t segment,uint8_t bus,uint8_t devfn)1974 void build_srat_pci_generic_initiator(GArray *table_data, uint32_t node,
1975                                       uint16_t segment, uint8_t bus,
1976                                       uint8_t devfn)
1977 {
1978     /* Type */
1979     build_append_int_noprefix(table_data, 5, 1);
1980     /* Length */
1981     build_append_int_noprefix(table_data, 32, 1);
1982     /* Reserved */
1983     build_append_int_noprefix(table_data, 0, 1);
1984     /* Device Handle Type: PCI */
1985     build_append_int_noprefix(table_data, 1, 1);
1986     /* Proximity Domain */
1987     build_append_int_noprefix(table_data, node, 4);
1988     /* Device Handle */
1989     build_append_srat_pci_device_handle(table_data, segment, bus, devfn);
1990     /* Flags - GI Enabled */
1991     build_append_int_noprefix(table_data, 1, 4);
1992     /* Reserved */
1993     build_append_int_noprefix(table_data, 0, 4);
1994 }
1995 
1996 /*
1997  * ACPI spec, Revision 6.5
1998  * 5.2.16.7 Generic Port Affinity Structure
1999  *   With ACPI Device Handle.
2000  */
build_srat_acpi_generic_port(GArray * table_data,uint32_t node,const char * hid,uint32_t uid)2001 void build_srat_acpi_generic_port(GArray *table_data, uint32_t node,
2002                                   const char *hid, uint32_t uid)
2003 {
2004     /* Type */
2005     build_append_int_noprefix(table_data, 6, 1);
2006     /* Length */
2007     build_append_int_noprefix(table_data, 32, 1);
2008     /* Reserved */
2009     build_append_int_noprefix(table_data, 0, 1);
2010     /* Device Handle Type: ACPI */
2011     build_append_int_noprefix(table_data, 0, 1);
2012     /* Proximity Domain */
2013     build_append_int_noprefix(table_data, node, 4);
2014     /* Device Handle */
2015     build_append_srat_acpi_device_handle(table_data, hid, uid);
2016     /* Flags - GP Enabled */
2017     build_append_int_noprefix(table_data, 1, 4);
2018     /* Reserved */
2019     build_append_int_noprefix(table_data, 0, 4);
2020 }
2021 
2022 /*
2023  * ACPI spec 5.2.17 System Locality Distance Information Table
2024  * (Revision 2.0 or later)
2025  */
build_slit(GArray * table_data,BIOSLinker * linker,MachineState * ms,const char * oem_id,const char * oem_table_id)2026 void build_slit(GArray *table_data, BIOSLinker *linker, MachineState *ms,
2027                 const char *oem_id, const char *oem_table_id)
2028 {
2029     int i, j;
2030     int nb_numa_nodes = ms->numa_state->num_nodes;
2031     AcpiTable table = { .sig = "SLIT", .rev = 1,
2032                         .oem_id = oem_id, .oem_table_id = oem_table_id };
2033 
2034     acpi_table_begin(&table, table_data);
2035 
2036     build_append_int_noprefix(table_data, nb_numa_nodes, 8);
2037     for (i = 0; i < nb_numa_nodes; i++) {
2038         for (j = 0; j < nb_numa_nodes; j++) {
2039             assert(ms->numa_state->nodes[i].distance[j]);
2040             build_append_int_noprefix(table_data,
2041                                       ms->numa_state->nodes[i].distance[j],
2042                                       1);
2043         }
2044     }
2045     acpi_table_end(linker, &table);
2046 }
2047 
2048 /*
2049  * ACPI spec, Revision 6.3
2050  * 5.2.29.1 Processor hierarchy node structure (Type 0)
2051  */
build_processor_hierarchy_node(GArray * tbl,uint32_t flags,uint32_t parent,uint32_t id,uint32_t * priv_rsrc,uint32_t priv_num)2052 static void build_processor_hierarchy_node(GArray *tbl, uint32_t flags,
2053                                            uint32_t parent, uint32_t id,
2054                                            uint32_t *priv_rsrc,
2055                                            uint32_t priv_num)
2056 {
2057     int i;
2058 
2059     build_append_byte(tbl, 0);                 /* Type 0 - processor */
2060     build_append_byte(tbl, 20 + priv_num * 4); /* Length */
2061     build_append_int_noprefix(tbl, 0, 2);      /* Reserved */
2062     build_append_int_noprefix(tbl, flags, 4);  /* Flags */
2063     build_append_int_noprefix(tbl, parent, 4); /* Parent */
2064     build_append_int_noprefix(tbl, id, 4);     /* ACPI Processor ID */
2065 
2066     /* Number of private resources */
2067     build_append_int_noprefix(tbl, priv_num, 4);
2068 
2069     /* Private resources[N] */
2070     if (priv_num > 0) {
2071         assert(priv_rsrc);
2072         for (i = 0; i < priv_num; i++) {
2073             build_append_int_noprefix(tbl, priv_rsrc[i], 4);
2074         }
2075     }
2076 }
2077 
build_spcr(GArray * table_data,BIOSLinker * linker,const AcpiSpcrData * f,const uint8_t rev,const char * oem_id,const char * oem_table_id,const char * name)2078 void build_spcr(GArray *table_data, BIOSLinker *linker,
2079                 const AcpiSpcrData *f, const uint8_t rev,
2080                 const char *oem_id, const char *oem_table_id, const char *name)
2081 {
2082     AcpiTable table = { .sig = "SPCR", .rev = rev, .oem_id = oem_id,
2083                         .oem_table_id = oem_table_id };
2084 
2085     acpi_table_begin(&table, table_data);
2086     /* Interface type */
2087     build_append_int_noprefix(table_data, f->interface_type, 1);
2088     /* Reserved */
2089     build_append_int_noprefix(table_data, 0, 3);
2090     /* Base Address */
2091     build_append_gas(table_data, f->base_addr.id, f->base_addr.width,
2092                      f->base_addr.offset, f->base_addr.size,
2093                      f->base_addr.addr);
2094     /* Interrupt type */
2095     build_append_int_noprefix(table_data, f->interrupt_type, 1);
2096     /* IRQ */
2097     build_append_int_noprefix(table_data, f->pc_interrupt, 1);
2098     /* Global System Interrupt */
2099     build_append_int_noprefix(table_data, f->interrupt, 4);
2100     /* Baud Rate */
2101     build_append_int_noprefix(table_data, f->baud_rate, 1);
2102     /* Parity */
2103     build_append_int_noprefix(table_data, f->parity, 1);
2104     /* Stop Bits */
2105     build_append_int_noprefix(table_data, f->stop_bits, 1);
2106     /* Flow Control */
2107     build_append_int_noprefix(table_data, f->flow_control, 1);
2108     /* Language */
2109     build_append_int_noprefix(table_data, f->language, 1);
2110     /* Terminal Type */
2111     build_append_int_noprefix(table_data, f->terminal_type, 1);
2112     /* PCI Device ID  */
2113     build_append_int_noprefix(table_data, f->pci_device_id, 2);
2114     /* PCI Vendor ID */
2115     build_append_int_noprefix(table_data, f->pci_vendor_id, 2);
2116     /* PCI Bus Number */
2117     build_append_int_noprefix(table_data, f->pci_bus, 1);
2118     /* PCI Device Number */
2119     build_append_int_noprefix(table_data, f->pci_device, 1);
2120     /* PCI Function Number */
2121     build_append_int_noprefix(table_data, f->pci_function, 1);
2122     /* PCI Flags */
2123     build_append_int_noprefix(table_data, f->pci_flags, 4);
2124     /* PCI Segment */
2125     build_append_int_noprefix(table_data, f->pci_segment, 1);
2126     if (rev < 4) {
2127         /* Reserved */
2128         build_append_int_noprefix(table_data, 0, 4);
2129     } else {
2130         /* UartClkFreq */
2131         build_append_int_noprefix(table_data, f->uart_clk_freq, 4);
2132         /* PreciseBaudrate */
2133         build_append_int_noprefix(table_data, f->precise_baudrate, 4);
2134         /* NameSpaceStringLength */
2135         build_append_int_noprefix(table_data, f->namespace_string_length, 2);
2136         /* NameSpaceStringOffset */
2137         build_append_int_noprefix(table_data, f->namespace_string_offset, 2);
2138         /* NamespaceString[] */
2139         g_array_append_vals(table_data, name, f->namespace_string_length);
2140     }
2141     acpi_table_end(linker, &table);
2142 }
2143 /*
2144  * ACPI spec, Revision 6.3
2145  * 5.2.29 Processor Properties Topology Table (PPTT)
2146  */
build_pptt(GArray * table_data,BIOSLinker * linker,MachineState * ms,const char * oem_id,const char * oem_table_id)2147 void build_pptt(GArray *table_data, BIOSLinker *linker, MachineState *ms,
2148                 const char *oem_id, const char *oem_table_id)
2149 {
2150     MachineClass *mc = MACHINE_GET_CLASS(ms);
2151     CPUArchIdList *cpus = ms->possible_cpus;
2152     int64_t socket_id = -1, cluster_id = -1, core_id = -1;
2153     uint32_t socket_offset = 0, cluster_offset = 0, core_offset = 0;
2154     uint32_t pptt_start = table_data->len;
2155     uint32_t root_offset;
2156     int n;
2157     AcpiTable table = { .sig = "PPTT", .rev = 2,
2158                         .oem_id = oem_id, .oem_table_id = oem_table_id };
2159 
2160     acpi_table_begin(&table, table_data);
2161 
2162     /*
2163      * Build a root node for all the processor nodes. Otherwise when
2164      * building a multi-socket system each socket tree is separated
2165      * and will be hard for the OS like Linux to know whether the
2166      * system is homogeneous.
2167      */
2168     root_offset = table_data->len - pptt_start;
2169     build_processor_hierarchy_node(table_data,
2170         (1 << 0) | /* Physical package */
2171         (1 << 4), /* Identical Implementation */
2172         0, 0, NULL, 0);
2173 
2174     /*
2175      * This works with the assumption that cpus[n].props.*_id has been
2176      * sorted from top to down levels in mc->possible_cpu_arch_ids().
2177      * Otherwise, the unexpected and duplicated containers will be
2178      * created.
2179      */
2180     for (n = 0; n < cpus->len; n++) {
2181         if (cpus->cpus[n].props.socket_id != socket_id) {
2182             assert(cpus->cpus[n].props.socket_id > socket_id);
2183             socket_id = cpus->cpus[n].props.socket_id;
2184             cluster_id = -1;
2185             core_id = -1;
2186             socket_offset = table_data->len - pptt_start;
2187             build_processor_hierarchy_node(table_data,
2188                 (1 << 0) | /* Physical package */
2189                 (1 << 4), /* Identical Implementation */
2190                 root_offset, socket_id, NULL, 0);
2191         }
2192 
2193         if (mc->smp_props.clusters_supported && mc->smp_props.has_clusters) {
2194             if (cpus->cpus[n].props.cluster_id != cluster_id) {
2195                 assert(cpus->cpus[n].props.cluster_id > cluster_id);
2196                 cluster_id = cpus->cpus[n].props.cluster_id;
2197                 core_id = -1;
2198                 cluster_offset = table_data->len - pptt_start;
2199                 build_processor_hierarchy_node(table_data,
2200                     (0 << 0) | /* Not a physical package */
2201                     (1 << 4), /* Identical Implementation */
2202                     socket_offset, cluster_id, NULL, 0);
2203             }
2204         } else {
2205             cluster_offset = socket_offset;
2206         }
2207 
2208         if (ms->smp.threads == 1) {
2209             build_processor_hierarchy_node(table_data,
2210                 (1 << 1) | /* ACPI Processor ID valid */
2211                 (1 << 3),  /* Node is a Leaf */
2212                 cluster_offset, n, NULL, 0);
2213         } else {
2214             if (cpus->cpus[n].props.core_id != core_id) {
2215                 assert(cpus->cpus[n].props.core_id > core_id);
2216                 core_id = cpus->cpus[n].props.core_id;
2217                 core_offset = table_data->len - pptt_start;
2218                 build_processor_hierarchy_node(table_data,
2219                     (0 << 0) | /* Not a physical package */
2220                     (1 << 4), /* Identical Implementation */
2221                     cluster_offset, core_id, NULL, 0);
2222             }
2223 
2224             build_processor_hierarchy_node(table_data,
2225                 (1 << 1) | /* ACPI Processor ID valid */
2226                 (1 << 2) | /* Processor is a Thread */
2227                 (1 << 3),  /* Node is a Leaf */
2228                 core_offset, n, NULL, 0);
2229         }
2230     }
2231 
2232     acpi_table_end(linker, &table);
2233 }
2234 
2235 /* build rev1/rev3/rev5.1/rev6.0 FADT */
build_fadt(GArray * tbl,BIOSLinker * linker,const AcpiFadtData * f,const char * oem_id,const char * oem_table_id)2236 void build_fadt(GArray *tbl, BIOSLinker *linker, const AcpiFadtData *f,
2237                 const char *oem_id, const char *oem_table_id)
2238 {
2239     int off;
2240     AcpiTable table = { .sig = "FACP", .rev = f->rev,
2241                         .oem_id = oem_id, .oem_table_id = oem_table_id };
2242 
2243     acpi_table_begin(&table, tbl);
2244 
2245     /* FACS address to be filled by Guest linker at runtime */
2246     off = tbl->len;
2247     build_append_int_noprefix(tbl, 0, 4); /* FIRMWARE_CTRL */
2248     if (f->facs_tbl_offset) { /* don't patch if not supported by platform */
2249         bios_linker_loader_add_pointer(linker,
2250             ACPI_BUILD_TABLE_FILE, off, 4,
2251             ACPI_BUILD_TABLE_FILE, *f->facs_tbl_offset);
2252     }
2253 
2254     /* DSDT address to be filled by Guest linker at runtime */
2255     off = tbl->len;
2256     build_append_int_noprefix(tbl, 0, 4); /* DSDT */
2257     if (f->dsdt_tbl_offset) { /* don't patch if not supported by platform */
2258         bios_linker_loader_add_pointer(linker,
2259             ACPI_BUILD_TABLE_FILE, off, 4,
2260             ACPI_BUILD_TABLE_FILE, *f->dsdt_tbl_offset);
2261     }
2262 
2263     /* ACPI1.0: INT_MODEL, ACPI2.0+: Reserved */
2264     build_append_int_noprefix(tbl, f->int_model /* Multiple APIC */, 1);
2265     /* Preferred_PM_Profile */
2266     build_append_int_noprefix(tbl, 0 /* Unspecified */, 1);
2267     build_append_int_noprefix(tbl, f->sci_int, 2); /* SCI_INT */
2268     build_append_int_noprefix(tbl, f->smi_cmd, 4); /* SMI_CMD */
2269     build_append_int_noprefix(tbl, f->acpi_enable_cmd, 1); /* ACPI_ENABLE */
2270     build_append_int_noprefix(tbl, f->acpi_disable_cmd, 1); /* ACPI_DISABLE */
2271     build_append_int_noprefix(tbl, 0 /* not supported */, 1); /* S4BIOS_REQ */
2272     /* ACPI1.0: Reserved, ACPI2.0+: PSTATE_CNT */
2273     build_append_int_noprefix(tbl, 0, 1);
2274     build_append_int_noprefix(tbl, f->pm1a_evt.address, 4); /* PM1a_EVT_BLK */
2275     build_append_int_noprefix(tbl, 0, 4); /* PM1b_EVT_BLK */
2276     build_append_int_noprefix(tbl, f->pm1a_cnt.address, 4); /* PM1a_CNT_BLK */
2277     build_append_int_noprefix(tbl, 0, 4); /* PM1b_CNT_BLK */
2278     build_append_int_noprefix(tbl, 0, 4); /* PM2_CNT_BLK */
2279     build_append_int_noprefix(tbl, f->pm_tmr.address, 4); /* PM_TMR_BLK */
2280     build_append_int_noprefix(tbl, f->gpe0_blk.address, 4); /* GPE0_BLK */
2281     build_append_int_noprefix(tbl, 0, 4); /* GPE1_BLK */
2282     /* PM1_EVT_LEN */
2283     build_append_int_noprefix(tbl, f->pm1a_evt.bit_width / 8, 1);
2284     /* PM1_CNT_LEN */
2285     build_append_int_noprefix(tbl, f->pm1a_cnt.bit_width / 8, 1);
2286     build_append_int_noprefix(tbl, 0, 1); /* PM2_CNT_LEN */
2287     build_append_int_noprefix(tbl, f->pm_tmr.bit_width / 8, 1); /* PM_TMR_LEN */
2288     /* GPE0_BLK_LEN */
2289     build_append_int_noprefix(tbl, f->gpe0_blk.bit_width / 8, 1);
2290     build_append_int_noprefix(tbl, 0, 1); /* GPE1_BLK_LEN */
2291     build_append_int_noprefix(tbl, 0, 1); /* GPE1_BASE */
2292     build_append_int_noprefix(tbl, 0, 1); /* CST_CNT */
2293     build_append_int_noprefix(tbl, f->plvl2_lat, 2); /* P_LVL2_LAT */
2294     build_append_int_noprefix(tbl, f->plvl3_lat, 2); /* P_LVL3_LAT */
2295     build_append_int_noprefix(tbl, 0, 2); /* FLUSH_SIZE */
2296     build_append_int_noprefix(tbl, 0, 2); /* FLUSH_STRIDE */
2297     build_append_int_noprefix(tbl, 0, 1); /* DUTY_OFFSET */
2298     build_append_int_noprefix(tbl, 0, 1); /* DUTY_WIDTH */
2299     build_append_int_noprefix(tbl, 0, 1); /* DAY_ALRM */
2300     build_append_int_noprefix(tbl, 0, 1); /* MON_ALRM */
2301     build_append_int_noprefix(tbl, f->rtc_century, 1); /* CENTURY */
2302     /* IAPC_BOOT_ARCH */
2303     if (f->rev == 1) {
2304         build_append_int_noprefix(tbl, 0, 2);
2305     } else {
2306         /* since ACPI v2.0 */
2307         build_append_int_noprefix(tbl, f->iapc_boot_arch, 2);
2308     }
2309     build_append_int_noprefix(tbl, 0, 1); /* Reserved */
2310     build_append_int_noprefix(tbl, f->flags, 4); /* Flags */
2311 
2312     if (f->rev == 1) {
2313         goto done;
2314     }
2315 
2316     build_append_gas_from_struct(tbl, &f->reset_reg); /* RESET_REG */
2317     build_append_int_noprefix(tbl, f->reset_val, 1); /* RESET_VALUE */
2318     /* Since ACPI 5.1 */
2319     if ((f->rev >= 6) || ((f->rev == 5) && f->minor_ver > 0)) {
2320         build_append_int_noprefix(tbl, f->arm_boot_arch, 2); /* ARM_BOOT_ARCH */
2321         /* FADT Minor Version */
2322         build_append_int_noprefix(tbl, f->minor_ver, 1);
2323     } else {
2324         build_append_int_noprefix(tbl, 0, 3); /* Reserved up to ACPI 5.0 */
2325     }
2326     build_append_int_noprefix(tbl, 0, 8); /* X_FIRMWARE_CTRL */
2327 
2328     /* XDSDT address to be filled by Guest linker at runtime */
2329     off = tbl->len;
2330     build_append_int_noprefix(tbl, 0, 8); /* X_DSDT */
2331     if (f->xdsdt_tbl_offset) {
2332         bios_linker_loader_add_pointer(linker,
2333             ACPI_BUILD_TABLE_FILE, off, 8,
2334             ACPI_BUILD_TABLE_FILE, *f->xdsdt_tbl_offset);
2335     }
2336 
2337     build_append_gas_from_struct(tbl, &f->pm1a_evt); /* X_PM1a_EVT_BLK */
2338     /* X_PM1b_EVT_BLK */
2339     build_append_gas(tbl, AML_AS_SYSTEM_MEMORY, 0 , 0, 0, 0);
2340     build_append_gas_from_struct(tbl, &f->pm1a_cnt); /* X_PM1a_CNT_BLK */
2341     /* X_PM1b_CNT_BLK */
2342     build_append_gas(tbl, AML_AS_SYSTEM_MEMORY, 0 , 0, 0, 0);
2343     /* X_PM2_CNT_BLK */
2344     build_append_gas(tbl, AML_AS_SYSTEM_MEMORY, 0 , 0, 0, 0);
2345     build_append_gas_from_struct(tbl, &f->pm_tmr); /* X_PM_TMR_BLK */
2346     build_append_gas_from_struct(tbl, &f->gpe0_blk); /* X_GPE0_BLK */
2347     build_append_gas(tbl, AML_AS_SYSTEM_MEMORY, 0 , 0, 0, 0); /* X_GPE1_BLK */
2348 
2349     if (f->rev <= 4) {
2350         goto done;
2351     }
2352 
2353     /* SLEEP_CONTROL_REG */
2354     build_append_gas_from_struct(tbl, &f->sleep_ctl);
2355     /* SLEEP_STATUS_REG */
2356     build_append_gas_from_struct(tbl, &f->sleep_sts);
2357 
2358     if (f->rev == 5) {
2359         goto done;
2360     }
2361 
2362     /* Hypervisor Vendor Identity */
2363     build_append_padded_str(tbl, "QEMU", 8, '\0');
2364 
2365     /* TODO: extra fields need to be added to support revisions above rev6 */
2366     assert(f->rev == 6);
2367 
2368 done:
2369     acpi_table_end(linker, &table);
2370 }
2371 
2372 #ifdef CONFIG_TPM
2373 /*
2374  * build_tpm2 - Build the TPM2 table as specified in
2375  * table 7: TCG Hardware Interface Description Table Format for TPM 2.0
2376  * of TCG ACPI Specification, Family “1.2” and “2.0”, Version 1.2, Rev 8
2377  */
build_tpm2(GArray * table_data,BIOSLinker * linker,GArray * tcpalog,const char * oem_id,const char * oem_table_id)2378 void build_tpm2(GArray *table_data, BIOSLinker *linker, GArray *tcpalog,
2379                 const char *oem_id, const char *oem_table_id)
2380 {
2381     uint8_t start_method_params[12] = {};
2382     unsigned log_addr_offset;
2383     uint64_t control_area_start_address;
2384     TPMIf *tpmif = tpm_find();
2385     uint32_t start_method;
2386     AcpiTable table = { .sig = "TPM2", .rev = 4,
2387                         .oem_id = oem_id, .oem_table_id = oem_table_id };
2388 
2389     acpi_table_begin(&table, table_data);
2390 
2391     /* Platform Class */
2392     build_append_int_noprefix(table_data, TPM2_ACPI_CLASS_CLIENT, 2);
2393     /* Reserved */
2394     build_append_int_noprefix(table_data, 0, 2);
2395     if (TPM_IS_TIS_ISA(tpmif) || TPM_IS_TIS_SYSBUS(tpmif)) {
2396         control_area_start_address = 0;
2397         start_method = TPM2_START_METHOD_MMIO;
2398     } else if (TPM_IS_CRB(tpmif)) {
2399         control_area_start_address = TPM_CRB_ADDR_CTRL;
2400         start_method = TPM2_START_METHOD_CRB;
2401     } else {
2402         g_assert_not_reached();
2403     }
2404     /* Address of Control Area */
2405     build_append_int_noprefix(table_data, control_area_start_address, 8);
2406     /* Start Method */
2407     build_append_int_noprefix(table_data, start_method, 4);
2408 
2409     /* Platform Specific Parameters */
2410     g_array_append_vals(table_data, &start_method_params,
2411                         ARRAY_SIZE(start_method_params));
2412 
2413     /* Log Area Minimum Length */
2414     build_append_int_noprefix(table_data, TPM_LOG_AREA_MINIMUM_SIZE, 4);
2415 
2416     acpi_data_push(tcpalog, TPM_LOG_AREA_MINIMUM_SIZE);
2417     bios_linker_loader_alloc(linker, ACPI_BUILD_TPMLOG_FILE, tcpalog, 1,
2418                              false);
2419 
2420     log_addr_offset = table_data->len;
2421 
2422     /* Log Area Start Address to be filled by Guest linker */
2423     build_append_int_noprefix(table_data, 0, 8);
2424     bios_linker_loader_add_pointer(linker, ACPI_BUILD_TABLE_FILE,
2425                                    log_addr_offset, 8,
2426                                    ACPI_BUILD_TPMLOG_FILE, 0);
2427     acpi_table_end(linker, &table);
2428 }
2429 #endif
2430 
build_crs(PCIHostState * host,CrsRangeSet * range_set,uint32_t io_offset,uint32_t mmio32_offset,uint64_t mmio64_offset,uint16_t bus_nr_offset)2431 Aml *build_crs(PCIHostState *host, CrsRangeSet *range_set, uint32_t io_offset,
2432                uint32_t mmio32_offset, uint64_t mmio64_offset,
2433                uint16_t bus_nr_offset)
2434 {
2435     Aml *crs = aml_resource_template();
2436     CrsRangeSet temp_range_set;
2437     CrsRangeEntry *entry;
2438     uint8_t max_bus = pci_bus_num(host->bus);
2439     uint8_t type;
2440     int devfn;
2441     int i;
2442 
2443     crs_range_set_init(&temp_range_set);
2444     for (devfn = 0; devfn < ARRAY_SIZE(host->bus->devices); devfn++) {
2445         uint64_t range_base, range_limit;
2446         PCIDevice *dev = host->bus->devices[devfn];
2447 
2448         if (!dev) {
2449             continue;
2450         }
2451 
2452         for (i = 0; i < PCI_NUM_REGIONS; i++) {
2453             PCIIORegion *r = &dev->io_regions[i];
2454 
2455             range_base = r->addr;
2456             range_limit = r->addr + r->size - 1;
2457 
2458             /*
2459              * Work-around for old bioses
2460              * that do not support multiple root buses
2461              */
2462             if (!range_base || range_base > range_limit) {
2463                 continue;
2464             }
2465 
2466             if (r->type & PCI_BASE_ADDRESS_SPACE_IO) {
2467                 crs_range_insert(temp_range_set.io_ranges,
2468                                  range_base, range_limit);
2469             } else { /* "memory" */
2470                 uint64_t length = range_limit - range_base + 1;
2471                 if (range_limit <= UINT32_MAX && length <= UINT32_MAX) {
2472                     crs_range_insert(temp_range_set.mem_ranges, range_base,
2473                                      range_limit);
2474                 } else {
2475                     crs_range_insert(temp_range_set.mem_64bit_ranges,
2476                                      range_base, range_limit);
2477                 }
2478             }
2479         }
2480 
2481         type = dev->config[PCI_HEADER_TYPE] & ~PCI_HEADER_TYPE_MULTI_FUNCTION;
2482         if (type == PCI_HEADER_TYPE_BRIDGE) {
2483             uint8_t subordinate = dev->config[PCI_SUBORDINATE_BUS];
2484             if (subordinate > max_bus) {
2485                 max_bus = subordinate;
2486             }
2487 
2488             range_base = pci_bridge_get_base(dev, PCI_BASE_ADDRESS_SPACE_IO);
2489             range_limit = pci_bridge_get_limit(dev, PCI_BASE_ADDRESS_SPACE_IO);
2490 
2491              /*
2492               * Work-around for old bioses
2493               * that do not support multiple root buses
2494               */
2495             if (range_base && range_base <= range_limit) {
2496                 crs_range_insert(temp_range_set.io_ranges,
2497                                  range_base, range_limit);
2498             }
2499 
2500             range_base =
2501                 pci_bridge_get_base(dev, PCI_BASE_ADDRESS_SPACE_MEMORY);
2502             range_limit =
2503                 pci_bridge_get_limit(dev, PCI_BASE_ADDRESS_SPACE_MEMORY);
2504 
2505             /*
2506              * Work-around for old bioses
2507              * that do not support multiple root buses
2508              */
2509             if (range_base && range_base <= range_limit) {
2510                 uint64_t length = range_limit - range_base + 1;
2511                 if (range_limit <= UINT32_MAX && length <= UINT32_MAX) {
2512                     crs_range_insert(temp_range_set.mem_ranges,
2513                                      range_base, range_limit);
2514                 } else {
2515                     crs_range_insert(temp_range_set.mem_64bit_ranges,
2516                                      range_base, range_limit);
2517                 }
2518             }
2519 
2520             range_base =
2521                 pci_bridge_get_base(dev, PCI_BASE_ADDRESS_MEM_PREFETCH);
2522             range_limit =
2523                 pci_bridge_get_limit(dev, PCI_BASE_ADDRESS_MEM_PREFETCH);
2524 
2525             /*
2526              * Work-around for old bioses
2527              * that do not support multiple root buses
2528              */
2529             if (range_base && range_base <= range_limit) {
2530                 uint64_t length = range_limit - range_base + 1;
2531                 if (range_limit <= UINT32_MAX && length <= UINT32_MAX) {
2532                     crs_range_insert(temp_range_set.mem_ranges,
2533                                      range_base, range_limit);
2534                 } else {
2535                     crs_range_insert(temp_range_set.mem_64bit_ranges,
2536                                      range_base, range_limit);
2537                 }
2538             }
2539         }
2540     }
2541 
2542     crs_range_merge(temp_range_set.io_ranges);
2543     for (i = 0; i < temp_range_set.io_ranges->len; i++) {
2544         entry = g_ptr_array_index(temp_range_set.io_ranges, i);
2545         aml_append(crs,
2546                    aml_dword_io(AML_MIN_FIXED, AML_MAX_FIXED,
2547                                 AML_POS_DECODE, AML_ENTIRE_RANGE,
2548                                 0, entry->base, entry->limit, io_offset,
2549                                 entry->limit - entry->base + 1));
2550         crs_range_insert(range_set->io_ranges, entry->base, entry->limit);
2551     }
2552 
2553     crs_range_merge(temp_range_set.mem_ranges);
2554     for (i = 0; i < temp_range_set.mem_ranges->len; i++) {
2555         entry = g_ptr_array_index(temp_range_set.mem_ranges, i);
2556         assert(entry->limit <= UINT32_MAX &&
2557                (entry->limit - entry->base + 1) <= UINT32_MAX);
2558         aml_append(crs,
2559                    aml_dword_memory(AML_POS_DECODE, AML_MIN_FIXED,
2560                                     AML_MAX_FIXED, AML_NON_CACHEABLE,
2561                                     AML_READ_WRITE,
2562                                     0, entry->base, entry->limit, mmio32_offset,
2563                                     entry->limit - entry->base + 1));
2564         crs_range_insert(range_set->mem_ranges, entry->base, entry->limit);
2565     }
2566 
2567     crs_range_merge(temp_range_set.mem_64bit_ranges);
2568     for (i = 0; i < temp_range_set.mem_64bit_ranges->len; i++) {
2569         entry = g_ptr_array_index(temp_range_set.mem_64bit_ranges, i);
2570         aml_append(crs,
2571                    aml_qword_memory(AML_POS_DECODE, AML_MIN_FIXED,
2572                                     AML_MAX_FIXED, AML_NON_CACHEABLE,
2573                                     AML_READ_WRITE,
2574                                     0, entry->base, entry->limit, mmio64_offset,
2575                                     entry->limit - entry->base + 1));
2576         crs_range_insert(range_set->mem_64bit_ranges,
2577                          entry->base, entry->limit);
2578     }
2579 
2580     crs_range_set_free(&temp_range_set);
2581 
2582     aml_append(crs,
2583         aml_word_bus_number(AML_MIN_FIXED, AML_MAX_FIXED, AML_POS_DECODE,
2584                             0,
2585                             pci_bus_num(host->bus),
2586                             max_bus,
2587                             bus_nr_offset,
2588                             max_bus - pci_bus_num(host->bus) + 1));
2589 
2590     return crs;
2591 }
2592 
2593 /* ACPI 5.0: 6.4.3.8.2 Serial Bus Connection Descriptors */
aml_serial_bus_device(uint8_t serial_bus_type,uint8_t flags,uint16_t type_flags,uint8_t revid,uint16_t data_length,uint16_t resource_source_len)2594 static Aml *aml_serial_bus_device(uint8_t serial_bus_type, uint8_t flags,
2595                                   uint16_t type_flags,
2596                                   uint8_t revid, uint16_t data_length,
2597                                   uint16_t resource_source_len)
2598 {
2599     Aml *var = aml_alloc();
2600     uint16_t length = data_length + resource_source_len + 9;
2601 
2602     build_append_byte(var->buf, 0x8e); /* Serial Bus Connection Descriptor */
2603     build_append_int_noprefix(var->buf, length, sizeof(length));
2604     build_append_byte(var->buf, 1);    /* Revision ID */
2605     build_append_byte(var->buf, 0);    /* Resource Source Index */
2606     build_append_byte(var->buf, serial_bus_type); /* Serial Bus Type */
2607     build_append_byte(var->buf, flags); /* General Flags */
2608     build_append_int_noprefix(var->buf, type_flags, /* Type Specific Flags */
2609                               sizeof(type_flags));
2610     build_append_byte(var->buf, revid); /* Type Specification Revision ID */
2611     build_append_int_noprefix(var->buf, data_length, sizeof(data_length));
2612 
2613     return var;
2614 }
2615 
2616 /* ACPI 5.0: 6.4.3.8.2.1 I2C Serial Bus Connection Resource Descriptor */
aml_i2c_serial_bus_device(uint16_t address,const char * resource_source)2617 Aml *aml_i2c_serial_bus_device(uint16_t address, const char *resource_source)
2618 {
2619     uint16_t resource_source_len = strlen(resource_source) + 1;
2620     Aml *var = aml_serial_bus_device(AML_SERIAL_BUS_TYPE_I2C, 0, 0, 1,
2621                                      6, resource_source_len);
2622 
2623     /* Connection Speed.  Just set to 100K for now, it doesn't really matter. */
2624     build_append_int_noprefix(var->buf, 100000, 4);
2625     build_append_int_noprefix(var->buf, address, sizeof(address));
2626 
2627     /* This is a string, not a name, so just copy it directly in. */
2628     g_array_append_vals(var->buf, resource_source, resource_source_len);
2629 
2630     return var;
2631 }
2632