1/******************************************************************************
2 *
3 * Module Name: utbuffer - Buffer dump routines
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2014, 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			buf_char = buffer[(acpi_size) i + j];
154			if (ACPI_IS_PRINT(buf_char)) {
155				acpi_os_printf("%c", buf_char);
156			} else {
157				acpi_os_printf(".");
158			}
159		}
160
161		/* Done with that line. */
162
163		acpi_os_printf("\n");
164		i += 16;
165	}
166
167	return;
168}
169
170/*******************************************************************************
171 *
172 * FUNCTION:    acpi_ut_debug_dump_buffer
173 *
174 * PARAMETERS:  buffer              - Buffer to dump
175 *              count               - Amount to dump, in bytes
176 *              display             - BYTE, WORD, DWORD, or QWORD display:
177 *                                      DB_BYTE_DISPLAY
178 *                                      DB_WORD_DISPLAY
179 *                                      DB_DWORD_DISPLAY
180 *                                      DB_QWORD_DISPLAY
181 *              component_ID        - Caller's component ID
182 *
183 * RETURN:      None
184 *
185 * DESCRIPTION: Generic dump buffer in both hex and ascii.
186 *
187 ******************************************************************************/
188
189void
190acpi_ut_debug_dump_buffer(u8 *buffer, u32 count, u32 display, u32 component_id)
191{
192
193	/* Only dump the buffer if tracing is enabled */
194
195	if (!((ACPI_LV_TABLES & acpi_dbg_level) &&
196	      (component_id & acpi_dbg_layer))) {
197		return;
198	}
199
200	acpi_ut_dump_buffer(buffer, count, display, 0);
201}
202
203#ifdef ACPI_APPLICATION
204/*******************************************************************************
205 *
206 * FUNCTION:    acpi_ut_dump_buffer_to_file
207 *
208 * PARAMETERS:  file                - File descriptor
209 *              buffer              - Buffer to dump
210 *              count               - Amount to dump, in bytes
211 *              display             - BYTE, WORD, DWORD, or QWORD display:
212 *                                      DB_BYTE_DISPLAY
213 *                                      DB_WORD_DISPLAY
214 *                                      DB_DWORD_DISPLAY
215 *                                      DB_QWORD_DISPLAY
216 *              base_offset         - Beginning buffer offset (display only)
217 *
218 * RETURN:      None
219 *
220 * DESCRIPTION: Generic dump buffer in both hex and ascii to a file.
221 *
222 ******************************************************************************/
223
224void
225acpi_ut_dump_buffer_to_file(ACPI_FILE file,
226			    u8 *buffer, u32 count, u32 display, u32 base_offset)
227{
228	u32 i = 0;
229	u32 j;
230	u32 temp32;
231	u8 buf_char;
232
233	if (!buffer) {
234		acpi_ut_file_printf(file,
235				    "Null Buffer Pointer in DumpBuffer!\n");
236		return;
237	}
238
239	if ((count < 4) || (count & 0x01)) {
240		display = DB_BYTE_DISPLAY;
241	}
242
243	/* Nasty little dump buffer routine! */
244
245	while (i < count) {
246
247		/* Print current offset */
248
249		acpi_ut_file_printf(file, "%6.4X: ", (base_offset + i));
250
251		/* Print 16 hex chars */
252
253		for (j = 0; j < 16;) {
254			if (i + j >= count) {
255
256				/* Dump fill spaces */
257
258				acpi_ut_file_printf(file, "%*s",
259						    ((display * 2) + 1), " ");
260				j += display;
261				continue;
262			}
263
264			switch (display) {
265			case DB_BYTE_DISPLAY:
266			default:	/* Default is BYTE display */
267
268				acpi_ut_file_printf(file, "%02X ",
269						    buffer[(acpi_size) i + j]);
270				break;
271
272			case DB_WORD_DISPLAY:
273
274				ACPI_MOVE_16_TO_32(&temp32,
275						   &buffer[(acpi_size) i + j]);
276				acpi_ut_file_printf(file, "%04X ", temp32);
277				break;
278
279			case DB_DWORD_DISPLAY:
280
281				ACPI_MOVE_32_TO_32(&temp32,
282						   &buffer[(acpi_size) i + j]);
283				acpi_ut_file_printf(file, "%08X ", temp32);
284				break;
285
286			case DB_QWORD_DISPLAY:
287
288				ACPI_MOVE_32_TO_32(&temp32,
289						   &buffer[(acpi_size) i + j]);
290				acpi_ut_file_printf(file, "%08X", temp32);
291
292				ACPI_MOVE_32_TO_32(&temp32,
293						   &buffer[(acpi_size) i + j +
294							   4]);
295				acpi_ut_file_printf(file, "%08X ", temp32);
296				break;
297			}
298
299			j += display;
300		}
301
302		/*
303		 * Print the ASCII equivalent characters but watch out for the bad
304		 * unprintable ones (printable chars are 0x20 through 0x7E)
305		 */
306		acpi_ut_file_printf(file, " ");
307		for (j = 0; j < 16; j++) {
308			if (i + j >= count) {
309				acpi_ut_file_printf(file, "\n");
310				return;
311			}
312
313			buf_char = buffer[(acpi_size) i + j];
314			if (ACPI_IS_PRINT(buf_char)) {
315				acpi_ut_file_printf(file, "%c", buf_char);
316			} else {
317				acpi_ut_file_printf(file, ".");
318			}
319		}
320
321		/* Done with that line. */
322
323		acpi_ut_file_printf(file, "\n");
324		i += 16;
325	}
326
327	return;
328}
329#endif
330