1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 2 /****************************************************************************** 3 * 4 * Module Name: exdebug - Support for stores to the AML Debug Object 5 * 6 * Copyright (C) 2000 - 2023, Intel Corp. 7 * 8 *****************************************************************************/ 9 10 #include <acpi/acpi.h> 11 #include "accommon.h" 12 #include "acinterp.h" 13 14 #define _COMPONENT ACPI_EXECUTER 15 ACPI_MODULE_NAME("exdebug") 16 17 #ifndef ACPI_NO_ERROR_MESSAGES 18 /******************************************************************************* 19 * 20 * FUNCTION: acpi_ex_do_debug_object 21 * 22 * PARAMETERS: source_desc - Object to be output to "Debug Object" 23 * level - Indentation level (used for packages) 24 * index - Current package element, zero if not pkg 25 * 26 * RETURN: None 27 * 28 * DESCRIPTION: Handles stores to the AML Debug Object. For example: 29 * Store(INT1, Debug) 30 * 31 * This function is not compiled if ACPI_NO_ERROR_MESSAGES is set. 32 * 33 * This function is only enabled if acpi_gbl_enable_aml_debug_object is set, or 34 * if ACPI_LV_DEBUG_OBJECT is set in the acpi_dbg_level. Thus, in the normal 35 * operational case, stores to the debug object are ignored but can be easily 36 * enabled if necessary. 37 * 38 ******************************************************************************/ 39 void 40 acpi_ex_do_debug_object(union acpi_operand_object *source_desc, 41 u32 level, u32 index) 42 { 43 u32 i; 44 u32 timer; 45 union acpi_operand_object *object_desc; 46 u32 value; 47 48 ACPI_FUNCTION_TRACE_PTR(ex_do_debug_object, source_desc); 49 50 /* Output must be enabled via the debug_object global or the dbg_level */ 51 52 if (!acpi_gbl_enable_aml_debug_object && 53 !(acpi_dbg_level & ACPI_LV_DEBUG_OBJECT)) { 54 return_VOID; 55 } 56 57 /* Newline -- don't emit the line header */ 58 59 if (source_desc && 60 (ACPI_GET_DESCRIPTOR_TYPE(source_desc) == ACPI_DESC_TYPE_OPERAND) && 61 (source_desc->common.type == ACPI_TYPE_STRING)) { 62 if ((source_desc->string.length == 1) && 63 (*source_desc->string.pointer == '\n')) { 64 acpi_os_printf("\n"); 65 return_VOID; 66 } 67 } 68 69 /* 70 * Print line header as long as we are not in the middle of an 71 * object display 72 */ 73 if (!((level > 0) && index == 0)) { 74 if (acpi_gbl_display_debug_timer) { 75 /* 76 * We will emit the current timer value (in microseconds) with each 77 * debug output. Only need the lower 26 bits. This allows for 67 78 * million microseconds or 67 seconds before rollover. 79 * 80 * Convert 100 nanosecond units to microseconds 81 */ 82 timer = ((u32)acpi_os_get_timer() / 10); 83 timer &= 0x03FFFFFF; 84 85 acpi_os_printf("ACPI Debug: T=0x%8.8X %*s", timer, 86 level, " "); 87 } else { 88 acpi_os_printf("ACPI Debug: %*s", level, " "); 89 } 90 } 91 92 /* Display the index for package output only */ 93 94 if (index > 0) { 95 acpi_os_printf("(%.2u) ", index - 1); 96 } 97 98 if (!source_desc) { 99 acpi_os_printf("[Null Object]\n"); 100 return_VOID; 101 } 102 103 if (ACPI_GET_DESCRIPTOR_TYPE(source_desc) == ACPI_DESC_TYPE_OPERAND) { 104 105 /* No object type prefix needed for integers and strings */ 106 107 if ((source_desc->common.type != ACPI_TYPE_INTEGER) && 108 (source_desc->common.type != ACPI_TYPE_STRING)) { 109 acpi_os_printf("%s ", 110 acpi_ut_get_object_type_name 111 (source_desc)); 112 } 113 114 if (!acpi_ut_valid_internal_object(source_desc)) { 115 acpi_os_printf("%p, Invalid Internal Object!\n", 116 source_desc); 117 return_VOID; 118 } 119 } else if (ACPI_GET_DESCRIPTOR_TYPE(source_desc) == 120 ACPI_DESC_TYPE_NAMED) { 121 acpi_os_printf("%s (Node %p)\n", 122 acpi_ut_get_type_name(((struct 123 acpi_namespace_node *) 124 source_desc)->type), 125 source_desc); 126 return_VOID; 127 } else { 128 return_VOID; 129 } 130 131 /* source_desc is of type ACPI_DESC_TYPE_OPERAND */ 132 133 switch (source_desc->common.type) { 134 case ACPI_TYPE_INTEGER: 135 136 /* Output correct integer width */ 137 138 if (acpi_gbl_integer_byte_width == 4) { 139 acpi_os_printf("0x%8.8X\n", 140 (u32)source_desc->integer.value); 141 } else { 142 acpi_os_printf("0x%8.8X%8.8X\n", 143 ACPI_FORMAT_UINT64(source_desc->integer. 144 value)); 145 } 146 break; 147 148 case ACPI_TYPE_BUFFER: 149 150 acpi_os_printf("[0x%.2X]\n", (u32)source_desc->buffer.length); 151 acpi_ut_dump_buffer(source_desc->buffer.pointer, 152 (source_desc->buffer.length < 256) ? 153 source_desc->buffer.length : 256, 154 DB_BYTE_DISPLAY, 0); 155 break; 156 157 case ACPI_TYPE_STRING: 158 159 acpi_os_printf("\"%s\"\n", source_desc->string.pointer); 160 break; 161 162 case ACPI_TYPE_PACKAGE: 163 164 acpi_os_printf("(Contains 0x%.2X Elements):\n", 165 source_desc->package.count); 166 167 /* Output the entire contents of the package */ 168 169 for (i = 0; i < source_desc->package.count; i++) { 170 acpi_ex_do_debug_object(source_desc->package. 171 elements[i], level + 4, i + 1); 172 } 173 break; 174 175 case ACPI_TYPE_LOCAL_REFERENCE: 176 177 acpi_os_printf("[%s] ", 178 acpi_ut_get_reference_name(source_desc)); 179 180 /* Decode the reference */ 181 182 switch (source_desc->reference.class) { 183 case ACPI_REFCLASS_INDEX: 184 185 acpi_os_printf("0x%X\n", source_desc->reference.value); 186 break; 187 188 case ACPI_REFCLASS_TABLE: 189 190 /* Case for ddb_handle */ 191 192 acpi_os_printf("Table Index 0x%X\n", 193 source_desc->reference.value); 194 return_VOID; 195 196 default: 197 198 break; 199 } 200 201 acpi_os_printf(" "); 202 203 /* Check for valid node first, then valid object */ 204 205 if (source_desc->reference.node) { 206 if (ACPI_GET_DESCRIPTOR_TYPE 207 (source_desc->reference.node) != 208 ACPI_DESC_TYPE_NAMED) { 209 acpi_os_printf 210 (" %p - Not a valid namespace node\n", 211 source_desc->reference.node); 212 } else { 213 acpi_os_printf("Node %p [%4.4s] ", 214 source_desc->reference.node, 215 (source_desc->reference.node)-> 216 name.ascii); 217 218 switch ((source_desc->reference.node)->type) { 219 220 /* These types have no attached object */ 221 222 case ACPI_TYPE_DEVICE: 223 acpi_os_printf("Device\n"); 224 break; 225 226 case ACPI_TYPE_THERMAL: 227 acpi_os_printf("Thermal Zone\n"); 228 break; 229 230 default: 231 232 acpi_ex_do_debug_object((source_desc-> 233 reference. 234 node)->object, 235 level + 4, 0); 236 break; 237 } 238 } 239 } else if (source_desc->reference.object) { 240 if (ACPI_GET_DESCRIPTOR_TYPE 241 (source_desc->reference.object) == 242 ACPI_DESC_TYPE_NAMED) { 243 244 /* Reference object is a namespace node */ 245 246 acpi_ex_do_debug_object(ACPI_CAST_PTR 247 (union 248 acpi_operand_object, 249 source_desc->reference. 250 object), level + 4, 0); 251 } else { 252 object_desc = source_desc->reference.object; 253 value = source_desc->reference.value; 254 255 switch (object_desc->common.type) { 256 case ACPI_TYPE_BUFFER: 257 258 acpi_os_printf("Buffer[%u] = 0x%2.2X\n", 259 value, 260 *source_desc->reference. 261 index_pointer); 262 break; 263 264 case ACPI_TYPE_STRING: 265 266 acpi_os_printf 267 ("String[%u] = \"%c\" (0x%2.2X)\n", 268 value, 269 *source_desc->reference. 270 index_pointer, 271 *source_desc->reference. 272 index_pointer); 273 break; 274 275 case ACPI_TYPE_PACKAGE: 276 277 acpi_os_printf("Package[%u] = ", value); 278 if (!(*source_desc->reference.where)) { 279 acpi_os_printf 280 ("[Uninitialized Package Element]\n"); 281 } else { 282 acpi_ex_do_debug_object 283 (*source_desc->reference. 284 where, level + 4, 0); 285 } 286 break; 287 288 default: 289 290 acpi_os_printf 291 ("Unknown Reference object type %X\n", 292 object_desc->common.type); 293 break; 294 } 295 } 296 } 297 break; 298 299 default: 300 301 acpi_os_printf("(Descriptor %p)\n", source_desc); 302 break; 303 } 304 305 ACPI_DEBUG_PRINT_RAW((ACPI_DB_EXEC, "\n")); 306 return_VOID; 307 } 308 #endif 309