static void nvdimm_build_nvdimm_devices(GSList *device_list, Aml *root_dev) { for (; device_list; device_list = device_list->next) { DeviceState *dev = device_list->data; int slot = object_property_get_int(OBJECT(dev), PC_DIMM_SLOT_PROP, NULL); uint32_t handle = nvdimm_slot_to_handle(slot); Aml *nvdimm_dev; nvdimm_dev = aml_device("NV%02X", slot); /* * ACPI 6.0: 9.20 NVDIMM Devices: * * _ADR object that is used to supply OSPM with unique address * of the NVDIMM device. This is done by returning the NFIT Device * handle that is used to identify the associated entries in ACPI * table NFIT or _FIT. */ aml_append(nvdimm_dev, aml_name_decl("_ADR", aml_int(handle))); nvdimm_build_device_dsm(nvdimm_dev); aml_append(root_dev, nvdimm_dev); } }
/* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefLEqual */ Aml *aml_equal(Aml *arg1, Aml *arg2) { Aml *var = aml_opcode(0x93 /* LequalOp */); aml_append(var, arg1); aml_append(var, arg2); return var; }
/* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefLLess */ Aml *aml_lless(Aml *arg1, Aml *arg2) { Aml *var = aml_opcode(0x95 /* LLessOp */); aml_append(var, arg1); aml_append(var, arg2); return var; }
/* ACPI 1.0b: 16.2.5.3 Type 1 Opcodes Encoding: DefNotify */ Aml *aml_notify(Aml *arg1, Aml *arg2) { Aml *var = aml_opcode(0x86 /* NotifyOp */); aml_append(var, arg1); aml_append(var, arg2); return var; }
/* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefStore */ Aml *aml_store(Aml *val, Aml *target) { Aml *var = aml_opcode(0x70 /* StoreOp */); aml_append(var, val); aml_append(var, target); return var; }
/* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefLGreater */ Aml *aml_lgreater(Aml *arg1, Aml *arg2) { Aml *var = aml_opcode(0x94 /* LGreaterOp */); aml_append(var, arg1); aml_append(var, arg2); return var; }
/* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefLOr */ Aml *aml_lor(Aml *arg1, Aml *arg2) { Aml *var = aml_opcode(0x91 /* LOrOp */); aml_append(var, arg1); aml_append(var, arg2); return var; }
/* ACPI 1.0b: 16.2.5.1 Name Space Modifier Objects Encoding: DefAlias */ Aml *aml_alias(const char *source_object, const char *alias_object) { Aml *var = aml_opcode(0x06 /* AliasOp */); aml_append(var, aml_name("%s", source_object)); aml_append(var, aml_name("%s", alias_object)); return var; }
/* helper to call method with 2 arguments */ Aml *aml_call2(const char *method, Aml *arg1, Aml *arg2) { Aml *var = aml_alloc(); build_append_namestring(var->buf, "%s", method); aml_append(var, arg1); aml_append(var, arg2); return var; }
static void acpi_dsdt_add_power_button(Aml *scope) { Aml *dev = aml_device(ACPI_POWER_BUTTON_DEVICE); aml_append(dev, aml_name_decl("_HID", aml_string("PNP0C0C"))); aml_append(dev, aml_name_decl("_ADR", aml_int(0))); aml_append(dev, aml_name_decl("_UID", aml_int(0))); aml_append(scope, dev); }
/* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefAnd */ Aml *aml_and(Aml *arg1, Aml *arg2) { Aml *var = aml_opcode(0x7B /* AndOp */); aml_append(var, arg1); aml_append(var, arg2); build_append_byte(var->buf, 0x00 /* NullNameOp */); return var; }
static Aml *create_field_common(int opcode, Aml *srcbuf, Aml *index, const char *name) { Aml *var = aml_opcode(opcode); aml_append(var, srcbuf); aml_append(var, index); build_append_namestring(var->buf, "%s", name); return var; }
/* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefLGreaterEqual */ Aml *aml_lgreater_equal(Aml *arg1, Aml *arg2) { /* LGreaterEqualOp := LNotOp LLessOp */ Aml *var = aml_opcode(0x92 /* LNotOp */); build_append_byte(var->buf, 0x95 /* LLessOp */); aml_append(var, arg1); aml_append(var, arg2); return var; }
static void nvdimm_build_device_dsm(Aml *dev) { Aml *method; method = aml_method("_DSM", 4, AML_NOTSERIALIZED); aml_append(method, aml_return(aml_call4(NVDIMM_COMMON_DSM, aml_arg(0), aml_arg(1), aml_arg(2), aml_arg(3)))); aml_append(dev, method); }
/* ACPI 2.0a: 17.2.4.4 Type 2 Opcodes Encoding: DefToHexString */ Aml *aml_to_hexstring(Aml *src, Aml *dst) { Aml *var = aml_opcode(0x98 /* ToHexStringOp */); aml_append(var, src); if (dst) { aml_append(var, dst); } else { build_append_byte(var->buf, 0x00 /* NullNameOp */); } return var; }
/* ACPI 2.0a: 17.2.4.4 Type 2 Opcodes Encoding: DefToBuffer */ Aml *aml_to_buffer(Aml *src, Aml *dst) { Aml *var = aml_opcode(0x96 /* ToBufferOp */); aml_append(var, src); if (dst) { aml_append(var, dst); } else { build_append_byte(var->buf, 0x00 /* NullNameOp */); } return var; }
static void acpi_dsdt_add_cpus(Aml *scope, int smp_cpus) { uint16_t i; for (i = 0; i < smp_cpus; i++) { Aml *dev = aml_device("C%03x", i); aml_append(dev, aml_name_decl("_HID", aml_string("ACPI0007"))); aml_append(dev, aml_name_decl("_UID", aml_int(i))); aml_append(scope, dev); } }
/* 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; }
static void acpi_dsdt_add_fw_cfg(Aml *scope, const MemMapEntry *fw_cfg_memmap) { Aml *dev = aml_device("FWCF"); aml_append(dev, aml_name_decl("_HID", aml_string("QEMU0002"))); /* device present, functioning, decoding, not shown in UI */ aml_append(dev, aml_name_decl("_STA", aml_int(0xB))); Aml *crs = aml_resource_template(); aml_append(crs, aml_memory32_fixed(fw_cfg_memmap->base, fw_cfg_memmap->size, AML_READ_WRITE)); aml_append(dev, aml_name_decl("_CRS", crs)); aml_append(scope, dev); }
/** * build_opcode_2arg_dst: * @op: 1-byte opcode * @arg1: 1st operand * @arg2: 2nd operand * @dst: optional target to store to, set to NULL if it's not required * * An internal helper to compose AML terms that have * "Op Operand Operand Target" * pattern. * * Returns: The newly allocated and composed according to patter Aml object. */ static Aml * build_opcode_2arg_dst(uint8_t op, Aml *arg1, Aml *arg2, Aml *dst) { Aml *var = aml_opcode(op); aml_append(var, arg1); aml_append(var, arg2); if (dst) { aml_append(var, dst); } else { build_append_byte(var->buf, 0x00 /* NullNameOp */); } return var; }
/* ACPI 2.0a: 17.2.4.4 Type 2 Opcodes Encoding: DefToInteger */ Aml *aml_to_integer(Aml *arg) { Aml *var = aml_opcode(0x99 /* ToIntegerOp */); aml_append(var, arg); build_append_byte(var->buf, 0x00 /* NullNameOp */); return var; }
/* ACPI 1.0b: 16.2.5.1 Namespace Modifier Objects Encoding: DefName */ Aml *aml_name_decl(const char *name, Aml *val) { Aml *var = aml_opcode(0x08 /* NameOp */); build_append_namestring(var->buf, "%s", name); aml_append(var, val); 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; }
/* 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.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; }
static void nvdimm_build_ssdt(GSList *device_list, GArray *table_offsets, GArray *table_data, GArray *linker) { Aml *ssdt, *sb_scope, *dev; acpi_add_table(table_offsets, table_data); ssdt = init_aml_allocator(); acpi_data_push(ssdt->buf, sizeof(AcpiTableHeader)); sb_scope = aml_scope("\\_SB"); dev = aml_device("NVDR"); /* * ACPI 6.0: 9.20 NVDIMM Devices: * * The ACPI Name Space device uses _HID of ACPI0012 to identify the root * NVDIMM interface device. Platform firmware is required to contain one * such device in _SB scope if NVDIMMs support is exposed by platform to * OSPM. * For each NVDIMM present or intended to be supported by platform, * platform firmware also exposes an ACPI Namespace Device under the * root device. */ aml_append(dev, aml_name_decl("_HID", aml_string("ACPI0012"))); nvdimm_build_common_dsm(dev); nvdimm_build_device_dsm(dev); nvdimm_build_nvdimm_devices(device_list, dev); aml_append(sb_scope, dev); aml_append(ssdt, sb_scope); /* copy AML table into ACPI tables blob and patch header there */ g_array_append_vals(table_data, ssdt->buf->data, ssdt->buf->len); build_header(linker, table_data, (void *)(table_data->data + table_data->len - ssdt->buf->len), "SSDT", ssdt->buf->len, 1, "NVDIMM"); free_aml_allocator(); }
/* 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; }
static void acpi_dsdt_add_flash(Aml *scope, const MemMapEntry *flash_memmap) { Aml *dev, *crs; hwaddr base = flash_memmap->base; hwaddr size = flash_memmap->size / 2; dev = aml_device("FLS0"); aml_append(dev, aml_name_decl("_HID", aml_string("LNRO0015"))); aml_append(dev, aml_name_decl("_UID", aml_int(0))); crs = aml_resource_template(); aml_append(crs, aml_memory32_fixed(base, size, AML_READ_WRITE)); aml_append(dev, aml_name_decl("_CRS", crs)); aml_append(scope, dev); dev = aml_device("FLS1"); aml_append(dev, aml_name_decl("_HID", aml_string("LNRO0015"))); aml_append(dev, aml_name_decl("_UID", aml_int(1))); crs = aml_resource_template(); aml_append(crs, aml_memory32_fixed(base + size, size, AML_READ_WRITE)); aml_append(dev, aml_name_decl("_CRS", crs)); aml_append(scope, dev); }
static void nvdimm_build_common_dsm(Aml *dev) { Aml *method, *ifctx, *function; uint8_t byte_list[1]; method = aml_method(NVDIMM_COMMON_DSM, 4, AML_NOTSERIALIZED); function = aml_arg(2); /* * function 0 is called to inquire what functions are supported by * OSPM */ ifctx = aml_if(aml_equal(function, aml_int(0))); byte_list[0] = 0 /* No function Supported */; aml_append(ifctx, aml_return(aml_buffer(1, byte_list))); aml_append(method, ifctx); /* No function is supported yet. */ byte_list[0] = 1 /* Not Supported */; aml_append(method, aml_return(aml_buffer(1, byte_list))); aml_append(dev, method); }
/* 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; }