ReactOS 0.4.16-dev-1946-g52006dd
opregion.c File Reference
Include dependency graph for opregion.c:

Go to the source code of this file.

Classes

struct  opregion_iter_ctx
 
struct  reg_run_ctx
 

Enumerations

enum  unreg { UNREG_NO = 0 , UNREG_YES }
 
enum  opregion_iter_action { OPREGION_ITER_ACTION_UNINSTALL , OPREGION_ITER_ACTION_INSTALL }
 

Functions

uacpi_status uacpi_initialize_opregion (void)
 
void uacpi_deinitialize_opregion (void)
 
void uacpi_trace_region_error (uacpi_namespace_node *node, uacpi_char *message, uacpi_status ret)
 
static void trace_region_io (uacpi_field_unit *field, uacpi_address_space space, uacpi_u64 offset, uacpi_region_op op, union uacpi_opregion_io_data data)
 
static uacpi_bool space_needs_reg (enum uacpi_address_space space)
 
static uacpi_status region_run_reg (uacpi_namespace_node *node, uacpi_u8 connection_code)
 
uacpi_address_space_handlersuacpi_node_get_address_space_handlers (uacpi_namespace_node *node)
 
static uacpi_address_space_handlerfind_handler (uacpi_address_space_handlers *handlers, enum uacpi_address_space space)
 
static uacpi_operation_regionfind_previous_region_link (uacpi_operation_region *region)
 
uacpi_status uacpi_opregion_attach (uacpi_namespace_node *node)
 
static void region_install_handler (uacpi_namespace_node *node, uacpi_address_space_handler *handler)
 
static void region_uninstall_handler (uacpi_namespace_node *node, enum unreg unreg)
 
static uacpi_status upgrade_to_opregion_lock (void)
 
void uacpi_opregion_uninstall_handler (uacpi_namespace_node *node)
 
uacpi_bool uacpi_address_space_handler_is_default (uacpi_address_space_handler *handler)
 
static uacpi_iteration_decision do_install_or_uninstall_handler (uacpi_handle opaque, uacpi_namespace_node *node, uacpi_u32 depth)
 
static uacpi_iteration_decision do_run_reg (void *opaque, uacpi_namespace_node *node, uacpi_u32 depth)
 
static uacpi_status reg_or_unreg_all_opregions (uacpi_namespace_node *device_node, enum uacpi_address_space space, uacpi_u8 connection_code)
 
static uacpi_address_space_handlersextract_handlers (uacpi_namespace_node *node)
 
uacpi_status uacpi_reg_all_opregions (uacpi_namespace_node *device_node, enum uacpi_address_space space)
 
uacpi_status uacpi_install_address_space_handler_with_flags (uacpi_namespace_node *device_node, enum uacpi_address_space space, uacpi_region_handler handler, uacpi_handle handler_context, uacpi_u16 flags)
 
uacpi_status uacpi_install_address_space_handler (uacpi_namespace_node *device_node, enum uacpi_address_space space, uacpi_region_handler handler, uacpi_handle handler_context)
 
uacpi_status uacpi_uninstall_address_space_handler (uacpi_namespace_node *device_node, enum uacpi_address_space space)
 
uacpi_status uacpi_initialize_opregion_node (uacpi_namespace_node *node)
 
uacpi_bool uacpi_is_buffer_access_address_space (uacpi_address_space space)
 
static uacpi_bool space_needs_bounds_checking (uacpi_address_space space)
 
uacpi_status uacpi_dispatch_opregion_io (uacpi_field_unit *field, uacpi_u32 offset, uacpi_region_op op, union uacpi_opregion_io_data data)
 

Variables

struct uacpi_recursive_lock g_opregion_lock
 

Enumeration Type Documentation

◆ opregion_iter_action

Enumerator
OPREGION_ITER_ACTION_UNINSTALL 
OPREGION_ITER_ACTION_INSTALL 

Definition at line 415 of file opregion.c.

415 {
418};
@ OPREGION_ITER_ACTION_UNINSTALL
Definition: opregion.c:416
@ OPREGION_ITER_ACTION_INSTALL
Definition: opregion.c:417

◆ unreg

Enumerator
UNREG_NO 
UNREG_YES 

Definition at line 311 of file opregion.c.

311 {
312 UNREG_NO = 0,
313 UNREG_YES,
314};
@ UNREG_YES
Definition: opregion.c:313
@ UNREG_NO
Definition: opregion.c:312

Function Documentation

◆ do_install_or_uninstall_handler()

static uacpi_iteration_decision do_install_or_uninstall_handler ( uacpi_handle  opaque,
uacpi_namespace_node node,
uacpi_u32  depth 
)
static

Definition at line 425 of file opregion.c.

