xref: /openbmc/qemu/hw/acpi/aml-build.c (revision 77a8257e)
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 <stdio.h>
23 #include <stdarg.h>
24 #include <assert.h>
25 #include <stdbool.h>
26 #include <string.h>
27 #include "hw/acpi/aml-build.h"
28 #include "qemu/bswap.h"
29 
30 static GArray *build_alloc_array(void)
31 {
32     return g_array_new(false, true /* clear */, 1);
33 }
34 
35 static void build_free_array(GArray *array)
36 {
37     g_array_free(array, true);
38 }
39 
40 static void build_prepend_byte(GArray *array, uint8_t val)
41 {
42     g_array_prepend_val(array, val);
43 }
44 
45 static void build_append_byte(GArray *array, uint8_t val)
46 {
47     g_array_append_val(array, val);
48 }
49 
50 static void build_append_array(GArray *array, GArray *val)
51 {
52     g_array_append_vals(array, val->data, val->len);
53 }
54 
55 #define ACPI_NAMESEG_LEN 4
56 
57 static void
58 build_append_nameseg(GArray *array, const char *seg)
59 {
60     /* It would be nicer to use g_string_vprintf but it's only there in 2.22 */
61     int len;
62 
63     len = strlen(seg);
64     assert(len <= ACPI_NAMESEG_LEN);
65 
66     g_array_append_vals(array, seg, len);
67     /* Pad up to ACPI_NAMESEG_LEN characters if necessary. */
68     g_array_append_vals(array, "____", ACPI_NAMESEG_LEN - len);
69 }
70 
71 static void
72 build_append_namestringv(GArray *array, const char *format, va_list ap)
73 {
74     /* It would be nicer to use g_string_vprintf but it's only there in 2.22 */
75     char *s;
76     int len;
77     va_list va_len;
78     char **segs;
79     char **segs_iter;
80     int seg_count = 0;
81 
82     va_copy(va_len, ap);
83     len = vsnprintf(NULL, 0, format, va_len);
84     va_end(va_len);
85     len += 1;
86     s = g_new(typeof(*s), len);
87 
88     len = vsnprintf(s, len, format, ap);
89 
90     segs = g_strsplit(s, ".", 0);
91     g_free(s);
92 
93     /* count segments */
94     segs_iter = segs;
95     while (*segs_iter) {
96         ++segs_iter;
97         ++seg_count;
98     }
99     /*
100      * ACPI 5.0 spec: 20.2.2 Name Objects Encoding:
101      * "SegCount can be from 1 to 255"
102      */
103     assert(seg_count > 0 && seg_count <= 255);
104 
105     /* handle RootPath || PrefixPath */
106     s = *segs;
107     while (*s == '\\' || *s == '^') {
108         build_append_byte(array, *s);
109         ++s;
110     }
111 
112     switch (seg_count) {
113     case 1:
114         if (!*s) {
115             build_append_byte(array, 0x00); /* NullName */
116         } else {
117             build_append_nameseg(array, s);
118         }
119         break;
120 
121     case 2:
122         build_append_byte(array, 0x2E); /* DualNamePrefix */
123         build_append_nameseg(array, s);
124         build_append_nameseg(array, segs[1]);
125         break;
126     default:
127         build_append_byte(array, 0x2F); /* MultiNamePrefix */
128         build_append_byte(array, seg_count);
129 
130         /* handle the 1st segment manually due to prefix/root path */
131         build_append_nameseg(array, s);
132 
133         /* add the rest of segments */
134         segs_iter = segs + 1;
135         while (*segs_iter) {
136             build_append_nameseg(array, *segs_iter);
137             ++segs_iter;
138         }
139         break;
140     }
141     g_strfreev(segs);
142 }
143 
144 GCC_FMT_ATTR(2, 3)
145 static void build_append_namestring(GArray *array, const char *format, ...)
146 {
147     va_list ap;
148 
149     va_start(ap, format);
150     build_append_namestringv(array, format, ap);
151     va_end(ap);
152 }
153 
154 /* 5.4 Definition Block Encoding */
155 enum {
156     PACKAGE_LENGTH_1BYTE_SHIFT = 6, /* Up to 63 - use extra 2 bits. */
157     PACKAGE_LENGTH_2BYTE_SHIFT = 4,
158     PACKAGE_LENGTH_3BYTE_SHIFT = 12,
159     PACKAGE_LENGTH_4BYTE_SHIFT = 20,
160 };
161 
162 static void
163 build_prepend_package_length(GArray *package, unsigned length, bool incl_self)
164 {
165     uint8_t byte;
166     unsigned length_bytes;
167 
168     if (length + 1 < (1 << PACKAGE_LENGTH_1BYTE_SHIFT)) {
169         length_bytes = 1;
170     } else if (length + 2 < (1 << PACKAGE_LENGTH_3BYTE_SHIFT)) {
171         length_bytes = 2;
172     } else if (length + 3 < (1 << PACKAGE_LENGTH_4BYTE_SHIFT)) {
173         length_bytes = 3;
174     } else {
175         length_bytes = 4;
176     }
177 
178     /*
179      * NamedField uses PkgLength encoding but it doesn't include length
180      * of PkgLength itself.
181      */
182     if (incl_self) {
183         /*
184          * PkgLength is the length of the inclusive length of the data
185          * and PkgLength's length itself when used for terms with
186          * explitit length.
187          */
188         length += length_bytes;
189     }
190 
191     switch (length_bytes) {
192     case 1:
193         byte = length;
194         build_prepend_byte(package, byte);
195         return;
196     case 4:
197         byte = length >> PACKAGE_LENGTH_4BYTE_SHIFT;
198         build_prepend_byte(package, byte);
199         length &= (1 << PACKAGE_LENGTH_4BYTE_SHIFT) - 1;
200         /* fall through */
201     case 3:
202         byte = length >> PACKAGE_LENGTH_3BYTE_SHIFT;
203         build_prepend_byte(package, byte);
204         length &= (1 << PACKAGE_LENGTH_3BYTE_SHIFT) - 1;
205         /* fall through */
206     case 2:
207         byte = length >> PACKAGE_LENGTH_2BYTE_SHIFT;
208         build_prepend_byte(package, byte);
209         length &= (1 << PACKAGE_LENGTH_2BYTE_SHIFT) - 1;
210         /* fall through */
211     }
212     /*
213      * Most significant two bits of byte zero indicate how many following bytes
214      * are in PkgLength encoding.
215      */
216     byte = ((length_bytes - 1) << PACKAGE_LENGTH_1BYTE_SHIFT) | length;
217     build_prepend_byte(package, byte);
218 }
219 
220 static void
221 build_append_pkg_length(GArray *array, unsigned length, bool incl_self)
222 {
223     GArray *tmp = build_alloc_array();
224 
225     build_prepend_package_length(tmp, length, incl_self);
226     build_append_array(array, tmp);
227     build_free_array(tmp);
228 }
229 
230 static void build_package(GArray *package, uint8_t op)
231 {
232     build_prepend_package_length(package, package->len, true);
233     build_prepend_byte(package, op);
234 }
235 
236 static void build_extop_package(GArray *package, uint8_t op)
237 {
238     build_package(package, op);
239     build_prepend_byte(package, 0x5B); /* ExtOpPrefix */
240 }
241 
242 static void build_append_int_noprefix(GArray *table, uint64_t value, int size)
243 {
244     int i;
245 
246     for (i = 0; i < size; ++i) {
247         build_append_byte(table, value & 0xFF);
248         value = value >> 8;
249     }
250 }
251 
252 static void build_append_int(GArray *table, uint64_t value)
253 {
254     if (value == 0x00) {
255         build_append_byte(table, 0x00); /* ZeroOp */
256     } else if (value == 0x01) {
257         build_append_byte(table, 0x01); /* OneOp */
258     } else if (value <= 0xFF) {
259         build_append_byte(table, 0x0A); /* BytePrefix */
260         build_append_int_noprefix(table, value, 1);
261     } else if (value <= 0xFFFF) {
262         build_append_byte(table, 0x0B); /* WordPrefix */
263         build_append_int_noprefix(table, value, 2);
264     } else if (value <= 0xFFFFFFFF) {
265         build_append_byte(table, 0x0C); /* DWordPrefix */
266         build_append_int_noprefix(table, value, 4);
267     } else {
268         build_append_byte(table, 0x0E); /* QWordPrefix */
269         build_append_int_noprefix(table, value, 8);
270     }
271 }
272 
273 static GPtrArray *alloc_list;
274 
275 static Aml *aml_alloc(void)
276 {
277     Aml *var = g_new0(typeof(*var), 1);
278 
279     g_ptr_array_add(alloc_list, var);
280     var->block_flags = AML_NO_OPCODE;
281     var->buf = build_alloc_array();
282     return var;
283 }
284 
285 static Aml *aml_opcode(uint8_t op)
286 {
287     Aml *var = aml_alloc();
288 
289     var->op  = op;
290     var->block_flags = AML_OPCODE;
291     return var;
292 }
293 
294 static Aml *aml_bundle(uint8_t op, AmlBlockFlags flags)
295 {
296     Aml *var = aml_alloc();
297 
298     var->op  = op;
299     var->block_flags = flags;
300     return var;
301 }
302 
303 static void aml_free(gpointer data, gpointer user_data)
304 {
305     Aml *var = data;
306     build_free_array(var->buf);
307 }
308 
309 Aml *init_aml_allocator(void)
310 {
311     Aml *var;
312 
313     assert(!alloc_list);
314     alloc_list = g_ptr_array_new();
315     var = aml_alloc();
316     return var;
317 }
318 
319 void free_aml_allocator(void)
320 {
321     g_ptr_array_foreach(alloc_list, aml_free, NULL);
322     g_ptr_array_free(alloc_list, true);
323     alloc_list = 0;
324 }
325 
326 /* pack data with DefBuffer encoding */
327 static void build_buffer(GArray *array, uint8_t op)
328 {
329     GArray *data = build_alloc_array();
330 
331     build_append_int(data, array->len);
332     g_array_prepend_vals(array, data->data, data->len);
333     build_free_array(data);
334     build_package(array, op);
335 }
336 
337 void aml_append(Aml *parent_ctx, Aml *child)
338 {
339     GArray *buf = build_alloc_array();
340     build_append_array(buf, child->buf);
341 
342     switch (child->block_flags) {
343     case AML_OPCODE:
344         build_append_byte(parent_ctx->buf, child->op);
345         break;
346     case AML_EXT_PACKAGE:
347         build_extop_package(buf, child->op);
348         break;
349     case AML_PACKAGE:
350         build_package(buf, child->op);
351         break;
352     case AML_RES_TEMPLATE:
353         build_append_byte(buf, 0x79); /* EndTag */
354         /*
355          * checksum operations are treated as succeeded if checksum
356          * field is zero. [ACPI Spec 1.0b, 6.4.2.8 End Tag]
357          */
358         build_append_byte(buf, 0);
359         /* fall through, to pack resources in buffer */
360     case AML_BUFFER:
361         build_buffer(buf, child->op);
362         break;
363     case AML_NO_OPCODE:
364         break;
365     default:
366         assert(0);
367         break;
368     }
369     build_append_array(parent_ctx->buf, buf);
370     build_free_array(buf);
371 }
372 
373 /* ACPI 1.0b: 16.2.5.1 Namespace Modifier Objects Encoding: DefScope */
374 Aml *aml_scope(const char *name_format, ...)
375 {
376     va_list ap;
377     Aml *var = aml_bundle(0x10 /* ScopeOp */, AML_PACKAGE);
378     va_start(ap, name_format);
379     build_append_namestringv(var->buf, name_format, ap);
380     va_end(ap);
381     return var;
382 }
383 
384 /* ACPI 1.0b: 16.2.5.3 Type 1 Opcodes Encoding: DefReturn */
385 Aml *aml_return(Aml *val)
386 {
387     Aml *var = aml_opcode(0xA4 /* ReturnOp */);
388     aml_append(var, val);
389     return var;
390 }
391 
392 /*
393  * ACPI 1.0b: 16.2.3 Data Objects Encoding:
394  * encodes: ByteConst, WordConst, DWordConst, QWordConst, ZeroOp, OneOp
395  */
396 Aml *aml_int(const uint64_t val)
397 {
398     Aml *var = aml_alloc();
399     build_append_int(var->buf, val);
400     return var;
401 }
402 
403 /*
404  * helper to construct NameString, which returns Aml object
405  * for using with aml_append or other aml_* terms
406  */
407 Aml *aml_name(const char *name_format, ...)
408 {
409     va_list ap;
410     Aml *var = aml_alloc();
411     va_start(ap, name_format);
412     build_append_namestringv(var->buf, name_format, ap);
413     va_end(ap);
414     return var;
415 }
416 
417 /* ACPI 1.0b: 16.2.5.1 Namespace Modifier Objects Encoding: DefName */
418 Aml *aml_name_decl(const char *name, Aml *val)
419 {
420     Aml *var = aml_opcode(0x08 /* NameOp */);
421     build_append_namestring(var->buf, "%s", name);
422     aml_append(var, val);
423     return var;
424 }
425 
426 /* ACPI 1.0b: 16.2.6.1 Arg Objects Encoding */
427 Aml *aml_arg(int pos)
428 {
429     Aml *var;
430     uint8_t op = 0x68 /* ARG0 op */ + pos;
431 
432     assert(pos <= 6);
433     var = aml_opcode(op);
434     return var;
435 }
436 
437 /* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefStore */
438 Aml *aml_store(Aml *val, Aml *target)
439 {
440     Aml *var = aml_opcode(0x70 /* StoreOp */);
441     aml_append(var, val);
442     aml_append(var, target);
443     return var;
444 }
445 
446 /* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefAnd */
447 Aml *aml_and(Aml *arg1, Aml *arg2)
448 {
449     Aml *var = aml_opcode(0x7B /* AndOp */);
450     aml_append(var, arg1);
451     aml_append(var, arg2);
452     build_append_byte(var->buf, 0x00 /* NullNameOp */);
453     return var;
454 }
455 
456 /* ACPI 1.0b: 16.2.5.3 Type 1 Opcodes Encoding: DefNotify */
457 Aml *aml_notify(Aml *arg1, Aml *arg2)
458 {
459     Aml *var = aml_opcode(0x86 /* NotifyOp */);
460     aml_append(var, arg1);
461     aml_append(var, arg2);
462     return var;
463 }
464 
465 /* helper to call method with 1 argument */
466 Aml *aml_call1(const char *method, Aml *arg1)
467 {
468     Aml *var = aml_alloc();
469     build_append_namestring(var->buf, "%s", method);
470     aml_append(var, arg1);
471     return var;
472 }
473 
474 /* helper to call method with 2 arguments */
475 Aml *aml_call2(const char *method, Aml *arg1, Aml *arg2)
476 {
477     Aml *var = aml_alloc();
478     build_append_namestring(var->buf, "%s", method);
479     aml_append(var, arg1);
480     aml_append(var, arg2);
481     return var;
482 }
483 
484 /* helper to call method with 3 arguments */
485 Aml *aml_call3(const char *method, Aml *arg1, Aml *arg2, Aml *arg3)
486 {
487     Aml *var = aml_alloc();
488     build_append_namestring(var->buf, "%s", method);
489     aml_append(var, arg1);
490     aml_append(var, arg2);
491     aml_append(var, arg3);
492     return var;
493 }
494 
495 /* helper to call method with 4 arguments */
496 Aml *aml_call4(const char *method, Aml *arg1, Aml *arg2, Aml *arg3, Aml *arg4)
497 {
498     Aml *var = aml_alloc();
499     build_append_namestring(var->buf, "%s", method);
500     aml_append(var, arg1);
501     aml_append(var, arg2);
502     aml_append(var, arg3);
503     aml_append(var, arg4);
504     return var;
505 }
506 
507 /* ACPI 1.0b: 6.4.2.5 I/O Port Descriptor */
508 Aml *aml_io(AmlIODecode dec, uint16_t min_base, uint16_t max_base,
509             uint8_t aln, uint8_t len)
510 {
511     Aml *var = aml_alloc();
512     build_append_byte(var->buf, 0x47); /* IO port descriptor */
513     build_append_byte(var->buf, dec);
514     build_append_byte(var->buf, min_base & 0xff);
515     build_append_byte(var->buf, (min_base >> 8) & 0xff);
516     build_append_byte(var->buf, max_base & 0xff);
517     build_append_byte(var->buf, (max_base >> 8) & 0xff);
518     build_append_byte(var->buf, aln);
519     build_append_byte(var->buf, len);
520     return var;
521 }
522 
523 /*
524  * ACPI 1.0b: 6.4.2.1.1 ASL Macro for IRQ Descriptor
525  *
526  * More verbose description at:
527  * ACPI 5.0: 19.5.64 IRQNoFlags (Interrupt Resource Descriptor Macro)
528  *           6.4.2.1 IRQ Descriptor
529  */
530 Aml *aml_irq_no_flags(uint8_t irq)
531 {
532     uint16_t irq_mask;
533     Aml *var = aml_alloc();
534 
535     assert(irq < 16);
536     build_append_byte(var->buf, 0x22); /* IRQ descriptor 2 byte form */
537 
538     irq_mask = 1U << irq;
539     build_append_byte(var->buf, irq_mask & 0xFF); /* IRQ mask bits[7:0] */
540     build_append_byte(var->buf, irq_mask >> 8); /* IRQ mask bits[15:8] */
541     return var;
542 }
543 
544 /* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefLEqual */
545 Aml *aml_equal(Aml *arg1, Aml *arg2)
546 {
547     Aml *var = aml_opcode(0x93 /* LequalOp */);
548     aml_append(var, arg1);
549     aml_append(var, arg2);
550     return var;
551 }
552 
553 /* ACPI 1.0b: 16.2.5.3 Type 1 Opcodes Encoding: DefIfElse */
554 Aml *aml_if(Aml *predicate)
555 {
556     Aml *var = aml_bundle(0xA0 /* IfOp */, AML_PACKAGE);
557     aml_append(var, predicate);
558     return var;
559 }
560 
561 /* ACPI 1.0b: 16.2.5.2 Named Objects Encoding: DefMethod */
562 Aml *aml_method(const char *name, int arg_count)
563 {
564     Aml *var = aml_bundle(0x14 /* MethodOp */, AML_PACKAGE);
565     build_append_namestring(var->buf, "%s", name);
566     build_append_byte(var->buf, arg_count); /* MethodFlags: ArgCount */
567     return var;
568 }
569 
570 /* ACPI 1.0b: 16.2.5.2 Named Objects Encoding: DefDevice */
571 Aml *aml_device(const char *name_format, ...)
572 {
573     va_list ap;
574     Aml *var = aml_bundle(0x82 /* DeviceOp */, AML_EXT_PACKAGE);
575     va_start(ap, name_format);
576     build_append_namestringv(var->buf, name_format, ap);
577     va_end(ap);
578     return var;
579 }
580 
581 /* ACPI 1.0b: 6.4.1 ASL Macros for Resource Descriptors */
582 Aml *aml_resource_template(void)
583 {
584     /* ResourceTemplate is a buffer of Resources with EndTag at the end */
585     Aml *var = aml_bundle(0x11 /* BufferOp */, AML_RES_TEMPLATE);
586     return var;
587 }
588 
589 /* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefBuffer */
590 Aml *aml_buffer(void)
591 {
592     Aml *var = aml_bundle(0x11 /* BufferOp */, AML_BUFFER);
593     return var;
594 }
595 
596 /* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefPackage */
597 Aml *aml_package(uint8_t num_elements)
598 {
599     Aml *var = aml_bundle(0x12 /* PackageOp */, AML_PACKAGE);
600     build_append_byte(var->buf, num_elements);
601     return var;
602 }
603 
604 /* ACPI 1.0b: 16.2.5.2 Named Objects Encoding: DefOpRegion */
605 Aml *aml_operation_region(const char *name, AmlRegionSpace rs,
606                           uint32_t offset, uint32_t len)
607 {
608     Aml *var = aml_alloc();
609     build_append_byte(var->buf, 0x5B); /* ExtOpPrefix */
610     build_append_byte(var->buf, 0x80); /* OpRegionOp */
611     build_append_namestring(var->buf, "%s", name);
612     build_append_byte(var->buf, rs);
613     build_append_int(var->buf, offset);
614     build_append_int(var->buf, len);
615     return var;
616 }
617 
618 /* ACPI 1.0b: 16.2.5.2 Named Objects Encoding: NamedField */
619 Aml *aml_named_field(const char *name, unsigned length)
620 {
621     Aml *var = aml_alloc();
622     build_append_nameseg(var->buf, name);
623     build_append_pkg_length(var->buf, length, false);
624     return var;
625 }
626 
627 /* ACPI 1.0b: 16.2.5.2 Named Objects Encoding: ReservedField */
628 Aml *aml_reserved_field(unsigned length)
629 {
630     Aml *var = aml_alloc();
631     /* ReservedField  := 0x00 PkgLength */
632     build_append_byte(var->buf, 0x00);
633     build_append_pkg_length(var->buf, length, false);
634     return var;
635 }
636 
637 /* ACPI 1.0b: 16.2.5.2 Named Objects Encoding: DefField */
638 Aml *aml_field(const char *name, AmlFieldFlags flags)
639 {
640     Aml *var = aml_bundle(0x81 /* FieldOp */, AML_EXT_PACKAGE);
641     build_append_namestring(var->buf, "%s", name);
642     build_append_byte(var->buf, flags);
643     return var;
644 }
645 
646 /* ACPI 1.0b: 16.2.3 Data Objects Encoding: String */
647 Aml *aml_string(const char *name_format, ...)
648 {
649     Aml *var = aml_opcode(0x0D /* StringPrefix */);
650     va_list ap, va_len;
651     char *s;
652     int len;
653 
654     va_start(ap, name_format);
655     va_copy(va_len, ap);
656     len = vsnprintf(NULL, 0, name_format, va_len);
657     va_end(va_len);
658     len += 1;
659     s = g_new0(typeof(*s), len);
660 
661     len = vsnprintf(s, len, name_format, ap);
662     va_end(ap);
663 
664     g_array_append_vals(var->buf, s, len);
665     build_append_byte(var->buf, 0x0); /* NullChar */
666     g_free(s);
667 
668     return var;
669 }
670 
671 /* ACPI 1.0b: 16.2.6.2 Local Objects Encoding */
672 Aml *aml_local(int num)
673 {
674     Aml *var;
675     uint8_t op = 0x60 /* Local0Op */ + num;
676 
677     assert(num <= 7);
678     var = aml_opcode(op);
679     return var;
680 }
681 
682 /* ACPI 2.0a: 17.2.2 Data Objects Encoding: DefVarPackage */
683 Aml *aml_varpackage(uint32_t num_elements)
684 {
685     Aml *var = aml_bundle(0x13 /* VarPackageOp */, AML_PACKAGE);
686     build_append_int(var->buf, num_elements);
687     return var;
688 }
689 
690 /* ACPI 1.0b: 16.2.5.2 Named Objects Encoding: DefProcessor */
691 Aml *aml_processor(uint8_t proc_id, uint32_t pblk_addr, uint8_t pblk_len,
692                    const char *name_format, ...)
693 {
694     va_list ap;
695     Aml *var = aml_bundle(0x83 /* ProcessorOp */, AML_EXT_PACKAGE);
696     va_start(ap, name_format);
697     build_append_namestringv(var->buf, name_format, ap);
698     va_end(ap);
699     build_append_byte(var->buf, proc_id); /* ProcID */
700     build_append_int_noprefix(var->buf, pblk_addr, sizeof(pblk_addr));
701     build_append_byte(var->buf, pblk_len); /* PblkLen */
702     return var;
703 }
704 
705 static uint8_t Hex2Digit(char c)
706 {
707     if (c >= 'A') {
708         return c - 'A' + 10;
709     }
710 
711     return c - '0';
712 }
713 
714 /* ACPI 1.0b: 15.2.3.6.4.1 EISAID Macro - Convert EISA ID String To Integer */
715 Aml *aml_eisaid(const char *str)
716 {
717     Aml *var = aml_alloc();
718     uint32_t id;
719 
720     g_assert(strlen(str) == 7);
721     id = (str[0] - 0x40) << 26 |
722     (str[1] - 0x40) << 21 |
723     (str[2] - 0x40) << 16 |
724     Hex2Digit(str[3]) << 12 |
725     Hex2Digit(str[4]) << 8 |
726     Hex2Digit(str[5]) << 4 |
727     Hex2Digit(str[6]);
728 
729     build_append_byte(var->buf, 0x0C); /* DWordPrefix */
730     build_append_int_noprefix(var->buf, bswap32(id), sizeof(id));
731     return var;
732 }
733 
734 /* ACPI 1.0b: 6.4.3.5.5 Word Address Space Descriptor: bytes 3-5 */
735 static Aml *aml_as_desc_header(AmlResourceType type, AmlMinFixed min_fixed,
736                                AmlMaxFixed max_fixed, AmlDecode dec,
737                                uint8_t type_flags)
738 {
739     uint8_t flags = max_fixed | min_fixed | dec;
740     Aml *var = aml_alloc();
741 
742     build_append_byte(var->buf, type);
743     build_append_byte(var->buf, flags);
744     build_append_byte(var->buf, type_flags); /* Type Specific Flags */
745     return var;
746 }
747 
748 /* ACPI 1.0b: 6.4.3.5.5 Word Address Space Descriptor */
749 static Aml *aml_word_as_desc(AmlResourceType type, AmlMinFixed min_fixed,
750                              AmlMaxFixed max_fixed, AmlDecode dec,
751                              uint16_t addr_gran, uint16_t addr_min,
752                              uint16_t addr_max, uint16_t addr_trans,
753                              uint16_t len, uint8_t type_flags)
754 {
755     Aml *var = aml_alloc();
756 
757     build_append_byte(var->buf, 0x88); /* Word Address Space Descriptor */
758     /* minimum length since we do not encode optional fields */
759     build_append_byte(var->buf, 0x0D);
760     build_append_byte(var->buf, 0x0);
761 
762     aml_append(var,
763         aml_as_desc_header(type, min_fixed, max_fixed, dec, type_flags));
764     build_append_int_noprefix(var->buf, addr_gran, sizeof(addr_gran));
765     build_append_int_noprefix(var->buf, addr_min, sizeof(addr_min));
766     build_append_int_noprefix(var->buf, addr_max, sizeof(addr_max));
767     build_append_int_noprefix(var->buf, addr_trans, sizeof(addr_trans));
768     build_append_int_noprefix(var->buf, len, sizeof(len));
769     return var;
770 }
771 
772 /* ACPI 1.0b: 6.4.3.5.3 DWord Address Space Descriptor */
773 static Aml *aml_dword_as_desc(AmlResourceType type, AmlMinFixed min_fixed,
774                               AmlMaxFixed max_fixed, AmlDecode dec,
775                               uint32_t addr_gran, uint32_t addr_min,
776                               uint32_t addr_max, uint32_t addr_trans,
777                               uint32_t len, uint8_t type_flags)
778 {
779     Aml *var = aml_alloc();
780 
781     build_append_byte(var->buf, 0x87); /* DWord Address Space Descriptor */
782     /* minimum length since we do not encode optional fields */
783     build_append_byte(var->buf, 23);
784     build_append_byte(var->buf, 0x0);
785 
786 
787     aml_append(var,
788         aml_as_desc_header(type, min_fixed, max_fixed, dec, type_flags));
789     build_append_int_noprefix(var->buf, addr_gran, sizeof(addr_gran));
790     build_append_int_noprefix(var->buf, addr_min, sizeof(addr_min));
791     build_append_int_noprefix(var->buf, addr_max, sizeof(addr_max));
792     build_append_int_noprefix(var->buf, addr_trans, sizeof(addr_trans));
793     build_append_int_noprefix(var->buf, len, sizeof(len));
794     return var;
795 }
796 
797 /* ACPI 1.0b: 6.4.3.5.1 QWord Address Space Descriptor */
798 static Aml *aml_qword_as_desc(AmlResourceType type, AmlMinFixed min_fixed,
799                               AmlMaxFixed max_fixed, AmlDecode dec,
800                               uint64_t addr_gran, uint64_t addr_min,
801                               uint64_t addr_max, uint64_t addr_trans,
802                               uint64_t len, uint8_t type_flags)
803 {
804     Aml *var = aml_alloc();
805 
806     build_append_byte(var->buf, 0x8A); /* QWord Address Space Descriptor */
807     /* minimum length since we do not encode optional fields */
808     build_append_byte(var->buf, 0x2B);
809     build_append_byte(var->buf, 0x0);
810 
811     aml_append(var,
812         aml_as_desc_header(type, min_fixed, max_fixed, dec, type_flags));
813     build_append_int_noprefix(var->buf, addr_gran, sizeof(addr_gran));
814     build_append_int_noprefix(var->buf, addr_min, sizeof(addr_min));
815     build_append_int_noprefix(var->buf, addr_max, sizeof(addr_max));
816     build_append_int_noprefix(var->buf, addr_trans, sizeof(addr_trans));
817     build_append_int_noprefix(var->buf, len, sizeof(len));
818     return var;
819 }
820 
821 /*
822  * ACPI 1.0b: 6.4.3.5.6 ASL Macros for WORD Address Descriptor
823  *
824  * More verbose description at:
825  * ACPI 5.0: 19.5.141 WordBusNumber (Word Bus Number Resource Descriptor Macro)
826  */
827 Aml *aml_word_bus_number(AmlMinFixed min_fixed, AmlMaxFixed max_fixed,
828                          AmlDecode dec, uint16_t addr_gran,
829                          uint16_t addr_min, uint16_t addr_max,
830                          uint16_t addr_trans, uint16_t len)
831 
832 {
833     return aml_word_as_desc(aml_bus_number_range, min_fixed, max_fixed, dec,
834                             addr_gran, addr_min, addr_max, addr_trans, len, 0);
835 }
836 
837 /*
838  * ACPI 1.0b: 6.4.3.5.6 ASL Macros for WORD Address Descriptor
839  *
840  * More verbose description at:
841  * ACPI 5.0: 19.5.142 WordIO (Word IO Resource Descriptor Macro)
842  */
843 Aml *aml_word_io(AmlMinFixed min_fixed, AmlMaxFixed max_fixed,
844                  AmlDecode dec, AmlISARanges isa_ranges,
845                  uint16_t addr_gran, uint16_t addr_min,
846                  uint16_t addr_max, uint16_t addr_trans,
847                  uint16_t len)
848 
849 {
850     return aml_word_as_desc(aml_io_range, min_fixed, max_fixed, dec,
851                             addr_gran, addr_min, addr_max, addr_trans, len,
852                             isa_ranges);
853 }
854 
855 /*
856  * ACPI 1.0b: 6.4.3.5.4 ASL Macros for DWORD Address Space Descriptor
857  *
858  * More verbose description at:
859  * ACPI 5.0: 19.5.34 DWordMemory (DWord Memory Resource Descriptor Macro)
860  */
861 Aml *aml_dword_memory(AmlDecode dec, AmlMinFixed min_fixed,
862                       AmlMaxFixed max_fixed, AmlCacheble cacheable,
863                       AmlReadAndWrite read_and_write,
864                       uint32_t addr_gran, uint32_t addr_min,
865                       uint32_t addr_max, uint32_t addr_trans,
866                       uint32_t len)
867 {
868     uint8_t flags = read_and_write | (cacheable << 1);
869 
870     return aml_dword_as_desc(aml_memory_range, min_fixed, max_fixed,
871                              dec, addr_gran, addr_min, addr_max,
872                              addr_trans, len, flags);
873 }
874 
875 /*
876  * ACPI 1.0b: 6.4.3.5.2 ASL Macros for QWORD Address Space Descriptor
877  *
878  * More verbose description at:
879  * ACPI 5.0: 19.5.102 QWordMemory (QWord Memory Resource Descriptor Macro)
880  */
881 Aml *aml_qword_memory(AmlDecode dec, AmlMinFixed min_fixed,
882                       AmlMaxFixed max_fixed, AmlCacheble cacheable,
883                       AmlReadAndWrite read_and_write,
884                       uint64_t addr_gran, uint64_t addr_min,
885                       uint64_t addr_max, uint64_t addr_trans,
886                       uint64_t len)
887 {
888     uint8_t flags = read_and_write | (cacheable << 1);
889 
890     return aml_qword_as_desc(aml_memory_range, min_fixed, max_fixed,
891                              dec, addr_gran, addr_min, addr_max,
892                              addr_trans, len, flags);
893 }
894