| 1 | // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 | 
|---|
| 2 | /****************************************************************************** | 
|---|
| 3 | * | 
|---|
| 4 | * Module Name: utbuffer - Buffer dump routines | 
|---|
| 5 | * | 
|---|
| 6 | * Copyright (C) 2000 - 2025, Intel Corp. | 
|---|
| 7 | * | 
|---|
| 8 | *****************************************************************************/ | 
|---|
| 9 |  | 
|---|
| 10 | #include <acpi/acpi.h> | 
|---|
| 11 | #include "accommon.h" | 
|---|
| 12 |  | 
|---|
| 13 | #define _COMPONENT          ACPI_UTILITIES | 
|---|
| 14 | ACPI_MODULE_NAME( "utbuffer") | 
|---|
| 15 |  | 
|---|
| 16 | /******************************************************************************* | 
|---|
| 17 | * | 
|---|
| 18 | * FUNCTION:    acpi_ut_dump_buffer | 
|---|
| 19 | * | 
|---|
| 20 | * PARAMETERS:  buffer              - Buffer to dump | 
|---|
| 21 | *              count               - Amount to dump, in bytes | 
|---|
| 22 | *              display             - BYTE, WORD, DWORD, or QWORD display: | 
|---|
| 23 | *                                      DB_BYTE_DISPLAY | 
|---|
| 24 | *                                      DB_WORD_DISPLAY | 
|---|
| 25 | *                                      DB_DWORD_DISPLAY | 
|---|
| 26 | *                                      DB_QWORD_DISPLAY | 
|---|
| 27 | *              base_offset         - Beginning buffer offset (display only) | 
|---|
| 28 | * | 
|---|
| 29 | * RETURN:      None | 
|---|
| 30 | * | 
|---|
| 31 | * DESCRIPTION: Generic dump buffer in both hex and ascii. | 
|---|
| 32 | * | 
|---|
| 33 | ******************************************************************************/ | 
|---|
| 34 | void acpi_ut_dump_buffer(u8 *buffer, u32 count, u32 display, u32 base_offset) | 
|---|
| 35 | { | 
|---|
| 36 | u32 i = 0; | 
|---|
| 37 | u32 j; | 
|---|
| 38 | u32 temp32; | 
|---|
| 39 | u8 buf_char; | 
|---|
| 40 | u32 display_data_only = display & DB_DISPLAY_DATA_ONLY; | 
|---|
| 41 |  | 
|---|
| 42 | display &= ~DB_DISPLAY_DATA_ONLY; | 
|---|
| 43 | if (!buffer) { | 
|---|
| 44 | acpi_os_printf(format: "Null Buffer Pointer in DumpBuffer!\n"); | 
|---|
| 45 | return; | 
|---|
| 46 | } | 
|---|
| 47 |  | 
|---|
| 48 | if ((count < 4) || (count & 0x01)) { | 
|---|
| 49 | display = DB_BYTE_DISPLAY; | 
|---|
| 50 | } | 
|---|
| 51 |  | 
|---|
| 52 | /* Nasty little dump buffer routine! */ | 
|---|
| 53 |  | 
|---|
| 54 | while (i < count) { | 
|---|
| 55 |  | 
|---|
| 56 | /* Print current offset */ | 
|---|
| 57 |  | 
|---|
| 58 | if (!display_data_only) { | 
|---|
| 59 | acpi_os_printf(format: "%8.4X: ", (base_offset + i)); | 
|---|
| 60 | } | 
|---|
| 61 |  | 
|---|
| 62 | /* Print 16 hex chars */ | 
|---|
| 63 |  | 
|---|
| 64 | for (j = 0; j < 16;) { | 
|---|
| 65 | if (i + j >= count) { | 
|---|
| 66 |  | 
|---|
| 67 | /* Dump fill spaces */ | 
|---|
| 68 |  | 
|---|
| 69 | acpi_os_printf(format: "%*s", ((display * 2) + 1), " "); | 
|---|
| 70 | j += display; | 
|---|
| 71 | continue; | 
|---|
| 72 | } | 
|---|
| 73 |  | 
|---|
| 74 | switch (display) { | 
|---|
| 75 | case DB_BYTE_DISPLAY: | 
|---|
| 76 | default:	/* Default is BYTE display */ | 
|---|
| 77 |  | 
|---|
| 78 | acpi_os_printf(format: "%02X ", | 
|---|
| 79 | buffer[(acpi_size)i + j]); | 
|---|
| 80 | break; | 
|---|
| 81 |  | 
|---|
| 82 | case DB_WORD_DISPLAY: | 
|---|
| 83 |  | 
|---|
| 84 | ACPI_MOVE_16_TO_32(&temp32, | 
|---|
| 85 | &buffer[(acpi_size)i + j]); | 
|---|
| 86 | acpi_os_printf(format: "%04X ", temp32); | 
|---|
| 87 | break; | 
|---|
| 88 |  | 
|---|
| 89 | case DB_DWORD_DISPLAY: | 
|---|
| 90 |  | 
|---|
| 91 | ACPI_MOVE_32_TO_32(&temp32, | 
|---|
| 92 | &buffer[(acpi_size)i + j]); | 
|---|
| 93 | acpi_os_printf(format: "%08X ", temp32); | 
|---|
| 94 | break; | 
|---|
| 95 |  | 
|---|
| 96 | case DB_QWORD_DISPLAY: | 
|---|
| 97 |  | 
|---|
| 98 | ACPI_MOVE_32_TO_32(&temp32, | 
|---|
| 99 | &buffer[(acpi_size)i + j]); | 
|---|
| 100 | acpi_os_printf(format: "%08X", temp32); | 
|---|
| 101 |  | 
|---|
| 102 | ACPI_MOVE_32_TO_32(&temp32, | 
|---|
| 103 | &buffer[(acpi_size)i + j + | 
|---|
| 104 | 4]); | 
|---|
| 105 | acpi_os_printf(format: "%08X ", temp32); | 
|---|
| 106 | break; | 
|---|
| 107 | } | 
|---|
| 108 |  | 
|---|
| 109 | j += display; | 
|---|
| 110 | } | 
|---|
| 111 |  | 
|---|
| 112 | /* | 
|---|
| 113 | * Print the ASCII equivalent characters but watch out for the bad | 
|---|
| 114 | * unprintable ones (printable chars are 0x20 through 0x7E) | 
|---|
| 115 | */ | 
|---|
| 116 | if (!display_data_only) { | 
|---|
| 117 | acpi_os_printf(format: " "); | 
|---|
| 118 | for (j = 0; j < 16; j++) { | 
|---|
| 119 | if (i + j >= count) { | 
|---|
| 120 | acpi_os_printf(format: "\n"); | 
|---|
| 121 | return; | 
|---|
| 122 | } | 
|---|
| 123 |  | 
|---|
| 124 | /* | 
|---|
| 125 | * Add comment characters so rest of line is ignored when | 
|---|
| 126 | * compiled | 
|---|
| 127 | */ | 
|---|
| 128 | if (j == 0) { | 
|---|
| 129 | acpi_os_printf(format: "// "); | 
|---|
| 130 | } | 
|---|
| 131 |  | 
|---|
| 132 | buf_char = buffer[(acpi_size)i + j]; | 
|---|
| 133 | if (isprint(buf_char)) { | 
|---|
| 134 | acpi_os_printf(format: "%c", buf_char); | 
|---|
| 135 | } else { | 
|---|
| 136 | acpi_os_printf(format: "."); | 
|---|
| 137 | } | 
|---|
| 138 | } | 
|---|
| 139 |  | 
|---|
| 140 | /* Done with that line. */ | 
|---|
| 141 |  | 
|---|
| 142 | acpi_os_printf(format: "\n"); | 
|---|
| 143 | } | 
|---|
| 144 | i += 16; | 
|---|
| 145 | } | 
|---|
| 146 |  | 
|---|
| 147 | return; | 
|---|
| 148 | } | 
|---|
| 149 |  | 
|---|
| 150 | /******************************************************************************* | 
|---|
| 151 | * | 
|---|
| 152 | * FUNCTION:    acpi_ut_debug_dump_buffer | 
|---|
| 153 | * | 
|---|
| 154 | * PARAMETERS:  buffer              - Buffer to dump | 
|---|
| 155 | *              count               - Amount to dump, in bytes | 
|---|
| 156 | *              display             - BYTE, WORD, DWORD, or QWORD display: | 
|---|
| 157 | *                                      DB_BYTE_DISPLAY | 
|---|
| 158 | *                                      DB_WORD_DISPLAY | 
|---|
| 159 | *                                      DB_DWORD_DISPLAY | 
|---|
| 160 | *                                      DB_QWORD_DISPLAY | 
|---|
| 161 | *              component_ID        - Caller's component ID | 
|---|
| 162 | * | 
|---|
| 163 | * RETURN:      None | 
|---|
| 164 | * | 
|---|
| 165 | * DESCRIPTION: Generic dump buffer in both hex and ascii. | 
|---|
| 166 | * | 
|---|
| 167 | ******************************************************************************/ | 
|---|
| 168 |  | 
|---|
| 169 | void | 
|---|
| 170 | acpi_ut_debug_dump_buffer(u8 *buffer, u32 count, u32 display, u32 component_id) | 
|---|
| 171 | { | 
|---|
| 172 |  | 
|---|
| 173 | /* Only dump the buffer if tracing is enabled */ | 
|---|
| 174 |  | 
|---|
| 175 | if (!((ACPI_LV_TABLES & acpi_dbg_level) && | 
|---|
| 176 | (component_id & acpi_dbg_layer))) { | 
|---|
| 177 | return; | 
|---|
| 178 | } | 
|---|
| 179 |  | 
|---|
| 180 | acpi_ut_dump_buffer(buffer, count, display, base_offset: 0); | 
|---|
| 181 | } | 
|---|
| 182 |  | 
|---|
| 183 | #ifdef ACPI_APPLICATION | 
|---|
| 184 | /******************************************************************************* | 
|---|
| 185 | * | 
|---|
| 186 | * FUNCTION:    acpi_ut_dump_buffer_to_file | 
|---|
| 187 | * | 
|---|
| 188 | * PARAMETERS:  file                - File descriptor | 
|---|
| 189 | *              buffer              - Buffer to dump | 
|---|
| 190 | *              count               - Amount to dump, in bytes | 
|---|
| 191 | *              display             - BYTE, WORD, DWORD, or QWORD display: | 
|---|
| 192 | *                                      DB_BYTE_DISPLAY | 
|---|
| 193 | *                                      DB_WORD_DISPLAY | 
|---|
| 194 | *                                      DB_DWORD_DISPLAY | 
|---|
| 195 | *                                      DB_QWORD_DISPLAY | 
|---|
| 196 | *              base_offset         - Beginning buffer offset (display only) | 
|---|
| 197 | * | 
|---|
| 198 | * RETURN:      None | 
|---|
| 199 | * | 
|---|
| 200 | * DESCRIPTION: Generic dump buffer in both hex and ascii to a file. | 
|---|
| 201 | * | 
|---|
| 202 | ******************************************************************************/ | 
|---|
| 203 |  | 
|---|
| 204 | void | 
|---|
| 205 | acpi_ut_dump_buffer_to_file(ACPI_FILE file, | 
|---|
| 206 | u8 *buffer, u32 count, u32 display, u32 base_offset) | 
|---|
| 207 | { | 
|---|
| 208 | u32 i = 0; | 
|---|
| 209 | u32 j; | 
|---|
| 210 | u32 temp32; | 
|---|
| 211 | u8 buf_char; | 
|---|
| 212 |  | 
|---|
| 213 | if (!buffer) { | 
|---|
| 214 | fprintf(file, "Null Buffer Pointer in DumpBuffer!\n"); | 
|---|
| 215 | return; | 
|---|
| 216 | } | 
|---|
| 217 |  | 
|---|
| 218 | if ((count < 4) || (count & 0x01)) { | 
|---|
| 219 | display = DB_BYTE_DISPLAY; | 
|---|
| 220 | } | 
|---|
| 221 |  | 
|---|
| 222 | /* Nasty little dump buffer routine! */ | 
|---|
| 223 |  | 
|---|
| 224 | while (i < count) { | 
|---|
| 225 |  | 
|---|
| 226 | /* Print current offset */ | 
|---|
| 227 |  | 
|---|
| 228 | fprintf(file, "%8.4X: ", (base_offset + i)); | 
|---|
| 229 |  | 
|---|
| 230 | /* Print 16 hex chars */ | 
|---|
| 231 |  | 
|---|
| 232 | for (j = 0; j < 16;) { | 
|---|
| 233 | if (i + j >= count) { | 
|---|
| 234 |  | 
|---|
| 235 | /* Dump fill spaces */ | 
|---|
| 236 |  | 
|---|
| 237 | fprintf(file, "%*s", ((display * 2) + 1), " "); | 
|---|
| 238 | j += display; | 
|---|
| 239 | continue; | 
|---|
| 240 | } | 
|---|
| 241 |  | 
|---|
| 242 | switch (display) { | 
|---|
| 243 | case DB_BYTE_DISPLAY: | 
|---|
| 244 | default:	/* Default is BYTE display */ | 
|---|
| 245 |  | 
|---|
| 246 | fprintf(file, "%02X ", | 
|---|
| 247 | buffer[(acpi_size)i + j]); | 
|---|
| 248 | break; | 
|---|
| 249 |  | 
|---|
| 250 | case DB_WORD_DISPLAY: | 
|---|
| 251 |  | 
|---|
| 252 | ACPI_MOVE_16_TO_32(&temp32, | 
|---|
| 253 | &buffer[(acpi_size)i + j]); | 
|---|
| 254 | fprintf(file, "%04X ", temp32); | 
|---|
| 255 | break; | 
|---|
| 256 |  | 
|---|
| 257 | case DB_DWORD_DISPLAY: | 
|---|
| 258 |  | 
|---|
| 259 | ACPI_MOVE_32_TO_32(&temp32, | 
|---|
| 260 | &buffer[(acpi_size)i + j]); | 
|---|
| 261 | fprintf(file, "%08X ", temp32); | 
|---|
| 262 | break; | 
|---|
| 263 |  | 
|---|
| 264 | case DB_QWORD_DISPLAY: | 
|---|
| 265 |  | 
|---|
| 266 | ACPI_MOVE_32_TO_32(&temp32, | 
|---|
| 267 | &buffer[(acpi_size)i + j]); | 
|---|
| 268 | fprintf(file, "%08X", temp32); | 
|---|
| 269 |  | 
|---|
| 270 | ACPI_MOVE_32_TO_32(&temp32, | 
|---|
| 271 | &buffer[(acpi_size)i + j + | 
|---|
| 272 | 4]); | 
|---|
| 273 | fprintf(file, "%08X ", temp32); | 
|---|
| 274 | break; | 
|---|
| 275 | } | 
|---|
| 276 |  | 
|---|
| 277 | j += display; | 
|---|
| 278 | } | 
|---|
| 279 |  | 
|---|
| 280 | /* | 
|---|
| 281 | * Print the ASCII equivalent characters but watch out for the bad | 
|---|
| 282 | * unprintable ones (printable chars are 0x20 through 0x7E) | 
|---|
| 283 | */ | 
|---|
| 284 | fprintf(file, " "); | 
|---|
| 285 | for (j = 0; j < 16; j++) { | 
|---|
| 286 | if (i + j >= count) { | 
|---|
| 287 | fprintf(file, "\n"); | 
|---|
| 288 | return; | 
|---|
| 289 | } | 
|---|
| 290 |  | 
|---|
| 291 | buf_char = buffer[(acpi_size)i + j]; | 
|---|
| 292 | if (isprint(buf_char)) { | 
|---|
| 293 | fprintf(file, "%c", buf_char); | 
|---|
| 294 | } else { | 
|---|
| 295 | fprintf(file, "."); | 
|---|
| 296 | } | 
|---|
| 297 | } | 
|---|
| 298 |  | 
|---|
| 299 | /* Done with that line. */ | 
|---|
| 300 |  | 
|---|
| 301 | fprintf(file, "\n"); | 
|---|
| 302 | i += 16; | 
|---|
| 303 | } | 
|---|
| 304 |  | 
|---|
| 305 | return; | 
|---|
| 306 | } | 
|---|
| 307 | #endif | 
|---|
| 308 |  | 
|---|