428{
429 struct opregion_iter_ctx *ctx = opaque;
432
434
437 uacpi_operation_region *region = object->op_region;
438
439 if (region->space != ctx->handler->space)
441
442 if (ctx->action == OPREGION_ITER_ACTION_INSTALL) {
443 if (region->handler)
445
447 } else {
448 if (uacpi_unlikely(region->handler != ctx->handler)) {
450 node, "handler mismatch for",
452 );
454 }
455
457 }
458
460 }
461
463 if (handlers == UACPI_NULL)
465
466 // Device already has a handler for this space installed
467 if (find_handler(handlers, ctx->handler->space) != UACPI_NULL)
469
471}
#define UACPI_UNUSED(x)
Definition: helpers.h:7
uacpi_object * uacpi_namespace_node_get_object(const uacpi_namespace_node *node)
Definition: namespace.c:646
#define uacpi_unlikely(expr)
Definition: compiler.h:58
#define UACPI_NULL
Definition: types.h:33
@ UACPI_STATUS_INTERNAL_ERROR
Definition: status.h:21
@ UACPI_ITERATION_DECISION_NEXT_PEER
Definition: types.h:33
@ UACPI_ITERATION_DECISION_CONTINUE
Definition: types.h:29
@ UACPI_OBJECT_OPERATION_REGION
Definition: types.h:115
static xmlCharEncodingHandlerPtr * handlers
Definition: encoding.c:1317
GLint GLint GLsizei GLsizei GLsizei depth
Definition: gl.h:1546
static uacpi_address_space_handler * find_handler(uacpi_address_space_handlers *handlers, enum uacpi_address_space space)
Definition: opregion.c:193
void uacpi_trace_region_error(uacpi_namespace_node *node, uacpi_char *message, uacpi_status ret)
Definition: opregion.c:25
static void region_uninstall_handler(uacpi_namespace_node *node, enum unreg unreg)
Definition: opregion.c:316
static void region_install_handler(uacpi_namespace_node *node, uacpi_address_space_handler *handler)
Definition: opregion.c:297
uacpi_address_space_handlers * uacpi_node_get_address_space_handlers(uacpi_namespace_node *node)
Definition: opregion.c:170
uacpi_u16 space
Definition: types.h:120
uacpi_address_space_handler * handler
Definition: types.h:118
Definition: dlist.c:348

Referenced by uacpi_install_address_space_handler_with_flags(), and uacpi_uninstall_address_space_handler().

◆ do_run_reg()

static uacpi_iteration_decision do_run_reg ( void opaque,
uacpi_namespace_node node,
uacpi_u32  depth 
)
static

Definition at line 480 of file opregion.c.

483{
484 struct reg_run_ctx *ctx = opaque;
487 uacpi_bool was_regged;
488
490
492
493 if (region->space != ctx->space)
495
496 was_regged = region->state_flags & UACPI_OP_REGION_STATE_REG_EXECUTED;
497 if (was_regged == (ctx->connection_code == ACPI_REG_CONNECT))
499
500 ret = region_run_reg(node, ctx->connection_code);
501 if (ctx->connection_code == ACPI_REG_DISCONNECT)
502 region->state_flags &= ~UACPI_OP_REGION_STATE_REG_EXECUTED;
503
506
507 if (ctx->connection_code == ACPI_REG_CONNECT)
509
510 ctx->reg_executed++;
511
513 ctx->reg_errors++;
515 }
516
518}
#define ACPI_REG_CONNECT
Definition: actypes.h:890
#define ACPI_REG_DISCONNECT
Definition: actypes.h:889
#define UACPI_OP_REGION_STATE_REG_EXECUTED
Definition: types.h:111
bool uacpi_bool
Definition: types.h:31
#define uacpi_unlikely_error(expr)
Definition: status.h:49
uacpi_status
Definition: status.h:10
@ UACPI_STATUS_NOT_FOUND
Definition: status.h:17
return ret
Definition: mutex.c:146
static uacpi_status region_run_reg(uacpi_namespace_node *node, uacpi_u8 connection_code)
Definition: opregion.c:122
uacpi_operation_region * op_region
Definition: types.h:262
uacpi_u8 state_flags
Definition: types.h:121

Referenced by reg_or_unreg_all_opregions().

◆ extract_handlers()

static uacpi_address_space_handlers * extract_handlers ( uacpi_namespace_node node)
static

Definition at line 565 of file opregion.c.

568{
569 uacpi_object *handlers_obj;
570
571 if (node == uacpi_namespace_root())
572 return g_uacpi_rt_ctx.root_object->address_space_handlers;
573
575 node,
578 );
579 if (uacpi_unlikely(handlers_obj == UACPI_NULL))
580 return UACPI_NULL;
581
582 return handlers_obj->address_space_handlers;
583}
struct uacpi_runtime_context g_uacpi_rt_ctx
Definition: uacpi.c:17
uacpi_object * uacpi_namespace_node_get_object_typed(const uacpi_namespace_node *node, uacpi_object_type_bits type_mask)
Definition: namespace.c:654
uacpi_namespace_node * uacpi_namespace_root(void)
Definition: namespace.c:267
@ UACPI_OBJECT_PROCESSOR_BIT
Definition: types.h:140
@ UACPI_OBJECT_THERMAL_ZONE_BIT
Definition: types.h:141
@ UACPI_OBJECT_DEVICE_BIT
Definition: types.h:134
uacpi_address_space_handlers * address_space_handlers
Definition: types.h:266

Referenced by uacpi_install_address_space_handler_with_flags(), uacpi_reg_all_opregions(), and uacpi_uninstall_address_space_handler().

◆ find_handler()

static uacpi_address_space_handler * find_handler ( uacpi_address_space_handlers handlers,
enum uacpi_address_space  space 
)
static

Definition at line 193 of file opregion.c.

197{
199
200 while (handler) {
201 if (handler->space == space)
202 return handler;
203
204 handler = handler->next;
205 }
206
207 return UACPI_NULL;
208}
UINT(* handler)(MSIPACKAGE *)
Definition: action.c:7512

Referenced by do_install_or_uninstall_handler(), reg_or_unreg_all_opregions(), uacpi_initialize_opregion_node(), uacpi_install_address_space_handler_with_flags(), and uacpi_uninstall_address_space_handler().

◆ find_previous_region_link()

