1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 2 /******************************************************************************* 3 * 4 * Module Name: dbutils - AML debugger utilities 5 * 6 ******************************************************************************/ 7 8 #include <acpi/acpi.h> 9 #include "accommon.h" 10 #include "acnamesp.h" 11 #include "acdebug.h" 12 13 #define _COMPONENT ACPI_CA_DEBUGGER 14 ACPI_MODULE_NAME("dbutils") 15 16 /* Local prototypes */ 17 #ifdef ACPI_OBSOLETE_FUNCTIONS 18 acpi_status acpi_db_second_pass_parse(union acpi_parse_object *root); 19 20 void acpi_db_dump_buffer(u32 address); 21 #endif 22 23 /******************************************************************************* 24 * 25 * FUNCTION: acpi_db_match_argument 26 * 27 * PARAMETERS: user_argument - User command line 28 * arguments - Array of commands to match against 29 * 30 * RETURN: Index into command array or ACPI_TYPE_NOT_FOUND if not found 31 * 32 * DESCRIPTION: Search command array for a command match 33 * 34 ******************************************************************************/ 35 36 acpi_object_type 37 acpi_db_match_argument(char *user_argument, 38 struct acpi_db_argument_info *arguments) 39 { 40 u32 i; 41 42 if (!user_argument || user_argument[0] == 0) { 43 return (ACPI_TYPE_NOT_FOUND); 44 } 45 46 for (i = 0; arguments[i].name; i++) { 47 if (strstr(ACPI_CAST_PTR(char, arguments[i].name), 48 ACPI_CAST_PTR(char, 49 user_argument)) == arguments[i].name) { 50 return (i); 51 } 52 } 53 54 /* Argument not recognized */ 55 56 return (ACPI_TYPE_NOT_FOUND); 57 } 58 59 /******************************************************************************* 60 * 61 * FUNCTION: acpi_db_set_output_destination 62 * 63 * PARAMETERS: output_flags - Current flags word 64 * 65 * RETURN: None 66 * 67 * DESCRIPTION: Set the current destination for debugger output. Also sets 68 * the debug output level accordingly. 69 * 70 ******************************************************************************/ 71 72 void acpi_db_set_output_destination(u32 output_flags) 73 { 74 75 acpi_gbl_db_output_flags = (u8)output_flags; 76 77 if ((output_flags & ACPI_DB_REDIRECTABLE_OUTPUT) && 78 acpi_gbl_db_output_to_file) { 79 acpi_dbg_level = acpi_gbl_db_debug_level; 80 } else { 81 acpi_dbg_level = acpi_gbl_db_console_debug_level; 82 } 83 } 84 85 /******************************************************************************* 86 * 87 * FUNCTION: acpi_db_dump_external_object 88 * 89 * PARAMETERS: obj_desc - External ACPI object to dump 90 * level - Nesting level. 91 * 92 * RETURN: None 93 * 94 * DESCRIPTION: Dump the contents of an ACPI external object 95 * 96 ******************************************************************************/ 97 98 void acpi_db_dump_external_object(union acpi_object *obj_desc, u32 level) 99 { 100 u32 i; 101 102 if (!obj_desc) { 103 acpi_os_printf("[Null Object]\n"); 104 return; 105 } 106 107 for (i = 0; i < level; i++) { 108 acpi_os_printf(" "); 109 } 110 111 switch (obj_desc->type) { 112 case ACPI_TYPE_ANY: 113 114 acpi_os_printf("[Null Object] (Type=0)\n"); 115 break; 116 117 case ACPI_TYPE_INTEGER: 118 119 acpi_os_printf("[Integer] = %8.8X%8.8X\n", 120 ACPI_FORMAT_UINT64(obj_desc->integer.value)); 121 break; 122 123 case ACPI_TYPE_STRING: 124 125 acpi_os_printf("[String] Length %.2X = ", 126 obj_desc->string.length); 127 acpi_ut_print_string(obj_desc->string.pointer, ACPI_UINT8_MAX); 128 acpi_os_printf("\n"); 129 break; 130 131 case ACPI_TYPE_BUFFER: 132 133 acpi_os_printf("[Buffer] Length %.2X = ", 134 obj_desc->buffer.length); 135 if (obj_desc->buffer.length) { 136 if (obj_desc->buffer.length > 16) { 137 acpi_os_printf("\n"); 138 } 139 140 acpi_ut_debug_dump_buffer(ACPI_CAST_PTR 141 (u8, 142 obj_desc->buffer.pointer), 143 obj_desc->buffer.length, 144 DB_BYTE_DISPLAY, _COMPONENT); 145 } else { 146 acpi_os_printf("\n"); 147 } 148 break; 149 150 case ACPI_TYPE_PACKAGE: 151 152 acpi_os_printf("[Package] Contains %u Elements:\n", 153 obj_desc->package.count); 154 155 for (i = 0; i < obj_desc->package.count; i++) { 156 acpi_db_dump_external_object(&obj_desc->package. 157 elements[i], level + 1); 158 } 159 break; 160 161 case ACPI_TYPE_LOCAL_REFERENCE: 162 163 acpi_os_printf("[Object Reference] = "); 164 acpi_db_display_internal_object(obj_desc->reference.handle, 165 NULL); 166 break; 167 168 case ACPI_TYPE_PROCESSOR: 169 170 acpi_os_printf("[Processor]\n"); 171 break; 172 173 case ACPI_TYPE_POWER: 174 175 acpi_os_printf("[Power Resource]\n"); 176 break; 177 178 default: 179 180 acpi_os_printf("[Unknown Type] %X\n", obj_desc->type); 181 break; 182 } 183 } 184 185 /******************************************************************************* 186 * 187 * FUNCTION: acpi_db_prep_namestring 188 * 189 * PARAMETERS: name - String to prepare 190 * 191 * RETURN: None 192 * 193 * DESCRIPTION: Translate all forward slashes and dots to backslashes. 194 * 195 ******************************************************************************/ 196 197 void acpi_db_prep_namestring(char *name) 198 { 199 200 if (!name) { 201 return; 202 } 203 204 acpi_ut_strupr(name); 205 206 /* Convert a leading forward slash to a backslash */ 207 208 if (*name == '/') { 209 *name = '\\'; 210 } 211 212 /* Ignore a leading backslash, this is the root prefix */ 213 214 if (ACPI_IS_ROOT_PREFIX(*name)) { 215 name++; 216 } 217 218 /* Convert all slash path separators to dots */ 219 220 while (*name) { 221 if ((*name == '/') || (*name == '\\')) { 222 *name = '.'; 223 } 224 225 name++; 226 } 227 } 228 229 /******************************************************************************* 230 * 231 * FUNCTION: acpi_db_local_ns_lookup 232 * 233 * PARAMETERS: name - Name to lookup 234 * 235 * RETURN: Pointer to a namespace node, null on failure 236 * 237 * DESCRIPTION: Lookup a name in the ACPI namespace 238 * 239 * Note: Currently begins search from the root. Could be enhanced to use 240 * the current prefix (scope) node as the search beginning point. 241 * 242 ******************************************************************************/ 243 244 struct acpi_namespace_node *acpi_db_local_ns_lookup(char *name) 245 { 246 char *internal_path; 247 acpi_status status; 248 struct acpi_namespace_node *node = NULL; 249 250 acpi_db_prep_namestring(name); 251 252 /* Build an internal namestring */ 253 254 status = acpi_ns_internalize_name(name, &internal_path); 255 if (ACPI_FAILURE(status)) { 256 acpi_os_printf("Invalid namestring: %s\n", name); 257 return (NULL); 258 } 259 260 /* 261 * Lookup the name. 262 * (Uses root node as the search starting point) 263 */ 264 status = acpi_ns_lookup(NULL, internal_path, ACPI_TYPE_ANY, 265 ACPI_IMODE_EXECUTE, 266 ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE, 267 NULL, &node); 268 if (ACPI_FAILURE(status)) { 269 acpi_os_printf("Could not locate name: %s, %s\n", 270 name, acpi_format_exception(status)); 271 } 272 273 ACPI_FREE(internal_path); 274 return (node); 275 } 276 277 /******************************************************************************* 278 * 279 * FUNCTION: acpi_db_uint32_to_hex_string 280 * 281 * PARAMETERS: value - The value to be converted to string 282 * buffer - Buffer for result (not less than 11 bytes) 283 * 284 * RETURN: None 285 * 286 * DESCRIPTION: Convert the unsigned 32-bit value to the hexadecimal image 287 * 288 * NOTE: It is the caller's responsibility to ensure that the length of buffer 289 * is sufficient. 290 * 291 ******************************************************************************/ 292 293 void acpi_db_uint32_to_hex_string(u32 value, char *buffer) 294 { 295 int i; 296 297 if (value == 0) { 298 strcpy(buffer, "0"); 299 return; 300 } 301 302 buffer[8] = '\0'; 303 304 for (i = 7; i >= 0; i--) { 305 buffer[i] = acpi_gbl_upper_hex_digits[value & 0x0F]; 306 value = value >> 4; 307 } 308 } 309 310 #ifdef ACPI_OBSOLETE_FUNCTIONS 311 /******************************************************************************* 312 * 313 * FUNCTION: acpi_db_second_pass_parse 314 * 315 * PARAMETERS: root - Root of the parse tree 316 * 317 * RETURN: Status 318 * 319 * DESCRIPTION: Second pass parse of the ACPI tables. We need to wait until 320 * second pass to parse the control methods 321 * 322 ******************************************************************************/ 323 324 acpi_status acpi_db_second_pass_parse(union acpi_parse_object *root) 325 { 326 union acpi_parse_object *op = root; 327 union acpi_parse_object *method; 328 union acpi_parse_object *search_op; 329 union acpi_parse_object *start_op; 330 acpi_status status = AE_OK; 331 u32 base_aml_offset; 332 struct acpi_walk_state *walk_state; 333 334 ACPI_FUNCTION_ENTRY(); 335 336 acpi_os_printf("Pass two parse ....\n"); 337 338 while (op) { 339 if (op->common.aml_opcode == AML_METHOD_OP) { 340 method = op; 341 342 /* Create a new walk state for the parse */ 343 344 walk_state = 345 acpi_ds_create_walk_state(0, NULL, NULL, NULL); 346 if (!walk_state) { 347 return (AE_NO_MEMORY); 348 } 349 350 /* Init the Walk State */ 351 352 walk_state->parser_state.aml = 353 walk_state->parser_state.aml_start = 354 method->named.data; 355 walk_state->parser_state.aml_end = 356 walk_state->parser_state.pkg_end = 357 method->named.data + method->named.length; 358 walk_state->parser_state.start_scope = op; 359 360 walk_state->descending_callback = 361 acpi_ds_load1_begin_op; 362 walk_state->ascending_callback = acpi_ds_load1_end_op; 363 364 /* Perform the AML parse */ 365 366 status = acpi_ps_parse_aml(walk_state); 367 368 base_aml_offset = 369 (method->common.value.arg)->common.aml_offset + 1; 370 start_op = (method->common.value.arg)->common.next; 371 search_op = start_op; 372 373 while (search_op) { 374 search_op->common.aml_offset += base_aml_offset; 375 search_op = 376 acpi_ps_get_depth_next(start_op, search_op); 377 } 378 } 379 380 if (op->common.aml_opcode == AML_REGION_OP) { 381 382 /* TBD: [Investigate] this isn't quite the right thing to do! */ 383 /* 384 * 385 * Method = (ACPI_DEFERRED_OP *) Op; 386 * Status = acpi_ps_parse_aml (Op, Method->Body, Method->body_length); 387 */ 388 } 389 390 if (ACPI_FAILURE(status)) { 391 break; 392 } 393 394 op = acpi_ps_get_depth_next(root, op); 395 } 396 397 return (status); 398 } 399 400 /******************************************************************************* 401 * 402 * FUNCTION: acpi_db_dump_buffer 403 * 404 * PARAMETERS: address - Pointer to the buffer 405 * 406 * RETURN: None 407 * 408 * DESCRIPTION: Print a portion of a buffer 409 * 410 ******************************************************************************/ 411 412 void acpi_db_dump_buffer(u32 address) 413 { 414 415 acpi_os_printf("\nLocation %X:\n", address); 416 417 acpi_dbg_level |= ACPI_LV_TABLES; 418 acpi_ut_debug_dump_buffer(ACPI_TO_POINTER(address), 64, DB_BYTE_DISPLAY, 419 ACPI_UINT32_MAX); 420 } 421 #endif 422