From 13a3e094ddab0722e84a4b9d2c5f08c0a567c53a Mon Sep 17 00:00:00 2001 From: Daniil Tatianin <99danilt@gmail.com> Date: Sat, 26 Oct 2024 18:27:58 +0300 Subject: [PATCH] Make uacpi_object a fully opaque type This commit reworks the way a client is supposed to interact with uacpi_object: instead of directly accessing internal object fields (some of which are not directly related to the object, but rather just an implementation detail of uACPI), the user is now expected to use the public API exposed via the types.h header, which not only abstracts away uACPI-specific details, but also does additional validation and type checking, which should make shooting yourself in the foot harder. Signed-off-by: Daniil Tatianin <99danilt@gmail.com> --- include/uacpi/internal/interpreter.h | 2 +- include/uacpi/internal/io.h | 2 +- include/uacpi/internal/mutex.h | 2 +- include/uacpi/internal/namespace.h | 1 + include/uacpi/internal/notify.h | 1 + include/uacpi/internal/opregion.h | 2 +- include/uacpi/internal/resources.h | 2 +- include/uacpi/internal/shareable.h | 4 + include/uacpi/internal/types.h | 265 +++++++++++++++- include/uacpi/types.h | 458 ++++++++++++--------------- include/uacpi/uacpi.h | 6 +- source/interpreter.c | 7 +- source/opregion.c | 2 +- source/resources.c | 2 +- source/sleep.c | 2 +- source/types.c | 387 +++++++++++++++++++++- source/uacpi.c | 6 +- source/utilities.c | 2 +- tests/runner/test_runner.cpp | 25 +- 19 files changed, 877 insertions(+), 301 deletions(-) diff --git a/include/uacpi/internal/interpreter.h b/include/uacpi/internal/interpreter.h index 88c18692..3f180d68 100644 --- a/include/uacpi/internal/interpreter.h +++ b/include/uacpi/internal/interpreter.h @@ -16,5 +16,5 @@ uacpi_status uacpi_osi(uacpi_handle handle, uacpi_object *retval); uacpi_status uacpi_execute_control_method( uacpi_namespace_node *scope, uacpi_control_method *method, - const uacpi_args *args, uacpi_object **ret + const uacpi_object_array *args, uacpi_object **ret ); diff --git a/include/uacpi/internal/io.h b/include/uacpi/internal/io.h index 8642edf3..4c875d88 100644 --- a/include/uacpi/internal/io.h +++ b/include/uacpi/internal/io.h @@ -1,6 +1,6 @@ #pragma once -#include +#include #include #include diff --git a/include/uacpi/internal/mutex.h b/include/uacpi/internal/mutex.h index ec253564..8764eb09 100644 --- a/include/uacpi/internal/mutex.h +++ b/include/uacpi/internal/mutex.h @@ -1,6 +1,6 @@ #pragma once -#include +#include uacpi_bool uacpi_this_thread_owns_aml_mutex(uacpi_mutex*); diff --git a/include/uacpi/internal/namespace.h b/include/uacpi/internal/namespace.h index 86c518ec..71ed9e20 100644 --- a/include/uacpi/internal/namespace.h +++ b/include/uacpi/internal/namespace.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include diff --git a/include/uacpi/internal/notify.h b/include/uacpi/internal/notify.h index 95949df1..a7ed53a3 100644 --- a/include/uacpi/internal/notify.h +++ b/include/uacpi/internal/notify.h @@ -1,5 +1,6 @@ #pragma once +#include #include uacpi_status uacpi_notify_all(uacpi_namespace_node *node, uacpi_u64 value); diff --git a/include/uacpi/internal/opregion.h b/include/uacpi/internal/opregion.h index 3eb8f1b4..31f67315 100644 --- a/include/uacpi/internal/opregion.h +++ b/include/uacpi/internal/opregion.h @@ -1,6 +1,6 @@ #pragma once -#include +#include #include void uacpi_trace_region_error( diff --git a/include/uacpi/internal/resources.h b/include/uacpi/internal/resources.h index ece17d63..e11f6956 100644 --- a/include/uacpi/internal/resources.h +++ b/include/uacpi/internal/resources.h @@ -1,6 +1,6 @@ #pragma once -#include +#include #include enum uacpi_aml_resource { diff --git a/include/uacpi/internal/shareable.h b/include/uacpi/internal/shareable.h index 78e61516..e00d850d 100644 --- a/include/uacpi/internal/shareable.h +++ b/include/uacpi/internal/shareable.h @@ -2,6 +2,10 @@ #include +struct uacpi_shareable { + uacpi_u32 reference_count; +}; + void uacpi_shareable_init(uacpi_handle); uacpi_bool uacpi_bugged_shareable(uacpi_handle); diff --git a/include/uacpi/internal/types.h b/include/uacpi/internal/types.h index 48312ae2..417d3677 100644 --- a/include/uacpi/internal/types.h +++ b/include/uacpi/internal/types.h @@ -2,6 +2,7 @@ #include #include +#include // object->flags field if object->type == UACPI_OBJECT_REFERENCE enum uacpi_reference_kind { @@ -18,10 +19,260 @@ enum uacpi_string_kind { UACPI_STRING_KIND_PATH, }; +typedef struct uacpi_buffer { + struct uacpi_shareable shareable; + union { + void *data; + uacpi_u8 *byte_data; + uacpi_char *text; + }; + uacpi_size size; +} uacpi_buffer; + +typedef struct uacpi_package { + struct uacpi_shareable shareable; + uacpi_object **objects; + uacpi_size count; +} uacpi_package; + +typedef struct uacpi_buffer_field { + uacpi_buffer *backing; + uacpi_size bit_index; + uacpi_u32 bit_length; + uacpi_bool force_buffer; +} uacpi_buffer_field; + +typedef struct uacpi_buffer_index { + uacpi_size idx; + uacpi_buffer *buffer; +} uacpi_buffer_index; + +typedef struct uacpi_mutex { + struct uacpi_shareable shareable; + uacpi_handle handle; + uacpi_thread_id owner; + uacpi_u16 depth; + uacpi_u8 sync_level; +} uacpi_mutex; + +typedef struct uacpi_event { + struct uacpi_shareable shareable; + uacpi_handle handle; +} uacpi_event; + +typedef struct uacpi_address_space_handler { + struct uacpi_shareable shareable; + uacpi_region_handler callback; + uacpi_handle user_context; + struct uacpi_address_space_handler *next; + struct uacpi_operation_region *regions; + uacpi_u16 space; +} uacpi_address_space_handler; + +/* + * NOTE: These are common object headers. + * Any changes to these structs must be propagated to all objects. + * ============================================================== + * Common for the following objects: + * - UACPI_OBJECT_OPERATION_REGION + * - UACPI_OBJECT_PROCESSOR + * - UACPI_OBJECT_DEVICE + * - UACPI_OBJECT_THERMAL_ZONE + */ +typedef struct uacpi_address_space_handlers { + struct uacpi_shareable shareable; + uacpi_address_space_handler *head; +} uacpi_address_space_handlers; + +typedef struct uacpi_device_notify_handler { + uacpi_notify_handler callback; + uacpi_handle user_context; + struct uacpi_device_notify_handler *next; +} uacpi_device_notify_handler; + /* - * TODO: Write a note here explaining how references are currently implemented - * and how some of the edge cases are handled. + * Common for the following objects: + * - UACPI_OBJECT_PROCESSOR + * - UACPI_OBJECT_DEVICE + * - UACPI_OBJECT_THERMAL_ZONE */ +typedef struct uacpi_handlers { + struct uacpi_shareable shareable; + uacpi_address_space_handler *address_space_head; + uacpi_device_notify_handler *notify_head; +} uacpi_handlers; + +// This region has a corresponding _REG method that was succesfully executed +#define UACPI_OP_REGION_STATE_REG_EXECUTED (1 << 0) + +// This region was successfully attached to a handler +#define UACPI_OP_REGION_STATE_ATTACHED (1 << 1) + +typedef struct uacpi_operation_region { + struct uacpi_shareable shareable; + uacpi_address_space_handler *handler; + uacpi_handle user_context; + uacpi_u16 space; + uacpi_u8 state_flags; + uacpi_u64 offset; + uacpi_u64 length; + + // If space == TABLE_DATA + uacpi_u64 table_idx; + + // Used to link regions sharing the same handler + struct uacpi_operation_region *next; +} uacpi_operation_region; + +typedef struct uacpi_device { + struct uacpi_shareable shareable; + uacpi_address_space_handler *address_space_handlers; + uacpi_device_notify_handler *notify_handlers; +} uacpi_device; + +typedef struct uacpi_processor { + struct uacpi_shareable shareable; + uacpi_address_space_handler *address_space_handlers; + uacpi_device_notify_handler *notify_handlers; + uacpi_u8 id; + uacpi_u32 block_address; + uacpi_u8 block_length; +} uacpi_processor; + +typedef struct uacpi_thermal_zone { + struct uacpi_shareable shareable; + uacpi_address_space_handler *address_space_handlers; + uacpi_device_notify_handler *notify_handlers; +} uacpi_thermal_zone; + +typedef struct uacpi_power_resource { + uacpi_u8 system_level; + uacpi_u16 resource_order; +} uacpi_power_resource; + +typedef uacpi_status (*uacpi_native_call_handler)( + uacpi_handle ctx, uacpi_object *retval +); + +typedef struct uacpi_control_method { + struct uacpi_shareable shareable; + union { + uacpi_u8 *code; + uacpi_native_call_handler handler; + }; + uacpi_mutex *mutex; + uacpi_u32 size; + uacpi_u8 sync_level : 4; + uacpi_u8 args : 3; + uacpi_u8 is_serialized : 1; + uacpi_u8 named_objects_persist: 1; + uacpi_u8 native_call : 1; + uacpi_u8 owns_code : 1; +} uacpi_control_method; + +typedef enum uacpi_access_type { + UACPI_ACCESS_TYPE_ANY = 0, + UACPI_ACCESS_TYPE_BYTE = 1, + UACPI_ACCESS_TYPE_WORD = 2, + UACPI_ACCESS_TYPE_DWORD = 3, + UACPI_ACCESS_TYPE_QWORD = 4, + UACPI_ACCESS_TYPE_BUFFER = 5, +} uacpi_access_type; + +typedef enum uacpi_access_attributes { + UACPI_ACCESS_ATTRIBUTE_QUICK = 0x02, + UACPI_ACCESS_ATTRIBUTE_SEND_RECEIVE = 0x04, + UACPI_ACCESS_ATTRIBUTE_BYTE = 0x06, + UACPI_ACCESS_ATTRIBUTE_WORD = 0x08, + UACPI_ACCESS_ATTRIBUTE_BLOCK = 0x0A, + UACPI_ACCESS_ATTRIBUTE_BYTES = 0x0B, + UACPI_ACCESS_ATTRIBUTE_PROCESS_CALL = 0x0C, + UACPI_ACCESS_ATTRIBUTE_BLOCK_PROCESS_CALL = 0x0D, + UACPI_ACCESS_ATTRIBUTE_RAW_BYTES = 0x0E, + UACPI_ACCESS_ATTRIBUTE_RAW_PROCESS_BYTES = 0x0F, +} uacpi_access_attributes; + +typedef enum uacpi_lock_rule { + UACPI_LOCK_RULE_NO_LOCK = 0, + UACPI_LOCK_RULE_LOCK = 1, +} uacpi_lock_rule; + +typedef enum uacpi_update_rule { + UACPI_UPDATE_RULE_PRESERVE = 0, + UACPI_UPDATE_RULE_WRITE_AS_ONES = 1, + UACPI_UPDATE_RULE_WRITE_AS_ZEROES = 2, +} uacpi_update_rule; + +typedef enum uacpi_field_unit_kind { + UACPI_FIELD_UNIT_KIND_NORMAL = 0, + UACPI_FIELD_UNIT_KIND_INDEX = 1, + UACPI_FIELD_UNIT_KIND_BANK = 2, +} uacpi_field_unit_kind; + +typedef struct uacpi_field_unit { + struct uacpi_shareable shareable; + + union { + // UACPI_FIELD_UNIT_KIND_NORMAL + struct { + uacpi_namespace_node *region; + }; + + // UACPI_FIELD_UNIT_KIND_INDEX + struct { + struct uacpi_field_unit *index; + struct uacpi_field_unit *data; + }; + + // UACPI_FIELD_UNIT_KIND_BANK + struct { + uacpi_namespace_node *bank_region; + struct uacpi_field_unit *bank_selection; + uacpi_u64 bank_value; + }; + }; + + uacpi_object *connection; + + uacpi_u32 byte_offset; + uacpi_u32 bit_length; + uacpi_u8 bit_offset_within_first_byte; + uacpi_u8 access_width_bytes; + uacpi_u8 access_length; + + uacpi_u8 attributes : 4; + uacpi_u8 update_rule : 2; + uacpi_u8 kind : 2; + uacpi_u8 lock_rule : 1; +} uacpi_field_unit; + +typedef struct uacpi_object { + struct uacpi_shareable shareable; + uacpi_u8 type; + uacpi_u8 flags; + + union { + uacpi_u64 integer; + uacpi_package *package; + uacpi_buffer_field buffer_field; + uacpi_object *inner_object; + uacpi_control_method *method; + uacpi_buffer *buffer; + uacpi_mutex *mutex; + uacpi_event *event; + uacpi_buffer_index buffer_index; + uacpi_operation_region *op_region; + uacpi_device *device; + uacpi_processor *processor; + uacpi_thermal_zone *thermal_zone; + uacpi_address_space_handlers *address_space_handlers; + uacpi_handlers *handlers; + uacpi_power_resource power_resource; + uacpi_field_unit *field_unit; + }; +} uacpi_object; + +uacpi_object *uacpi_create_object(uacpi_object_type type); enum uacpi_assign_behavior { UACPI_ASSIGN_BEHAVIOR_DEEP_COPY, @@ -39,7 +290,15 @@ struct uacpi_object *uacpi_create_internal_reference( ); uacpi_object *uacpi_unwrap_internal_reference(uacpi_object *object); -uacpi_bool uacpi_package_fill(uacpi_package *pkg, uacpi_size num_elements); +enum uacpi_prealloc_objects { + UACPI_PREALLOC_OBJECTS_NO, + UACPI_PREALLOC_OBJECTS_YES, +}; + +uacpi_bool uacpi_package_fill( + uacpi_package *pkg, uacpi_size num_elements, + enum uacpi_prealloc_objects prealloc_objects +); uacpi_mutex *uacpi_create_mutex(void); void uacpi_mutex_unref(uacpi_mutex*); diff --git a/include/uacpi/types.h b/include/uacpi/types.h index 38140378..6c475408 100644 --- a/include/uacpi/types.h +++ b/include/uacpi/types.h @@ -77,6 +77,17 @@ typedef struct uacpi_pci_address { uacpi_u8 function; } uacpi_pci_address; +typedef struct uacpi_data_view { + union { + uacpi_u8 *bytes; + const uacpi_u8 *const_bytes; + + uacpi_char *text; + const uacpi_char *const_text; + }; + uacpi_size length; +} uacpi_data_view; + typedef void *uacpi_handle; typedef struct uacpi_namespace_node uacpi_namespace_node; @@ -122,53 +133,196 @@ typedef enum uacpi_object_type { #define UACPI_OBJECT_REFERENCE_BIT (1 << UACPI_OBJECT_REFERENCE) #define UACPI_OBJECT_BUFFER_INDEX_BIT (1 << UACPI_OBJECT_BUFFER_INDEX) -const uacpi_char *uacpi_object_type_to_string(uacpi_object_type); typedef struct uacpi_object uacpi_object; -struct uacpi_shareable { - uacpi_u32 reference_count; -}; +void uacpi_object_ref(uacpi_object *obj); +void uacpi_object_unref(uacpi_object *obj); -typedef struct uacpi_buffer { - struct uacpi_shareable shareable; - union { - void *data; - uacpi_u8 *byte_data; - uacpi_char *text; - }; - uacpi_size size; -} uacpi_buffer; +uacpi_object_type uacpi_object_get_type(uacpi_object*); +uacpi_object_type uacpi_object_get_type_bit(uacpi_object*); + +/* + * Returns UACPI_TRUE if the provided object's type matches this type. + */ +uacpi_bool uacpi_object_is(uacpi_object*, uacpi_object_type); + +/* + * Returns UACPI_TRUE if the provided object's type is one of the values + * specified in the 'type_mask' of UACPI_OBJECT_*_BIT. + */ +uacpi_bool uacpi_object_is_one_of(uacpi_object*, uacpi_u32 type_mask); + +const uacpi_char *uacpi_object_type_to_string(uacpi_object_type); + +/* + * Create an uninitialized object. The object can be further overwritten via + * uacpi_object_assign_* to anything. + */ +uacpi_object *uacpi_object_create_uninitialized(void); + +/* + * Create an integer object with the value provided. + */ +uacpi_object *uacpi_object_create_integer(uacpi_u64); + +typedef enum uacpi_overflow_behavior { + UACPI_OVERFLOW_ALLOW = 0, + UACPI_OVERFLOW_TRUNCATE, + UACPI_OVERFLOW_DISALLOW, +} uacpi_overflow_behavior; -typedef struct uacpi_package { - struct uacpi_shareable shareable; +/* + * Same as uacpi_object_create_integer, but introduces additional ways to + * control what happens if the provided integer is larger than 32-bits, and the + * AML code expects 32-bit integers. + * + * - UACPI_OVERFLOW_ALLOW -> do nothing, same as the vanilla helper + * - UACPI_OVERFLOW_TRUNCATE -> truncate the integer to 32-bits if it happens to + * be larger than allowed by the DSDT + * - UACPI_OVERFLOW_DISALLOW -> fail object creation with + * UACPI_STATUS_INVALID_ARGUMENT if the provided + * value happens to be too large + */ +uacpi_status uacpi_object_create_integer_safe( + uacpi_u64, uacpi_overflow_behavior, uacpi_object **out_obj +); + +uacpi_status uacpi_object_assign_integer(uacpi_object*, uacpi_u64 value); +uacpi_status uacpi_object_get_integer(uacpi_object*, uacpi_u64 *out); + +/* + * Create a string/buffer object. Takes in a constant view of the data. + * + * NOTE: The data is copied to a separately allocated buffer and is not taken + * ownership of. + */ +uacpi_object *uacpi_object_create_string(uacpi_data_view); +uacpi_object *uacpi_object_create_cstring(const uacpi_char*); +uacpi_object *uacpi_object_create_buffer(uacpi_data_view); + +/* + * Returns a writable view of the data stored in the string or buffer type + * object. + */ +uacpi_status uacpi_object_get_string_or_buffer( + uacpi_object*, uacpi_data_view *out +); +uacpi_status uacpi_object_get_string(uacpi_object*, uacpi_data_view *out); +uacpi_status uacpi_object_get_buffer(uacpi_object*, uacpi_data_view *out); + +/* + * Returns UACPI_TRUE if the provided string object is actually an AML namepath. + * + * This can only be the case for package elements. If a package element is + * specified as a path to an object in AML, it's not resolved by the interpreter + * right away as it might not have been defined at that point yet, and is + * instead stored as a special string object to be resolved by client code + * when needed. + * + * Example usage: + * uacpi_namespace_node *target_node = UACPI_NULL; + * + * uacpi_object *obj = UACPI_NULL; + * uacpi_eval(scope, path, UACPI_NULL, &obj); + * + * uacpi_object_array arr; + * uacpi_object_get_package(obj, &arr); + * + * if (uacpi_object_is_aml_namepath(arr.objects[0])) { + * uacpi_object_resolve_as_aml_namepath( + * arr.objects[0], scope, &target_node + * ); + * } + */ +uacpi_bool uacpi_object_is_aml_namepath(uacpi_object*); + +/* + * Resolve an AML namepath contained in a string object. + * + * This is only applicable to objects that are package elements. See an + * explanation of how this works in the comment above the declaration of + * uacpi_object_is_aml_namepath. + * + * This is a shorthand for: + * uacpi_data_view view; + * uacpi_object_get_string(object, &view); + * + * target_node = uacpi_namespace_node_resolve_from_aml_namepath( + * scope, view.text + * ); + */ +uacpi_status uacpi_object_resolve_as_aml_namepath( + uacpi_object*, uacpi_namespace_node *scope, uacpi_namespace_node **out_node +); + +/* + * Make the provided object a string/buffer. + * Takes in a constant view of the data to be stored in the object. + * + * NOTE: The data is copied to a separately allocated buffer and is not taken + * ownership of. + */ +uacpi_status uacpi_object_assign_string(uacpi_object*, uacpi_data_view in); +uacpi_status uacpi_object_assign_buffer(uacpi_object*, uacpi_data_view in); + +typedef struct uacpi_object_array { uacpi_object **objects; uacpi_size count; -} uacpi_package; - -typedef struct uacpi_buffer_field { - uacpi_buffer *backing; - uacpi_size bit_index; - uacpi_u32 bit_length; - uacpi_bool force_buffer; -} uacpi_buffer_field; - -typedef struct uacpi_buffer_index { - uacpi_size idx; - uacpi_buffer *buffer; -} uacpi_buffer_index; - -typedef struct uacpi_mutex { - struct uacpi_shareable shareable; - uacpi_handle handle; - uacpi_thread_id owner; - uacpi_u16 depth; - uacpi_u8 sync_level; -} uacpi_mutex; - -typedef struct uacpi_event { - struct uacpi_shareable shareable; - uacpi_handle handle; -} uacpi_event; +} uacpi_object_array; + +/* + * Create a package object and store all of the objects in the array inside. + * The array is allowed to be empty. + * + * NOTE: the reference count of each object is incremented before being stored + * in the object. Client code must remove all of the locally created + * references at its own discretion. + */ +uacpi_object *uacpi_object_create_package(uacpi_object_array in); + +/* + * Returns the list of objects stored in a package object. + * + * NOTE: the reference count of the objects stored inside is not incremented, + * which means destorying/overwriting the object also potentially destroys + * all of the objects stored inside unless the reference count is + * incremented by the client via uacpi_object_ref. + */ +uacpi_status uacpi_object_get_package(uacpi_object*, uacpi_object_array *out); + +/* + * Make the provided object a package and store all of the objects in the array + * inside. The array is allowed to be empty. + * + * NOTE: the reference count of each object is incremented before being stored + * in the object. Client code must remove all of the locally created + * references at its own discretion. + */ +uacpi_status uacpi_object_assign_package(uacpi_object*, uacpi_object_array in); + +/* + * Create a reference object and make it point to 'child'. + * + * NOTE: child's reference count is incremented by one. Client code must remove + * all of the locally created references at its own discretion. + */ +uacpi_object *uacpi_object_create_reference(uacpi_object *child); + +/* + * Make the provided object a reference and make it point to 'child'. + * + * NOTE: child's reference count is incremented by one. Client code must remove + * all of the locally created references at its own discretion. + */ +uacpi_status uacpi_object_assign_reference(uacpi_object*, uacpi_object *child); + +/* + * Retrieve the object pointed to by a reference object. + * + * NOTE: the reference count of the returned object is incremented by one and + * must be uacpi_object_unref'ed by the client when no longer needed. + */ +uacpi_status uacpi_object_get_dereferenced(uacpi_object*, uacpi_object **out); typedef enum uacpi_region_op { UACPI_REGION_OP_ATTACH = 1, @@ -203,51 +357,9 @@ typedef struct uacpi_region_detach_data { typedef uacpi_status (*uacpi_region_handler) (uacpi_region_op op, uacpi_handle op_data); -typedef struct uacpi_address_space_handler { - struct uacpi_shareable shareable; - uacpi_region_handler callback; - uacpi_handle user_context; - struct uacpi_address_space_handler *next; - struct uacpi_operation_region *regions; - uacpi_u16 space; -} uacpi_address_space_handler; - typedef uacpi_status (*uacpi_notify_handler) (uacpi_handle context, uacpi_namespace_node *node, uacpi_u64 value); -typedef struct uacpi_device_notify_handler { - uacpi_notify_handler callback; - uacpi_handle user_context; - struct uacpi_device_notify_handler *next; -} uacpi_device_notify_handler; - -/* - * NOTE: These are common object headers. - * Any changes to these structs must be propagated to all objects. - * ============================================================== - * Common for the following objects: - * - UACPI_OBJECT_OPERATION_REGION - * - UACPI_OBJECT_PROCESSOR - * - UACPI_OBJECT_DEVICE - * - UACPI_OBJECT_THERMAL_ZONE - */ -typedef struct uacpi_address_space_handlers { - struct uacpi_shareable shareable; - uacpi_address_space_handler *head; -} uacpi_address_space_handlers; - -/* - * Common for the following objects: - * - UACPI_OBJECT_PROCESSOR - * - UACPI_OBJECT_DEVICE - * - UACPI_OBJECT_THERMAL_ZONE - */ -typedef struct uacpi_handlers { - struct uacpi_shareable shareable; - uacpi_address_space_handler *address_space_head; - uacpi_device_notify_handler *notify_head; -} uacpi_handlers; - typedef enum uacpi_address_space { UACPI_ADDRESS_SPACE_SYSTEM_MEMORY = 0, UACPI_ADDRESS_SPACE_SYSTEM_IO = 1, @@ -268,181 +380,6 @@ typedef enum uacpi_address_space { } uacpi_address_space; const uacpi_char *uacpi_address_space_to_string(uacpi_address_space space); -// This region has a corresponding _REG method that was succesfully executed -#define UACPI_OP_REGION_STATE_REG_EXECUTED (1 << 0) - -// This region was successfully attached to a handler -#define UACPI_OP_REGION_STATE_ATTACHED (1 << 1) - -typedef struct uacpi_operation_region { - struct uacpi_shareable shareable; - uacpi_address_space_handler *handler; - uacpi_handle user_context; - uacpi_u16 space; - uacpi_u8 state_flags; - uacpi_u64 offset; - uacpi_u64 length; - - // If space == TABLE_DATA - uacpi_u64 table_idx; - - // Used to link regions sharing the same handler - struct uacpi_operation_region *next; -} uacpi_operation_region; - -typedef struct uacpi_device { - struct uacpi_shareable shareable; - uacpi_address_space_handler *address_space_handlers; - uacpi_device_notify_handler *notify_handlers; -} uacpi_device; - -typedef struct uacpi_processor { - struct uacpi_shareable shareable; - uacpi_address_space_handler *address_space_handlers; - uacpi_device_notify_handler *notify_handlers; - uacpi_u8 id; - uacpi_u32 block_address; - uacpi_u8 block_length; -} uacpi_processor; - -typedef struct uacpi_thermal_zone { - struct uacpi_shareable shareable; - uacpi_address_space_handler *address_space_handlers; - uacpi_device_notify_handler *notify_handlers; -} uacpi_thermal_zone; - -typedef struct uacpi_power_resource { - uacpi_u8 system_level; - uacpi_u16 resource_order; -} uacpi_power_resource; - -typedef uacpi_status (*uacpi_native_call_handler)( - uacpi_handle ctx, uacpi_object *retval -); - -typedef struct uacpi_control_method { - struct uacpi_shareable shareable; - union { - uacpi_u8 *code; - uacpi_native_call_handler handler; - }; - uacpi_mutex *mutex; - uacpi_u32 size; - uacpi_u8 sync_level : 4; - uacpi_u8 args : 3; - uacpi_u8 is_serialized : 1; - uacpi_u8 named_objects_persist: 1; - uacpi_u8 native_call : 1; - uacpi_u8 owns_code : 1; -} uacpi_control_method; - -typedef enum uacpi_access_type { - UACPI_ACCESS_TYPE_ANY = 0, - UACPI_ACCESS_TYPE_BYTE = 1, - UACPI_ACCESS_TYPE_WORD = 2, - UACPI_ACCESS_TYPE_DWORD = 3, - UACPI_ACCESS_TYPE_QWORD = 4, - UACPI_ACCESS_TYPE_BUFFER = 5, -} uacpi_access_type; - -typedef enum uacpi_access_attributes { - UACPI_ACCESS_ATTRIBUTE_QUICK = 0x02, - UACPI_ACCESS_ATTRIBUTE_SEND_RECEIVE = 0x04, - UACPI_ACCESS_ATTRIBUTE_BYTE = 0x06, - UACPI_ACCESS_ATTRIBUTE_WORD = 0x08, - UACPI_ACCESS_ATTRIBUTE_BLOCK = 0x0A, - UACPI_ACCESS_ATTRIBUTE_BYTES = 0x0B, - UACPI_ACCESS_ATTRIBUTE_PROCESS_CALL = 0x0C, - UACPI_ACCESS_ATTRIBUTE_BLOCK_PROCESS_CALL = 0x0D, - UACPI_ACCESS_ATTRIBUTE_RAW_BYTES = 0x0E, - UACPI_ACCESS_ATTRIBUTE_RAW_PROCESS_BYTES = 0x0F, -} uacpi_access_attributes; - -typedef enum uacpi_lock_rule { - UACPI_LOCK_RULE_NO_LOCK = 0, - UACPI_LOCK_RULE_LOCK = 1, -} uacpi_lock_rule; - -typedef enum uacpi_update_rule { - UACPI_UPDATE_RULE_PRESERVE = 0, - UACPI_UPDATE_RULE_WRITE_AS_ONES = 1, - UACPI_UPDATE_RULE_WRITE_AS_ZEROES = 2, -} uacpi_update_rule; - -typedef enum uacpi_field_unit_kind { - UACPI_FIELD_UNIT_KIND_NORMAL = 0, - UACPI_FIELD_UNIT_KIND_INDEX = 1, - UACPI_FIELD_UNIT_KIND_BANK = 2, -} uacpi_field_unit_kind; - -typedef struct uacpi_field_unit { - struct uacpi_shareable shareable; - - union { - // UACPI_FIELD_UNIT_KIND_NORMAL - struct { - uacpi_namespace_node *region; - }; - - // UACPI_FIELD_UNIT_KIND_INDEX - struct { - struct uacpi_field_unit *index; - struct uacpi_field_unit *data; - }; - - // UACPI_FIELD_UNIT_KIND_BANK - struct { - uacpi_namespace_node *bank_region; - struct uacpi_field_unit *bank_selection; - uacpi_u64 bank_value; - }; - }; - - uacpi_object *connection; - - uacpi_u32 byte_offset; - uacpi_u32 bit_length; - uacpi_u8 bit_offset_within_first_byte; - uacpi_u8 access_width_bytes; - uacpi_u8 access_length; - - uacpi_u8 attributes : 4; - uacpi_u8 update_rule : 2; - uacpi_u8 kind : 2; - uacpi_u8 lock_rule : 1; -} uacpi_field_unit; - -typedef struct uacpi_object { - struct uacpi_shareable shareable; - uacpi_u8 type; - uacpi_u8 flags; - - union { - uacpi_u64 integer; - uacpi_package *package; - uacpi_buffer_field buffer_field; - uacpi_object *inner_object; - uacpi_control_method *method; - uacpi_buffer *buffer; - uacpi_mutex *mutex; - uacpi_event *event; - uacpi_buffer_index buffer_index; - uacpi_operation_region *op_region; - uacpi_device *device; - uacpi_processor *processor; - uacpi_thermal_zone *thermal_zone; - uacpi_address_space_handlers *address_space_handlers; - uacpi_handlers *handlers; - uacpi_power_resource power_resource; - uacpi_field_unit *field_unit; - }; -} uacpi_object; - -typedef struct uacpi_args { - uacpi_object **objects; - uacpi_size count; -} uacpi_args; - typedef union uacpi_object_name { uacpi_char text[4]; uacpi_u32 id; @@ -478,11 +415,6 @@ typedef uacpi_u32 uacpi_interrupt_ret; typedef uacpi_interrupt_ret (*uacpi_interrupt_handler)(uacpi_handle); -uacpi_object *uacpi_create_object(uacpi_object_type type); - -void uacpi_object_ref(uacpi_object *obj); -void uacpi_object_unref(uacpi_object *obj); - #ifdef __cplusplus } #endif diff --git a/include/uacpi/uacpi.h b/include/uacpi/uacpi.h index b1d572f5..6cbeba1b 100644 --- a/include/uacpi/uacpi.h +++ b/include/uacpi/uacpi.h @@ -118,7 +118,7 @@ uacpi_init_level uacpi_get_current_init_level(void); * lookups, unless 'path' is already absolute. */ uacpi_status uacpi_eval(uacpi_namespace_node *parent, const uacpi_char *path, - const uacpi_args *args, uacpi_object **ret); + const uacpi_object_array *args, uacpi_object **ret); /* * Same as uacpi_eval, but the return value type is validated against @@ -126,7 +126,7 @@ uacpi_status uacpi_eval(uacpi_namespace_node *parent, const uacpi_char *path, */ uacpi_status uacpi_eval_typed( uacpi_namespace_node *parent, const uacpi_char *path, - const uacpi_args *args, uacpi_u32 ret_mask, uacpi_object **ret + const uacpi_object_array *args, uacpi_u32 ret_mask, uacpi_object **ret ); /* @@ -134,7 +134,7 @@ uacpi_status uacpi_eval_typed( */ uacpi_status uacpi_eval_integer( uacpi_namespace_node *parent, const uacpi_char *path, - const uacpi_args *args, uacpi_u64 *out_value + const uacpi_object_array *args, uacpi_u64 *out_value ); /* diff --git a/source/interpreter.c b/source/interpreter.c index 88908045..7bce1547 100644 --- a/source/interpreter.c +++ b/source/interpreter.c @@ -796,7 +796,8 @@ static uacpi_status handle_package(struct execution_context *ctx) } // 2. Create every object in the package, start as uninitialized - if (uacpi_unlikely(!uacpi_package_fill(package, num_elements))) + if (uacpi_unlikely(!uacpi_package_fill(package, num_elements, + UACPI_PREALLOC_OBJECTS_YES))) return UACPI_STATUS_OUT_OF_MEMORY; // 3. Go through every defined object and copy it into the package @@ -4921,7 +4922,7 @@ enum method_call_type { static uacpi_status prepare_method_call( struct execution_context *ctx, uacpi_namespace_node *node, uacpi_control_method *method, enum method_call_type type, - const uacpi_args *args + const uacpi_object_array *args ) { uacpi_status ret; @@ -5638,7 +5639,7 @@ static void execution_context_release(struct execution_context *ctx) uacpi_status uacpi_execute_control_method( uacpi_namespace_node *scope, uacpi_control_method *method, - const uacpi_args *args, uacpi_object **out_obj + const uacpi_object_array *args, uacpi_object **out_obj ) { uacpi_status ret = UACPI_STATUS_OK; diff --git a/source/opregion.c b/source/opregion.c index f3221e5d..bd698936 100644 --- a/source/opregion.c +++ b/source/opregion.c @@ -85,7 +85,7 @@ static uacpi_status region_run_reg( ) { uacpi_status ret; - uacpi_args method_args; + uacpi_object_array method_args; uacpi_object *args[2]; args[0] = uacpi_create_object(UACPI_OBJECT_INTEGER); diff --git a/source/resources.c b/source/resources.c index 4c2cb93b..65429f7f 100644 --- a/source/resources.c +++ b/source/resources.c @@ -2484,7 +2484,7 @@ uacpi_status uacpi_set_resources( { uacpi_status ret; uacpi_object *res_template; - uacpi_args args; + uacpi_object_array args; ret = uacpi_native_resources_to_aml(resources, &res_template); if (uacpi_unlikely_error(ret)) diff --git a/source/sleep.c b/source/sleep.c index bca0938e..d6e45166 100644 --- a/source/sleep.c +++ b/source/sleep.c @@ -268,7 +268,7 @@ static uacpi_status eval_sleep_helper( ) { uacpi_object *arg; - uacpi_args args; + uacpi_object_array args; uacpi_status ret; arg = uacpi_create_object(UACPI_OBJECT_INTEGER); diff --git a/source/types.c b/source/types.c index d42c5f14..c89393f1 100644 --- a/source/types.c +++ b/source/types.c @@ -119,7 +119,10 @@ static uacpi_bool empty_buffer_or_string_alloc(uacpi_object *object) return buffer_alloc(object, 0); } -uacpi_bool uacpi_package_fill(uacpi_package *pkg, uacpi_size num_elements) +uacpi_bool uacpi_package_fill( + uacpi_package *pkg, uacpi_size num_elements, + enum uacpi_prealloc_objects prealloc_objects +) { uacpi_size i; @@ -131,17 +134,23 @@ uacpi_bool uacpi_package_fill(uacpi_package *pkg, uacpi_size num_elements) return UACPI_FALSE; pkg->count = num_elements; - for (i = 0; i < num_elements; ++i) { - pkg->objects[i] = uacpi_create_object(UACPI_OBJECT_UNINITIALIZED); - if (uacpi_unlikely(pkg->objects[i] == UACPI_NULL)) - return UACPI_FALSE; + if (prealloc_objects == UACPI_PREALLOC_OBJECTS_YES) { + for (i = 0; i < num_elements; ++i) { + pkg->objects[i] = uacpi_create_object(UACPI_OBJECT_UNINITIALIZED); + + if (uacpi_unlikely(pkg->objects[i] == UACPI_NULL)) + return UACPI_FALSE; + } } return UACPI_TRUE; } -static uacpi_bool package_alloc(uacpi_object *obj, uacpi_size initial_size) +static uacpi_bool package_alloc( + uacpi_object *obj, uacpi_size initial_size, + enum uacpi_prealloc_objects prealloc +) { uacpi_package *pkg; @@ -151,7 +160,7 @@ static uacpi_bool package_alloc(uacpi_object *obj, uacpi_size initial_size) uacpi_shareable_init(pkg); - if (uacpi_unlikely(!uacpi_package_fill(pkg, initial_size))) { + if (uacpi_unlikely(!uacpi_package_fill(pkg, initial_size, prealloc))) { uacpi_free(pkg, sizeof(*pkg)); return UACPI_FALSE; } @@ -162,7 +171,7 @@ static uacpi_bool package_alloc(uacpi_object *obj, uacpi_size initial_size) static uacpi_bool empty_package_alloc(uacpi_object *object) { - return package_alloc(object, 0); + return package_alloc(object, 0, UACPI_PREALLOC_OBJECTS_NO); } uacpi_mutex *uacpi_create_mutex(void) @@ -829,7 +838,8 @@ static uacpi_status deep_copy_package_no_recurse( uacpi_size i; uacpi_package *dst_package; - if (uacpi_unlikely(!package_alloc(dst, src->count))) + if (uacpi_unlikely(!package_alloc(dst, src->count, + UACPI_PREALLOC_OBJECTS_YES))) return UACPI_STATUS_OUT_OF_MEMORY; dst->type = UACPI_OBJECT_PACKAGE; @@ -964,6 +974,365 @@ void uacpi_object_detach_child(uacpi_object *parent) uacpi_object_unref(child); } +uacpi_object_type uacpi_object_get_type(uacpi_object *obj) +{ + return obj->type; +} + +uacpi_object_type uacpi_object_get_type_bit(uacpi_object *obj) +{ + return (1u << obj->type); +} + +uacpi_bool uacpi_object_is(uacpi_object *obj, uacpi_object_type type) +{ + return obj->type == type; +} + +uacpi_bool uacpi_object_is_one_of(uacpi_object *obj, uacpi_u32 type_mask) +{ + return (uacpi_object_get_type_bit(obj) & type_mask) != 0; +} + +#define TYPE_CHECK_USER_OBJ_RET(obj, type_bits, ret) \ + do { \ + if (uacpi_unlikely(obj == UACPI_NULL || \ + !uacpi_object_is_one_of(obj, type_bits))) \ + return ret; \ + } while (0) + +#define TYPE_CHECK_USER_OBJ(obj, type_bits) \ + TYPE_CHECK_USER_OBJ_RET(obj, type_bits, UACPI_STATUS_INVALID_ARGUMENT) + +#define ENSURE_VALID_USER_OBJ_RET(obj, ret) \ + do { \ + if (uacpi_unlikely(obj == UACPI_NULL)) \ + return ret; \ + } while (0) + +#define ENSURE_VALID_USER_OBJ(obj) \ + ENSURE_VALID_USER_OBJ_RET(obj, UACPI_STATUS_INVALID_ARGUMENT) + +uacpi_status uacpi_object_get_integer(uacpi_object *obj, uacpi_u64 *out) +{ + TYPE_CHECK_USER_OBJ(obj, UACPI_OBJECT_INTEGER_BIT); + + *out = obj->integer; + return UACPI_STATUS_OK; +} + +uacpi_status uacpi_object_assign_integer(uacpi_object *obj, uacpi_u64 value) +{ + ENSURE_VALID_USER_OBJ(obj); + + return uacpi_object_assign(obj, &(uacpi_object) { + .type = UACPI_OBJECT_INTEGER, + .integer = value, + }, UACPI_ASSIGN_BEHAVIOR_DEEP_COPY); +} + +uacpi_status uacpi_object_do_get_string_or_buffer( + uacpi_object *obj, uacpi_data_view *out, uacpi_u32 mask +) +{ + TYPE_CHECK_USER_OBJ(obj, mask); + + out->bytes = obj->buffer->data; + out->length = obj->buffer->size; + return UACPI_STATUS_OK; +} + +uacpi_status uacpi_object_get_string_or_buffer( + uacpi_object *obj, uacpi_data_view *out +) +{ + return uacpi_object_do_get_string_or_buffer( + obj, out, UACPI_OBJECT_STRING_BIT | UACPI_OBJECT_BUFFER_BIT + ); +} + +uacpi_status uacpi_object_get_string(uacpi_object *obj, uacpi_data_view *out) +{ + return uacpi_object_do_get_string_or_buffer( + obj, out, UACPI_OBJECT_STRING_BIT + ); +} + +uacpi_status uacpi_object_get_buffer(uacpi_object *obj, uacpi_data_view *out) +{ + return uacpi_object_do_get_string_or_buffer( + obj, out, UACPI_OBJECT_BUFFER_BIT + ); +} + +uacpi_bool uacpi_object_is_aml_namepath(uacpi_object *obj) +{ + TYPE_CHECK_USER_OBJ_RET(obj, UACPI_OBJECT_STRING_BIT, UACPI_FALSE); + return obj->flags == UACPI_STRING_KIND_PATH; +} + +uacpi_status uacpi_object_resolve_as_aml_namepath( + uacpi_object *obj, uacpi_namespace_node *scope, + uacpi_namespace_node **out_node +) +{ + uacpi_namespace_node *node; + + if (!uacpi_object_is_aml_namepath(obj)) + return UACPI_STATUS_INVALID_ARGUMENT; + + node = uacpi_namespace_node_resolve_from_aml_namepath( + scope, obj->buffer->text + ); + if (node == UACPI_NULL) + return UACPI_STATUS_NOT_FOUND; + + *out_node = node; + return UACPI_STATUS_OK; +} + +static uacpi_status uacpi_object_do_assign_buffer( + uacpi_object *obj, uacpi_data_view in, uacpi_object_type type +) +{ + uacpi_status ret; + uacpi_object tmp_obj = { + .type = type, + }; + uacpi_size dst_buf_size = in.length; + + ENSURE_VALID_USER_OBJ(obj); + + if (type == UACPI_OBJECT_STRING && (in.length == 0 || + in.const_bytes[in.length - 1] != 0x00)) + dst_buf_size++; + + ret = buffer_alloc_and_store( + &tmp_obj, dst_buf_size, in.const_bytes, in.length + ); + if (uacpi_unlikely_error(ret)) + return ret; + + ret = uacpi_object_assign( + obj, &tmp_obj, UACPI_ASSIGN_BEHAVIOR_SHALLOW_COPY + ); + uacpi_shareable_unref_and_delete_if_last(tmp_obj.buffer, free_buffer); + + return ret; +} + +uacpi_status uacpi_object_assign_string(uacpi_object *obj, uacpi_data_view in) +{ + return uacpi_object_do_assign_buffer(obj, in, UACPI_OBJECT_STRING); +} + +uacpi_status uacpi_object_assign_buffer(uacpi_object *obj, uacpi_data_view in) +{ + return uacpi_object_do_assign_buffer(obj, in, UACPI_OBJECT_BUFFER); +} + +uacpi_object *uacpi_object_create_uninitialized(void) +{ + return uacpi_create_object(UACPI_OBJECT_UNINITIALIZED); +} + +uacpi_status uacpi_object_create_integer_safe( + uacpi_u64 value, uacpi_overflow_behavior behavior, uacpi_object **out_obj +) +{ + uacpi_status ret; + uacpi_u8 bitness; + uacpi_object *obj; + + ret = uacpi_get_aml_bitness(&bitness); + if (uacpi_unlikely_error(ret)) + return ret; + + switch (behavior) { + case UACPI_OVERFLOW_TRUNCATE: + case UACPI_OVERFLOW_DISALLOW: + if (bitness == 32 && value > 0xFFFFFFFF) { + if (behavior == UACPI_OVERFLOW_DISALLOW) + return UACPI_STATUS_INVALID_ARGUMENT; + + value &= 0xFFFFFFFF; + } + UACPI_FALLTHROUGH; + case UACPI_OVERFLOW_ALLOW: + obj = uacpi_object_create_integer(value); + if (uacpi_unlikely(obj == UACPI_NULL)) + return UACPI_STATUS_OUT_OF_MEMORY; + + *out_obj = obj; + return ret; + default: + return UACPI_STATUS_INVALID_ARGUMENT; + } +} + +/* + * Create an integer object with the value provided. + */ +uacpi_object *uacpi_object_create_integer(uacpi_u64 value) +{ + uacpi_object *obj; + + obj = uacpi_create_object(UACPI_OBJECT_INTEGER); + if (uacpi_unlikely(obj == UACPI_NULL)) + return obj; + + obj->integer = value; + return obj; +} + +uacpi_object *uacpi_object_do_create_string_or_buffer( + uacpi_data_view view, uacpi_object_type type +) +{ + uacpi_status ret; + uacpi_object *obj; + + obj = uacpi_create_object(UACPI_OBJECT_UNINITIALIZED); + if (uacpi_unlikely(obj == UACPI_NULL)) + return UACPI_NULL; + + ret = uacpi_object_do_assign_buffer(obj, view, type); + if (uacpi_unlikely_error(ret)) { + uacpi_object_unref(obj); + return UACPI_NULL; + } + + return obj; +} + +uacpi_object *uacpi_object_create_string(uacpi_data_view view) +{ + return uacpi_object_do_create_string_or_buffer(view, UACPI_OBJECT_STRING); +} + +uacpi_object *uacpi_object_create_buffer(uacpi_data_view view) +{ + return uacpi_object_do_create_string_or_buffer(view, UACPI_OBJECT_BUFFER); +} + +uacpi_object *uacpi_object_create_cstring(const uacpi_char *str) +{ + return uacpi_object_create_string((uacpi_data_view) { + .const_text = str, + .length = uacpi_strlen(str) + 1, + }); +} + +uacpi_status uacpi_object_get_package( + uacpi_object *obj, uacpi_object_array *out +) +{ + TYPE_CHECK_USER_OBJ(obj, UACPI_OBJECT_PACKAGE_BIT); + + out->objects = obj->package->objects; + out->count = obj->package->count; + return UACPI_STATUS_OK; +} + +uacpi_object *uacpi_object_create_reference(uacpi_object *child) +{ + uacpi_object *obj; + + ENSURE_VALID_USER_OBJ_RET(child, UACPI_NULL); + + obj = uacpi_create_object(UACPI_OBJECT_REFERENCE); + if (uacpi_unlikely(obj == UACPI_NULL)) + return UACPI_NULL; + + uacpi_object_attach_child(obj, child); + obj->flags = UACPI_REFERENCE_KIND_REFOF; + + return obj; +} + +uacpi_status uacpi_object_assign_reference( + uacpi_object *obj, uacpi_object *child +) +{ + uacpi_status ret; + + ENSURE_VALID_USER_OBJ(obj); + ENSURE_VALID_USER_OBJ(child); + + // First clear out the object + ret = uacpi_object_assign( + obj, &(uacpi_object) { .type = UACPI_OBJECT_UNINITIALIZED }, + UACPI_ASSIGN_BEHAVIOR_DEEP_COPY + ); + if (uacpi_unlikely_error(ret)) + return ret; + + obj->type = UACPI_OBJECT_REFERENCE; + uacpi_object_attach_child(obj, child); + obj->flags = UACPI_REFERENCE_KIND_REFOF; + + return UACPI_STATUS_OK; +} + +uacpi_status uacpi_object_get_dereferenced( + uacpi_object *obj, uacpi_object **out +) +{ + TYPE_CHECK_USER_OBJ(obj, UACPI_OBJECT_REFERENCE_BIT); + + *out = obj->inner_object; + uacpi_shareable_ref(*out); + + return UACPI_STATUS_OK; +} + +uacpi_status uacpi_object_assign_package( + uacpi_object *obj, uacpi_object_array in +) +{ + uacpi_status ret; + uacpi_size i; + uacpi_object tmp_obj = { + .type = UACPI_OBJECT_PACKAGE, + }; + + ENSURE_VALID_USER_OBJ(obj); + + if (uacpi_unlikely(!package_alloc(&tmp_obj, in.count, + UACPI_PREALLOC_OBJECTS_NO))) + return UACPI_STATUS_OUT_OF_MEMORY; + + obj->type = UACPI_OBJECT_PACKAGE; + + for (i = 0; i < in.count; ++i) { + tmp_obj.package->objects[i] = in.objects[i]; + uacpi_object_ref(tmp_obj.package->objects[i]); + } + + ret = uacpi_object_assign(obj, &tmp_obj, UACPI_ASSIGN_BEHAVIOR_SHALLOW_COPY); + uacpi_shareable_unref_and_delete_if_last(tmp_obj.package, free_package); + + return ret; +} + +uacpi_object *uacpi_object_create_package(uacpi_object_array in) +{ + uacpi_status ret; + uacpi_object *obj; + + obj = uacpi_object_create_uninitialized(); + if (uacpi_unlikely(obj == UACPI_NULL)) + return obj; + + ret = uacpi_object_assign_package(obj, in); + if (uacpi_unlikely_error(ret)) { + uacpi_object_unref(obj); + return UACPI_NULL; + } + + return obj; +} + uacpi_status uacpi_object_assign(uacpi_object *dst, uacpi_object *src, enum uacpi_assign_behavior behavior) { diff --git a/source/uacpi.c b/source/uacpi.c index f7f8f508..64c3ec7c 100644 --- a/source/uacpi.c +++ b/source/uacpi.c @@ -583,7 +583,7 @@ uacpi_status uacpi_namespace_initialize(void) uacpi_status uacpi_eval(uacpi_namespace_node *parent, const uacpi_char *path, - const uacpi_args *args, uacpi_object **ret) + const uacpi_object_array *args, uacpi_object **ret) { struct uacpi_namespace_node *node; uacpi_object *obj; @@ -659,7 +659,7 @@ static void trace_invalid_return_type( uacpi_status uacpi_eval_typed( uacpi_namespace_node *parent, const uacpi_char *path, - const uacpi_args *args, uacpi_u32 ret_mask, uacpi_object **out_obj + const uacpi_object_array *args, uacpi_u32 ret_mask, uacpi_object **out_obj ) { uacpi_status ret; @@ -688,7 +688,7 @@ uacpi_status uacpi_eval_typed( uacpi_status uacpi_eval_integer( uacpi_namespace_node *parent, const uacpi_char *path, - const uacpi_args *args, uacpi_u64 *out_value + const uacpi_object_array *args, uacpi_u64 *out_value ) { uacpi_object *int_obj; diff --git a/source/utilities.c b/source/utilities.c index ab00c869..e2ffe6d9 100644 --- a/source/utilities.c +++ b/source/utilities.c @@ -989,7 +989,7 @@ uacpi_status uacpi_set_interrupt_model(uacpi_interrupt_model model) { uacpi_status ret; uacpi_object *arg; - uacpi_args args; + uacpi_object_array args; UACPI_ENSURE_INIT_LEVEL_AT_LEAST(UACPI_INIT_LEVEL_NAMESPACE_LOADED); diff --git a/tests/runner/test_runner.cpp b/tests/runner/test_runner.cpp index fe7cbdb3..0dfb7470 100644 --- a/tests/runner/test_runner.cpp +++ b/tests/runner/test_runner.cpp @@ -47,11 +47,12 @@ static void validate_ret_against_expected( throw std::runtime_error(err); }; + auto type = uacpi_object_get_type(&obj); - if (obj.type != expected_type) { + if (type != expected_type) { std::string err; err += "returned type '"; - err += uacpi_object_type_to_string((uacpi_object_type)obj.type); + err += uacpi_object_type_to_string(type); err += "' doesn't match expected '"; err += uacpi_object_type_to_string(expected_type); err += "'"; @@ -59,17 +60,21 @@ static void validate_ret_against_expected( throw std::runtime_error(err); } - switch (obj.type) { + switch (type) { case UACPI_OBJECT_INTEGER: { auto expected_int = std::stoull(expected_val.data(), nullptr, 0); - auto& actual_int = obj.integer; + uacpi_u64 actual_int; + + uacpi_object_get_integer(&obj, &actual_int); if (expected_int != actual_int) ret_is_wrong(expected_val, std::to_string(actual_int)); } break; case UACPI_OBJECT_STRING: { - auto actual_str = std::string_view(obj.buffer->text, - obj.buffer->size - 1); + uacpi_data_view view; + + uacpi_object_get_string_or_buffer(&obj, &view); + auto actual_str = std::string_view(view.text, view.length - 1); if (expected_val != actual_str) ret_is_wrong(expected_val, actual_str); @@ -385,12 +390,16 @@ static void run_test( ensure_ok_status(st); if (is_test_mode) { - uacpi_object *runner_id; + uacpi_object *runner_id = UACPI_NULL; st = uacpi_eval_typed(UACPI_NULL, "\\_SI.TID", UACPI_NULL, UACPI_OBJECT_STRING_BIT, &runner_id); ensure_ok_status(st); - if (strcmp(runner_id->buffer->text, "uACPI") != 0) + uacpi_data_view view; + st = uacpi_object_get_string_or_buffer(runner_id, &view); + ensure_ok_status(st); + + if (strcmp(view.text, "uACPI") != 0) throw std::runtime_error("invalid test runner id"); uacpi_object_unref(runner_id); }