static uacpi_operation_region * find_previous_region_link ( uacpi_operation_region region)
static

Definition at line 210 of file opregion.c.

213{
216
217 if (parent == region)
218 // This is the last attached region, it has no previous link
219 return region;
220
221 while (parent->next != region) {
222 parent = parent->next;
223
225 return UACPI_NULL;
226 }
227
228 return parent;
229}
r parent
Definition: btrfs.c:3010

Referenced by region_uninstall_handler().

◆ reg_or_unreg_all_opregions()

static uacpi_status reg_or_unreg_all_opregions ( uacpi_namespace_node device_node,
enum uacpi_address_space  space,
uacpi_u8  connection_code 
)
static

Definition at line 520 of file opregion.c.

524{
526 uacpi_bool is_connect;
527 enum uacpi_permanent_only perm_only;
528 struct reg_run_ctx ctx = {
529 .space = space,
530 .connection_code = connection_code,
531 };
532
536
537 is_connect = connection_code == ACPI_REG_CONNECT;
538 if (uacpi_unlikely(is_connect &&
541
542 /*
543 * We want to unreg non-permanent opregions as well, however,
544 * registering them is handled separately and should not be
545 * done by us.
546 */
547 perm_only = is_connect ? UACPI_PERMANENT_ONLY_YES : UACPI_PERMANENT_ONLY_NO;
548
550 device_node, do_run_reg, UACPI_NULL,
552 UACPI_SHOULD_LOCK_NO, perm_only, &ctx
553 );
554
556 "%sactivated all '%s' opregions controlled by '%.4s', "
557 "%zu _REG() calls (%zu errors)\n",
558 connection_code == ACPI_REG_CONNECT ? "" : "de",
560 device_node->name.text, ctx.reg_executed, ctx.reg_errors
561 );
562 return UACPI_STATUS_OK;
563}
#define uacpi_trace(...)
Definition: log.h:18
uacpi_status uacpi_namespace_do_for_each_child(uacpi_namespace_node *parent, uacpi_iteration_callback descending_callback, uacpi_iteration_callback ascending_callback, uacpi_object_type_bits, uacpi_u32 max_depth, enum uacpi_should_lock, enum uacpi_permanent_only, void *user)
Definition: namespace.c:834
uacpi_permanent_only
Definition: namespace.h:90
@ UACPI_PERMANENT_ONLY_YES
Definition: namespace.h:92
@ UACPI_PERMANENT_ONLY_NO
Definition: namespace.h:91
@ UACPI_SHOULD_LOCK_NO
Definition: namespace.h:96
#define UACPI_MAX_DEPTH_ANY
Definition: namespace.h:102
@ UACPI_STATUS_INVALID_ARGUMENT
Definition: status.h:18
@ UACPI_STATUS_OK
Definition: status.h:11
@ UACPI_STATUS_NO_HANDLER
Definition: status.h:25
const uacpi_char * uacpi_address_space_to_string(uacpi_address_space space)
Definition: types.c:11
@ UACPI_OBJECT_OPERATION_REGION_BIT
Definition: types.h:138
static uacpi_iteration_decision do_run_reg(void *opaque, uacpi_namespace_node *node, uacpi_u32 depth)
Definition: opregion.c:480
uacpi_u8 space
Definition: opregion.c:474
uacpi_u8 connection_code
Definition: opregion.c:475
uacpi_object_name name
Definition: namespace.h:31
uacpi_char text[4]
Definition: types.h:24

Referenced by uacpi_install_address_space_handler_with_flags(), uacpi_reg_all_opregions(), and uacpi_uninstall_address_space_handler().

◆ region_install_handler()

static void region_install_handler ( uacpi_namespace_node node,
uacpi_address_space_handler handler 
)
static

Definition at line 297 of file opregion.c.

300{
302
304 region->handler = handler;
306
307 region->next = handler->regions;
308 handler->regions = region;
309}
uacpi_u32 uacpi_shareable_ref(uacpi_handle)
Definition: shareable.c:31
struct uacpi_operation_region * next
Definition: types.h:134

Referenced by do_install_or_uninstall_handler(), and uacpi_initialize_opregion_node().

◆ region_run_reg()

static uacpi_status region_run_reg ( uacpi_namespace_node node,
uacpi_u8  connection_code 
)
static

Definition at line 122 of file opregion.c.

125{
127 uacpi_namespace_node *reg_node;
128 uacpi_object_array method_args;
129 uacpi_object *reg_obj, *args[2];
130
132 node->parent, "_REG", UACPI_SHOULD_LOCK_NO,
134 );
136 return ret;
137
140 );
141 if (uacpi_unlikely(reg_obj == UACPI_NULL))
142 return UACPI_STATUS_OK;
143
145 if (uacpi_unlikely(args[0] == UACPI_NULL))
147
149 if (uacpi_unlikely(args[1] == UACPI_NULL)) {
152 }
153
155 args[1]->integer = connection_code;
156 method_args.objects = args;
157 method_args.count = 2;
158
160 reg_node, reg_obj->method, &method_args, UACPI_NULL
161 );
163 uacpi_trace_region_error(node, "error during _REG execution for", ret);
164
167 return ret;
168}
@ UACPI_MAY_SEARCH_ABOVE_PARENT_NO
Definition: namespace.h:86
uacpi_status uacpi_namespace_node_resolve(uacpi_namespace_node *scope, const uacpi_char *path, enum uacpi_should_lock, enum uacpi_may_search_above_parent, enum uacpi_permanent_only, uacpi_namespace_node **out_node)
Definition: namespace.c:491
uacpi_object * uacpi_create_object(uacpi_object_type type)
Definition: types.c:327
@ UACPI_STATUS_OUT_OF_MEMORY
Definition: status.h:13
@ UACPI_OBJECT_METHOD_BIT
Definition: types.h:136
@ UACPI_OBJECT_INTEGER
Definition: types.h:106
void uacpi_object_unref(uacpi_object *obj)
Definition: types.c:755
uacpi_status uacpi_execute_control_method(uacpi_namespace_node *scope, uacpi_control_method *method, const uacpi_object_array *args, uacpi_object **ret)
Definition: interpreter.c:5934
#define args
Definition: format.c:66
Definition: match.c:390
uacpi_object ** objects
Definition: types.h:284
uacpi_size count
Definition: types.h:285
uacpi_control_method * method
Definition: types.h:257

