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