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