Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
at v2.6.12-rc2 427 lines 12 kB view raw
1 2/****************************************************************************** 3 * 4 * Module Name: exnames - interpreter/scanner name load/execute 5 * 6 *****************************************************************************/ 7 8/* 9 * Copyright (C) 2000 - 2005, R. Byron Moore 10 * All rights reserved. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions, and the following disclaimer, 17 * without modification. 18 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 19 * substantially similar to the "NO WARRANTY" disclaimer below 20 * ("Disclaimer") and any redistribution must be conditioned upon 21 * including a substantially similar Disclaimer requirement for further 22 * binary redistribution. 23 * 3. Neither the names of the above-listed copyright holders nor the names 24 * of any contributors may be used to endorse or promote products derived 25 * from this software without specific prior written permission. 26 * 27 * Alternatively, this software may be distributed under the terms of the 28 * GNU General Public License ("GPL") version 2 as published by the Free 29 * Software Foundation. 30 * 31 * NO WARRANTY 32 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 33 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 34 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 35 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 36 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 40 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 41 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 42 * POSSIBILITY OF SUCH DAMAGES. 43 */ 44 45 46#include <acpi/acpi.h> 47#include <acpi/acinterp.h> 48#include <acpi/amlcode.h> 49 50#define _COMPONENT ACPI_EXECUTER 51 ACPI_MODULE_NAME ("exnames") 52 53 54/* AML Package Length encodings */ 55 56#define ACPI_AML_PACKAGE_TYPE1 0x40 57#define ACPI_AML_PACKAGE_TYPE2 0x4000 58#define ACPI_AML_PACKAGE_TYPE3 0x400000 59#define ACPI_AML_PACKAGE_TYPE4 0x40000000 60 61 62/******************************************************************************* 63 * 64 * FUNCTION: acpi_ex_allocate_name_string 65 * 66 * PARAMETERS: prefix_count - Count of parent levels. Special cases: 67 * (-1) = root, 0 = none 68 * num_name_segs - count of 4-character name segments 69 * 70 * RETURN: A pointer to the allocated string segment. This segment must 71 * be deleted by the caller. 72 * 73 * DESCRIPTION: Allocate a buffer for a name string. Ensure allocated name 74 * string is long enough, and set up prefix if any. 75 * 76 ******************************************************************************/ 77 78char * 79acpi_ex_allocate_name_string ( 80 u32 prefix_count, 81 u32 num_name_segs) 82{ 83 char *temp_ptr; 84 char *name_string; 85 u32 size_needed; 86 87 ACPI_FUNCTION_TRACE ("ex_allocate_name_string"); 88 89 90 /* 91 * Allow room for all \ and ^ prefixes, all segments, and a multi_name_prefix. 92 * Also, one byte for the null terminator. 93 * This may actually be somewhat longer than needed. 94 */ 95 if (prefix_count == ACPI_UINT32_MAX) { 96 /* Special case for root */ 97 98 size_needed = 1 + (ACPI_NAME_SIZE * num_name_segs) + 2 + 1; 99 } 100 else { 101 size_needed = prefix_count + (ACPI_NAME_SIZE * num_name_segs) + 2 + 1; 102 } 103 104 /* 105 * Allocate a buffer for the name. 106 * This buffer must be deleted by the caller! 107 */ 108 name_string = ACPI_MEM_ALLOCATE (size_needed); 109 if (!name_string) { 110 ACPI_REPORT_ERROR (("ex_allocate_name_string: Could not allocate size %d\n", size_needed)); 111 return_PTR (NULL); 112 } 113 114 temp_ptr = name_string; 115 116 /* Set up Root or Parent prefixes if needed */ 117 118 if (prefix_count == ACPI_UINT32_MAX) { 119 *temp_ptr++ = AML_ROOT_PREFIX; 120 } 121 else { 122 while (prefix_count--) { 123 *temp_ptr++ = AML_PARENT_PREFIX; 124 } 125 } 126 127 128 /* Set up Dual or Multi prefixes if needed */ 129 130 if (num_name_segs > 2) { 131 /* Set up multi prefixes */ 132 133 *temp_ptr++ = AML_MULTI_NAME_PREFIX_OP; 134 *temp_ptr++ = (char) num_name_segs; 135 } 136 else if (2 == num_name_segs) { 137 /* Set up dual prefixes */ 138 139 *temp_ptr++ = AML_DUAL_NAME_PREFIX; 140 } 141 142 /* 143 * Terminate string following prefixes. acpi_ex_name_segment() will 144 * append the segment(s) 145 */ 146 *temp_ptr = 0; 147 148 return_PTR (name_string); 149} 150 151/******************************************************************************* 152 * 153 * FUNCTION: acpi_ex_name_segment 154 * 155 * PARAMETERS: interpreter_mode - Current running mode (load1/Load2/Exec) 156 * 157 * RETURN: Status 158 * 159 * DESCRIPTION: Execute a name segment (4 bytes) 160 * 161 ******************************************************************************/ 162 163acpi_status 164acpi_ex_name_segment ( 165 u8 **in_aml_address, 166 char *name_string) 167{ 168 char *aml_address = (void *) *in_aml_address; 169 acpi_status status = AE_OK; 170 u32 index; 171 char char_buf[5]; 172 173 174 ACPI_FUNCTION_TRACE ("ex_name_segment"); 175 176 177 /* 178 * If first character is a digit, then we know that we aren't looking at a 179 * valid name segment 180 */ 181 char_buf[0] = *aml_address; 182 183 if ('0' <= char_buf[0] && char_buf[0] <= '9') { 184 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "leading digit: %c\n", char_buf[0])); 185 return_ACPI_STATUS (AE_CTRL_PENDING); 186 } 187 188 ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "Bytes from stream:\n")); 189 190 for (index = 0; 191 (index < ACPI_NAME_SIZE) && (acpi_ut_valid_acpi_character (*aml_address)); 192 index++) { 193 char_buf[index] = *aml_address++; 194 ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "%c\n", char_buf[index])); 195 } 196 197 198 /* Valid name segment */ 199 200 if (index == 4) { 201 /* Found 4 valid characters */ 202 203 char_buf[4] = '\0'; 204 205 if (name_string) { 206 ACPI_STRCAT (name_string, char_buf); 207 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, 208 "Appended to - %s \n", name_string)); 209 } 210 else { 211 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, 212 "No Name string - %s \n", char_buf)); 213 } 214 } 215 else if (index == 0) { 216 /* 217 * First character was not a valid name character, 218 * so we are looking at something other than a name. 219 */ 220 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, 221 "Leading character is not alpha: %02Xh (not a name)\n", 222 char_buf[0])); 223 status = AE_CTRL_PENDING; 224 } 225 else { 226 /* Segment started with one or more valid characters, but fewer than 4 */ 227 228 status = AE_AML_BAD_NAME; 229 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Bad character %02x in name, at %p\n", 230 *aml_address, aml_address)); 231 } 232 233 *in_aml_address = (u8 *) aml_address; 234 return_ACPI_STATUS (status); 235} 236 237 238/******************************************************************************* 239 * 240 * FUNCTION: acpi_ex_get_name_string 241 * 242 * PARAMETERS: data_type - Data type to be associated with this name 243 * 244 * RETURN: Status 245 * 246 * DESCRIPTION: Get a name, including any prefixes. 247 * 248 ******************************************************************************/ 249 250acpi_status 251acpi_ex_get_name_string ( 252 acpi_object_type data_type, 253 u8 *in_aml_address, 254 char **out_name_string, 255 u32 *out_name_length) 256{ 257 acpi_status status = AE_OK; 258 u8 *aml_address = in_aml_address; 259 char *name_string = NULL; 260 u32 num_segments; 261 u32 prefix_count = 0; 262 u8 has_prefix = FALSE; 263 264 265 ACPI_FUNCTION_TRACE_PTR ("ex_get_name_string", aml_address); 266 267 268 if (ACPI_TYPE_LOCAL_REGION_FIELD == data_type || 269 ACPI_TYPE_LOCAL_BANK_FIELD == data_type || 270 ACPI_TYPE_LOCAL_INDEX_FIELD == data_type) { 271 /* Disallow prefixes for types associated with field_unit names */ 272 273 name_string = acpi_ex_allocate_name_string (0, 1); 274 if (!name_string) { 275 status = AE_NO_MEMORY; 276 } 277 else { 278 status = acpi_ex_name_segment (&aml_address, name_string); 279 } 280 } 281 else { 282 /* 283 * data_type is not a field name. 284 * Examine first character of name for root or parent prefix operators 285 */ 286 switch (*aml_address) { 287 case AML_ROOT_PREFIX: 288 289 ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "root_prefix(\\) at %p\n", aml_address)); 290 291 /* 292 * Remember that we have a root_prefix -- 293 * see comment in acpi_ex_allocate_name_string() 294 */ 295 aml_address++; 296 prefix_count = ACPI_UINT32_MAX; 297 has_prefix = TRUE; 298 break; 299 300 301 case AML_PARENT_PREFIX: 302 303 /* Increment past possibly multiple parent prefixes */ 304 305 do { 306 ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "parent_prefix (^) at %p\n", aml_address)); 307 308 aml_address++; 309 prefix_count++; 310 311 } while (*aml_address == AML_PARENT_PREFIX); 312 313 has_prefix = TRUE; 314 break; 315 316 317 default: 318 319 /* Not a prefix character */ 320 321 break; 322 } 323 324 325 /* Examine first character of name for name segment prefix operator */ 326 327 switch (*aml_address) { 328 case AML_DUAL_NAME_PREFIX: 329 330 ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "dual_name_prefix at %p\n", aml_address)); 331 332 aml_address++; 333 name_string = acpi_ex_allocate_name_string (prefix_count, 2); 334 if (!name_string) { 335 status = AE_NO_MEMORY; 336 break; 337 } 338 339 /* Indicate that we processed a prefix */ 340 341 has_prefix = TRUE; 342 343 status = acpi_ex_name_segment (&aml_address, name_string); 344 if (ACPI_SUCCESS (status)) { 345 status = acpi_ex_name_segment (&aml_address, name_string); 346 } 347 break; 348 349 350 case AML_MULTI_NAME_PREFIX_OP: 351 352 ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "multi_name_prefix at %p\n", aml_address)); 353 354 /* Fetch count of segments remaining in name path */ 355 356 aml_address++; 357 num_segments = *aml_address; 358 359 name_string = acpi_ex_allocate_name_string (prefix_count, num_segments); 360 if (!name_string) { 361 status = AE_NO_MEMORY; 362 break; 363 } 364 365 /* Indicate that we processed a prefix */ 366 367 aml_address++; 368 has_prefix = TRUE; 369 370 while (num_segments && 371 (status = acpi_ex_name_segment (&aml_address, name_string)) == AE_OK) { 372 num_segments--; 373 } 374 375 break; 376 377 378 case 0: 379 380 /* null_name valid as of 8-12-98 ASL/AML Grammar Update */ 381 382 if (prefix_count == ACPI_UINT32_MAX) { 383 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "name_seg is \"\\\" followed by NULL\n")); 384 } 385 386 /* Consume the NULL byte */ 387 388 aml_address++; 389 name_string = acpi_ex_allocate_name_string (prefix_count, 0); 390 if (!name_string) { 391 status = AE_NO_MEMORY; 392 break; 393 } 394 395 break; 396 397 398 default: 399 400 /* Name segment string */ 401 402 name_string = acpi_ex_allocate_name_string (prefix_count, 1); 403 if (!name_string) { 404 status = AE_NO_MEMORY; 405 break; 406 } 407 408 status = acpi_ex_name_segment (&aml_address, name_string); 409 break; 410 } 411 } 412 413 if (AE_CTRL_PENDING == status && has_prefix) { 414 /* Ran out of segments after processing a prefix */ 415 416 ACPI_REPORT_ERROR ( 417 ("ex_do_name: Malformed Name at %p\n", name_string)); 418 status = AE_AML_BAD_NAME; 419 } 420 421 *out_name_string = name_string; 422 *out_name_length = (u32) (aml_address - in_aml_address); 423 424 return_ACPI_STATUS (status); 425} 426 427