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