mirror of
https://github.com/u-boot/u-boot.git
synced 2025-04-23 13:56:20 +00:00
acpi: Support writing Device Properties objects via _DSD
More complex device properties can be provided to drivers via a device-specific data (_DSD) object. To create this we need to build it up in a separate data structure and then generate the ACPI code, due to its recursive nature. Add an implementation of this. Signed-off-by: Simon Glass <sjg@chromium.org> Reviewed-by: Wolfgang Wallner <wolfgang.wallner@br-automation.com> Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
This commit is contained in:
parent
29df845204
commit
0e5a0a00d6
8 changed files with 974 additions and 22 deletions
217
include/acpi/acpi_dp.h
Normal file
217
include/acpi/acpi_dp.h
Normal file
|
@ -0,0 +1,217 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Device properties, a temporary data structure for adding to ACPI code
|
||||
*
|
||||
* Copyright 2019 Google LLC
|
||||
* Mostly taken from coreboot file acpi_device.h
|
||||
*/
|
||||
|
||||
#ifndef __ACPI_DP_H
|
||||
#define __ACPI_DP_H
|
||||
|
||||
struct acpi_ctx;
|
||||
|
||||
/*
|
||||
* Writing Device Properties objects via _DSD
|
||||
*
|
||||
* This is described in ACPI 6.3 section 6.2.5
|
||||
*
|
||||
* This provides a structure to handle nested device-specific data which ends
|
||||
* up in a _DSD table.
|
||||
*
|
||||
* https://www.kernel.org/doc/html/latest/firmware-guide/acpi/DSD-properties-rules.html
|
||||
* https://uefi.org/sites/default/files/resources/_DSD-device-properties-UUID.pdf
|
||||
* https://uefi.org/sites/default/files/resources/_DSD-hierarchical-data-extension-UUID-v1.1.pdf
|
||||
*
|
||||
* The Device Property Hierarchy can be multiple levels deep with multiple
|
||||
* children possible in each level. In order to support this flexibility
|
||||
* the device property hierarchy must be built up before being written out.
|
||||
*
|
||||
* For example:
|
||||
*
|
||||
* Child table with string and integer:
|
||||
* struct acpi_dp *child = acpi_dp_new_table("CHLD");
|
||||
* acpi_dp_add_string(child, "childstring", "CHILD");
|
||||
* acpi_dp_add_integer(child, "childint", 100);
|
||||
*
|
||||
* _DSD table with integer and gpio and child pointer:
|
||||
* struct acpi_dp *dsd = acpi_dp_new_table("_DSD");
|
||||
* acpi_dp_add_integer(dsd, "number1", 1);
|
||||
* acpi_dp_add_gpio(dsd, "gpio", "\_SB.PCI0.GPIO", 0, 0, 1);
|
||||
* acpi_dp_add_child(dsd, "child", child);
|
||||
*
|
||||
* Write entries into SSDT and clean up resources:
|
||||
* acpi_dp_write(dsd);
|
||||
*
|
||||
* Name(_DSD, Package() {
|
||||
* ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301")
|
||||
* Package() {
|
||||
* Package() { "gpio", Package() { \_SB.PCI0.GPIO, 0, 0, 0 } }
|
||||
* Package() { "number1", 1 }
|
||||
* }
|
||||
* ToUUID("dbb8e3e6-5886-4ba6-8795-1319f52a966b")
|
||||
* Package() {
|
||||
* Package() { "child", CHLD }
|
||||
* }
|
||||
* }
|
||||
* Name(CHLD, Package() {
|
||||
* ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301")
|
||||
* Package() {
|
||||
* Package() { "childstring", "CHILD" }
|
||||
* Package() { "childint", 100 }
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
|
||||
#define ACPI_DP_UUID "daffd814-6eba-4d8c-8a91-bc9bbf4aa301"
|
||||
#define ACPI_DP_CHILD_UUID "dbb8e3e6-5886-4ba6-8795-1319f52a966b"
|
||||
|
||||
/**
|
||||
* enum acpi_dp_type - types of device property objects
|
||||
*
|
||||
* These refer to the types defined by struct acpi_dp below
|
||||
*
|
||||
* @ACPI_DP_TYPE_UNKNOWN: Unknown / do not use
|
||||
* @ACPI_DP_TYPE_INTEGER: Integer value (u64) in @integer
|
||||
* @ACPI_DP_TYPE_STRING: String value in @string
|
||||
* @ACPI_DP_TYPE_REFERENCE: Reference to another object, with value in @string
|
||||
* @ACPI_DP_TYPE_TABLE: Type for a top-level table which may have children
|
||||
* @ACPI_DP_TYPE_ARRAY: Array of items with first item in @array and following
|
||||
* items linked from that item's @next
|
||||
* @ACPI_DP_TYPE_CHILD: Child object, with siblings in that child's @next
|
||||
*/
|
||||
enum acpi_dp_type {
|
||||
ACPI_DP_TYPE_UNKNOWN,
|
||||
ACPI_DP_TYPE_INTEGER,
|
||||
ACPI_DP_TYPE_STRING,
|
||||
ACPI_DP_TYPE_REFERENCE,
|
||||
ACPI_DP_TYPE_TABLE,
|
||||
ACPI_DP_TYPE_ARRAY,
|
||||
ACPI_DP_TYPE_CHILD,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct acpi_dp - ACPI device properties
|
||||
*
|
||||
* @type: Table type
|
||||
* @name: Name of object, typically _DSD but could be CHLD for a child object.
|
||||
* This can be NULL if there is no name
|
||||
* @next: Next object in list (next array element or next sibling)
|
||||
* @child: Pointer to first child, if @type == ACPI_DP_TYPE_CHILD, else NULL
|
||||
* @array: First array element, if @type == ACPI_DP_TYPE_ARRAY, else NULL
|
||||
* @integer: Integer value of the property, if @type == ACPI_DP_TYPE_INTEGER
|
||||
* @string: String value of the property, if @type == ACPI_DP_TYPE_STRING;
|
||||
* child name if @type == ACPI_DP_TYPE_CHILD;
|
||||
* reference name if @type == ACPI_DP_TYPE_REFERENCE;
|
||||
*/
|
||||
struct acpi_dp {
|
||||
enum acpi_dp_type type;
|
||||
const char *name;
|
||||
struct acpi_dp *next;
|
||||
union {
|
||||
struct acpi_dp *child;
|
||||
struct acpi_dp *array;
|
||||
};
|
||||
union {
|
||||
u64 integer;
|
||||
const char *string;
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* acpi_dp_new_table() - Start a new Device Property table
|
||||
*
|
||||
* @ref: ACPI reference (e.g. "_DSD")
|
||||
* @return pointer to table, or NULL if out of memory
|
||||
*/
|
||||
struct acpi_dp *acpi_dp_new_table(const char *ref);
|
||||
|
||||
/**
|
||||
* acpi_dp_add_integer() - Add integer Device Property
|
||||
*
|
||||
* A new node is added to the end of the property list of @dp
|
||||
*
|
||||
* @dp: Table to add this property to
|
||||
* @name: Name of property, or NULL for none
|
||||
* @value: Integer value
|
||||
* @return pointer to new node, or NULL if out of memory
|
||||
*/
|
||||
struct acpi_dp *acpi_dp_add_integer(struct acpi_dp *dp, const char *name,
|
||||
u64 value);
|
||||
|
||||
/**
|
||||
* acpi_dp_add_string() - Add string Device Property
|
||||
*
|
||||
* A new node is added to the end of the property list of @dp
|
||||
*
|
||||
* @dp: Table to add this property to
|
||||
* @name: Name of property, or NULL for none
|
||||
* @string: String value
|
||||
* @return pointer to new node, or NULL if out of memory
|
||||
*/
|
||||
struct acpi_dp *acpi_dp_add_string(struct acpi_dp *dp, const char *name,
|
||||
const char *string);
|
||||
|
||||
/**
|
||||
* acpi_dp_add_reference() - Add reference Device Property
|
||||
*
|
||||
* A new node is added to the end of the property list of @dp
|
||||
*
|
||||
* @dp: Table to add this property to
|
||||
* @name: Name of property, or NULL for none
|
||||
* @reference: Reference value
|
||||
* @return pointer to new node, or NULL if out of memory
|
||||
*/
|
||||
struct acpi_dp *acpi_dp_add_reference(struct acpi_dp *dp, const char *name,
|
||||
const char *reference);
|
||||
|
||||
/**
|
||||
* acpi_dp_add_array() - Add array Device Property
|
||||
*
|
||||
* A new node is added to the end of the property list of @dp, with the array
|
||||
* attached to that.
|
||||
*
|
||||
* @dp: Table to add this property to
|
||||
* @name: Name of property, or NULL for none
|
||||
* @return pointer to new node, or NULL if out of memory
|
||||
*/
|
||||
struct acpi_dp *acpi_dp_add_array(struct acpi_dp *dp, struct acpi_dp *array);
|
||||
|
||||
/**
|
||||
* acpi_dp_add_integer_array() - Add an array of integers
|
||||
*
|
||||
* A new node is added to the end of the property list of @dp, with the array
|
||||
* attached to that. Each element of the array becomes a new node.
|
||||
*
|
||||
* @dp: Table to add this property to
|
||||
* @name: Name of property, or NULL for none
|
||||
* @return pointer to new array node, or NULL if out of memory
|
||||
*/
|
||||
struct acpi_dp *acpi_dp_add_integer_array(struct acpi_dp *dp, const char *name,
|
||||
u64 *array, int len);
|
||||
|
||||
/**
|
||||
* acpi_dp_add_child() - Add a child table of Device Properties
|
||||
*
|
||||
* A new node is added as a child of @dp
|
||||
*
|
||||
* @dp: Table to add this child to
|
||||
* @name: Name of child, or NULL for none
|
||||
* @child: Child node to add
|
||||
* @return pointer to new child node, or NULL if out of memory
|
||||
*/
|
||||
struct acpi_dp *acpi_dp_add_child(struct acpi_dp *dp, const char *name,
|
||||
struct acpi_dp *child);
|
||||
|
||||
/**
|
||||
* acpi_dp_write() - Write Device Property hierarchy and clean up resources
|
||||
*
|
||||
* This writes the table using acpigen and then frees it
|
||||
*
|
||||
* @ctx: ACPI context
|
||||
* @table: Table to write
|
||||
* @return 0 if OK, -ve on error
|
||||
*/
|
||||
int acpi_dp_write(struct acpi_ctx *ctx, struct acpi_dp *table);
|
||||
|
||||
#endif
|
|
@ -31,6 +31,7 @@ enum {
|
|||
PACKAGE_OP = 0x12,
|
||||
DUAL_NAME_PREFIX = 0x2e,
|
||||
MULTI_NAME_PREFIX = 0x2f,
|
||||
ROOT_PREFIX = 0x5c,
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -3,4 +3,5 @@
|
|||
|
||||
obj-y += acpigen.o
|
||||
obj-y += acpi_device.o
|
||||
obj-y += acpi_dp.o
|
||||
obj-y += acpi_table.o
|
||||
|
|
323
lib/acpi/acpi_dp.c
Normal file
323
lib/acpi/acpi_dp.c
Normal file
|
@ -0,0 +1,323 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Generation of tables for particular device types
|
||||
*
|
||||
* Copyright 2019 Google LLC
|
||||
* Mostly taken from coreboot file acpi_device.c
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <log.h>
|
||||
#include <malloc.h>
|
||||
#include <uuid.h>
|
||||
#include <acpi/acpigen.h>
|
||||
#include <acpi/acpi_dp.h>
|
||||
#include <dm/acpi.h>
|
||||
|
||||
static void acpi_dp_write_array(struct acpi_ctx *ctx,
|
||||
const struct acpi_dp *array);
|
||||
|
||||
static void acpi_dp_write_value(struct acpi_ctx *ctx,
|
||||
const struct acpi_dp *prop)
|
||||
{
|
||||
switch (prop->type) {
|
||||
case ACPI_DP_TYPE_INTEGER:
|
||||
acpigen_write_integer(ctx, prop->integer);
|
||||
break;
|
||||
case ACPI_DP_TYPE_STRING:
|
||||
case ACPI_DP_TYPE_CHILD:
|
||||
acpigen_write_string(ctx, prop->string);
|
||||
break;
|
||||
case ACPI_DP_TYPE_REFERENCE:
|
||||
acpigen_emit_namestring(ctx, prop->string);
|
||||
break;
|
||||
case ACPI_DP_TYPE_ARRAY:
|
||||
acpi_dp_write_array(ctx, prop->array);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Package (2) { "prop->name", VALUE } */
|
||||
static void acpi_dp_write_property(struct acpi_ctx *ctx,
|
||||
const struct acpi_dp *prop)
|
||||
{
|
||||
acpigen_write_package(ctx, 2);
|
||||
acpigen_write_string(ctx, prop->name);
|
||||
acpi_dp_write_value(ctx, prop);
|
||||
acpigen_pop_len(ctx);
|
||||
}
|
||||
|
||||
/* Write array of Device Properties */
|
||||
static void acpi_dp_write_array(struct acpi_ctx *ctx,
|
||||
const struct acpi_dp *array)
|
||||
{
|
||||
const struct acpi_dp *dp;
|
||||
char *pkg_count;
|
||||
|
||||
/* Package element count determined as it is populated */
|
||||
pkg_count = acpigen_write_package(ctx, 0);
|
||||
|
||||
/*
|
||||
* Only acpi_dp of type DP_TYPE_TABLE is allowed to be an array.
|
||||
* DP_TYPE_TABLE does not have a value to be written. Thus, start
|
||||
* the loop from next type in the array.
|
||||
*/
|
||||
for (dp = array->next; dp; dp = dp->next) {
|
||||
acpi_dp_write_value(ctx, dp);
|
||||
(*pkg_count)++;
|
||||
}
|
||||
|
||||
acpigen_pop_len(ctx);
|
||||
}
|
||||
|
||||
static void acpi_dp_free(struct acpi_dp *dp)
|
||||
{
|
||||
assert(dp);
|
||||
while (dp) {
|
||||
struct acpi_dp *p = dp->next;
|
||||
|
||||
switch (dp->type) {
|
||||
case ACPI_DP_TYPE_CHILD:
|
||||
acpi_dp_free(dp->child);
|
||||
break;
|
||||
case ACPI_DP_TYPE_ARRAY:
|
||||
acpi_dp_free(dp->array);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
free(dp);
|
||||
dp = p;
|
||||
}
|
||||
}
|
||||
|
||||
static int acpi_dp_write_internal(struct acpi_ctx *ctx, struct acpi_dp *table)
|
||||
{
|
||||
struct acpi_dp *dp, *prop;
|
||||
char *dp_count, *prop_count = NULL;
|
||||
int child_count = 0;
|
||||
int ret;
|
||||
|
||||
assert(table);
|
||||
if (table->type != ACPI_DP_TYPE_TABLE)
|
||||
return 0;
|
||||
|
||||
/* Name (name) */
|
||||
acpigen_write_name(ctx, table->name);
|
||||
|
||||
/* Device Property list starts with the next entry */
|
||||
prop = table->next;
|
||||
|
||||
/* Package (DP), default to assuming no properties or children */
|
||||
dp_count = acpigen_write_package(ctx, 0);
|
||||
|
||||
/* Print base properties */
|
||||
for (dp = prop; dp; dp = dp->next) {
|
||||
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;
|
||||
/* ToUUID (ACPI_DP_UUID) */
|
||||
ret = acpigen_write_uuid(ctx, ACPI_DP_UUID);
|
||||
if (ret)
|
||||
return log_msg_ret("touuid", ret);
|
||||
/*
|
||||
* Package (PROP), element count determined as
|
||||
* it is populated
|
||||
*/
|
||||
prop_count = acpigen_write_package(ctx, 0);
|
||||
}
|
||||
(*prop_count)++;
|
||||
acpi_dp_write_property(ctx, dp);
|
||||
}
|
||||
}
|
||||
|
||||
if (prop_count) {
|
||||
/* Package (PROP) length, if a package was written */
|
||||
acpigen_pop_len(ctx);
|
||||
}
|
||||
|
||||
if (child_count) {
|
||||
/* Update DP package count to 2 or 4 */
|
||||
*dp_count += 2;
|
||||
/* ToUUID (ACPI_DP_CHILD_UUID) */
|
||||
ret = acpigen_write_uuid(ctx, ACPI_DP_CHILD_UUID);
|
||||
if (ret)
|
||||
return log_msg_ret("child uuid", ret);
|
||||
|
||||
/* Print child pointer properties */
|
||||
acpigen_write_package(ctx, child_count);
|
||||
|
||||
for (dp = prop; dp; dp = dp->next)
|
||||
if (dp->type == ACPI_DP_TYPE_CHILD)
|
||||
acpi_dp_write_property(ctx, dp);
|
||||
/* Package (CHILD) length */
|
||||
acpigen_pop_len(ctx);
|
||||
}
|
||||
|
||||
/* Package (DP) length */
|
||||
acpigen_pop_len(ctx);
|
||||
|
||||
/* Recursively parse children into separate tables */
|
||||
for (dp = prop; dp; dp = dp->next) {
|
||||
if (dp->type == ACPI_DP_TYPE_CHILD) {
|
||||
ret = acpi_dp_write_internal(ctx, dp->child);
|
||||
if (ret)
|
||||
return log_msg_ret("dp child", ret);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int acpi_dp_write(struct acpi_ctx *ctx, struct acpi_dp *table)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = acpi_dp_write_internal(ctx, table);
|
||||
|
||||
/* Clean up */
|
||||
acpi_dp_free(table);
|
||||
|
||||
if (ret)
|
||||
return log_msg_ret("write", ret);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct acpi_dp *acpi_dp_new(struct acpi_dp *dp, enum acpi_dp_type type,
|
||||
const char *name)
|
||||
{
|
||||
struct acpi_dp *new;
|
||||
|
||||
new = malloc(sizeof(struct acpi_dp));
|
||||
if (!new)
|
||||
return NULL;
|
||||
|
||||
memset(new, '\0', sizeof(*new));
|
||||
new->type = type;
|
||||
new->name = name;
|
||||
|
||||
if (dp) {
|
||||
/* Add to end of property list */
|
||||
while (dp->next)
|
||||
dp = dp->next;
|
||||
dp->next = new;
|
||||
}
|
||||
|
||||
return new;
|
||||
}
|
||||
|
||||
struct acpi_dp *acpi_dp_new_table(const char *name)
|
||||
{
|
||||
return acpi_dp_new(NULL, ACPI_DP_TYPE_TABLE, name);
|
||||
}
|
||||
|
||||
struct acpi_dp *acpi_dp_add_integer(struct acpi_dp *dp, const char *name,
|
||||
u64 value)
|
||||
{
|
||||
struct acpi_dp *new;
|
||||
|
||||
assert(dp);
|
||||
new = acpi_dp_new(dp, ACPI_DP_TYPE_INTEGER, name);
|
||||
|
||||
if (new)
|
||||
new->integer = value;
|
||||
|
||||
return new;
|
||||
}
|
||||
|
||||
struct acpi_dp *acpi_dp_add_string(struct acpi_dp *dp, const char *name,
|
||||
const char *string)
|
||||
{
|
||||
struct acpi_dp *new;
|
||||
|
||||
assert(dp);
|
||||
new = acpi_dp_new(dp, ACPI_DP_TYPE_STRING, name);
|
||||
if (new)
|
||||
new->string = string;
|
||||
|
||||
return new;
|
||||
}
|
||||
|
||||
struct acpi_dp *acpi_dp_add_reference(struct acpi_dp *dp, const char *name,
|
||||
const char *reference)
|
||||
{
|
||||
struct acpi_dp *new;
|
||||
|
||||
assert(dp);
|
||||
new = acpi_dp_new(dp, ACPI_DP_TYPE_REFERENCE, name);
|
||||
if (new)
|
||||
new->string = reference;
|
||||
|
||||
return new;
|
||||
}
|
||||
|
||||
struct acpi_dp *acpi_dp_add_child(struct acpi_dp *dp, const char *name,
|
||||
struct acpi_dp *child)
|
||||
{
|
||||
struct acpi_dp *new;
|
||||
|
||||
assert(dp);
|
||||
if (child->type != ACPI_DP_TYPE_TABLE)
|
||||
return NULL;
|
||||
|
||||
new = acpi_dp_new(dp, ACPI_DP_TYPE_CHILD, name);
|
||||
if (new) {
|
||||
new->child = child;
|
||||
new->string = child->name;
|
||||
}
|
||||
|
||||
return new;
|
||||
}
|
||||
|
||||
struct acpi_dp *acpi_dp_add_array(struct acpi_dp *dp, struct acpi_dp *array)
|
||||
{
|
||||
struct acpi_dp *new;
|
||||
|
||||
assert(dp);
|
||||
assert(array);
|
||||
if (array->type != ACPI_DP_TYPE_TABLE)
|
||||
return NULL;
|
||||
|
||||
new = acpi_dp_new(dp, ACPI_DP_TYPE_ARRAY, array->name);
|
||||
if (new)
|
||||
new->array = array;
|
||||
|
||||
return new;
|
||||
}
|
||||
|
||||
struct acpi_dp *acpi_dp_add_integer_array(struct acpi_dp *dp, const char *name,
|
||||
u64 *array, int len)
|
||||
{
|
||||
struct acpi_dp *dp_array;
|
||||
int i;
|
||||
|
||||
assert(dp);
|
||||
if (len <= 0)
|
||||
return NULL;
|
||||
|
||||
dp_array = acpi_dp_new_table(name);
|
||||
if (!dp_array)
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
if (!acpi_dp_add_integer(dp_array, NULL, array[i]))
|
||||
break;
|
||||
|
||||
if (!acpi_dp_add_array(dp, dp_array))
|
||||
return NULL;
|
||||
|
||||
return dp_array;
|
||||
}
|
|
@ -15,6 +15,7 @@ obj-$(CONFIG_UT_DM) += core.o
|
|||
ifneq ($(CONFIG_SANDBOX),)
|
||||
obj-$(CONFIG_ACPIGEN) += acpi.o
|
||||
obj-$(CONFIG_ACPIGEN) += acpigen.o
|
||||
obj-$(CONFIG_ACPIGEN) += acpi_dp.o
|
||||
obj-$(CONFIG_SOUND) += audio.o
|
||||
obj-$(CONFIG_BLK) += blk.o
|
||||
obj-$(CONFIG_BOARD) += board.o
|
||||
|
|
29
test/dm/acpi.h
Normal file
29
test/dm/acpi.h
Normal file
|
@ -0,0 +1,29 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Common functions for ACPI tests
|
||||
*
|
||||
* Copyright 2020 Google LLC
|
||||
* Written by Simon Glass <sjg@chromium.org>
|
||||
*/
|
||||
|
||||
#ifndef __TEST_DM_ACPI_H
|
||||
#define __TEST_DM_ACPI_H
|
||||
|
||||
/**
|
||||
* acpi_test_alloc_context_size() - Allocate an ACPI context of a given size
|
||||
*
|
||||
* @ctxp: Returns allocated context
|
||||
* @size: Size to allocate in bytes
|
||||
* @return 0 if OK, -ENOMEM if out of memory
|
||||
*/
|
||||
int acpi_test_alloc_context_size(struct acpi_ctx **ctxp, int size);
|
||||
|
||||
/**
|
||||
* acpi_test_get_length() - decode a three-byte length field
|
||||
*
|
||||
* @ptr: Length encoded as per ACPI
|
||||
* @return decoded length, or -EINVAL on error
|
||||
*/
|
||||
int acpi_test_get_length(u8 *ptr);
|
||||
|
||||
#endif /*__TEST_DM_ACPI_H */
|
385
test/dm/acpi_dp.c
Normal file
385
test/dm/acpi_dp.c
Normal file
|
@ -0,0 +1,385 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Tests for ACPI code generation via a device-property table
|
||||
*
|
||||
* Copyright 2019 Google LLC
|
||||
* Written by Simon Glass <sjg@chromium.org>
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <uuid.h>
|
||||
#include <acpi/acpigen.h>
|
||||
#include <acpi/acpi_dp.h>
|
||||
#include <asm/unaligned.h>
|
||||
#include <dm/acpi.h>
|
||||
#include <dm/test.h>
|
||||
#include <test/ut.h>
|
||||
#include "acpi.h"
|
||||
|
||||
/* Maximum size of the ACPI context needed for most tests */
|
||||
#define ACPI_CONTEXT_SIZE 500
|
||||
|
||||
#define TEST_INT8 0x7d
|
||||
#define TEST_INT16 0x2345
|
||||
#define TEST_INT32 0x12345678
|
||||
#define TEST_INT64 0x4567890123456
|
||||
#define TEST_STR "testing acpi strings"
|
||||
#define TEST_REF "\\SB.I2C0.TPM2"
|
||||
#define EXPECT_REF "SB__I2C0TPM2"
|
||||
|
||||
static int alloc_context(struct acpi_ctx **ctxp)
|
||||
{
|
||||
return acpi_test_alloc_context_size(ctxp, ACPI_CONTEXT_SIZE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void free_context(struct acpi_ctx **ctxp)
|
||||
{
|
||||
free(*ctxp);
|
||||
*ctxp = NULL;
|
||||
}
|
||||
|
||||
/* Test emitting an empty table */
|
||||
static int dm_test_acpi_dp_new_table(struct unit_test_state *uts)
|
||||
{
|
||||
struct acpi_ctx *ctx;
|
||||
struct acpi_dp *dp;
|
||||
u8 *ptr;
|
||||
|
||||
ut_assertok(alloc_context(&ctx));
|
||||
|
||||
dp = acpi_dp_new_table("FRED");
|
||||
ut_assertnonnull(dp);
|
||||
|
||||
ptr = acpigen_get_current(ctx);
|
||||
ut_assertok(acpi_dp_write(ctx, dp));
|
||||
ut_asserteq(10, acpigen_get_current(ctx) - ptr);
|
||||
ut_asserteq(NAME_OP, *(u8 *)ptr);
|
||||
ut_asserteq_strn("FRED", (char *)ptr + 1);
|
||||
ut_asserteq(PACKAGE_OP, ptr[5]);
|
||||
ut_asserteq(4, acpi_test_get_length(ptr + 6));
|
||||
ut_asserteq(0, ptr[9]);
|
||||
|
||||
free_context(&ctx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
DM_TEST(dm_test_acpi_dp_new_table, 0);
|
||||
|
||||
/* Test emitting an integer */
|
||||
static int dm_test_acpi_dp_int(struct unit_test_state *uts)
|
||||
{
|
||||
struct acpi_ctx *ctx;
|
||||
char uuid[UUID_STR_LEN + 1];
|
||||
struct acpi_dp *dp;
|
||||
u8 *ptr;
|
||||
|
||||
ut_assertok(alloc_context(&ctx));
|
||||
|
||||
dp = acpi_dp_new_table("FRED");
|
||||
ut_assertnonnull(dp);
|
||||
ut_assertnonnull(acpi_dp_add_integer(dp, "MARY", TEST_INT32));
|
||||
|
||||
ptr = acpigen_get_current(ctx);
|
||||
ut_assertok(acpi_dp_write(ctx, dp));
|
||||
ut_asserteq(54, acpigen_get_current(ctx) - ptr);
|
||||
ut_asserteq(NAME_OP, *(u8 *)ptr);
|
||||
ut_asserteq_strn("FRED", (char *)ptr + 1);
|
||||
ut_asserteq(PACKAGE_OP, ptr[5]);
|
||||
ut_asserteq(48, acpi_test_get_length(ptr + 6));
|
||||
ut_asserteq(2, ptr[9]);
|
||||
|
||||
/* UUID */
|
||||
ut_asserteq(BUFFER_OP, ptr[10]);
|
||||
ut_asserteq(22, acpi_test_get_length(ptr + 11));
|
||||
ut_asserteq(WORD_PREFIX, ptr[14]);
|
||||
ut_asserteq(16, get_unaligned((u16 *)(ptr + 15)));
|
||||
uuid_bin_to_str(ptr + 17, uuid, 1);
|
||||
ut_asserteq_str(ACPI_DP_UUID, uuid);
|
||||
|
||||
/* Container package */
|
||||
ut_asserteq(PACKAGE_OP, ptr[33]);
|
||||
ut_asserteq(20, acpi_test_get_length(ptr + 34));
|
||||
ut_asserteq(1, ptr[37]);
|
||||
|
||||
/* Package with name and (integer) value */
|
||||
ut_asserteq(PACKAGE_OP, ptr[38]);
|
||||
ut_asserteq(15, acpi_test_get_length(ptr + 39));
|
||||
ut_asserteq(2, ptr[42]);
|
||||
ut_asserteq(STRING_PREFIX, ptr[43]);
|
||||
ut_asserteq_str("MARY", (char *)ptr + 44);
|
||||
|
||||
ut_asserteq(DWORD_PREFIX, ptr[49]);
|
||||
ut_asserteq(TEST_INT32, get_unaligned((u32 *)(ptr + 50)));
|
||||
|
||||
free_context(&ctx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
DM_TEST(dm_test_acpi_dp_int, 0);
|
||||
|
||||
/* Test emitting a 64-bit integer */
|
||||
static int dm_test_acpi_dp_int64(struct unit_test_state *uts)
|
||||
{
|
||||
struct acpi_ctx *ctx;
|
||||
struct acpi_dp *dp;
|
||||
u8 *ptr;
|
||||
|
||||
ut_assertok(alloc_context(&ctx));
|
||||
|
||||
dp = acpi_dp_new_table("FRED");
|
||||
ut_assertnonnull(dp);
|
||||
ut_assertnonnull(acpi_dp_add_integer(dp, "MARY", TEST_INT64));
|
||||
|
||||
ptr = acpigen_get_current(ctx);
|
||||
ut_assertok(acpi_dp_write(ctx, dp));
|
||||
ut_asserteq(58, acpigen_get_current(ctx) - ptr);
|
||||
|
||||
ut_asserteq(QWORD_PREFIX, ptr[49]);
|
||||
ut_asserteq_64(TEST_INT64, get_unaligned((u64 *)(ptr + 50)));
|
||||
|
||||
free_context(&ctx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
DM_TEST(dm_test_acpi_dp_int64, 0);
|
||||
|
||||
/* Test emitting a 16-bit integer */
|
||||
static int dm_test_acpi_dp_int16(struct unit_test_state *uts)
|
||||
{
|
||||
struct acpi_ctx *ctx;
|
||||
struct acpi_dp *dp;
|
||||
u8 *ptr;
|
||||
|
||||
ut_assertok(alloc_context(&ctx));
|
||||
|
||||
dp = acpi_dp_new_table("FRED");
|
||||
ut_assertnonnull(dp);
|
||||
ut_assertnonnull(acpi_dp_add_integer(dp, "MARY", TEST_INT16));
|
||||
|
||||
ptr = acpigen_get_current(ctx);
|
||||
ut_assertok(acpi_dp_write(ctx, dp));
|
||||
ut_asserteq(52, acpigen_get_current(ctx) - ptr);
|
||||
|
||||
ut_asserteq(WORD_PREFIX, ptr[49]);
|
||||
ut_asserteq(TEST_INT16, get_unaligned((u16 *)(ptr + 50)));
|
||||
|
||||
free_context(&ctx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
DM_TEST(dm_test_acpi_dp_int16, 0);
|
||||
|
||||
/* Test emitting a 8-bit integer */
|
||||
static int dm_test_acpi_dp_int8(struct unit_test_state *uts)
|
||||
{
|
||||
struct acpi_ctx *ctx;
|
||||
struct acpi_dp *dp;
|
||||
u8 *ptr;
|
||||
|
||||
ut_assertok(alloc_context(&ctx));
|
||||
|
||||
dp = acpi_dp_new_table("FRED");
|
||||
ut_assertnonnull(dp);
|
||||
ut_assertnonnull(acpi_dp_add_integer(dp, "MARY", TEST_INT8));
|
||||
|
||||
ptr = acpigen_get_current(ctx);
|
||||
ut_assertok(acpi_dp_write(ctx, dp));
|
||||
ut_asserteq(51, acpigen_get_current(ctx) - ptr);
|
||||
|
||||
ut_asserteq(BYTE_PREFIX, ptr[49]);
|
||||
ut_asserteq(TEST_INT8, ptr[50]);
|
||||
|
||||
free_context(&ctx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
DM_TEST(dm_test_acpi_dp_int8, 0);
|
||||
|
||||
/* Test emitting multiple values */
|
||||
static int dm_test_acpi_dp_multiple(struct unit_test_state *uts)
|
||||
{
|
||||
struct acpi_ctx *ctx;
|
||||
struct acpi_dp *dp;
|
||||
u8 *ptr;
|
||||
|
||||
ut_assertok(alloc_context(&ctx));
|
||||
|
||||
dp = acpi_dp_new_table("FRED");
|
||||
ut_assertnonnull(dp);
|
||||
ut_assertnonnull(acpi_dp_add_integer(dp, "int16", TEST_INT16));
|
||||
ut_assertnonnull(acpi_dp_add_string(dp, "str", TEST_STR));
|
||||
ut_assertnonnull(acpi_dp_add_reference(dp, "ref", TEST_REF));
|
||||
|
||||
ptr = acpigen_get_current(ctx);
|
||||
ut_assertok(acpi_dp_write(ctx, dp));
|
||||
ut_asserteq(110, acpigen_get_current(ctx) - ptr);
|
||||
|
||||
ut_asserteq(WORD_PREFIX, ptr[0x32]);
|
||||
ut_asserteq(TEST_INT16, get_unaligned((u16 *)(ptr + 0x33)));
|
||||
ut_asserteq(STRING_PREFIX, ptr[0x3f]);
|
||||
ut_asserteq_str(TEST_STR, (char *)ptr + 0x40);
|
||||
ut_asserteq(ROOT_PREFIX, ptr[0x5f]);
|
||||
ut_asserteq(MULTI_NAME_PREFIX, ptr[0x60]);
|
||||
ut_asserteq(3, ptr[0x61]);
|
||||
ut_asserteq_strn(EXPECT_REF, (char *)ptr + 0x62);
|
||||
|
||||
free_context(&ctx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
DM_TEST(dm_test_acpi_dp_multiple, 0);
|
||||
|
||||
/* Test emitting an array */
|
||||
static int dm_test_acpi_dp_array(struct unit_test_state *uts)
|
||||
{
|
||||
struct acpi_ctx *ctx;
|
||||
struct acpi_dp *dp;
|
||||
u64 speed[4];
|
||||
u8 *ptr;
|
||||
|
||||
ut_assertok(alloc_context(&ctx));
|
||||
|
||||
dp = acpi_dp_new_table("FRED");
|
||||
ut_assertnonnull(dp);
|
||||
speed[0] = TEST_INT8;
|
||||
speed[1] = TEST_INT16;
|
||||
speed[2] = TEST_INT32;
|
||||
speed[3] = TEST_INT64;
|
||||
ut_assertnonnull(acpi_dp_add_integer_array(dp, "speeds", speed,
|
||||
ARRAY_SIZE(speed)));
|
||||
|
||||
ptr = acpigen_get_current(ctx);
|
||||
ut_assertok(acpi_dp_write(ctx, dp));
|
||||
ut_asserteq(75, acpigen_get_current(ctx) - ptr);
|
||||
|
||||
ut_asserteq(BYTE_PREFIX, ptr[0x38]);
|
||||
ut_asserteq(TEST_INT8, ptr[0x39]);
|
||||
|
||||
ut_asserteq(WORD_PREFIX, ptr[0x3a]);
|
||||
ut_asserteq(TEST_INT16, get_unaligned((u16 *)(ptr + 0x3b)));
|
||||
|
||||
ut_asserteq(DWORD_PREFIX, ptr[0x3d]);
|
||||
ut_asserteq(TEST_INT32, get_unaligned((u32 *)(ptr + 0x3e)));
|
||||
|
||||
ut_asserteq(QWORD_PREFIX, ptr[0x42]);
|
||||
ut_asserteq_64(TEST_INT64, get_unaligned((u64 *)(ptr + 0x43)));
|
||||
|
||||
free_context(&ctx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
DM_TEST(dm_test_acpi_dp_array, 0);
|
||||
|
||||
/* Test emitting a child */
|
||||
static int dm_test_acpi_dp_child(struct unit_test_state *uts)
|
||||
{
|
||||
struct acpi_ctx *ctx;
|
||||
struct acpi_dp *dp, *child1, *child2;
|
||||
char uuid[UUID_STR_LEN + 1];
|
||||
u8 *ptr, *pptr;
|
||||
int i;
|
||||
|
||||
ut_assertok(alloc_context(&ctx));
|
||||
|
||||
child1 = acpi_dp_new_table("child");
|
||||
ut_assertnonnull(child1);
|
||||
ut_assertnonnull(acpi_dp_add_integer(child1, "height", TEST_INT16));
|
||||
|
||||
child2 = acpi_dp_new_table("child");
|
||||
ut_assertnonnull(child2);
|
||||
ut_assertnonnull(acpi_dp_add_integer(child2, "age", TEST_INT8));
|
||||
|
||||
dp = acpi_dp_new_table("FRED");
|
||||
ut_assertnonnull(dp);
|
||||
|
||||
ut_assertnonnull(acpi_dp_add_child(dp, "anna", child1));
|
||||
ut_assertnonnull(acpi_dp_add_child(dp, "john", child2));
|
||||
|
||||
ptr = acpigen_get_current(ctx);
|
||||
ut_assertok(acpi_dp_write(ctx, dp));
|
||||
ut_asserteq(178, acpigen_get_current(ctx) - ptr);
|
||||
|
||||
/* UUID for child extension using Hierarchical Data Extension UUID */
|
||||
ut_asserteq(BUFFER_OP, ptr[10]);
|
||||
ut_asserteq(22, acpi_test_get_length(ptr + 11));
|
||||
ut_asserteq(WORD_PREFIX, ptr[14]);
|
||||
ut_asserteq(16, get_unaligned((u16 *)(ptr + 15)));
|
||||
uuid_bin_to_str(ptr + 17, uuid, 1);
|
||||
ut_asserteq_str(ACPI_DP_CHILD_UUID, uuid);
|
||||
|
||||
/* Package with two children */
|
||||
ut_asserteq(PACKAGE_OP, ptr[0x21]);
|
||||
ut_asserteq(0x28, acpi_test_get_length(ptr + 0x22));
|
||||
ut_asserteq(2, ptr[0x25]);
|
||||
|
||||
/* First we expect the two children as string/value */
|
||||
pptr = ptr + 0x26;
|
||||
for (i = 0; i < 2; i++) {
|
||||
ut_asserteq(PACKAGE_OP, pptr[0]);
|
||||
ut_asserteq(0x11, acpi_test_get_length(pptr + 1));
|
||||
ut_asserteq(2, pptr[4]);
|
||||
ut_asserteq(STRING_PREFIX, pptr[5]);
|
||||
ut_asserteq_str(i ? "john" : "anna", (char *)pptr + 6);
|
||||
ut_asserteq(STRING_PREFIX, pptr[11]);
|
||||
ut_asserteq_str("child", (char *)pptr + 12);
|
||||
pptr += 0x12;
|
||||
}
|
||||
|
||||
/* Write the two children */
|
||||
ut_asserteq(0x4a, pptr - ptr);
|
||||
for (i = 0; i < 2; i++) {
|
||||
const char *prop = i ? "age" : "height";
|
||||
const int datalen = i ? 1 : 2;
|
||||
int len = strlen(prop) + 1;
|
||||
|
||||
ut_asserteq(NAME_OP, pptr[0]);
|
||||
ut_asserteq_strn("chil", (char *)pptr + 1);
|
||||
ut_asserteq(PACKAGE_OP, pptr[5]);
|
||||
ut_asserteq(0x27 + len + datalen, acpi_test_get_length(pptr + 6));
|
||||
ut_asserteq(2, pptr[9]);
|
||||
|
||||
/* UUID */
|
||||
ut_asserteq(BUFFER_OP, pptr[10]);
|
||||
ut_asserteq(22, acpi_test_get_length(pptr + 11));
|
||||
ut_asserteq(WORD_PREFIX, pptr[14]);
|
||||
ut_asserteq(16, get_unaligned((u16 *)(pptr + 15)));
|
||||
uuid_bin_to_str(pptr + 17, uuid, 1);
|
||||
ut_asserteq_str(ACPI_DP_UUID, uuid);
|
||||
pptr += 33;
|
||||
|
||||
/* Containing package */
|
||||
ut_asserteq(i ? 0xa1 : 0x6b, pptr - ptr);
|
||||
ut_asserteq(PACKAGE_OP, pptr[0]);
|
||||
ut_asserteq(0xb + len + datalen, acpi_test_get_length(pptr + 1));
|
||||
ut_asserteq(1, pptr[4]);
|
||||
|
||||
/* Package containing the property-name string and the value */
|
||||
pptr += 5;
|
||||
ut_asserteq(i ? 0xa6 : 0x70, pptr - ptr);
|
||||
ut_asserteq(PACKAGE_OP, pptr[0]);
|
||||
ut_asserteq(6 + len + datalen, acpi_test_get_length(pptr + 1));
|
||||
ut_asserteq(2, pptr[4]);
|
||||
|
||||
ut_asserteq(STRING_PREFIX, pptr[5]);
|
||||
ut_asserteq_str(i ? "age" : "height", (char *)pptr + 6);
|
||||
pptr += 6 + len;
|
||||
if (i) {
|
||||
ut_asserteq(BYTE_PREFIX, pptr[0]);
|
||||
ut_asserteq(TEST_INT8, pptr[1]);
|
||||
} else {
|
||||
ut_asserteq(WORD_PREFIX, pptr[0]);
|
||||
ut_asserteq(TEST_INT16,
|
||||
get_unaligned((u16 *)(pptr + 1)));
|
||||
}
|
||||
pptr += 1 + datalen;
|
||||
}
|
||||
ut_asserteq(178, pptr - ptr);
|
||||
|
||||
free_context(&ctx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
DM_TEST(dm_test_acpi_dp_child, 0);
|
|
@ -18,6 +18,7 @@
|
|||
#include <dm/test.h>
|
||||
#include <dm/uclass-internal.h>
|
||||
#include <test/ut.h>
|
||||
#include "acpi.h"
|
||||
|
||||
/* Maximum size of the ACPI context needed for most tests */
|
||||
#define ACPI_CONTEXT_SIZE 150
|
||||
|
@ -31,7 +32,7 @@
|
|||
#define TEST_INT32 0x12345678
|
||||
#define TEST_INT64 0x4567890123456
|
||||
|
||||
static int alloc_context_size(struct acpi_ctx **ctxp, int size)
|
||||
int acpi_test_alloc_context_size(struct acpi_ctx **ctxp, int size)
|
||||
{
|
||||
struct acpi_ctx *ctx;
|
||||
|
||||
|
@ -51,9 +52,17 @@ static int alloc_context_size(struct acpi_ctx **ctxp, int size)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int acpi_test_get_length(u8 *ptr)
|
||||
{
|
||||
if (!(*ptr & 0x80))
|
||||
return -EINVAL;
|
||||
|
||||
return (*ptr & 0xf) | ptr[1] << 4 | ptr[2] << 12;
|
||||
}
|
||||
|
||||
static int alloc_context(struct acpi_ctx **ctxp)
|
||||
{
|
||||
return alloc_context_size(ctxp, ACPI_CONTEXT_SIZE);
|
||||
return acpi_test_alloc_context_size(ctxp, ACPI_CONTEXT_SIZE);
|
||||
}
|
||||
|
||||
static void free_context(struct acpi_ctx **ctxp)
|
||||
|
@ -357,20 +366,6 @@ static int dm_test_acpi_spi(struct unit_test_state *uts)
|
|||
}
|
||||
DM_TEST(dm_test_acpi_spi, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
|
||||
|
||||
/**
|
||||
* get_length() - decode a three-byte length field
|
||||
*
|
||||
* @ptr: Length encoded as per ACPI
|
||||
* @return decoded length, or -EINVAL on error
|
||||
*/
|
||||
static int get_length(u8 *ptr)
|
||||
{
|
||||
if (!(*ptr & 0x80))
|
||||
return -EINVAL;
|
||||
|
||||
return (*ptr & 0xf) | ptr[1] << 4 | ptr[2] << 12;
|
||||
}
|
||||
|
||||
/* Test emitting a length */
|
||||
static int dm_test_acpi_len(struct unit_test_state *uts)
|
||||
{
|
||||
|
@ -379,7 +374,7 @@ static int dm_test_acpi_len(struct unit_test_state *uts)
|
|||
u8 *ptr;
|
||||
int i;
|
||||
|
||||
ut_assertok(alloc_context_size(&ctx, size));
|
||||
ut_assertok(acpi_test_alloc_context_size(&ctx, size));
|
||||
|
||||
ptr = acpigen_get_current(ctx);
|
||||
|
||||
|
@ -387,7 +382,7 @@ static int dm_test_acpi_len(struct unit_test_state *uts)
|
|||
acpigen_write_len_f(ctx);
|
||||
acpigen_emit_byte(ctx, 0x23);
|
||||
acpigen_pop_len(ctx);
|
||||
ut_asserteq(1 + 3, get_length(ptr));
|
||||
ut_asserteq(1 + 3, acpi_test_get_length(ptr));
|
||||
|
||||
/* Write 200 bytes so we need two length bytes */
|
||||
ptr = ctx->current;
|
||||
|
@ -395,7 +390,7 @@ static int dm_test_acpi_len(struct unit_test_state *uts)
|
|||
for (i = 0; i < 200; i++)
|
||||
acpigen_emit_byte(ctx, 0x23);
|
||||
acpigen_pop_len(ctx);
|
||||
ut_asserteq(200 + 3, get_length(ptr));
|
||||
ut_asserteq(200 + 3, acpi_test_get_length(ptr));
|
||||
|
||||
/* Write 40KB so we need three length bytes */
|
||||
ptr = ctx->current;
|
||||
|
@ -403,7 +398,7 @@ static int dm_test_acpi_len(struct unit_test_state *uts)
|
|||
for (i = 0; i < 40000; i++)
|
||||
acpigen_emit_byte(ctx, 0x23);
|
||||
acpigen_pop_len(ctx);
|
||||
ut_asserteq(40000 + 3, get_length(ptr));
|
||||
ut_asserteq(40000 + 3, acpi_test_get_length(ptr));
|
||||
|
||||
free_context(&ctx);
|
||||
|
||||
|
@ -429,7 +424,7 @@ static int dm_test_acpi_package(struct unit_test_state *uts)
|
|||
acpigen_emit_byte(ctx, 0x23);
|
||||
acpigen_pop_len(ctx);
|
||||
ut_asserteq(PACKAGE_OP, ptr[0]);
|
||||
ut_asserteq(5, get_length(ptr + 1));
|
||||
ut_asserteq(5, acpi_test_get_length(ptr + 1));
|
||||
ut_asserteq(3, ptr[4]);
|
||||
|
||||
free_context(&ctx);
|
||||
|
@ -613,7 +608,7 @@ static int dm_test_acpi_uuid(struct unit_test_state *uts)
|
|||
"dbb8e3e6-5886-4ba6-8795-1319f52a966b"));
|
||||
ut_asserteq(23, acpigen_get_current(ctx) - ptr);
|
||||
ut_asserteq(BUFFER_OP, ptr[0]);
|
||||
ut_asserteq(22, get_length(ptr + 1));
|
||||
ut_asserteq(22, acpi_test_get_length(ptr + 1));
|
||||
ut_asserteq(0xdbb8e3e6, get_unaligned((u32 *)(ptr + 7)));
|
||||
ut_asserteq(0x5886, get_unaligned((u16 *)(ptr + 11)));
|
||||
ut_asserteq(0x4ba6, get_unaligned((u16 *)(ptr + 13)));
|
||||
|
|
Loading…
Add table
Reference in a new issue