aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi
diff options
context:
space:
mode:
authorLv Zheng <lv.zheng@intel.com>2014-07-07 22:07:00 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2014-07-08 08:22:25 -0400
commit80a648c12e4bda45c4f1bb93d83184fb3010ac12 (patch)
tree8ecf2e0765862b97b6b9c8666aa11869e7ad4c5a /drivers/acpi
parent7824f44ecfef4f05caaa8f9536c523b8d645f102 (diff)
ACPICA: Utilities: Add formatted printing APIs
This patch introduces formatted printing APIs to handle ACPICA specific formatted print requirements. Currently only specific OSPMs will use this customized printing support, Linux kernel doesn't use these APIs at this time. It will be enabled for Linux kernel resident ACPICA after being well tested. So currently this patch is a no-op. The specific formatted printing APIs are useful to ACPICA as: 1. Some portable applications do not link standard C library, so they cannot use standard formatted print APIs directly. 2. Platform specific printing format may differ and thus not portable, for example, u64 is %ull for Linux kernel and is %uI64 for some MSVC versions. 3. Platform specific printing format may conflict with ACPICA's usages while it is not possible for ACPICA developers to test their code for all platforms. For example, developers may generate %pRxxx while Linux kernel treats %pR as structured resource printing and decodes variable argument as a "struct resource" pointer. This patch solves above issues by introducing the new APIs. Note that users of such APIs are not introduced in this patch. Users of acpi_os_file_vprintf()/acpi_ut_file_printf() need to invoke acpi_os_initialize(), this should be taken care by the further patches where such users are introduced. Lv Zheng. Signed-off-by: Lv Zheng <lv.zheng@intel.com> Signed-off-by: Bob Moore <robert.moore@intel.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'drivers/acpi')
-rw-r--r--drivers/acpi/acpica/Makefile2
-rw-r--r--drivers/acpi/acpica/acglobal.h5
-rw-r--r--drivers/acpi/acpica/acutils.h19
-rw-r--r--drivers/acpi/acpica/utprint.c649
4 files changed, 674 insertions, 1 deletions
diff --git a/drivers/acpi/acpica/Makefile b/drivers/acpi/acpica/Makefile
index 14b851f1a278..6b9ec239d578 100644
--- a/drivers/acpi/acpica/Makefile
+++ b/drivers/acpi/acpica/Makefile
@@ -175,5 +175,5 @@ acpi-y += \
175 utxferror.o \ 175 utxferror.o \
176 utxfmutex.o 176 utxfmutex.o
177 177
178acpi-$(ACPI_FUTURE_USAGE) += utfileio.o uttrack.o utcache.o 178acpi-$(ACPI_FUTURE_USAGE) += utfileio.o utprint.o uttrack.o utcache.o
179 179
diff --git a/drivers/acpi/acpica/acglobal.h b/drivers/acpi/acpica/acglobal.h
index 78cc366ca878..ebf02cc10a43 100644
--- a/drivers/acpi/acpica/acglobal.h
+++ b/drivers/acpi/acpica/acglobal.h
@@ -364,6 +364,11 @@ ACPI_GLOBAL(u32, acpi_gbl_num_objects);
364ACPI_INIT_GLOBAL(ACPI_FILE, acpi_gbl_debug_file, NULL); 364ACPI_INIT_GLOBAL(ACPI_FILE, acpi_gbl_debug_file, NULL);
365ACPI_INIT_GLOBAL(ACPI_FILE, acpi_gbl_output_file, NULL); 365ACPI_INIT_GLOBAL(ACPI_FILE, acpi_gbl_output_file, NULL);
366 366
367/* Print buffer */
368
369ACPI_GLOBAL(acpi_spinlock, acpi_gbl_print_lock); /* For print buffer */
370ACPI_GLOBAL(char, acpi_gbl_print_buffer[1024]);
371
367#endif /* ACPI_APPLICATION */ 372#endif /* ACPI_APPLICATION */
368 373
369/***************************************************************************** 374/*****************************************************************************
diff --git a/drivers/acpi/acpica/acutils.h b/drivers/acpi/acpica/acutils.h
index e0adbc1f52ed..85871c639cc2 100644
--- a/drivers/acpi/acpica/acutils.h
+++ b/drivers/acpi/acpica/acutils.h
@@ -750,4 +750,23 @@ const struct ah_predefined_name *acpi_ah_match_predefined_name(char *nameseg);
750 750
751const struct ah_device_id *acpi_ah_match_hardware_id(char *hid); 751const struct ah_device_id *acpi_ah_match_hardware_id(char *hid);
752 752
753/*
754 * utprint - printf/vprintf output functions
755 */
756const char *acpi_ut_scan_number(const char *string, u64 *number_ptr);
757
758const char *acpi_ut_print_number(char *string, u64 number);
759
760int
761acpi_ut_vsnprintf(char *string,
762 acpi_size size, const char *format, va_list args);
763
764int acpi_ut_snprintf(char *string, acpi_size size, const char *format, ...);
765
766#ifdef ACPI_APPLICATION
767int acpi_ut_file_vprintf(ACPI_FILE file, const char *format, va_list args);
768
769int acpi_ut_file_printf(ACPI_FILE file, const char *format, ...);
770#endif
771
753#endif /* _ACUTILS_H */ 772#endif /* _ACUTILS_H */
diff --git a/drivers/acpi/acpica/utprint.c b/drivers/acpi/acpica/utprint.c
new file mode 100644
index 000000000000..9d5293fd992f
--- /dev/null
+++ b/drivers/acpi/acpica/utprint.c
@@ -0,0 +1,649 @@
1/******************************************************************************
2 *
3 * Module Name: utprint - Formatted printing 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("utprint")
49
50#define ACPI_FORMAT_SIGN 0x01
51#define ACPI_FORMAT_SIGN_PLUS 0x02
52#define ACPI_FORMAT_SIGN_PLUS_SPACE 0x04
53#define ACPI_FORMAT_ZERO 0x08
54#define ACPI_FORMAT_LEFT 0x10
55#define ACPI_FORMAT_UPPER 0x20
56#define ACPI_FORMAT_PREFIX 0x40
57/* Local prototypes */
58static acpi_size
59acpi_ut_bound_string_length(const char *string, acpi_size count);
60
61static char *acpi_ut_bound_string_output(char *string, const char *end, char c);
62
63static char *acpi_ut_format_number(char *string,
64 char *end,
65 u64 number,
66 u8 base, s32 width, s32 precision, u8 type);
67
68static char *acpi_ut_put_number(char *string, u64 number, u8 base, u8 upper);
69
70/*******************************************************************************
71 *
72 * FUNCTION: acpi_ut_bound_string_length
73 *
74 * PARAMETERS: string - String with boundary
75 * count - Boundary of the string
76 *
77 * RETURN: Length of the string.
78 *
79 * DESCRIPTION: Calculate the length of a string with boundary.
80 *
81 ******************************************************************************/
82
83static acpi_size
84acpi_ut_bound_string_length(const char *string, acpi_size count)
85{
86 u32 length = 0;
87
88 while (*string && count) {
89 length++;
90 string++;
91 count--;
92 }
93
94 return (length);
95}
96
97/*******************************************************************************
98 *
99 * FUNCTION: acpi_ut_bound_string_output
100 *
101 * PARAMETERS: string - String with boundary
102 * end - Boundary of the string
103 * c - Character to be output to the string
104 *
105 * RETURN: Updated position for next valid character
106 *
107 * DESCRIPTION: Output a character into a string with boundary check.
108 *
109 ******************************************************************************/
110
111static char *acpi_ut_bound_string_output(char *string, const char *end, char c)
112{
113
114 if (string < end) {
115 *string = c;
116 }
117 ++string;
118
119 return (string);
120}
121
122/*******************************************************************************
123 *
124 * FUNCTION: acpi_ut_put_number
125 *
126 * PARAMETERS: string - Buffer to hold reverse-ordered string
127 * number - Integer to be converted
128 * base - Base of the integer
129 * upper - Whether or not using upper cased digits
130 *
131 * RETURN: Updated position for next valid character
132 *
133 * DESCRIPTION: Convert an integer into a string, note that, the string holds a
134 * reversed ordered number without the trailing zero.
135 *
136 ******************************************************************************/
137
138static char *acpi_ut_put_number(char *string, u64 number, u8 base, u8 upper)
139{
140 const char lower_digits[] = "0123456789abcdef";
141 const char upper_digits[] = "0123456789ABCDEF";
142 const char *digits;
143 u64 digit_index;
144 char *pos;
145
146 pos = string;
147 digits = upper ? upper_digits : lower_digits;
148
149 if (number == 0) {
150 *(pos++) = '0';
151 } else {
152 while (number) {
153 (void)acpi_ut_divide(number, base, &number,
154 &digit_index);
155 *(pos++) = digits[digit_index];
156 }
157 }
158 /* *(Pos++) = '0'; */
159
160 return (pos);
161}
162
163/*******************************************************************************
164 *
165 * FUNCTION: acpi_ut_scan_number
166 *
167 * PARAMETERS: string - String buffer
168 * number_ptr - Where the number is returned
169 *
170 * RETURN: Updated position for next valid character
171 *
172 * DESCRIPTION: Scan a string for a decimal integer.
173 *
174 ******************************************************************************/
175
176const char *acpi_ut_scan_number(const char *string, u64 *number_ptr)
177{
178 u64 number = 0;
179
180 while (ACPI_IS_DIGIT(*string)) {
181 number *= 10;
182 number += *(string++) - '0';
183 }
184 *number_ptr = number;
185
186 return (string);
187}
188
189/*******************************************************************************
190 *
191 * FUNCTION: acpi_ut_print_number
192 *
193 * PARAMETERS: string - String buffer
194 * number - The number to be converted
195 *
196 * RETURN: Updated position for next valid character
197 *
198 * DESCRIPTION: Print a decimal integer into a string.
199 *
200 ******************************************************************************/
201
202const char *acpi_ut_print_number(char *string, u64 number)
203{
204 char ascii_string[20];
205 const char *pos1;
206 char *pos2;
207
208 pos1 = acpi_ut_put_number(ascii_string, number, 10, FALSE);
209 pos2 = string;
210
211 while (pos1 != ascii_string) {
212 *(pos2++) = *(--pos1);
213 }
214 *pos2 = 0;
215
216 return (string);
217}
218
219/*******************************************************************************
220 *
221 * FUNCTION: acpi_ut_format_number
222 *
223 * PARAMETERS: string - String buffer with boundary
224 * end - Boundary of the string
225 * number - The number to be converted
226 * base - Base of the integer
227 * width - Field width
228 * precision - Precision of the integer
229 * type - Special printing flags
230 *
231 * RETURN: Updated position for next valid character
232 *
233 * DESCRIPTION: Print an integer into a string with any base and any precision.
234 *
235 ******************************************************************************/
236
237static char *acpi_ut_format_number(char *string,
238 char *end,
239 u64 number,
240 u8 base, s32 width, s32 precision, u8 type)
241{
242 char sign;
243 char zero;
244 u8 need_prefix;
245 u8 upper;
246 s32 i;
247 char reversed_string[66];
248
249 /* Perform sanity checks */
250
251 if (base < 2 || base > 16) {
252 return NULL;
253 }
254 if (type & ACPI_FORMAT_LEFT) {
255 type &= ~ACPI_FORMAT_ZERO;
256 }
257
258 need_prefix = ((type & ACPI_FORMAT_PREFIX)
259 && base != 10) ? TRUE : FALSE;
260 upper = (type & ACPI_FORMAT_UPPER) ? TRUE : FALSE;
261 zero = (type & ACPI_FORMAT_ZERO) ? '0' : ' ';
262
263 /* Calculate size according to sign and prefix */
264
265 sign = '\0';
266 if (type & ACPI_FORMAT_SIGN) {
267 if ((s64) number < 0) {
268 sign = '-';
269 number = -(s64) number;
270 width--;
271 } else if (type & ACPI_FORMAT_SIGN_PLUS) {
272 sign = '+';
273 width--;
274 } else if (type & ACPI_FORMAT_SIGN_PLUS_SPACE) {
275 sign = ' ';
276 width--;
277 }
278 }
279 if (need_prefix) {
280 width--;
281 if (base == 16) {
282 width--;
283 }
284 }
285
286 /* Generate full string in reverse order */
287
288 i = ACPI_PTR_DIFF(acpi_ut_put_number
289 (reversed_string, number, base, upper),
290 reversed_string);
291
292 /* Printing 100 using %2d gives "100", not "00" */
293
294 if (i > precision) {
295 precision = i;
296 }
297 width -= precision;
298
299 /* Output the string */
300
301 if (!(type & (ACPI_FORMAT_ZERO | ACPI_FORMAT_LEFT))) {
302 while (--width >= 0) {
303 string = acpi_ut_bound_string_output(string, end, ' ');
304 }
305 }
306 if (sign) {
307 string = acpi_ut_bound_string_output(string, end, sign);
308 }
309 if (need_prefix) {
310 string = acpi_ut_bound_string_output(string, end, '0');
311 if (base == 16) {
312 string = acpi_ut_bound_string_output(string, end,
313 upper ? 'X' : 'x');
314 }
315 }
316 if (!(type & ACPI_FORMAT_LEFT)) {
317 while (--width >= 0) {
318 string = acpi_ut_bound_string_output(string, end, zero);
319 }
320 }
321 while (i <= --precision) {
322 string = acpi_ut_bound_string_output(string, end, '0');
323 }
324 while (--i >= 0) {
325 string = acpi_ut_bound_string_output(string, end,
326 reversed_string[i]);
327 }
328 while (--width >= 0) {
329 string = acpi_ut_bound_string_output(string, end, ' ');
330 }
331
332 return (string);
333}
334
335/*******************************************************************************
336 *
337 * FUNCTION: acpi_ut_vsnprintf
338 *
339 * PARAMETERS: string - String with boundary
340 * size - Boundary of the string
341 * format - Standard printf format
342 * args - Argument list
343 *
344 * RETURN: Size of successfully output bytes
345 *
346 * DESCRIPTION: Formatted output to a string using argument list pointer.
347 *
348 ******************************************************************************/
349
350int
351acpi_ut_vsnprintf(char *string,
352 acpi_size size, const char *format, va_list args)
353{
354 u8 base = 10;
355 u8 type = 0;
356 s32 width = -1;
357 s32 precision = -1;
358 char qualifier = 0;
359 u64 number;
360 char *pos;
361 char *end;
362 char c;
363 const char *s;
364 const void *p;
365 s32 length;
366 int i;
367
368 pos = string;
369 end = string + size;
370
371 for (; *format; ++format) {
372 if (*format != '%') {
373 pos = acpi_ut_bound_string_output(pos, end, *format);
374 continue;
375 }
376
377 /* Process sign */
378
379 do {
380 ++format;
381 if (*format == '#') {
382 type |= ACPI_FORMAT_PREFIX;
383 } else if (*format == '0') {
384 type |= ACPI_FORMAT_ZERO;
385 } else if (*format == '+') {
386 type |= ACPI_FORMAT_SIGN_PLUS;
387 } else if (*format == ' ') {
388 type |= ACPI_FORMAT_SIGN_PLUS_SPACE;
389 } else if (*format == '-') {
390 type |= ACPI_FORMAT_LEFT;
391 } else {
392 break;
393 }
394 } while (1);
395
396 /* Process width */
397
398 if (ACPI_IS_DIGIT(*format)) {
399 format = acpi_ut_scan_number(format, &number);
400 width = (s32) number;
401 } else if (*format == '*') {
402 ++format;
403 width = va_arg(args, int);
404 if (width < 0) {
405 width = -width;
406 type |= ACPI_FORMAT_LEFT;
407 }
408 }
409
410 /* Process precision */
411
412 if (*format == '.') {
413 ++format;
414 if (ACPI_IS_DIGIT(*format)) {
415 format = acpi_ut_scan_number(format, &number);
416 precision = (s32) number;
417 } else if (*format == '*') {
418 ++format;
419 precision = va_arg(args, int);
420 }
421 if (precision < 0) {
422 precision = 0;
423 }
424 }
425
426 /* Process qualifier */
427
428 if (*format == 'h' || *format == 'l' || *format == 'L') {
429 qualifier = *format;
430 ++format;
431 if (qualifier == 'l' && *format == 'l') {
432 qualifier = 'L';
433 ++format;
434 }
435 }
436
437 switch (*format) {
438 case '%':
439
440 pos = acpi_ut_bound_string_output(pos, end, '%');
441 continue;
442
443 case 'c':
444
445 if (!(type & ACPI_FORMAT_LEFT)) {
446 while (--width > 0) {
447 pos =
448 acpi_ut_bound_string_output(pos,
449 end,
450 ' ');
451 }
452 }
453 c = (char)va_arg(args, int);
454 pos = acpi_ut_bound_string_output(pos, end, c);
455 while (--width > 0) {
456 pos =
457 acpi_ut_bound_string_output(pos, end, ' ');
458 }
459 continue;
460
461 case 's':
462
463 s = va_arg(args, char *);
464 if (!s) {
465 s = "<NULL>";
466 }
467 length = acpi_ut_bound_string_length(s, precision);
468 if (!(type & ACPI_FORMAT_LEFT)) {
469 while (length < width--) {
470 pos =
471 acpi_ut_bound_string_output(pos,
472 end,
473 ' ');
474 }
475 }
476 for (i = 0; i < length; ++i) {
477 pos = acpi_ut_bound_string_output(pos, end, *s);
478 ++s;
479 }
480 while (length < width--) {
481 pos =
482 acpi_ut_bound_string_output(pos, end, ' ');
483 }
484 continue;
485
486 case 'o':
487
488 base = 8;
489 break;
490
491 case 'X':
492
493 type |= ACPI_FORMAT_UPPER;
494
495 case 'x':
496
497 base = 16;
498 break;
499
500 case 'd':
501 case 'i':
502
503 type |= ACPI_FORMAT_SIGN;
504
505 case 'u':
506
507 break;
508
509 case 'p':
510
511 if (width == -1) {
512 width = 2 * sizeof(void *);
513 type |= ACPI_FORMAT_ZERO;
514 }
515 p = va_arg(args, void *);
516 pos = acpi_ut_format_number(pos, end,
517 ACPI_TO_INTEGER(p),
518 16, width, precision, type);
519 continue;
520
521 default:
522
523 pos = acpi_ut_bound_string_output(pos, end, '%');
524 if (*format) {
525 pos =
526 acpi_ut_bound_string_output(pos, end,
527 *format);
528 } else {
529 --format;
530 }
531 continue;
532 }
533
534 if (qualifier == 'L') {
535 number = va_arg(args, u64);
536 if (type & ACPI_FORMAT_SIGN) {
537 number = (s64) number;
538 }
539 } else if (qualifier == 'l') {
540 number = va_arg(args, unsigned long);
541 if (type & ACPI_FORMAT_SIGN) {
542 number = (s32) number;
543 }
544 } else if (qualifier == 'h') {
545 number = (u16)va_arg(args, int);
546 if (type & ACPI_FORMAT_SIGN) {
547 number = (s16) number;
548 }
549 } else {
550 number = va_arg(args, unsigned int);
551 if (type & ACPI_FORMAT_SIGN) {
552 number = (signed int)number;
553 }
554 }
555 pos = acpi_ut_format_number(pos, end, number, base,
556 width, precision, type);
557 }
558
559 if (size > 0) {
560 if (pos < end) {
561 *pos = '\0';
562 } else {
563 end[-1] = '\0';
564 }
565 }
566
567 return (ACPI_PTR_DIFF(pos, string));
568}
569
570/*******************************************************************************
571 *
572 * FUNCTION: acpi_ut_snprintf
573 *
574 * PARAMETERS: string - String with boundary
575 * size - Boundary of the string
576 * Format, ... - Standard printf format
577 *
578 * RETURN: Size of successfully output bytes
579 *
580 * DESCRIPTION: Formatted output to a string.
581 *
582 ******************************************************************************/
583
584int acpi_ut_snprintf(char *string, acpi_size size, const char *format, ...)
585{
586 va_list args;
587 int length;
588
589 va_start(args, format);
590 length = acpi_ut_vsnprintf(string, size, format, args);
591 va_end(args);
592
593 return (length);
594}
595
596#ifdef ACPI_APPLICATION
597/*******************************************************************************
598 *
599 * FUNCTION: acpi_ut_file_vprintf
600 *
601 * PARAMETERS: file - File descriptor
602 * format - Standard printf format
603 * args - Argument list
604 *
605 * RETURN: Size of successfully output bytes
606 *
607 * DESCRIPTION: Formatted output to a file using argument list pointer.
608 *
609 ******************************************************************************/
610
611int acpi_ut_file_vprintf(ACPI_FILE file, const char *format, va_list args)
612{
613 acpi_cpu_flags flags;
614 int length;
615
616 flags = acpi_os_acquire_lock(acpi_gbl_print_lock);
617 length = acpi_ut_vsnprintf(acpi_gbl_print_buffer,
618 sizeof(acpi_gbl_print_buffer), format, args);
619 (void)acpi_os_write_file(file, acpi_gbl_print_buffer, length, 1);
620 acpi_os_release_lock(acpi_gbl_print_lock, flags);
621
622 return (length);
623}
624
625/*******************************************************************************
626 *
627 * FUNCTION: acpi_ut_file_printf
628 *
629 * PARAMETERS: file - File descriptor
630 * Format, ... - Standard printf format
631 *
632 * RETURN: Size of successfully output bytes
633 *
634 * DESCRIPTION: Formatted output to a file.
635 *
636 ******************************************************************************/
637
638int acpi_ut_file_printf(ACPI_FILE file, const char *format, ...)
639{
640 va_list args;
641 int length;
642
643 va_start(args, format);
644 length = acpi_ut_file_vprintf(file, format, args);
645 va_end(args);
646
647 return (length);
648}
649#endif