Skip to content

Commit f468434

Browse files
committed
Introduce support for IPMI opregions
This also serves as the foundation for supporting other write-then-read and serial address space types. Signed-off-by: Daniil Tatianin <99danilt@gmail.com>
1 parent 777187b commit f468434

File tree

7 files changed

+383
-144
lines changed

7 files changed

+383
-144
lines changed

include/uacpi/internal/io.h

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,21 @@ void uacpi_write_buffer_field(
1313
uacpi_buffer_field *field, const void *src, uacpi_size size
1414
);
1515

16+
uacpi_status uacpi_field_unit_get_read_type(
17+
struct uacpi_field_unit *field, uacpi_object_type *out_type
18+
);
19+
20+
uacpi_status uacpi_field_unit_get_bit_length(
21+
struct uacpi_field_unit *field, uacpi_size *out_length
22+
);
23+
1624
uacpi_status uacpi_read_field_unit(
17-
uacpi_field_unit *field, void *dst, uacpi_size size
25+
uacpi_field_unit *field, void *dst, uacpi_size size,
26+
uacpi_data_view *wtr_response
1827
);
1928
uacpi_status uacpi_write_field_unit(
20-
uacpi_field_unit *field, const void *src, uacpi_size size
29+
uacpi_field_unit *field, const void *src, uacpi_size size,
30+
uacpi_data_view *wtr_response
2131
);
2232

