/* ACPI 1.0b: 16.2.6.3 Debug Objects Encoding: DebugObj */ Aml *aml_debug(void) { Aml *var = aml_alloc(); build_append_byte(var->buf, 0x5B); /* ExtOpPrefix */ build_append_byte(var->buf, 0x31); /* DebugOp */ return var; }
/* ACPI 1.0b: 16.2.5.2 Named Objects Encoding: NamedField */ Aml *aml_named_field(const char *name, unsigned length) { Aml *var = aml_alloc(); build_append_nameseg(var->buf, name); build_append_pkg_length(var->buf, length, false); return var; }
/* helper to call method with 1 argument */ Aml *aml_call1(const char *method, Aml *arg1) { Aml *var = aml_alloc(); build_append_namestring(var->buf, "%s", method); aml_append(var, arg1); return var; }
/* * ACPI 5.0: 6.4.3.6 Extended Interrupt Descriptor * Type 1, Large Item Name 0x9 */ Aml *aml_interrupt(AmlConsumerAndProducer con_and_pro, AmlLevelAndEdge level_and_edge, AmlActiveHighAndLow high_and_low, AmlShared shared, uint32_t *irq_list, uint8_t irq_count) { int i; Aml *var = aml_alloc(); uint8_t irq_flags = con_and_pro | (level_and_edge << 1) | (high_and_low << 2) | (shared << 3); const int header_bytes_in_len = 2; uint16_t len = header_bytes_in_len + irq_count * sizeof(uint32_t); assert(irq_count > 0); build_append_byte(var->buf, 0x89); /* Extended irq descriptor */ build_append_byte(var->buf, len & 0xFF); /* Length, bits[7:0] */ build_append_byte(var->buf, len >> 8); /* Length, bits[15:8] */ build_append_byte(var->buf, irq_flags); /* Interrupt Vector Information. */ build_append_byte(var->buf, irq_count); /* Interrupt table length */ /* Interrupt Number List */ for (i = 0; i < irq_count; i++) { build_append_int_noprefix(var->buf, irq_list[i], 4); } return var; }
/* ACPI 1.0b: 16.2.5.3 Type 1 Opcodes Encoding: DefRelease */ Aml *aml_release(Aml *mutex) { Aml *var = aml_alloc(); build_append_byte(var->buf, 0x5B); /* ExtOpPrefix */ build_append_byte(var->buf, 0x27); /* ReleaseOp */ aml_append(var, mutex); return var; }
/* ACPI 1.0b: 16.2.5.3 Type 1 Opcodes Encoding: DefSleep */ Aml *aml_sleep(uint64_t msec) { Aml *var = aml_alloc(); build_append_byte(var->buf, 0x5B); /* ExtOpPrefix */ build_append_byte(var->buf, 0x22); /* SleepOp */ aml_append(var, aml_int(msec)); return var; }
static Aml *aml_opcode(uint8_t op) { Aml *var = aml_alloc(); var->op = op; var->block_flags = AML_OPCODE; return var; }
/* ACPI 1.0b: 16.2.5.2 Named Objects Encoding: ReservedField */ Aml *aml_reserved_field(unsigned length) { Aml *var = aml_alloc(); /* ReservedField := 0x00 PkgLength */ build_append_byte(var->buf, 0x00); build_append_pkg_length(var->buf, length, false); return var; }
static Aml *aml_bundle(uint8_t op, AmlBlockFlags flags) { Aml *var = aml_alloc(); var->op = op; var->block_flags = flags; return var; }
/* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefAcquire */ Aml *aml_acquire(Aml *mutex, uint16_t timeout) { Aml *var = aml_alloc(); build_append_byte(var->buf, 0x5B); /* ExtOpPrefix */ build_append_byte(var->buf, 0x23); /* AcquireOp */ aml_append(var, mutex); build_append_int_noprefix(var->buf, timeout, sizeof(timeout)); return var; }
Aml *init_aml_allocator(void) { Aml *var; assert(!alloc_list); alloc_list = g_ptr_array_new(); var = aml_alloc(); return var; }
/* * helper to construct NameString, which returns Aml object * for using with aml_append or other aml_* terms */ Aml *aml_name(const char *name_format, ...) { va_list ap; Aml *var = aml_alloc(); va_start(ap, name_format); build_append_namestringv(var->buf, name_format, ap); va_end(ap); return var; }
/* ACPI 1.0b: 16.2.5.2 Named Objects Encoding: DefMutex */ Aml *aml_mutex(const char *name, uint8_t sync_level) { Aml *var = aml_alloc(); build_append_byte(var->buf, 0x5B); /* ExtOpPrefix */ build_append_byte(var->buf, 0x01); /* MutexOp */ build_append_namestring(var->buf, "%s", name); assert(!(sync_level & 0xF0)); build_append_byte(var->buf, sync_level); return var; }
/* ACPI 1.0b: 16.2.5.2 Named Objects Encoding: DefOpRegion */ Aml *aml_operation_region(const char *name, AmlRegionSpace rs, Aml *offset, uint32_t len) { Aml *var = aml_alloc(); build_append_byte(var->buf, 0x5B); /* ExtOpPrefix */ build_append_byte(var->buf, 0x80); /* OpRegionOp */ build_append_namestring(var->buf, "%s", name); build_append_byte(var->buf, rs); aml_append(var, offset); build_append_int(var->buf, len); return var; }
/* ACPI 1.0b: 16.2.5.2 Named Objects Encoding: DefCreateField */ Aml *aml_create_field(Aml *srcbuf, Aml *bit_index, Aml *num_bits, const char *name) { Aml *var = aml_alloc(); build_append_byte(var->buf, 0x5B); /* ExtOpPrefix */ build_append_byte(var->buf, 0x13); /* CreateFieldOp */ aml_append(var, srcbuf); aml_append(var, bit_index); aml_append(var, num_bits); build_append_namestring(var->buf, "%s", name); return var; }
/* helper to call method with 5 arguments */ Aml *aml_call5(const char *method, Aml *arg1, Aml *arg2, Aml *arg3, Aml *arg4, Aml *arg5) { Aml *var = aml_alloc(); build_append_namestring(var->buf, "%s", method); aml_append(var, arg1); aml_append(var, arg2); aml_append(var, arg3); aml_append(var, arg4); aml_append(var, arg5); return var; }
/* ACPI 1.0b: 6.4.3.5.5 Word Address Space Descriptor: bytes 3-5 */ static Aml *aml_as_desc_header(AmlResourceType type, AmlMinFixed min_fixed, AmlMaxFixed max_fixed, AmlDecode dec, uint8_t type_flags) { uint8_t flags = max_fixed | min_fixed | dec; Aml *var = aml_alloc(); build_append_byte(var->buf, type); build_append_byte(var->buf, flags); build_append_byte(var->buf, type_flags); /* Type Specific Flags */ return var; }
/* ACPI 1.0b: 6.4.2.2 DMA Format/6.4.2.2.1 ASL Macro for DMA Descriptor */ Aml *aml_dma(AmlDmaType typ, AmlDmaBusMaster bm, AmlTransferSize sz, uint8_t channel) { Aml *var = aml_alloc(); uint8_t flags = sz | bm << 2 | typ << 5; assert(channel < 8); build_append_byte(var->buf, 0x2A); /* Byte 0: DMA Descriptor */ build_append_byte(var->buf, 1U << channel); /* Byte 1: _DMA - DmaChannel */ build_append_byte(var->buf, flags); /* Byte 2 */ return var; }
/* * ACPI 1.0b: 6.4.2.1.1 ASL Macro for IRQ Descriptor * * More verbose description at: * ACPI 5.0: 19.5.64 IRQNoFlags (Interrupt Resource Descriptor Macro) * 6.4.2.1 IRQ Descriptor */ Aml *aml_irq_no_flags(uint8_t irq) { uint16_t irq_mask; Aml *var = aml_alloc(); assert(irq < 16); build_append_byte(var->buf, 0x22); /* IRQ descriptor 2 byte form */ irq_mask = 1U << irq; build_append_byte(var->buf, irq_mask & 0xFF); /* IRQ mask bits[7:0] */ build_append_byte(var->buf, irq_mask >> 8); /* IRQ mask bits[15:8] */ return var; }
/* ACPI 1.0b: 6.4.2.5 I/O Port Descriptor */ Aml *aml_io(AmlIODecode dec, uint16_t min_base, uint16_t max_base, uint8_t aln, uint8_t len) { Aml *var = aml_alloc(); build_append_byte(var->buf, 0x47); /* IO port descriptor */ build_append_byte(var->buf, dec); build_append_byte(var->buf, min_base & 0xff); build_append_byte(var->buf, (min_base >> 8) & 0xff); build_append_byte(var->buf, max_base & 0xff); build_append_byte(var->buf, (max_base >> 8) & 0xff); build_append_byte(var->buf, aln); build_append_byte(var->buf, len); return var; }
/* ACPI 1.0b: 15.2.3.6.4.1 EISAID Macro - Convert EISA ID String To Integer */ Aml *aml_eisaid(const char *str) { Aml *var = aml_alloc(); uint32_t id; g_assert(strlen(str) == 7); id = (str[0] - 0x40) << 26 | (str[1] - 0x40) << 21 | (str[2] - 0x40) << 16 | Hex2Digit(str[3]) << 12 | Hex2Digit(str[4]) << 8 | Hex2Digit(str[5]) << 4 | Hex2Digit(str[6]); build_append_byte(var->buf, 0x0C); /* DWordPrefix */ build_append_int_noprefix(var->buf, bswap32(id), sizeof(id)); return var; }
/* * ACPI 1.0b: 6.4.3.4 32-Bit Fixed Location Memory Range Descriptor * (Type 1, Large Item Name 0x6) */ Aml *aml_memory32_fixed(uint32_t addr, uint32_t size, AmlReadAndWrite read_and_write) { Aml *var = aml_alloc(); build_append_byte(var->buf, 0x86); /* Memory32Fixed Resource Descriptor */ build_append_byte(var->buf, 9); /* Length, bits[7:0] value = 9 */ build_append_byte(var->buf, 0); /* Length, bits[15:8] value = 0 */ build_append_byte(var->buf, read_and_write); /* Write status, 1 rw 0 ro */ /* Range base address */ build_append_byte(var->buf, extract32(addr, 0, 8)); /* bits[7:0] */ build_append_byte(var->buf, extract32(addr, 8, 8)); /* bits[15:8] */ build_append_byte(var->buf, extract32(addr, 16, 8)); /* bits[23:16] */ build_append_byte(var->buf, extract32(addr, 24, 8)); /* bits[31:24] */ /* Range length */ build_append_byte(var->buf, extract32(size, 0, 8)); /* bits[7:0] */ build_append_byte(var->buf, extract32(size, 8, 8)); /* bits[15:8] */ build_append_byte(var->buf, extract32(size, 16, 8)); /* bits[23:16] */ build_append_byte(var->buf, extract32(size, 24, 8)); /* bits[31:24] */ return var; }
/* ACPI 1.0b: 6.4.3.5.1 QWord Address Space Descriptor */ static Aml *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) { Aml *var = aml_alloc(); build_append_byte(var->buf, 0x8A); /* QWord Address Space Descriptor */ /* minimum length since we do not encode optional fields */ build_append_byte(var->buf, 0x2B); build_append_byte(var->buf, 0x0); aml_append(var, aml_as_desc_header(type, min_fixed, max_fixed, dec, type_flags)); build_append_int_noprefix(var->buf, addr_gran, sizeof(addr_gran)); build_append_int_noprefix(var->buf, addr_min, sizeof(addr_min)); build_append_int_noprefix(var->buf, addr_max, sizeof(addr_max)); build_append_int_noprefix(var->buf, addr_trans, sizeof(addr_trans)); build_append_int_noprefix(var->buf, len, sizeof(len)); return var; }
static Aml *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) { Aml *var = aml_alloc(); const uint16_t min_desc_len = 0x16; uint16_t resource_source_name_len, length; uint16_t pin_table_offset, resource_source_name_offset, vendor_data_offset; uint32_t i; assert(resource_source_name); resource_source_name_len = strlen(resource_source_name) + 1; length = min_desc_len + resource_source_name_len + vendor_data_len; pin_table_offset = min_desc_len + 1; resource_source_name_offset = pin_table_offset + pin_count * 2; vendor_data_offset = resource_source_name_offset + resource_source_name_len; build_append_byte(var->buf, 0x8C); /* GPIO Connection Descriptor */ build_append_int_noprefix(var->buf, length, 2); /* Length */ build_append_byte(var->buf, 1); /* Revision ID */ build_append_byte(var->buf, type); /* GPIO Connection Type */ /* General Flags (2 bytes) */ build_append_int_noprefix(var->buf, con_and_pro, 2); /* Interrupt and IO Flags (2 bytes) */ build_append_int_noprefix(var->buf, flags, 2); /* Pin Configuration 0 = Default 1 = Pull-up 2 = Pull-down 3 = No Pull */ build_append_byte(var->buf, pin_config); /* Output Drive Strength (2 bytes) */ build_append_int_noprefix(var->buf, output_drive, 2); /* Debounce Timeout (2 bytes) */ build_append_int_noprefix(var->buf, debounce_timeout, 2); /* Pin Table Offset (2 bytes) */ build_append_int_noprefix(var->buf, pin_table_offset, 2); build_append_byte(var->buf, 0); /* Resource Source Index */ /* Resource Source Name Offset (2 bytes) */ build_append_int_noprefix(var->buf, resource_source_name_offset, 2); /* Vendor Data Offset (2 bytes) */ build_append_int_noprefix(var->buf, vendor_data_offset, 2); /* Vendor Data Length (2 bytes) */ build_append_int_noprefix(var->buf, vendor_data_len, 2); /* Pin Number (2n bytes)*/ for (i = 0; i < pin_count; i++) { build_append_int_noprefix(var->buf, pin_list[i], 2); } /* Resource Source Name */ build_append_namestring(var->buf, "%s", resource_source_name); build_append_byte(var->buf, '\0'); /* Vendor-defined Data */ if (vendor_data != NULL) { g_array_append_vals(var->buf, vendor_data, vendor_data_len); } return var; }
/* helper to call method with 1 argument */ Aml *aml_call0(const char *method) { Aml *var = aml_alloc(); build_append_namestring(var->buf, "%s", method); return var; }
/* * ACPI 1.0b: 16.2.3 Data Objects Encoding: * encodes: ByteConst, WordConst, DWordConst, QWordConst, ZeroOp, OneOp */ Aml *aml_int(const uint64_t val) { Aml *var = aml_alloc(); build_append_int(var->buf, val); return var; }
Aml *init_aml_allocator(void) { assert(!alloc_list); alloc_list = g_ptr_array_new(); return aml_alloc(); }