xref: /linux/drivers/acpi/acpica/utstring.c (revision 2da68a77)
1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2 /*******************************************************************************
3  *
4  * Module Name: utstring - Common functions for strings and characters
5  *
6  ******************************************************************************/
7 
8 #include <acpi/acpi.h>
9 #include "accommon.h"
10 #include "acnamesp.h"
11 
12 #define _COMPONENT          ACPI_UTILITIES
13 ACPI_MODULE_NAME("utstring")
14 
15 /*******************************************************************************
16  *
17  * FUNCTION:    acpi_ut_print_string
18  *
19  * PARAMETERS:  string          - Null terminated ASCII string
20  *              max_length      - Maximum output length. Used to constrain the
21  *                                length of strings during debug output only.
22  *
23  * RETURN:      None
24  *
25  * DESCRIPTION: Dump an ASCII string with support for ACPI-defined escape
26  *              sequences.
27  *
28  ******************************************************************************/
29 void acpi_ut_print_string(char *string, u16 max_length)
30 {
31 	u32 i;
32 
33 	if (!string) {
34 		acpi_os_printf("<\"NULL STRING PTR\">");
35 		return;
36 	}
37 
38 	acpi_os_printf("\"");
39 	for (i = 0; (i < max_length) && string[i]; i++) {
40 
41 		/* Escape sequences */
42 
43 		switch (string[i]) {
44 		case 0x07:
45 
46 			acpi_os_printf("\\a");	/* BELL */
47 			break;
48 
49 		case 0x08:
50 
51 			acpi_os_printf("\\b");	/* BACKSPACE */
52 			break;
53 
54 		case 0x0C:
55 
56 			acpi_os_printf("\\f");	/* FORMFEED */
57 			break;
58 
59 		case 0x0A:
60 
61 			acpi_os_printf("\\n");	/* LINEFEED */
62 			break;
63 
64 		case 0x0D:
65 
66 			acpi_os_printf("\\r");	/* CARRIAGE RETURN */
67 			break;
68 
69 		case 0x09:
70 
71 			acpi_os_printf("\\t");	/* HORIZONTAL TAB */
72 			break;
73 
74 		case 0x0B:
75 
76 			acpi_os_printf("\\v");	/* VERTICAL TAB */
77 			break;
78 
79 		case '\'':	/* Single Quote */
80 		case '\"':	/* Double Quote */
81 		case '\\':	/* Backslash */
82 
83 			acpi_os_printf("\\%c", (int)string[i]);
84 			break;
85 
86 		default:
87 
88 			/* Check for printable character or hex escape */
89 
90 			if (isprint((int)string[i])) {
91 				/* This is a normal character */
92 
93 				acpi_os_printf("%c", (int)string[i]);
94 			} else {
95 				/* All others will be Hex escapes */
96 
97 				acpi_os_printf("\\x%2.2X", (s32)string[i]);
98 			}
99 			break;
100 		}
101 	}
102 
103 	acpi_os_printf("\"");
104 
105 	if (i == max_length && string[i]) {
106 		acpi_os_printf("...");
107 	}
108 }
109 
110 /*******************************************************************************
111  *
112  * FUNCTION:    acpi_ut_repair_name
113  *
114  * PARAMETERS:  name            - The ACPI name to be repaired
115  *
116  * RETURN:      Repaired version of the name
117  *
118  * DESCRIPTION: Repair an ACPI name: Change invalid characters to '*' and
119  *              return the new name. NOTE: the Name parameter must reside in
120  *              read/write memory, cannot be a const.
121  *
122  * An ACPI Name must consist of valid ACPI characters. We will repair the name
123  * if necessary because we don't want to abort because of this, but we want
124  * all namespace names to be printable. A warning message is appropriate.
125  *
126  * This issue came up because there are in fact machines that exhibit
127  * this problem, and we want to be able to enable ACPI support for them,
128  * even though there are a few bad names.
129  *
130  ******************************************************************************/
131 
132 void acpi_ut_repair_name(char *name)
133 {
134 	u32 i;
135 	u8 found_bad_char = FALSE;
136 	u32 original_name;
137 
138 	ACPI_FUNCTION_NAME(ut_repair_name);
139 
140 	/*
141 	 * Special case for the root node. This can happen if we get an
142 	 * error during the execution of module-level code.
143 	 */
144 	if (ACPI_COMPARE_NAMESEG(name, ACPI_ROOT_PATHNAME)) {
145 		return;
146 	}
147 
148 	ACPI_COPY_NAMESEG(&original_name, &name[0]);
149 
150 	/* Check each character in the name */
151 
152 	for (i = 0; i < ACPI_NAMESEG_SIZE; i++) {
153 		if (acpi_ut_valid_name_char(name[i], i)) {
154 			continue;
155 		}
156 
157 		/*
158 		 * Replace a bad character with something printable, yet technically
159 		 * "odd". This prevents any collisions with existing "good"
160 		 * names in the namespace.
161 		 */
162 		name[i] = '_';
163 		found_bad_char = TRUE;
164 	}
165 
166 	if (found_bad_char) {
167 
168 		/* Report warning only if in strict mode or debug mode */
169 
170 		if (!acpi_gbl_enable_interpreter_slack) {
171 			ACPI_WARNING((AE_INFO,
172 				      "Invalid character(s) in name (0x%.8X) %p, repaired: [%4.4s]",
173 				      original_name, name, &name[0]));
174 		} else {
175 			ACPI_DEBUG_PRINT((ACPI_DB_INFO,
176 					  "Invalid character(s) in name (0x%.8X), repaired: [%4.4s]",
177 					  original_name, name));
178 		}
179 	}
180 }
181 
182 #if defined ACPI_ASL_COMPILER || defined ACPI_EXEC_APP
183 /*******************************************************************************
184  *
185  * FUNCTION:    ut_convert_backslashes
186  *
187  * PARAMETERS:  pathname        - File pathname string to be converted
188  *
189  * RETURN:      Modifies the input Pathname
190  *
191  * DESCRIPTION: Convert all backslashes (0x5C) to forward slashes (0x2F) within
192  *              the entire input file pathname string.
193  *
194  ******************************************************************************/
195 
196 void ut_convert_backslashes(char *pathname)
197 {
198 
199 	if (!pathname) {
200 		return;
201 	}
202 
203 	while (*pathname) {
204 		if (*pathname == '\\') {
205 			*pathname = '/';
206 		}
207 
208 		pathname++;
209 	}
210 }
211 #endif
212