Referenced by do_run_reg(), region_uninstall_handler(), and uacpi_initialize_opregion_node().

◆ region_uninstall_handler()

static void region_uninstall_handler ( uacpi_namespace_node node,
enum unreg  unreg 
)
static

Definition at line 316 of file opregion.c.

319{
324
327 );
329 return;
330
331 region = obj->op_region;
332
333 handler = region->handler;
334 if (handler == UACPI_NULL)
335 return;
336
339 uacpi_error("operation region @%p not in the handler@%p list(?)\n",
340 region, handler);
341 goto out;
342 } else if (link == region) {
343 link = link->next;
344 handler->regions = link;
345 } else {
346 link->next = region->next;
347 }
348
349out:
351 uacpi_region_detach_data detach_data = {
352 .region_node = node,
353 .region_context = region->user_context,
354 .handler_context = handler->user_context,
355 };
356
359
360 ret = handler->callback(UACPI_REGION_OP_DETACH, &detach_data);
361
364
367 node, "error during handler detach for", ret
368 );
369 }
370 }
371
373 unreg == UNREG_YES) {
375 region->state_flags &= ~UACPI_OP_REGION_STATE_REG_EXECUTED;
376 }
377
379 region->handler = UACPI_NULL;
380 region->state_flags &= ~UACPI_OP_REGION_STATE_ATTACHED;
381}
const WCHAR * link
Definition: db.cpp:998
#define uacpi_error(...)
Definition: log.h:21
void uacpi_namespace_node_unref(uacpi_namespace_node *node)
Definition: namespace.c:297
uacpi_status uacpi_namespace_write_unlock(void)
Definition: namespace.c:54
uacpi_status uacpi_namespace_write_lock(void)
Definition: namespace.c:49
void uacpi_address_space_handler_unref(uacpi_address_space_handler *handler)
Definition: types.c:548
#define UACPI_OP_REGION_STATE_ATTACHED
Definition: types.h:114
@ UACPI_REGION_OP_DETACH
Definition: types.h:371
static uacpi_operation_region * find_previous_region_link(uacpi_operation_region *region)
Definition: opregion.c:210
unreg
Definition: opregion.c:311
uacpi_handle user_context
Definition: types.h:119
uacpi_namespace_node * region_node
Definition: types.h:501
wchar_t tm const _CrtWcstime_Writes_and_advances_ptr_ count wchar_t ** out
Definition: wcsftime.cpp:383

Referenced by do_install_or_uninstall_handler(), and uacpi_opregion_uninstall_handler().

◆ space_needs_bounds_checking()

static uacpi_bool space_needs_bounds_checking ( uacpi_address_space  space)
static

Definition at line 842 of file opregion.c.

843{
846}
@ UACPI_ADDRESS_SPACE_GENERAL_PURPOSE_IO
Definition: types.h:45
uacpi_bool uacpi_is_buffer_access_address_space(uacpi_address_space space)
Definition: opregion.c:828

Referenced by uacpi_dispatch_opregion_io().

◆ space_needs_reg()

static uacpi_bool space_needs_reg ( enum uacpi_address_space  space)
static

Definition at line 112 of file opregion.c.

113{
117 return UACPI_FALSE;
118
119 return UACPI_TRUE;
120}
#define UACPI_FALSE
Definition: types.h:30
#define UACPI_TRUE
Definition: types.h:29
@ UACPI_ADDRESS_SPACE_SYSTEM_MEMORY
Definition: types.h:37
@ UACPI_ADDRESS_SPACE_TABLE_DATA
Definition: types.h:52
@ UACPI_ADDRESS_SPACE_SYSTEM_IO
Definition: types.h:38

Referenced by uacpi_initialize_opregion_node(), uacpi_install_address_space_handler_with_flags(), uacpi_reg_all_opregions(), and uacpi_uninstall_address_space_handler().

◆ trace_region_io()

static void trace_region_io ( uacpi_field_unit field,
uacpi_address_space  space,
uacpi_u64  offset,
uacpi_region_op  op,
union uacpi_opregion_io_data  data 
)
static

Definition at line 47 of file opregion.c.

