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