2333
uacpi_status uacpi_system_io_read(

include/uacpi/internal/opcodes.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -665,9 +665,10 @@ UACPI_OP( \
665665
StoreOp, 0x70, \
666666
{ \
667667
UACPI_PARSE_OP_TERM_ARG, \
668-
UACPI_PARSE_OP_OBJECT_COPY_TO_PREV, \
669668
UACPI_PARSE_OP_SUPERNAME, \
670669
UACPI_PARSE_OP_INVOKE_HANDLER, \
670+
UACPI_PARSE_OP_ITEM_POP, \
671+
UACPI_PARSE_OP_OBJECT_COPY_TO_PREV, \
671672
}, \
672673
UACPI_OP_PROPERTY_TERM_ARG \
673674
) \

include/uacpi/internal/opregion.h

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,6 @@ void uacpi_deinitialize_opregion(void);
99
void uacpi_trace_region_error(
1010
uacpi_namespace_node *node, uacpi_char *message, uacpi_status ret
1111
);
12-
void uacpi_trace_region_io(
13-
uacpi_namespace_node *node, uacpi_address_space space, uacpi_region_op op,
14-
uacpi_u64 offset, uacpi_u8 byte_size, uacpi_u64 ret
15-
);
1612

1713
uacpi_status uacpi_install_address_space_handler_with_flags(
1814
uacpi_namespace_node *device_node, enum uacpi_address_space space,
@@ -36,7 +32,14 @@ uacpi_status uacpi_opregion_attach(uacpi_namespace_node *node);
3632

3733
void uacpi_install_default_address_space_handlers(void);
3834

35+
uacpi_bool uacpi_is_buffer_access_address_space(uacpi_address_space space);
36+
37+
union uacpi_opregion_io_data {
38+
uacpi_u64 *integer;
39+
uacpi_data_view buffer;
40+
};
41+
3942
uacpi_status uacpi_dispatch_opregion_io(
4043
uacpi_field_unit *field, uacpi_u32 offset,
41-
uacpi_region_op op, uacpi_u64 *in_out
44+
uacpi_region_op op, union uacpi_opregion_io_data data
4245
);

include/uacpi/types.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,8 @@ typedef enum uacpi_region_op {
367367
UACPI_REGION_OP_PCC_SEND,
368368
UACPI_REGION_OP_GPIO_READ,
369369
UACPI_REGION_OP_GPIO_WRITE,
370+
371+
UACPI_REGION_OP_IPMI_COMMAND,
370372
} uacpi_region_op;
371373

372374
typedef struct uacpi_generic_region_info {
@@ -422,6 +424,14 @@ typedef struct uacpi_region_gpio_rw_data
422424
uacpi_u64 value;
423425
} uacpi_region_gpio_rw_data;
424426

427+
typedef struct uacpi_region_ipmi_rw_data
428+
{
429+
void *handler_context;
430+
void *region_context;
431+
uacpi_data_view in_out_message;
432+
uacpi_u64 command;
433+
} uacpi_region_ipmi_rw_data;
434+
425435
typedef struct uacpi_region_detach_data {
426436
void *handler_context;
427437
void *region_context;

source/interpreter.c

Lines changed: 125 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -867,18 +867,6 @@ static uacpi_status handle_package(struct execution_context *ctx)
867867
return UACPI_STATUS_OK;
868868
}
869869

870-
static uacpi_size field_byte_size(uacpi_object *obj)
871-
{
872-
uacpi_size bit_length;
873-
874-
if (obj->type == UACPI_OBJECT_BUFFER_FIELD)
875-
bit_length = obj->buffer_field.bit_length;
876-
else
877-
bit_length = obj->field_unit->bit_length;
878-
879-
return uacpi_round_up_bits_to_bytes(bit_length);
880-
}
881-
882870
static uacpi_size sizeof_int(void)
883871
{
884872
return g_uacpi_rt_ctx.is_rev1 ? 4 : 8;
@@ -941,8 +929,9 @@ static void write_buffer_index(uacpi_buffer_index *buf_idx,
941929
* the specification. In reality, we just copy one buffer to another
942930
* because that's what NT does.
943931
*/
944-
static uacpi_status object_assign_with_implicit_cast(uacpi_object *dst,
945-
uacpi_object *src)
932+
static uacpi_status object_assign_with_implicit_cast(
933+
uacpi_object *dst, uacpi_object *src, uacpi_data_view *wtr_response
934+
)
946935
{
947936
uacpi_status ret;
948937
uacpi_data_view src_buf;
@@ -975,7 +964,8 @@ static uacpi_status object_assign_with_implicit_cast(uacpi_object *dst,
975964

976965
case UACPI_OBJECT_FIELD_UNIT:
977966
return uacpi_write_field_unit(
978-
dst->field_unit, src_buf.bytes, src_buf.length
967+
dst->field_unit, src_buf.bytes, src_buf.length,
968+
wtr_response
979969
);
980970

981971
case UACPI_OBJECT_BUFFER_INDEX:
@@ -2279,8 +2269,9 @@ static void object_replace_child(uacpi_object *parent, uacpi_object *new_child)
22792269
* 3. NAME -> Store with implicit cast.
22802270
* 4. RefOf -> Not allowed here.
22812271
*/
2282-
static uacpi_status store_to_reference(uacpi_object *dst,
2283-
uacpi_object *src)
2272+
static uacpi_status store_to_reference(
2273+
uacpi_object *dst, uacpi_object *src, uacpi_data_view *wtr_response
2274+
)
22842275
{
22852276
uacpi_object *src_obj;
22862277
uacpi_bool overwrite = UACPI_FALSE;
@@ -2335,7 +2326,9 @@ static uacpi_status store_to_reference(uacpi_object *dst,
23352326
return UACPI_STATUS_OK;
23362327
}
23372328

2338-
return object_assign_with_implicit_cast(dst->inner_object, src_obj);
2329+
return object_assign_with_implicit_cast(
2330+
dst->inner_object, src_obj, wtr_response
2331+
);
23392332
}
23402333

23412334
static uacpi_status handle_ref_or_deref_of(struct execution_context *ctx)
@@ -3769,48 +3762,69 @@ static uacpi_object_type buffer_field_get_read_type(
37693762
return UACPI_OBJECT_INTEGER;
37703763
}
37713764

3772-
static uacpi_object_type field_unit_get_read_type(
3773-
struct uacpi_field_unit *field
3765+
static uacpi_status field_get_read_type(
3766+
uacpi_object *obj, uacpi_object_type *out_type
37743767
)
37753768
{
3776-
if (field->bit_length > (g_uacpi_rt_ctx.is_rev1 ? 32u : 64u))
3777-
return UACPI_OBJECT_BUFFER;
3769+
if (obj->type == UACPI_OBJECT_BUFFER_FIELD) {
3770+
*out_type = buffer_field_get_read_type(&obj->buffer_field);
3771+
return UACPI_STATUS_OK;
3772+
}
37783773

3779-
return UACPI_OBJECT_INTEGER;
3774+
return uacpi_field_unit_get_read_type(obj->field_unit, out_type);
37803775
}
37813776

3782-
static uacpi_object_type field_get_read_type(uacpi_object *obj)
3777+
static uacpi_status field_byte_size(
3778+
uacpi_object *obj, uacpi_size *out_size
3779+
)
37833780
{
3784-
if (obj->type == UACPI_OBJECT_BUFFER_FIELD)
3785-
return buffer_field_get_read_type(&obj->buffer_field);
3781+
uacpi_size bit_length;
37863782

3787-
return field_unit_get_read_type(obj->field_unit);
3783+
if (obj->type == UACPI_OBJECT_BUFFER_FIELD) {
3784+
bit_length = obj->buffer_field.bit_length;
3785+
} else {
3786+
uacpi_status ret;
3787+
3788+
ret = uacpi_field_unit_get_bit_length(obj->field_unit, &bit_length);
3789+
if (uacpi_unlikely_error(ret))
3790+
return ret;
3791+
}
3792+
3793+
*out_size = uacpi_round_up_bits_to_bytes(bit_length);
3794+
return UACPI_STATUS_OK;
37883795
}
37893796

37903797
static uacpi_status handle_field_read(struct execution_context *ctx)
37913798
{
3799+
uacpi_status ret;
37923800
struct op_context *op_ctx = ctx->cur_op_ctx;
37933801
struct uacpi_namespace_node *node;
37943802
uacpi_object *src_obj, *dst_obj;
37953803
uacpi_size dst_size;
3796-
void *dst;
3804+
void *dst = UACPI_NULL;
3805+
uacpi_data_view wtr_response = { 0 };
37973806

37983807
node = item_array_at(&op_ctx->items, 0)->node;
37993808
src_obj = uacpi_namespace_node_get_object(node);
38003809
dst_obj = item_array_at(&op_ctx->items, 1)->obj;
38013810

3802-
if (field_get_read_type(src_obj) == UACPI_OBJECT_BUFFER) {
3811+
if (op_ctx->op->code == UACPI_AML_OP_InternalOpReadFieldAsBuffer) {
38033812
uacpi_buffer *buf;
38043813

3805-
buf = dst_obj->buffer;
3806-
dst_size = field_byte_size(src_obj);
3814+
ret = field_byte_size(src_obj, &dst_size);
3815+
if (uacpi_unlikely_error(ret))
3816+
return ret;
38073817

3808-
dst = uacpi_kernel_alloc_zeroed(dst_size);
3809-
if (dst == UACPI_NULL)
3810-
return UACPI_STATUS_OUT_OF_MEMORY;
3818+
if (dst_size != 0) {
3819+
buf = dst_obj->buffer;
3820+
3821+
dst = uacpi_kernel_alloc_zeroed(dst_size);
3822+
if (dst == UACPI_NULL)
3823+
return UACPI_STATUS_OUT_OF_MEMORY;
38113824

3812-
buf->data = dst;
3813-
buf->size = dst_size;
3825+
buf->data = dst;
3826+
buf->size = dst_size;
3827+
}
38143828
} else {
38153829
dst = &dst_obj->integer;
38163830
dst_size = sizeof(uacpi_u64);
@@ -3821,7 +3835,21 @@ static uacpi_status handle_field_read(struct execution_context *ctx)
38213835
return UACPI_STATUS_OK;
38223836
}
38233837

3824-
return uacpi_read_field_unit(src_obj->field_unit, dst, dst_size);
3838+
ret = uacpi_read_field_unit(
3839+
src_obj->field_unit, dst, dst_size, &wtr_response
3840+
);
3841+
if (uacpi_unlikely_error(ret))
3842+
return ret;
3843+
3844+
if (wtr_response.data != UACPI_NULL) {
3845+
uacpi_buffer *buf;
3846+
3847+
buf = dst_obj->buffer;
3848+
buf->data = wtr_response.data;
3849+
buf->size = wtr_response.length;
3850+
}
3851+
3852+
return ret;
38253853
}
38263854

38273855
static uacpi_status handle_create_buffer_field(struct execution_context *ctx)
@@ -4192,7 +4220,9 @@ static uacpi_bool maybe_end_block(struct execution_context *ctx)
41924220
return UACPI_TRUE;
41934221
}
41944222

4195-
static uacpi_status store_to_target(uacpi_object *dst, uacpi_object *src)
4223+
static uacpi_status store_to_target(
4224+
uacpi_object *dst, uacpi_object *src, uacpi_data_view *wtr_response
4225+
)
41964226
{
41974227
uacpi_status ret;
41984228

@@ -4201,12 +4231,12 @@ static uacpi_status store_to_target(uacpi_object *dst, uacpi_object *src)
42014231
ret = debug_store(src);
42024232
break;
42034233
case UACPI_OBJECT_REFERENCE:
4204-
ret = store_to_reference(dst, src);
4234+
ret = store_to_reference(dst, src, wtr_response);
42054235
break;
42064236

42074237
case UACPI_OBJECT_BUFFER_INDEX:
42084238
src = uacpi_unwrap_internal_reference(src);
4209-
ret = object_assign_with_implicit_cast(dst, src);
4239+
ret = object_assign_with_implicit_cast(dst, src, wtr_response);
42104240
break;
42114241

42124242
case UACPI_OBJECT_INTEGER:
@@ -4233,8 +4263,35 @@ static uacpi_status handle_copy_object_or_store(struct execution_context *ctx)
42334263
src = item_array_at(&op_ctx->items, 0)->obj;
42344264
dst = item_array_at(&op_ctx->items, 1)->obj;
42354265

4236-
if (op_ctx->op->code == UACPI_AML_OP_StoreOp)
4237-
return store_to_target(dst, src);
4266+
if (op_ctx->op->code == UACPI_AML_OP_StoreOp) {
4267+
uacpi_status ret;
4268+
uacpi_data_view wtr_response = { 0 };
4269+
4270+
ret = store_to_target(dst, src, &wtr_response);
4271+
if (uacpi_unlikely_error(ret))
4272+
return ret;
4273+
4274+
/*
4275+
* This was a write-then-read field access since we got a response
4276+
* buffer back from this store. Now we have to return this buffer
4277+
* as a prvalue from the StoreOp so that it can be used by AML to
4278+
* retrieve the response.
4279+
*/
4280+
if (wtr_response.data != UACPI_NULL) {
4281+
uacpi_object *wtr_response_obj;
4282+
4283+
wtr_response_obj = uacpi_object_create_buffer(wtr_response);
4284+
if (wtr_response_obj == UACPI_NULL) {
4285+
uacpi_free(wtr_response.data, wtr_response.length);
4286+
return UACPI_STATUS_OUT_OF_MEMORY;
4287+
}
4288+
4289+
uacpi_object_unref(src);
4290+
item_array_at(&op_ctx->items, 0)->obj = wtr_response_obj;
4291+
}
4292+
4293+
return ret;
4294+
}
42384295

42394296
if (dst->type != UACPI_OBJECT_REFERENCE)
42404297
return UACPI_STATUS_AML_INCOMPATIBLE_OBJECT_TYPE;
@@ -4279,13 +4336,16 @@ static uacpi_status handle_inc_dec(struct execution_context *ctx)
42794336
if (uacpi_unlikely(!field_allowed))
42804337
goto out_bad_type;
42814338

4282-
true_src_type = field_get_read_type(src);
4339+
ret = field_get_read_type(src, &true_src_type);
4340+
if (uacpi_unlikely_error(ret))
4341+
goto out_bad_type;
42834342
if (true_src_type != UACPI_OBJECT_INTEGER)
42844343
goto out_bad_type;
42854344

42864345
if (src->type == UACPI_OBJECT_FIELD_UNIT) {
42874346
ret = uacpi_read_field_unit(
4288-
src->field_unit, &dst->integer, sizeof_int()
4347+
src->field_unit, &dst->integer, sizeof_int(),
4348+
UACPI_NULL
42894349
);
42904350
if (uacpi_unlikely_error(ret))
42914351
return ret;
@@ -5497,7 +5557,7 @@ static uacpi_status exec_op(struct execution_context *ctx)
54975557
src = item->obj;
54985558
}
54995559

5500-
ret = store_to_target(dst, src);
5560+
ret = store_to_target(dst, src, UACPI_NULL);
55015561
break;
55025562
}
55035563

@@ -5589,11 +5649,28 @@ static uacpi_status exec_op(struct execution_context *ctx)
55895649
}
55905650

55915651
case UACPI_OBJECT_BUFFER_FIELD:
5592-
case UACPI_OBJECT_FIELD_UNIT:
5652+
case UACPI_OBJECT_FIELD_UNIT: {
5653+
uacpi_object_type type;
5654+
55935655
if (!op_wants_term_arg_or_operand(prev_op))
55945656
break;
55955657

5596-
switch (field_get_read_type(obj)) {
5658+
ret = field_get_read_type(obj, &type);
5659+
if (uacpi_unlikely_error(ret)) {
5660+
const uacpi_char *field_path;
5661+
5662+
field_path = uacpi_namespace_node_generate_absolute_path(
5663+
item->node
5664+
);
5665+
5666+
uacpi_error(
5667+
"unable to perform a read from field %s: "
5668+
"parent opregion gone\n", field_path
5669+
);
5670+
uacpi_free_absolute_path(field_path);
5671+
}
5672+
5673+
switch (type) {
55975674
case UACPI_OBJECT_BUFFER:
55985675
new_op = UACPI_AML_OP_InternalOpReadFieldAsBuffer;
55995676
break;
@@ -5605,6 +5682,7 @@ static uacpi_status exec_op(struct execution_context *ctx)
56055682
continue;
56065683
}
56075684
break;
5685+
}
56085686
default:
56095687
break;
56105688
}

0 commit comments

Comments
 (0)