51{
52 const uacpi_char *path;
53 const uacpi_char *type_str;
54
56 return;
57
58 switch (op) {
60 type_str = "read from";
61 break;
63 type_str = "write to";
64 break;
65 default:
66 type_str = "<INVALID-OP>";
67 }
68
70
71 switch (space) {
76 "write-then-read from [%s] %s[0x%016"UACPI_PRIX64"] = "
77 "<buffer of %zu bytes>\n", path,
79 UACPI_FMT64(offset), data.buffer.length
80 );
81 break;
85 "%s [%s] %s[0x%016"UACPI_PRIX64"] = "
86 "<buffer of %zu bytes>\n", type_str, path,
88 UACPI_FMT64(offset), data.buffer.length
89 );
90 break;
93 "%s [%s] %s pins[%u..%u] = 0x%"UACPI_PRIX64"\n",
95 field->pin_offset, (field->pin_offset + field->bit_length) - 1,
96 UACPI_FMT64(*data.integer)
97 );
98 break;
99 default:
101 "%s [%s] (%d bytes) %s[0x%016"UACPI_PRIX64"] = 0x%"UACPI_PRIX64"\n",
102 type_str, path, field->access_width_bytes,
105 );
106 break;
107 }
108
110}
UINT op
Definition: effect.c:236
static uacpi_bool uacpi_should_log(enum uacpi_log_level lvl)
Definition: context.h:95
@ UACPI_LOG_TRACE
Definition: log.h:18
const uacpi_char * uacpi_namespace_node_generate_absolute_path(const uacpi_namespace_node *node)
Definition: namespace.c:1034
#define UACPI_PRIX64
Definition: types.h:61
char uacpi_char
Definition: types.h:44
#define UACPI_FMT64(val)
Definition: types.h:62
@ UACPI_REGION_OP_WRITE
Definition: types.h:375
@ UACPI_REGION_OP_READ
Definition: types.h:374
@ UACPI_ADDRESS_SPACE_IPMI
Definition: types.h:44
@ UACPI_ADDRESS_SPACE_PRM
Definition: types.h:48
@ UACPI_ADDRESS_SPACE_FFIXEDHW
Definition: types.h:49
@ UACPI_ADDRESS_SPACE_GENERIC_SERIAL_BUS
Definition: types.h:46
@ UACPI_ADDRESS_SPACE_SMBUS
Definition: types.h:41
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLintptr offset
Definition: glext.h:5920
void uacpi_free_dynamic_string(const uacpi_char *str)
Definition: utilities.c:1135
Definition: parser.c:44

Referenced by uacpi_dispatch_opregion_io().

◆ uacpi_address_space_handler_is_default()

uacpi_bool uacpi_address_space_handler_is_default ( uacpi_address_space_handler handler)

Definition at line 408 of file opregion.c.

411{
413}
#define UACPI_ADDRESS_SPACE_HANDLER_DEFAULT
Definition: types.h:73

Referenced by uacpi_namespace_initialize().

◆ uacpi_deinitialize_opregion()

void uacpi_deinitialize_opregion ( void  )

Definition at line 20 of file opregion.c.

21{
23}
uacpi_status uacpi_recursive_lock_deinit(struct uacpi_recursive_lock *lock)
Definition: mutex.c:267
struct uacpi_recursive_lock g_opregion_lock
Definition: opregion.c:13

Referenced by uacpi_state_reset().

◆ uacpi_dispatch_opregion_io()

uacpi_status uacpi_dispatch_opregion_io ( uacpi_field_unit field,
uacpi_u32  offset,
uacpi_region_op  op,
union uacpi_opregion_io_data  data 
)

Definition at line 848 of file opregion.c.

