xref: /linux/drivers/acpi/acpica/utbuffer.c (revision be239684b18e1cdcafcf8c7face4a2f562c745ad)
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 - 2023, 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("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("%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("%*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("%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("%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("%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("%08X", temp32);
101 
102 				ACPI_MOVE_32_TO_32(&temp32,
103 						   &buffer[(acpi_size)i + j +
104 							   4]);
105 				acpi_os_printf("%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(" ");
118 			for (j = 0; j < 16; j++) {
119 				if (i + j >= count) {
120 					acpi_os_printf("\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("// ");
130 				}
131 
132 				buf_char = buffer[(acpi_size)i + j];
133 				if (isprint(buf_char)) {
134 					acpi_os_printf("%c", buf_char);
135 				} else {
136 					acpi_os_printf(".");
137 				}
138 			}
139 
140 			/* Done with that line. */
141 
142 			acpi_os_printf("\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, 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