Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.13-rc4 447 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/* Local prototypes */ 54 55static char * 56acpi_ex_allocate_name_string ( 57 u32 prefix_count, 58 u32 num_name_segs); 59 60static acpi_status 61acpi_ex_name_segment ( 62 u8 **in_aml_address, 63 char *name_string); 64 65 66/******************************************************************************* 67 * 68 * FUNCTION: acpi_ex_allocate_name_string 69 * 70 * PARAMETERS: prefix_count - Count of parent levels. Special cases: 71 * (-1)==root, 0==none 72 * num_name_segs - count of 4-character name segments 73 * 74 * RETURN: A pointer to the allocated string segment. This segment must 75 * be deleted by the caller. 76 * 77 * DESCRIPTION: Allocate a buffer for a name string. Ensure allocated name 78 * string is long enough, and set up prefix if any. 79 * 80 ******************************************************************************/ 81 82static char * 83acpi_ex_allocate_name_string ( 84 u32 prefix_count, 85 u32 num_name_segs) 86{ 87 char *temp_ptr; 88 char *name_string; 89 u32 size_needed; 90 91 ACPI_FUNCTION_TRACE ("ex_allocate_name_string"); 92 93 94 /* 95 * Allow room for all \ and ^ prefixes, all segments and a multi_name_prefix. 96 * Also, one byte for the null terminator. 97 * This may actually be somewhat longer than needed. 98 */ 99 if (prefix_count == ACPI_UINT32_MAX) { 100 /* Special case for root */ 101 102 size_needed = 1 + (ACPI_NAME_SIZE * num_name_segs) + 2 + 1; 103 } 104 else { 105 size_needed = prefix_count + (ACPI_NAME_SIZE * num_name_segs) + 2 + 1; 106 } 107 108 /* 109 * Allocate a buffer for the name. 110 * This buffer must be deleted by the caller! 111 */ 112 name_string = ACPI_MEM_ALLOCATE (size_needed); 113 if (!name_string) { 114 ACPI_REPORT_ERROR (( 115 "ex_allocate_name_string: Could not allocate size %d\n", size_needed)); 116 return_PTR (NULL); 117 } 118 119 temp_ptr = name_string; 120 121 /* Set up Root or Parent prefixes if needed */ 122 123 if (prefix_count == ACPI_UINT32_MAX) { 124 *temp_ptr++ = AML_ROOT_PREFIX; 125 } 126 else { 127 while (prefix_count--) { 128 *temp_ptr++ = AML_PARENT_PREFIX; 129 } 130 } 131 132 133 /* Set up Dual or Multi prefixes if needed */ 134 135 if (num_name_segs > 2) { 136 /* Set up multi prefixes */ 137 138 *temp_ptr++ = AML_MULTI_NAME_PREFIX_OP; 139 *temp_ptr++ = (char) num_name_segs; 140 } 141 else if (2 == num_name_segs) { 142 /* Set up dual prefixes */ 143 144 *temp_ptr++ = AML_DUAL_NAME_PREFIX; 145 } 146 147 /* 148 * Terminate string following prefixes. acpi_ex_name_segment() will 149 * append the segment(s) 150 */ 151 *temp_ptr = 0; 152 153 return_PTR (name_string); 154} 155 156/******************************************************************************* 157 * 158 * FUNCTION: acpi_ex_name_segment 159 * 160 * PARAMETERS: in_aml_address - Pointer to the name in the AML code 161 * name_string - Where to return the name. The name is appended 162 * to any existing string to form a namepath 163 * 164 * RETURN: Status 165 * 166 * DESCRIPTION: Extract an ACPI name (4 bytes) from the AML byte stream 167 * 168 ******************************************************************************/ 169 170static acpi_status 171acpi_ex_name_segment ( 172 u8 **in_aml_address, 173 char *name_string) 174{ 175 char *aml_address = (void *) *in_aml_address; 176 acpi_status status = AE_OK; 177 u32 index; 178 char char_buf[5]; 179 180 181 ACPI_FUNCTION_TRACE ("ex_name_segment"); 182 183 184 /* 185 * If first character is a digit, then we know that we aren't looking at a 186 * valid name segment 187 */ 188 char_buf[0] = *aml_address; 189 190 if ('0' <= char_buf[0] && char_buf[0] <= '9') { 191 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "leading digit: %c\n", char_buf[0])); 192 return_ACPI_STATUS (AE_CTRL_PENDING); 193 } 194 195 ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "Bytes from stream:\n")); 196 197 for (index = 0; 198 (index < ACPI_NAME_SIZE) && (acpi_ut_valid_acpi_character (*aml_address)); 199 index++) { 200 char_buf[index] = *aml_address++; 201 ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "%c\n", char_buf[index])); 202 } 203 204 205 /* Valid name segment */ 206 207 if (index == 4) { 208 /* Found 4 valid characters */ 209 210 char_buf[4] = '\0'; 211 212 if (name_string) { 213 ACPI_STRCAT (name_string, char_buf); 214 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, 215 "Appended to - %s \n", name_string)); 216 } 217 else { 218 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, 219 "No Name string - %s \n", char_buf)); 220 } 221 } 222 else if (index == 0) { 223 /* 224 * First character was not a valid name character, 225 * so we are looking at something other than a name. 226 */ 227 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, 228 "Leading character is not alpha: %02Xh (not a name)\n", 229 char_buf[0])); 230 status = AE_CTRL_PENDING; 231 } 232 else { 233 /* 234 * Segment started with one or more valid characters, but fewer than 235 * the required 4 236 */ 237 status = AE_AML_BAD_NAME; 238 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, 239 "Bad character %02x in name, at %p\n", 240 *aml_address, aml_address)); 241 } 242 243 *in_aml_address = (u8 *) aml_address; 244 return_ACPI_STATUS (status); 245} 246 247 248/******************************************************************************* 249 * 250 * FUNCTION: acpi_ex_get_name_string 251 * 252 * PARAMETERS: data_type - Object type to be associated with this 253 * name 254 * in_aml_address - Pointer to the namestring in the AML code 255 * out_name_string - Where the namestring is returned 256 * out_name_length - Length of the returned string 257 * 258 * RETURN: Status, namestring and length 259 * 260 * DESCRIPTION: Extract a full namepath from the AML byte stream, 261 * including any prefixes. 262 * 263 ******************************************************************************/ 264 265acpi_status 266acpi_ex_get_name_string ( 267 acpi_object_type data_type, 268 u8 *in_aml_address, 269 char **out_name_string, 270 u32 *out_name_length) 271{ 272 acpi_status status = AE_OK; 273 u8 *aml_address = in_aml_address; 274 char *name_string = NULL; 275 u32 num_segments; 276 u32 prefix_count = 0; 277 u8 has_prefix = FALSE; 278 279 280 ACPI_FUNCTION_TRACE_PTR ("ex_get_name_string", aml_address); 281 282 283 if (ACPI_TYPE_LOCAL_REGION_FIELD == data_type || 284 ACPI_TYPE_LOCAL_BANK_FIELD == data_type || 285 ACPI_TYPE_LOCAL_INDEX_FIELD == data_type) { 286 /* Disallow prefixes for types associated with field_unit names */ 287 288 name_string = acpi_ex_allocate_name_string (0, 1); 289 if (!name_string) { 290 status = AE_NO_MEMORY; 291 } 292 else { 293 status = acpi_ex_name_segment (&aml_address, name_string); 294 } 295 } 296 else { 297 /* 298 * data_type is not a field name. 299 * Examine first character of name for root or parent prefix operators 300 */ 301 switch (*aml_address) { 302 case AML_ROOT_PREFIX: 303 304 ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "root_prefix(\\) at %p\n", 305 aml_address)); 306 307 /* 308 * Remember that we have a root_prefix -- 309 * see comment in acpi_ex_allocate_name_string() 310 */ 311 aml_address++; 312 prefix_count = ACPI_UINT32_MAX; 313 has_prefix = TRUE; 314 break; 315 316 317 case AML_PARENT_PREFIX: 318 319 /* Increment past possibly multiple parent prefixes */ 320 321 do { 322 ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "parent_prefix (^) at %p\n", 323 aml_address)); 324 325 aml_address++; 326 prefix_count++; 327 328 } while (*aml_address == AML_PARENT_PREFIX); 329 330 has_prefix = TRUE; 331 break; 332 333 334 default: 335 336 /* Not a prefix character */ 337 338 break; 339 } 340 341 /* Examine first character of name for name segment prefix operator */ 342 343 switch (*aml_address) { 344 case AML_DUAL_NAME_PREFIX: 345 346 ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "dual_name_prefix at %p\n", 347 aml_address)); 348 349 aml_address++; 350 name_string = acpi_ex_allocate_name_string (prefix_count, 2); 351 if (!name_string) { 352 status = AE_NO_MEMORY; 353 break; 354 } 355 356 /* Indicate that we processed a prefix */ 357 358 has_prefix = TRUE; 359 360 status = acpi_ex_name_segment (&aml_address, name_string); 361 if (ACPI_SUCCESS (status)) { 362 status = acpi_ex_name_segment (&aml_address, name_string); 363 } 364 break; 365 366 367 case AML_MULTI_NAME_PREFIX_OP: 368 369 ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "multi_name_prefix at %p\n", 370 aml_address)); 371 372 /* Fetch count of segments remaining in name path */ 373 374 aml_address++; 375 num_segments = *aml_address; 376 377 name_string = acpi_ex_allocate_name_string (prefix_count, num_segments); 378 if (!name_string) { 379 status = AE_NO_MEMORY; 380 break; 381 } 382 383 /* Indicate that we processed a prefix */ 384 385 aml_address++; 386 has_prefix = TRUE; 387 388 while (num_segments && 389 (status = acpi_ex_name_segment (&aml_address, name_string)) == 390 AE_OK) { 391 num_segments--; 392 } 393 394 break; 395 396 397 case 0: 398 399 /* null_name valid as of 8-12-98 ASL/AML Grammar Update */ 400 401 if (prefix_count == ACPI_UINT32_MAX) { 402 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, 403 "name_seg is \"\\\" followed by NULL\n")); 404 } 405 406 /* Consume the NULL byte */ 407 408 aml_address++; 409 name_string = acpi_ex_allocate_name_string (prefix_count, 0); 410 if (!name_string) { 411 status = AE_NO_MEMORY; 412 break; 413 } 414 415 break; 416 417 418 default: 419 420 /* Name segment string */ 421 422 name_string = acpi_ex_allocate_name_string (prefix_count, 1); 423 if (!name_string) { 424 status = AE_NO_MEMORY; 425 break; 426 } 427 428 status = acpi_ex_name_segment (&aml_address, name_string); 429 break; 430 } 431 } 432 433 if (AE_CTRL_PENDING == status && has_prefix) { 434 /* Ran out of segments after processing a prefix */ 435 436 ACPI_REPORT_ERROR ( 437 ("ex_do_name: Malformed Name at %p\n", name_string)); 438 status = AE_AML_BAD_NAME; 439 } 440 441 *out_name_string = name_string; 442 *out_name_length = (u32) (aml_address - in_aml_address); 443 444 return_ACPI_STATUS (status); 445} 446 447