852{
858 uacpi_u64 abs_offset, offset_end = offset;
859 uacpi_bool is_oob = UACPI_FALSE;
860 uacpi_region_op orig_op = op;
861
862 union {
870 } handler_data;
871
874 return ret;
875
879 field->region, "unable to attach", ret
880 );
881 goto out;
882 }
883
886 );
887 if (uacpi_unlikely(obj == UACPI_NULL)) {
889 goto out;
890 }
891
892 region = obj->op_region;
893 space = region->space;
894 handler = region->handler;
895
896 abs_offset = region->offset + offset;
897 offset_end += field->access_width_bytes;
898
900 is_oob = region->length < offset_end || abs_offset < offset;
901 if (uacpi_unlikely(is_oob)) {
902 const uacpi_char *path;
903
906 "out-of-bounds access to opregion %s[0x%"UACPI_PRIX64"->"
907 "0x%"UACPI_PRIX64"] at 0x%"UACPI_PRIX64" (idx=%u, width=%d)\n",
908 path, UACPI_FMT64(region->offset),
909 UACPI_FMT64(region->offset + region->length),
910 UACPI_FMT64(abs_offset), offset, field->access_width_bytes
911 );
914 goto out;
915 }
916
917 handler_data.rw.region_context = region->user_context;
918 handler_data.rw.handler_context = handler->user_context;
919
920 switch (region->space) {
923
924 cursor = region->internal_buffer + offset;
925
926 /*
927 * Reads from PCC just return the current contents of the internal
928 * buffer.
929 */
930 if (op == UACPI_REGION_OP_READ) {
932 data.integer, cursor, sizeof(*data.integer),
933 field->access_width_bytes
934 );
935 goto io_done;
936 }
937
938 uacpi_memcpy(cursor, data.integer, field->access_width_bytes);
939
940 /*
941 * Dispatch a PCC send command if this was a write to the command field
942 *
943 * ACPI 6.5: 14.3. Extended PCC Subspace Shared Memory Region
944 */
945 if (offset >= 12 && offset < 16) {
946 handler_data.pcc.buffer = (uacpi_data_view){
947 .bytes = region->internal_buffer,
948 .length = region->length,
949 };
950
952 break;
953 }
954
955 // No dispatch needed, IO is done
956 goto io_done;
957 }
959 handler_data.gpio.pin_offset = field->pin_offset;
960 handler_data.gpio.num_pins = field->bit_length;
961 handler_data.gpio.value = *data.integer;
962
964 field->connection, &handler_data.gpio.connection
965 );
967 goto io_done;
968
971 break;
973 handler_data.ipmi.in_out_message = data.buffer;
974 handler_data.ipmi.command = abs_offset;
976 break;
978 handler_data.ffixedhw.in_out_message = data.buffer;
979 handler_data.ffixedhw.command = abs_offset;
981 break;
983 handler_data.prm.in_out_message = data.buffer;
985 break;
989 field->connection, &handler_data.serial.connection
990 );
992 goto io_done;
993
994 handler_data.serial.command = abs_offset;
995 handler_data.serial.in_out_buffer = data.buffer;
996 handler_data.serial.access_attribute = field->attributes;
997
998 switch (field->attributes) {
1002 handler_data.serial.access_length = field->access_length;
1003 break;
1004 default:
1005 handler_data.serial.access_length = 0;
1006 }
1007
1010 break;
1011 default:
1012 handler_data.rw.byte_width = field->access_width_bytes;
1013 handler_data.rw.offset = abs_offset;
1014 handler_data.rw.value = *data.integer;
1015 break;
1016 }
1017
1020
1021 ret = handler->callback(op, &handler_data);
1022
1025
1026io_done:
1028 uacpi_trace_region_error(field->region, "unable to perform IO", ret);
1029 goto out;
1030 }
1031
1032 if (orig_op == UACPI_REGION_OP_READ) {
1033 switch (region->space) {
1040 break;
1042 *data.integer = handler_data.gpio.value;
1043 break;
1044 default:
1045 *data.integer = handler_data.rw.value;
1046 break;
1047 }
1048 }
1049
1050 trace_region_io(field, space, abs_offset, orig_op, data);
1051
1052out:
1054 return ret;
1055}
uacpi_status uacpi_recursive_lock_release(struct uacpi_recursive_lock *lock)
Definition: mutex.c:307
#define uacpi_memcpy
Definition: stdlib.h:34
void uacpi_memcpy_zerout(void *dst, const void *src, uacpi_size dst_size, uacpi_size src_size)
Definition: stdlib.c:112
#define uacpi_likely(expr)
Definition: compiler.h:59
uint64_t uacpi_u64
Definition: types.h:22
uint8_t uacpi_u8
Definition: types.h:19
@ UACPI_STATUS_AML_OUT_OF_BOUNDS_INDEX
Definition: status.h:40
void uacpi_object_ref(uacpi_object *obj)
Definition: types.c:727
@ UACPI_ACCESS_ATTRIBUTE_RAW_BYTES
Definition: types.h:477
@ UACPI_ACCESS_ATTRIBUTE_RAW_PROCESS_BYTES
Definition: types.h:478
@ UACPI_ACCESS_ATTRIBUTE_BYTES
Definition: types.h:474
uacpi_region_op
Definition: types.h:367
@ UACPI_REGION_OP_FFIXEDHW_COMMAND
Definition: types.h:388
@ UACPI_REGION_OP_PCC_SEND
Definition: types.h:378
@ UACPI_REGION_OP_GPIO_READ
Definition: types.h:381
@ UACPI_REGION_OP_SERIAL_WRITE
Definition: types.h:395
@ UACPI_REGION_OP_PRM_COMMAND
Definition: types.h:391
@ UACPI_REGION_OP_GPIO_WRITE
Definition: types.h:382
@ UACPI_REGION_OP_SERIAL_READ
Definition: types.h:394
@ UACPI_REGION_OP_IPMI_COMMAND
Definition: types.h:385
uacpi_address_space
Definition: types.h:36
@ UACPI_ADDRESS_SPACE_PCC
Definition: types.h:47
uacpi_status uacpi_object_get_string_or_buffer(uacpi_object *, uacpi_data_view *out)
Definition: types.c:1050
uint32_t serial
Definition: fsck.fat.h:29
const char cursor[]
Definition: icontest.c:13
static void trace_region_io(uacpi_field_unit *field, uacpi_address_space space, uacpi_u64 offset, uacpi_region_op op, union uacpi_opregion_io_data data)
Definition: opregion.c:47
static uacpi_bool space_needs_bounds_checking(uacpi_address_space space)
Definition: opregion.c:842
uacpi_status uacpi_opregion_attach(uacpi_namespace_node *node)
Definition: opregion.c:231
static uacpi_status upgrade_to_opregion_lock(void)
Definition: opregion.c:383
#define rw
Definition: rosglue.h:38
uacpi_u64 offset
Definition: types.h:122
uacpi_u8 * internal_buffer
Definition: types.h:130
uacpi_u64 length
Definition: types.h:123

Referenced by access_field_unit().

◆ uacpi_initialize_opregion()

uacpi_status uacpi_initialize_opregion ( void  )

Definition at line 15 of file opregion.c.

16{
18}
uacpi_status uacpi_recursive_lock_init(struct uacpi_recursive_lock *lock)
Definition: mutex.c:255

Referenced by uacpi_initialize().

◆ uacpi_initialize_opregion_node()

uacpi_status uacpi_initialize_opregion_node ( uacpi_namespace_node node)

Definition at line 783 of file opregion.c.

784{
790
793 return ret;
794
797
798 while (parent) {
800 if (handlers != UACPI_NULL) {
802
803 if (handler != UACPI_NULL) {
806 break;
807 }
808 }
809
810 parent = parent->parent;
811 }
812
813 if (ret != UACPI_STATUS_OK)
814 goto out;
815 if (!space_needs_reg(region->space))
816 goto out;
818 goto out;
819
822
823out:
825 return ret;
826}
@ UACPI_INIT_LEVEL_NAMESPACE_LOADED
Definition: types.h:72
static uacpi_bool space_needs_reg(enum uacpi_address_space space)
Definition: opregion.c:112
uacpi_init_level uacpi_get_current_init_level(void)
Definition: uacpi.c:300

