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