acpi: Accomodate non-standard UUIDs in device properties
There have been changes to the way device properties are supported in Linux[1] and Windows[2] which add flexibilty: - non-standard UUIDs can be used instead of only ACPI_DP_UUID - support for multiple different packages within the _DSD that associate different properties with unique UUIDs. To handle this I extracted the part that does the write of UUID and properties to a separate function and defined a new PACKAGE type which has the custom UUID as a name and can be used the same way that child properties are today. For example a PCIe root port for a USB4 port has a standard property indicating the USB4 reference, and then two custom properties which are defined for different attributes. Example code: /* Create property table */ acpi_dp *dsd = acpi_dp_new_table("_DSD"); acpi_dp_add_reference(dsd, "usb4-port", usb4_path); /* Add package for hotplug */ acpi_dp *pkg = acpi_dp_new_table("6211e2c0-58a3-4af3-90e1-927a4e0c55a4"); acpi_dp_add_integer(pkg, "HotPlugSupportInD3", 1); acpi_dp_add_package(dsd, pkg); /* Add package for external port info */ pkg = acpi_dp_new_table("efcc06cc-73ac-4bc3-bff0-76143807c389"); acpi_dp_add_integer(pkg, "ExternalFacingPort", 1); acpi_dp_add_package(dsd, pkg); /* Write all properties */ acpi_dp_write(dsd); Resulting ACPI: Scope (\_SB.PCI0.TRP0) { Name (_DSD, Package () { ToUUID ("daffd814-6eba-4d8c-8a91-bc9bbf4aa301") Package () { Package () { "usb4-port", \_SB.PCI0.TDM0.RHUB.PRTA } }, ToUUID ("6211e2c0-58a3-4af3-90e1-927a4e0c55a4"), Package () { Package () { "HotPlugSupportInD3", One } }, ToUUID ("efcc06cc-73ac-4bc3-bff0-76143807c389"), Package () { Package () { "ExternalFacingPort", One }, } }) } [1] https://patchwork.kernel.org/patch/10599675/ [2] https://docs.microsoft.com/en-us/windows-hardware/drivers/pci/dsd-for-pcie-root-ports Change-Id: I75f47825bf4ffc5e9e92af2c45790d1b5945576e Signed-off-by: Duncan Laurie <dlaurie@google.com> Reviewed-on: https://review.coreboot.org/c/coreboot/+/42047 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Furquan Shaikh <furquan@google.com>
This commit is contained in:
parent
fba0ad84d1
commit
84fac41d35
|
@ -53,7 +53,7 @@ const char *acpi_device_name(const struct device *dev)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
/* Check for device specific handler */
|
/* Check for device specific handler */
|
||||||
if (dev->ops->acpi_name)
|
if (dev->ops && dev->ops->acpi_name)
|
||||||
return dev->ops->acpi_name(dev);
|
return dev->ops->acpi_name(dev);
|
||||||
|
|
||||||
/* Walk up the tree to find if any parent can identify this device */
|
/* Walk up the tree to find if any parent can identify this device */
|
||||||
|
@ -658,10 +658,48 @@ static void acpi_dp_free(struct acpi_dp *dp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool acpi_dp_write_properties(struct acpi_dp *prop, const char *uuid)
|
||||||
|
{
|
||||||
|
struct acpi_dp *dp;
|
||||||
|
char *prop_count = NULL;
|
||||||
|
|
||||||
|
/* Print base properties */
|
||||||
|
for (dp = prop; dp; dp = dp->next) {
|
||||||
|
if (dp->type == ACPI_DP_TYPE_TABLE ||
|
||||||
|
dp->type == ACPI_DP_TYPE_CHILD ||
|
||||||
|
dp->type == ACPI_DP_TYPE_PACKAGE)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The UUID and package is only added when
|
||||||
|
* we come across the first property. This
|
||||||
|
* is to avoid creating a zero-length package
|
||||||
|
* in situations where there are only children.
|
||||||
|
*/
|
||||||
|
if (!prop_count) {
|
||||||
|
/* ToUUID (dp->uuid) */
|
||||||
|
acpigen_write_uuid(uuid);
|
||||||
|
/*
|
||||||
|
* Package (PROP), element count determined as
|
||||||
|
* it is populated
|
||||||
|
*/
|
||||||
|
prop_count = acpigen_write_package(0);
|
||||||
|
}
|
||||||
|
(*prop_count)++;
|
||||||
|
acpi_dp_write_property(dp);
|
||||||
|
}
|
||||||
|
if (prop_count) {
|
||||||
|
/* Package (PROP) length, if a package was written */
|
||||||
|
acpigen_pop_len();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void acpi_dp_write(struct acpi_dp *table)
|
void acpi_dp_write(struct acpi_dp *table)
|
||||||
{
|
{
|
||||||
struct acpi_dp *dp, *prop;
|
struct acpi_dp *dp, *prop;
|
||||||
char *dp_count, *prop_count = NULL;
|
char *dp_count;
|
||||||
int child_count = 0;
|
int child_count = 0;
|
||||||
|
|
||||||
if (!table || table->type != ACPI_DP_TYPE_TABLE || !table->next)
|
if (!table || table->type != ACPI_DP_TYPE_TABLE || !table->next)
|
||||||
|
@ -677,37 +715,17 @@ void acpi_dp_write(struct acpi_dp *table)
|
||||||
dp_count = acpigen_write_package(0);
|
dp_count = acpigen_write_package(0);
|
||||||
|
|
||||||
/* Print base properties */
|
/* Print base properties */
|
||||||
for (dp = prop; dp; dp = dp->next) {
|
if (acpi_dp_write_properties(prop, table->uuid))
|
||||||
if (dp->type == ACPI_DP_TYPE_CHILD) {
|
|
||||||
child_count++;
|
|
||||||
} else {
|
|
||||||
/*
|
|
||||||
* The UUID and package is only added when
|
|
||||||
* we come across the first property. This
|
|
||||||
* is to avoid creating a zero-length package
|
|
||||||
* in situations where there are only children.
|
|
||||||
*/
|
|
||||||
if (!prop_count) {
|
|
||||||
*dp_count += 2;
|
*dp_count += 2;
|
||||||
/* ToUUID (ACPI_DP_UUID) */
|
|
||||||
acpigen_write_uuid(ACPI_DP_UUID);
|
|
||||||
/*
|
|
||||||
* Package (PROP), element count determined as
|
|
||||||
* it is populated
|
|
||||||
*/
|
|
||||||
prop_count = acpigen_write_package(0);
|
|
||||||
}
|
|
||||||
(*prop_count)++;
|
|
||||||
acpi_dp_write_property(dp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (prop_count) {
|
|
||||||
/* Package (PROP) length, if a package was written */
|
|
||||||
acpigen_pop_len();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/* Count child properties */
|
||||||
|
for (dp = prop; dp; dp = dp->next)
|
||||||
|
if (dp->type == ACPI_DP_TYPE_CHILD)
|
||||||
|
child_count++;
|
||||||
|
|
||||||
|
/* Add child properties to the base table */
|
||||||
if (child_count) {
|
if (child_count) {
|
||||||
/* Update DP package count to 2 or 4 */
|
/* Update DP package count */
|
||||||
*dp_count += 2;
|
*dp_count += 2;
|
||||||
/* ToUUID (ACPI_DP_CHILD_UUID) */
|
/* ToUUID (ACPI_DP_CHILD_UUID) */
|
||||||
acpigen_write_uuid(ACPI_DP_CHILD_UUID);
|
acpigen_write_uuid(ACPI_DP_CHILD_UUID);
|
||||||
|
@ -722,6 +740,12 @@ void acpi_dp_write(struct acpi_dp *table)
|
||||||
acpigen_pop_len();
|
acpigen_pop_len();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Write packages of properties with unique UUID */
|
||||||
|
for (dp = prop; dp; dp = dp->next)
|
||||||
|
if (dp->type == ACPI_DP_TYPE_PACKAGE)
|
||||||
|
if (acpi_dp_write_properties(dp->child, dp->uuid))
|
||||||
|
*dp_count += 2;
|
||||||
|
|
||||||
/* Package (DP) length */
|
/* Package (DP) length */
|
||||||
acpigen_pop_len();
|
acpigen_pop_len();
|
||||||
|
|
||||||
|
@ -746,6 +770,7 @@ static struct acpi_dp *acpi_dp_new(struct acpi_dp *dp, enum acpi_dp_type type,
|
||||||
memset(new, 0, sizeof(*new));
|
memset(new, 0, sizeof(*new));
|
||||||
new->type = type;
|
new->type = type;
|
||||||
new->name = name;
|
new->name = name;
|
||||||
|
new->uuid = ACPI_DP_UUID;
|
||||||
|
|
||||||
if (dp) {
|
if (dp) {
|
||||||
/* Add to end of property list */
|
/* Add to end of property list */
|
||||||
|
@ -863,6 +888,22 @@ struct acpi_dp *acpi_dp_add_child(struct acpi_dp *dp, const char *name,
|
||||||
return new;
|
return new;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct acpi_dp *acpi_dp_add_package(struct acpi_dp *dp, struct acpi_dp *package)
|
||||||
|
{
|
||||||
|
struct acpi_dp *new;
|
||||||
|
|
||||||
|
if (!dp || !package || package->type != ACPI_DP_TYPE_TABLE)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
new = acpi_dp_new(dp, ACPI_DP_TYPE_PACKAGE, NULL);
|
||||||
|
if (new) {
|
||||||
|
new->uuid = package->name;
|
||||||
|
new->child = package;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new;
|
||||||
|
}
|
||||||
|
|
||||||
struct acpi_dp *acpi_dp_add_array(struct acpi_dp *dp, struct acpi_dp *array)
|
struct acpi_dp *acpi_dp_add_array(struct acpi_dp *dp, struct acpi_dp *array)
|
||||||
{
|
{
|
||||||
struct acpi_dp *new;
|
struct acpi_dp *new;
|
||||||
|
|
|
@ -15,11 +15,13 @@ enum acpi_dp_type {
|
||||||
ACPI_DP_TYPE_TABLE,
|
ACPI_DP_TYPE_TABLE,
|
||||||
ACPI_DP_TYPE_ARRAY,
|
ACPI_DP_TYPE_ARRAY,
|
||||||
ACPI_DP_TYPE_CHILD,
|
ACPI_DP_TYPE_CHILD,
|
||||||
|
ACPI_DP_TYPE_PACKAGE,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct acpi_dp {
|
struct acpi_dp {
|
||||||
enum acpi_dp_type type;
|
enum acpi_dp_type type;
|
||||||
const char *name;
|
const char *name;
|
||||||
|
const char *uuid;
|
||||||
struct acpi_dp *next;
|
struct acpi_dp *next;
|
||||||
union {
|
union {
|
||||||
struct acpi_dp *child;
|
struct acpi_dp *child;
|
||||||
|
@ -464,6 +466,9 @@ void acpi_device_add_power_res(const struct acpi_power_res_params *params);
|
||||||
/* Start a new Device Property table with provided ACPI reference */
|
/* Start a new Device Property table with provided ACPI reference */
|
||||||
struct acpi_dp *acpi_dp_new_table(const char *ref);
|
struct acpi_dp *acpi_dp_new_table(const char *ref);
|
||||||
|
|
||||||
|
/* Add package of device properties with a unique UUID */
|
||||||
|
struct acpi_dp *acpi_dp_add_package(struct acpi_dp *dp, struct acpi_dp *package);
|
||||||
|
|
||||||
/* Add integer Device Property */
|
/* Add integer Device Property */
|
||||||
struct acpi_dp *acpi_dp_add_integer(struct acpi_dp *dp, const char *name,
|
struct acpi_dp *acpi_dp_add_integer(struct acpi_dp *dp, const char *name,
|
||||||
uint64_t value);
|
uint64_t value);
|
||||||
|
|
Loading…
Reference in New Issue