Referenced by handle_create_data_region(), and handle_create_op_region().

◆ uacpi_install_address_space_handler()

uacpi_status uacpi_install_address_space_handler ( uacpi_namespace_node device_node,
enum uacpi_address_space  space,
uacpi_region_handler  handler,
uacpi_handle  handler_context 
)

Definition at line 701 of file opregion.c.

705{
707 device_node, space, handler, handler_context, 0
708 );
709}
uacpi_status uacpi_install_address_space_handler_with_flags(uacpi_namespace_node *device_node, enum uacpi_address_space space, uacpi_region_handler handler, uacpi_handle handler_context, uacpi_u16 flags)
Definition: opregion.c:620

◆ uacpi_install_address_space_handler_with_flags()

uacpi_status uacpi_install_address_space_handler_with_flags ( uacpi_namespace_node device_node,
enum uacpi_address_space  space,
uacpi_region_handler  handler,
uacpi_handle  handler_context,
uacpi_u16  flags 
)

Definition at line 620 of file opregion.c.

625{
628 uacpi_address_space_handler *this_handler, *new_handler;
629 struct opregion_iter_ctx iter_ctx;
630
633 return ret;
634
638 return ret;
639 }
640
641 handlers = extract_handlers(device_node);
644 goto out;
645 }
646
647 this_handler = find_handler(handlers, space);
648 if (this_handler != UACPI_NULL) {
650 goto out;
651 }
652
653 new_handler = uacpi_kernel_alloc(sizeof(*new_handler));
654 if (new_handler == UACPI_NULL) {
656 goto out;
657 }
658 uacpi_shareable_init(new_handler);
659
660 new_handler->next = handlers->head;
661 new_handler->space = space;
662 new_handler->user_context = handler_context;
663 new_handler->callback = handler;
664 new_handler->regions = UACPI_NULL;
665 new_handler->flags = flags;
666 handlers->head = new_handler;
667
668 iter_ctx.handler = new_handler;
669 iter_ctx.action = OPREGION_ITER_ACTION_INSTALL;
670
674 UACPI_PERMANENT_ONLY_YES, &iter_ctx
675 );
676
678 goto out;
679
680 /*
681 * Installing an early address space handler, obviously not possible to
682 * execute any _REG methods here. Just return and hope that it is either
683 * a global address space handler, or a handler installed by a user who
684 * will run uacpi_reg_all_opregions manually after loading/initializing
685 * the namespace.
686 */
688 goto out;
689
690 // Init level is NAMESPACE_INITIALIZED, so we can safely run _REG now
692 device_node, space, ACPI_REG_CONNECT
693 );
694
695out:
698 return ret;
699}
uacpi_status uacpi_recursive_lock_acquire(struct uacpi_recursive_lock *lock)
Definition: mutex.c:287
@ UACPI_STATUS_ALREADY_EXISTS
Definition: status.h:20
@ UACPI_OBJECT_ANY_BIT
Definition: types.h:146
GLbitfield flags
Definition: glext.h:7161
void * uacpi_kernel_alloc(uacpi_size size)
Definition: uacpiosl.c:111
static uacpi_status reg_or_unreg_all_opregions(uacpi_namespace_node *device_node, enum uacpi_address_space space, uacpi_u8 connection_code)
Definition: opregion.c:520
static uacpi_iteration_decision do_install_or_uninstall_handler(uacpi_handle opaque, uacpi_namespace_node *node, uacpi_u32 depth)
Definition: opregion.c:425
static uacpi_address_space_handlers * extract_handlers(uacpi_namespace_node *node)
Definition: opregion.c:565
void uacpi_shareable_init(uacpi_handle)
Definition: shareable.c:9
uacpi_region_handler callback
Definition: types.h:67
uacpi_handle user_context
Definition: types.h:68
struct uacpi_address_space_handler * next
Definition: types.h:69
struct uacpi_operation_region * regions
Definition: types.h:70

Referenced by uacpi_install_address_space_handler(), and uacpi_install_default_address_space_handlers().

◆ uacpi_is_buffer_access_address_space()

uacpi_bool uacpi_is_buffer_access_address_space ( uacpi_address_space  space)

Definition at line 828 of file opregion.c.

829{
830 switch (space) {
836 return UACPI_TRUE;
837 default:
838 return UACPI_FALSE;
839 }
840}

Referenced by space_needs_bounds_checking(), uacpi_field_unit_get_bit_length(), and uacpi_field_unit_get_read_type().

◆ uacpi_node_get_address_space_handlers()

uacpi_address_space_handlers * uacpi_node_get_address_space_handlers ( uacpi_namespace_node node)

Definition at line 170 of file opregion.c.

173{
175
176 if (node == uacpi_namespace_root())
177 return g_uacpi_rt_ctx.root_object->address_space_handlers;
178
180 if (uacpi_unlikely(object == UACPI_NULL))
181 return UACPI_NULL;
182
183 switch (object->type) {
187 return object->address_space_handlers;
188 default:
189 return UACPI_NULL;
190 }
191}
@ UACPI_OBJECT_PROCESSOR
Definition: types.h:117
@ UACPI_OBJECT_DEVICE
Definition: types.h:111
@ UACPI_OBJECT_THERMAL_ZONE
Definition: types.h:118

