| 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(format: "<\"NULL STRING PTR\">"); | 
|---|
| 35 | return; | 
|---|
| 36 | } | 
|---|
| 37 |  | 
|---|
| 38 | acpi_os_printf(format: "\""); | 
|---|
| 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(format: "\\a");	/* BELL */ | 
|---|
| 47 | break; | 
|---|
| 48 |  | 
|---|
| 49 | case 0x08: | 
|---|
| 50 |  | 
|---|
| 51 | acpi_os_printf(format: "\\b");	/* BACKSPACE */ | 
|---|
| 52 | break; | 
|---|
| 53 |  | 
|---|
| 54 | case 0x0C: | 
|---|
| 55 |  | 
|---|
| 56 | acpi_os_printf(format: "\\f");	/* FORMFEED */ | 
|---|
| 57 | break; | 
|---|
| 58 |  | 
|---|
| 59 | case 0x0A: | 
|---|
| 60 |  | 
|---|
| 61 | acpi_os_printf(format: "\\n");	/* LINEFEED */ | 
|---|
| 62 | break; | 
|---|
| 63 |  | 
|---|
| 64 | case 0x0D: | 
|---|
| 65 |  | 
|---|
| 66 | acpi_os_printf(format: "\\r");	/* CARRIAGE RETURN */ | 
|---|
| 67 | break; | 
|---|
| 68 |  | 
|---|
| 69 | case 0x09: | 
|---|
| 70 |  | 
|---|
| 71 | acpi_os_printf(format: "\\t");	/* HORIZONTAL TAB */ | 
|---|
| 72 | break; | 
|---|
| 73 |  | 
|---|
| 74 | case 0x0B: | 
|---|
| 75 |  | 
|---|
| 76 | acpi_os_printf(format: "\\v");	/* VERTICAL TAB */ | 
|---|
| 77 | break; | 
|---|
| 78 |  | 
|---|
| 79 | case '\'':	/* Single Quote */ | 
|---|
| 80 | case '\"':	/* Double Quote */ | 
|---|
| 81 | case '\\':	/* Backslash */ | 
|---|
| 82 |  | 
|---|
| 83 | acpi_os_printf(format: "\\%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(format: "%c", (int)string[i]); | 
|---|
| 94 | } else { | 
|---|
| 95 | /* All others will be Hex escapes */ | 
|---|
| 96 |  | 
|---|
| 97 | acpi_os_printf(format: "\\x%2.2X", (s32)string[i]); | 
|---|
| 98 | } | 
|---|
| 99 | break; | 
|---|
| 100 | } | 
|---|
| 101 | } | 
|---|
| 102 |  | 
|---|
| 103 | acpi_os_printf(format: "\""); | 
|---|
| 104 |  | 
|---|
| 105 | if (i == max_length && string[i]) { | 
|---|
| 106 | acpi_os_printf(format: "..."); | 
|---|
| 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(character: name[i], position: 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 |  | 
|---|