0001
0002
0003
0004
0005
0006
0007
0008 #include <acpi/acpi.h>
0009 #include "accommon.h"
0010 #include "acdispat.h"
0011 #include "acnamesp.h"
0012 #include "acdebug.h"
0013 #include "acparser.h"
0014 #include "acpredef.h"
0015
0016 #define _COMPONENT ACPI_CA_DEBUGGER
0017 ACPI_MODULE_NAME("dbmethod")
0018
0019
0020 static acpi_status
0021 acpi_db_walk_for_execute(acpi_handle obj_handle,
0022 u32 nesting_level, void *context, void **return_value);
0023
0024 static acpi_status acpi_db_evaluate_object(struct acpi_namespace_node *node);
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041 void
0042 acpi_db_set_method_breakpoint(char *location,
0043 struct acpi_walk_state *walk_state,
0044 union acpi_parse_object *op)
0045 {
0046 u32 address;
0047 u32 aml_offset;
0048
0049 if (!op) {
0050 acpi_os_printf("There is no method currently executing\n");
0051 return;
0052 }
0053
0054
0055
0056 address = strtoul(location, NULL, 16);
0057 aml_offset = (u32)ACPI_PTR_DIFF(op->common.aml,
0058 walk_state->parser_state.aml_start);
0059 if (address <= aml_offset) {
0060 acpi_os_printf("Breakpoint %X is beyond current address %X\n",
0061 address, aml_offset);
0062 }
0063
0064
0065
0066 walk_state->user_breakpoint = address;
0067 acpi_os_printf("Breakpoint set at AML offset %X\n", address);
0068 }
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083 void acpi_db_set_method_call_breakpoint(union acpi_parse_object *op)
0084 {
0085
0086 if (!op) {
0087 acpi_os_printf("There is no method currently executing\n");
0088 return;
0089 }
0090
0091 acpi_gbl_step_to_next_call = TRUE;
0092 }
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109 void acpi_db_set_method_data(char *type_arg, char *index_arg, char *value_arg)
0110 {
0111 char type;
0112 u32 index;
0113 u32 value;
0114 struct acpi_walk_state *walk_state;
0115 union acpi_operand_object *obj_desc;
0116 acpi_status status;
0117 struct acpi_namespace_node *node;
0118
0119
0120
0121 acpi_ut_strupr(type_arg);
0122 type = type_arg[0];
0123 if ((type != 'L') && (type != 'A') && (type != 'N')) {
0124 acpi_os_printf("Invalid SET operand: %s\n", type_arg);
0125 return;
0126 }
0127
0128 value = strtoul(value_arg, NULL, 16);
0129
0130 if (type == 'N') {
0131 node = acpi_db_convert_to_node(index_arg);
0132 if (!node) {
0133 return;
0134 }
0135
0136 if (node->type != ACPI_TYPE_INTEGER) {
0137 acpi_os_printf("Can only set Integer nodes\n");
0138 return;
0139 }
0140 obj_desc = node->object;
0141 obj_desc->integer.value = value;
0142 return;
0143 }
0144
0145
0146
0147 index = strtoul(index_arg, NULL, 16);
0148
0149 walk_state = acpi_ds_get_current_walk_state(acpi_gbl_current_walk_list);
0150 if (!walk_state) {
0151 acpi_os_printf("There is no method currently executing\n");
0152 return;
0153 }
0154
0155
0156
0157 obj_desc = acpi_ut_create_integer_object((u64)value);
0158 if (!obj_desc) {
0159 acpi_os_printf("Could not create an internal object\n");
0160 return;
0161 }
0162
0163
0164
0165 switch (type) {
0166 case 'A':
0167
0168
0169
0170 if (index > ACPI_METHOD_MAX_ARG) {
0171 acpi_os_printf("Arg%u - Invalid argument name\n",
0172 index);
0173 goto cleanup;
0174 }
0175
0176 status = acpi_ds_store_object_to_local(ACPI_REFCLASS_ARG,
0177 index, obj_desc,
0178 walk_state);
0179 if (ACPI_FAILURE(status)) {
0180 goto cleanup;
0181 }
0182
0183 obj_desc = walk_state->arguments[index].object;
0184
0185 acpi_os_printf("Arg%u: ", index);
0186 acpi_db_display_internal_object(obj_desc, walk_state);
0187 break;
0188
0189 case 'L':
0190
0191
0192
0193 if (index > ACPI_METHOD_MAX_LOCAL) {
0194 acpi_os_printf
0195 ("Local%u - Invalid local variable name\n", index);
0196 goto cleanup;
0197 }
0198
0199 status = acpi_ds_store_object_to_local(ACPI_REFCLASS_LOCAL,
0200 index, obj_desc,
0201 walk_state);
0202 if (ACPI_FAILURE(status)) {
0203 goto cleanup;
0204 }
0205
0206 obj_desc = walk_state->local_variables[index].object;
0207
0208 acpi_os_printf("Local%u: ", index);
0209 acpi_db_display_internal_object(obj_desc, walk_state);
0210 break;
0211
0212 default:
0213
0214 break;
0215 }
0216
0217 cleanup:
0218 acpi_ut_remove_reference(obj_desc);
0219 }
0220
0221 #ifdef ACPI_DISASSEMBLER
0222
0223
0224
0225
0226
0227
0228
0229
0230
0231
0232
0233
0234
0235
0236 void acpi_db_disassemble_aml(char *statements, union acpi_parse_object *op)
0237 {
0238 u32 num_statements = 8;
0239
0240 if (!op) {
0241 acpi_os_printf("There is no method currently executing\n");
0242 return;
0243 }
0244
0245 if (statements) {
0246 num_statements = strtoul(statements, NULL, 0);
0247 }
0248
0249 acpi_dm_disassemble(NULL, op, num_statements);
0250 }
0251
0252
0253
0254
0255
0256
0257
0258
0259
0260
0261
0262
0263
0264
0265 acpi_status acpi_db_disassemble_method(char *name)
0266 {
0267 acpi_status status;
0268 union acpi_parse_object *op;
0269 struct acpi_walk_state *walk_state;
0270 union acpi_operand_object *obj_desc;
0271 struct acpi_namespace_node *method;
0272
0273 method = acpi_db_convert_to_node(name);
0274 if (!method) {
0275 return (AE_BAD_PARAMETER);
0276 }
0277
0278 if (method->type != ACPI_TYPE_METHOD) {
0279 ACPI_ERROR((AE_INFO, "%s (%s): Object must be a control method",
0280 name, acpi_ut_get_type_name(method->type)));
0281 return (AE_BAD_PARAMETER);
0282 }
0283
0284 obj_desc = method->object;
0285
0286 op = acpi_ps_create_scope_op(obj_desc->method.aml_start);
0287 if (!op) {
0288 return (AE_NO_MEMORY);
0289 }
0290
0291
0292
0293 walk_state = acpi_ds_create_walk_state(0, op, NULL, NULL);
0294 if (!walk_state) {
0295 return (AE_NO_MEMORY);
0296 }
0297
0298 status = acpi_ds_init_aml_walk(walk_state, op, NULL,
0299 obj_desc->method.aml_start,
0300 obj_desc->method.aml_length, NULL,
0301 ACPI_IMODE_LOAD_PASS1);
0302 if (ACPI_FAILURE(status)) {
0303 return (status);
0304 }
0305
0306 status = acpi_ut_allocate_owner_id(&obj_desc->method.owner_id);
0307 if (ACPI_FAILURE(status)) {
0308 return (status);
0309 }
0310
0311 walk_state->owner_id = obj_desc->method.owner_id;
0312
0313
0314
0315 status = acpi_ds_scope_stack_push(method, method->type, walk_state);
0316 if (ACPI_FAILURE(status)) {
0317 return (status);
0318 }
0319
0320
0321
0322 walk_state->parse_flags &= ~ACPI_PARSE_DELETE_TREE;
0323 walk_state->parse_flags |= ACPI_PARSE_DISASSEMBLE;
0324
0325 status = acpi_ps_parse_aml(walk_state);
0326 if (ACPI_FAILURE(status)) {
0327 return (status);
0328 }
0329
0330 (void)acpi_dm_parse_deferred_ops(op);
0331
0332
0333
0334 acpi_gbl_dm_opt_verbose = FALSE;
0335 acpi_dm_disassemble(NULL, op, 0);
0336 acpi_gbl_dm_opt_verbose = TRUE;
0337
0338 acpi_ps_delete_parse_tree(op);
0339
0340
0341
0342 acpi_ns_delete_namespace_subtree(method);
0343 acpi_ns_delete_namespace_by_owner(obj_desc->method.owner_id);
0344 acpi_ut_release_owner_id(&obj_desc->method.owner_id);
0345 return (AE_OK);
0346 }
0347 #endif
0348
0349
0350
0351
0352
0353
0354
0355
0356
0357
0358
0359
0360
0361
0362 static acpi_status acpi_db_evaluate_object(struct acpi_namespace_node *node)
0363 {
0364 char *pathname;
0365 u32 i;
0366 struct acpi_device_info *obj_info;
0367 struct acpi_object_list param_objects;
0368 union acpi_object params[ACPI_METHOD_NUM_ARGS];
0369 struct acpi_buffer return_obj;
0370 acpi_status status;
0371
0372 pathname = acpi_ns_get_external_pathname(node);
0373 if (!pathname) {
0374 return (AE_OK);
0375 }
0376
0377
0378
0379 status = acpi_get_object_info(node, &obj_info);
0380 if (ACPI_FAILURE(status)) {
0381 ACPI_FREE(pathname);
0382 return (status);
0383 }
0384
0385 param_objects.pointer = NULL;
0386 param_objects.count = 0;
0387
0388 if (obj_info->type == ACPI_TYPE_METHOD) {
0389
0390
0391
0392 for (i = 0; i < obj_info->param_count; i++) {
0393 params[i].type = ACPI_TYPE_INTEGER;
0394 params[i].integer.value = 1;
0395 }
0396
0397 param_objects.pointer = params;
0398 param_objects.count = obj_info->param_count;
0399 }
0400
0401 ACPI_FREE(obj_info);
0402 return_obj.pointer = NULL;
0403 return_obj.length = ACPI_ALLOCATE_BUFFER;
0404
0405
0406
0407 acpi_gbl_method_executing = TRUE;
0408
0409 status = acpi_evaluate_object(node, NULL, ¶m_objects, &return_obj);
0410 acpi_gbl_method_executing = FALSE;
0411
0412 acpi_os_printf("%-32s returned %s\n", pathname,
0413 acpi_format_exception(status));
0414 if (return_obj.length) {
0415 acpi_os_printf("Evaluation of %s returned object %p, "
0416 "external buffer length %X\n",
0417 pathname, return_obj.pointer,
0418 (u32)return_obj.length);
0419
0420 acpi_db_dump_external_object(return_obj.pointer, 1);
0421 acpi_os_printf("\n");
0422 }
0423
0424 ACPI_FREE(pathname);
0425
0426
0427
0428 return (AE_OK);
0429
0430
0431
0432 }
0433
0434
0435
0436
0437
0438
0439
0440
0441
0442
0443
0444
0445
0446
0447 static acpi_status
0448 acpi_db_walk_for_execute(acpi_handle obj_handle,
0449 u32 nesting_level, void *context, void **return_value)
0450 {
0451 struct acpi_namespace_node *node =
0452 (struct acpi_namespace_node *)obj_handle;
0453 struct acpi_db_execute_walk *info =
0454 (struct acpi_db_execute_walk *)context;
0455 acpi_status status;
0456 const union acpi_predefined_info *predefined;
0457
0458 predefined = acpi_ut_match_predefined_method(node->name.ascii);
0459 if (!predefined) {
0460 return (AE_OK);
0461 }
0462
0463 if (node->type == ACPI_TYPE_LOCAL_SCOPE) {
0464 return (AE_OK);
0465 }
0466
0467 acpi_db_evaluate_object(node);
0468
0469
0470
0471 status = AE_OK;
0472
0473
0474
0475 info->count++;
0476 if (info->count >= info->max_count) {
0477 status = AE_CTRL_TERMINATE;
0478 }
0479
0480 return (status);
0481 }
0482
0483
0484
0485
0486
0487
0488
0489
0490
0491
0492
0493
0494
0495
0496 static acpi_status
0497 acpi_db_walk_for_execute_all(acpi_handle obj_handle,
0498 u32 nesting_level,
0499 void *context, void **return_value)
0500 {
0501 struct acpi_namespace_node *node =
0502 (struct acpi_namespace_node *)obj_handle;
0503 struct acpi_db_execute_walk *info =
0504 (struct acpi_db_execute_walk *)context;
0505 acpi_status status;
0506
0507 if (!ACPI_COMPARE_NAMESEG(node->name.ascii, info->name_seg)) {
0508 return (AE_OK);
0509 }
0510
0511 if (node->type == ACPI_TYPE_LOCAL_SCOPE) {
0512 return (AE_OK);
0513 }
0514
0515
0516
0517 acpi_db_evaluate_object(node);
0518
0519
0520
0521 status = AE_OK;
0522
0523
0524
0525 info->count++;
0526 return (status);
0527 }
0528
0529
0530
0531
0532
0533
0534
0535
0536
0537
0538
0539
0540
0541
0542 void acpi_db_evaluate_predefined_names(void)
0543 {
0544 struct acpi_db_execute_walk info;
0545
0546 info.count = 0;
0547 info.max_count = ACPI_UINT32_MAX;
0548
0549
0550
0551 (void)acpi_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
0552 ACPI_UINT32_MAX, acpi_db_walk_for_execute,
0553 NULL, (void *)&info, NULL);
0554
0555 acpi_os_printf("Evaluated %u predefined names in the namespace\n",
0556 info.count);
0557 }
0558
0559
0560
0561
0562
0563
0564
0565
0566
0567
0568
0569
0570
0571
0572
0573 void acpi_db_evaluate_all(char *name_seg)
0574 {
0575 struct acpi_db_execute_walk info;
0576
0577 info.count = 0;
0578 info.max_count = ACPI_UINT32_MAX;
0579 ACPI_COPY_NAMESEG(info.name_seg, name_seg);
0580 info.name_seg[ACPI_NAMESEG_SIZE] = 0;
0581
0582
0583
0584 (void)acpi_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
0585 ACPI_UINT32_MAX, acpi_db_walk_for_execute_all,
0586 NULL, (void *)&info, NULL);
0587
0588 acpi_os_printf("Evaluated %u names in the namespace\n", info.count);
0589 }