Referenced by do_install_or_uninstall_handler(), reg_or_unreg_all_opregions(), uacpi_initialize_opregion_node(), and uacpi_namespace_initialize().

◆ uacpi_opregion_attach()

uacpi_status uacpi_opregion_attach ( uacpi_namespace_node node)

Definition at line 231 of file opregion.c.

232{
237 uacpi_region_attach_data attach_data = { 0 };
238
241
244 );
247
248 region = obj->op_region;
249
250 if (region->handler == UACPI_NULL)
253 return UACPI_STATUS_OK;
254
255 handler = region->handler;
256 attach_data.region_node = node;
257
258 switch (region->space) {
260 if (region->length) {
264 }
265
266 attach_data.pcc_info.buffer.bytes = region->internal_buffer;
267 attach_data.pcc_info.buffer.length = region->length;
268 attach_data.pcc_info.subspace_id = region->offset;
269 break;
271 attach_data.gpio_info.num_pins = region->length;
272 break;
273 default:
274 attach_data.generic_info.base = region->offset;
275 attach_data.generic_info.length = region->length;
276 break;
277 }
278
279 attach_data.handler_context = handler->user_context;
280
283 ret = handler->callback(UACPI_REGION_OP_ATTACH, &attach_data);
285
288 return ret;
289 }
290
292 region->user_context = attach_data.out_region_context;
294 return ret;
295}
uacpi_bool uacpi_namespace_node_is_dangling(uacpi_namespace_node *node)
Definition: namespace.c:336
#define uacpi_kernel_alloc_zeroed
Definition: stdlib.h:127
@ UACPI_STATUS_NAMESPACE_NODE_DANGLING
Definition: status.h:24
@ UACPI_REGION_OP_ATTACH
Definition: types.h:369
uacpi_size length
Definition: types.h:99
uacpi_u8 * bytes
Definition: types.h:90
uacpi_u64 num_pins
Definition: types.h:410
uacpi_data_view buffer
Definition: types.h:404
uacpi_u8 subspace_id
Definition: types.h:405
void * out_region_context
Definition: types.h:421
uacpi_gpio_region_info gpio_info
Definition: types.h:419
uacpi_pcc_region_info pcc_info
Definition: types.h:418
uacpi_namespace_node * region_node
Definition: types.h:415
uacpi_generic_region_info generic_info
Definition: types.h:417

Referenced by uacpi_dispatch_opregion_io().

◆ uacpi_opregion_uninstall_handler()

void uacpi_opregion_uninstall_handler ( uacpi_namespace_node node)

◆ uacpi_reg_all_opregions()

uacpi_status uacpi_reg_all_opregions ( uacpi_namespace_node device_node,
enum uacpi_address_space  space 
)

Definition at line 585 of file opregion.c.

Referenced by uacpi_namespace_initialize().

◆ uacpi_trace_region_error()

void uacpi_trace_region_error ( uacpi_namespace_node node,
uacpi_char message,
uacpi_status  ret 
)

Definition at line 25 of file opregion.c.

28{
29 const uacpi_char *path, *space_string = "<unknown>";
31
33
36 );
38 space_string = uacpi_address_space_to_string(obj->op_region->space);
39
41 "%s (%s) operation region %s: %s\n",
42 message, space_string, path, uacpi_status_to_string(ret)
43 );
45}
const uacpi_char * uacpi_status_to_string(uacpi_status)
Definition: uacpi.c:50
Definition: tftpd.h:60

Referenced by do_install_or_uninstall_handler(), find_pci_root(), handle_special_field(), io_region_attach(), memory_region_attach(), pci_region_attach(), region_run_reg(), region_uninstall_handler(), and uacpi_dispatch_opregion_io().

◆ uacpi_uninstall_address_space_handler()

uacpi_status uacpi_uninstall_address_space_handler ( uacpi_namespace_node device_node,
enum uacpi_address_space  space 
)

Definition at line 711 of file opregion.c.

715{
719 struct opregion_iter_ctx iter_ctx;
720
723 return ret;
724
728 return ret;
729 }
730
731 handlers = extract_handlers(device_node);
734 goto out;
735 }
736
740 goto out;
741 }
742
743 iter_ctx.handler = handler;
744 iter_ctx.action = OPREGION_ITER_ACTION_UNINSTALL;
745
749 UACPI_PERMANENT_ONLY_NO, &iter_ctx
750 );
751
752 prev_handler = handlers->head;
753
754 // Are we the last linked handler?
755 if (prev_handler == handler) {
756 handlers->head = handler->next;
757 goto out_unreg;
758 }
759
760 // Nope, we're somewhere in the middle. Do a search.
761 while (prev_handler) {
762 if (prev_handler->next == handler) {
763 prev_handler->next = handler->next;
764 goto out;
765 }
766
767 prev_handler = prev_handler->next;
768 }
769
770out_unreg:
773
774out:
775 if (handler != UACPI_NULL)
777
780 return ret;
781}

◆ upgrade_to_opregion_lock()

static uacpi_status upgrade_to_opregion_lock ( void  )
static

Definition at line 383 of file opregion.c.

384{
386
387 /*
388 * Drop the namespace lock, and reacquire it after the opregion lock
389 * so we keep the ordering with user API.
390 */
392
395 return ret;
396}

Referenced by uacpi_dispatch_opregion_io(), uacpi_initialize_opregion_node(), and uacpi_opregion_uninstall_handler().

Variable Documentation

◆ g_opregion_lock