nsaccess.c 14.8 KB
Newer Older
Linus Torvalds's avatar
Linus Torvalds committed
1 2 3
/*******************************************************************************
 *
 * Module Name: nsaccess - Top-level functions for accessing ACPI namespace
Andy Grover's avatar
Andy Grover committed
4
 *              $Revision: 152 $
Linus Torvalds's avatar
Linus Torvalds committed
5 6 7 8
 *
 ******************************************************************************/

/*
Andy Grover's avatar
Andy Grover committed
9
 *  Copyright (C) 2000 - 2002, R. Byron Moore
Linus Torvalds's avatar
Linus Torvalds committed
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */


#include "acpi.h"
#include "amlcode.h"
#include "acinterp.h"
#include "acnamesp.h"
#include "acdispat.h"


Linus Torvalds's avatar
Linus Torvalds committed
34
#define _COMPONENT          ACPI_NAMESPACE
Andy Grover's avatar
Andy Grover committed
35
	 ACPI_MODULE_NAME    ("nsaccess")
Linus Torvalds's avatar
Linus Torvalds committed
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51


/*******************************************************************************
 *
 * FUNCTION:    Acpi_ns_root_initialize
 *
 * PARAMETERS:  None
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Allocate and initialize the default root named objects
 *
 * MUTEX:       Locks namespace for entire execution
 *
 ******************************************************************************/

Linus Torvalds's avatar
Linus Torvalds committed
52
acpi_status
Linus Torvalds's avatar
Linus Torvalds committed
53 54
acpi_ns_root_initialize (void)
{
Andy Grover's avatar
Andy Grover committed
55 56 57 58
	acpi_status                 status;
	const acpi_predefined_names *init_val = NULL;
	acpi_namespace_node         *new_node;
	acpi_operand_object         *obj_desc;
Linus Torvalds's avatar
Linus Torvalds committed
59 60


Andy Grover's avatar
Andy Grover committed
61
	ACPI_FUNCTION_TRACE ("Ns_root_initialize");
Linus Torvalds's avatar
Linus Torvalds committed
62 63


Andy Grover's avatar
Andy Grover committed
64 65 66 67
	status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
	if (ACPI_FAILURE (status)) {
		return_ACPI_STATUS (status);
	}
Linus Torvalds's avatar
Linus Torvalds committed
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85

	/*
	 * The global root ptr is initially NULL, so a non-NULL value indicates
	 * that Acpi_ns_root_initialize() has already been called; just return.
	 */
	if (acpi_gbl_root_node) {
		status = AE_OK;
		goto unlock_and_exit;
	}

	/*
	 * Tell the rest of the subsystem that the root is initialized
	 * (This is OK because the namespace is locked)
	 */
	acpi_gbl_root_node = &acpi_gbl_root_node_struct;

	/* Enter the pre-defined names in the name table */

Andy Grover's avatar
Andy Grover committed
86 87
	ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
		"Entering predefined entries into namespace\n"));
Linus Torvalds's avatar
Linus Torvalds committed
88

Linus Torvalds's avatar
Linus Torvalds committed
89
	for (init_val = acpi_gbl_pre_defined_names; init_val->name; init_val++) {
Linus Torvalds's avatar
Linus Torvalds committed
90
		status = acpi_ns_lookup (NULL, init_val->name, init_val->type,
Andy Grover's avatar
Andy Grover committed
91
				  ACPI_IMODE_LOAD_PASS2, ACPI_NS_NO_UPSEARCH, NULL, &new_node);
Linus Torvalds's avatar
Linus Torvalds committed
92

Linus Torvalds's avatar
Linus Torvalds committed
93 94 95 96 97
		if (ACPI_FAILURE (status) || (!new_node)) /* Must be on same line for code converter */ {
			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
				"Could not create predefined name %s, %s\n",
				init_val->name, acpi_format_exception (status)));
		}
Linus Torvalds's avatar
Linus Torvalds committed
98 99 100 101 102 103 104 105 106 107 108

		/*
		 * Name entered successfully.
		 * If entry in Pre_defined_names[] specifies an
		 * initial value, create the initial value.
		 */
		if (init_val->val) {
			/*
			 * Entry requests an initial value, allocate a
			 * descriptor for it.
			 */
Linus Torvalds's avatar
Linus Torvalds committed
109
			obj_desc = acpi_ut_create_internal_object (init_val->type);
Linus Torvalds's avatar
Linus Torvalds committed
110 111 112 113 114 115 116 117 118 119
			if (!obj_desc) {
				status = AE_NO_MEMORY;
				goto unlock_and_exit;
			}

			/*
			 * Convert value string from table entry to
			 * internal representation. Only types actually
			 * used for initial values are implemented here.
			 */
Linus Torvalds's avatar
Linus Torvalds committed
120
			switch (init_val->type) {
Linus Torvalds's avatar
Linus Torvalds committed
121
			case ACPI_TYPE_INTEGER:
Linus Torvalds's avatar
Linus Torvalds committed
122

Linus Torvalds's avatar
Linus Torvalds committed
123
				obj_desc->integer.value =
Andy Grover's avatar
Andy Grover committed
124
						(acpi_integer) ACPI_STRTOUL (init_val->val, NULL, 10);
Linus Torvalds's avatar
Linus Torvalds committed
125 126 127 128 129 130
				break;


			case ACPI_TYPE_STRING:

				/*
Linus Torvalds's avatar
Linus Torvalds committed
131
				 * Build an object around the static string
Linus Torvalds's avatar
Linus Torvalds committed
132
				 */
Andy Grover's avatar
Andy Grover committed
133
				obj_desc->string.length = ACPI_STRLEN (init_val->val);
Linus Torvalds's avatar
Linus Torvalds committed
134 135
				obj_desc->string.pointer = init_val->val;
				obj_desc->common.flags |= AOPOBJ_STATIC_POINTER;
Linus Torvalds's avatar
Linus Torvalds committed
136 137 138 139 140 141
				break;


			case ACPI_TYPE_MUTEX:

				obj_desc->mutex.sync_level =
Andy Grover's avatar
Andy Grover committed
142
						 (u16) ACPI_STRTOUL (init_val->val, NULL, 10);
Linus Torvalds's avatar
Linus Torvalds committed
143

Andy Grover's avatar
Andy Grover committed
144
				if (ACPI_STRCMP (init_val->name, "_GL_") == 0) {
Linus Torvalds's avatar
Linus Torvalds committed
145 146 147 148 149 150 151 152 153
					/*
					 * Create a counting semaphore for the
					 * global lock
					 */
					status = acpi_os_create_semaphore (ACPI_NO_UNIT_LIMIT,
							 1, &obj_desc->mutex.semaphore);
					if (ACPI_FAILURE (status)) {
						goto unlock_and_exit;
					}
Linus Torvalds's avatar
Linus Torvalds committed
154

Linus Torvalds's avatar
Linus Torvalds committed
155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173
					/*
					 * We just created the mutex for the
					 * global lock, save it
					 */
					acpi_gbl_global_lock_semaphore = obj_desc->mutex.semaphore;
				}
				else {
					/* Create a mutex */

					status = acpi_os_create_semaphore (1, 1,
							   &obj_desc->mutex.semaphore);
					if (ACPI_FAILURE (status)) {
						goto unlock_and_exit;
					}
				}
				break;


			default:
Andy Grover's avatar
Andy Grover committed
174
				ACPI_REPORT_ERROR (("Unsupported initial type value %X\n",
Linus Torvalds's avatar
Linus Torvalds committed
175
					init_val->type));
Linus Torvalds's avatar
Linus Torvalds committed
176
				acpi_ut_remove_reference (obj_desc);
Linus Torvalds's avatar
Linus Torvalds committed
177 178 179 180 181 182
				obj_desc = NULL;
				continue;
			}

			/* Store pointer to value descriptor in the Node */

Linus Torvalds's avatar
Linus Torvalds committed
183
			acpi_ns_attach_object (new_node, obj_desc, obj_desc->common.type);
Linus Torvalds's avatar
Linus Torvalds committed
184 185 186 187

			/* Remove local reference to the object */

			acpi_ut_remove_reference (obj_desc);
Linus Torvalds's avatar
Linus Torvalds committed
188 189 190 191 192
		}
	}


unlock_and_exit:
Andy Grover's avatar
Andy Grover committed
193
	(void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
Linus Torvalds's avatar
Linus Torvalds committed
194
	return_ACPI_STATUS (status);
Linus Torvalds's avatar
Linus Torvalds committed
195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220
}


/*******************************************************************************
 *
 * FUNCTION:    Acpi_ns_lookup
 *
 * PARAMETERS:  Prefix_node     - Search scope if name is not fully qualified
 *              Pathname        - Search pathname, in internal format
 *                                (as represented in the AML stream)
 *              Type            - Type associated with name
 *              Interpreter_mode - IMODE_LOAD_PASS2 => add name if not found
 *              Flags           - Flags describing the search restrictions
 *              Walk_state      - Current state of the walk
 *              Return_node     - Where the Node is placed (if found
 *                                or created successfully)
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Find or enter the passed name in the name space.
 *              Log an error if name not found in Exec mode.
 *
 * MUTEX:       Assumes namespace is locked.
 *
 ******************************************************************************/

Linus Torvalds's avatar
Linus Torvalds committed
221
acpi_status
Linus Torvalds's avatar
Linus Torvalds committed
222
acpi_ns_lookup (
Linus Torvalds's avatar
Linus Torvalds committed
223
	acpi_generic_state      *scope_info,
Linus Torvalds's avatar
Linus Torvalds committed
224
	NATIVE_CHAR             *pathname,
Andy Grover's avatar
Andy Grover committed
225 226
	acpi_object_type        type,
	acpi_interpreter_mode   interpreter_mode,
Linus Torvalds's avatar
Linus Torvalds committed
227
	u32                     flags,
Linus Torvalds's avatar
Linus Torvalds committed
228 229
	acpi_walk_state         *walk_state,
	acpi_namespace_node     **return_node)
Linus Torvalds's avatar
Linus Torvalds committed
230
{
Linus Torvalds's avatar
Linus Torvalds committed
231 232 233 234
	acpi_status             status;
	acpi_namespace_node     *prefix_node;
	acpi_namespace_node     *current_node = NULL;
	acpi_namespace_node     *this_node = NULL;
Linus Torvalds's avatar
Linus Torvalds committed
235
	u32                     num_segments;
Linus Torvalds's avatar
Linus Torvalds committed
236
	acpi_name               simple_name;
Andy Grover's avatar
Andy Grover committed
237 238 239
	acpi_object_type        type_to_check_for;
	acpi_object_type        this_search_type;
	u32                     local_flags = flags & ~ACPI_NS_ERROR_IF_FOUND;
Linus Torvalds's avatar
Linus Torvalds committed
240

Linus Torvalds's avatar
Linus Torvalds committed
241

Andy Grover's avatar
Andy Grover committed
242
	ACPI_FUNCTION_TRACE ("Ns_lookup");
Linus Torvalds's avatar
Linus Torvalds committed
243

Linus Torvalds's avatar
Linus Torvalds committed
244 245

	if (!return_node) {
Linus Torvalds's avatar
Linus Torvalds committed
246
		return_ACPI_STATUS (AE_BAD_PARAMETER);
Linus Torvalds's avatar
Linus Torvalds committed
247 248 249
	}

	acpi_gbl_ns_lookup_count++;
Andy Grover's avatar
Andy Grover committed
250
	*return_node = ACPI_ENTRY_NOT_FOUND;
Linus Torvalds's avatar
Linus Torvalds committed
251 252

	if (!acpi_gbl_root_node) {
Andy Grover's avatar
Andy Grover committed
253
		return_ACPI_STATUS (AE_NO_NAMESPACE);
Linus Torvalds's avatar
Linus Torvalds committed
254 255 256 257 258 259 260
	}

	/*
	 * Get the prefix scope.
	 * A null scope means use the root scope
	 */
	if ((!scope_info) ||
Linus Torvalds's avatar
Linus Torvalds committed
261
		(!scope_info->scope.node)) {
Andy Grover's avatar
Andy Grover committed
262 263
		ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
			"Null scope prefix, using root node (%p)\n",
Linus Torvalds's avatar
Linus Torvalds committed
264 265
			acpi_gbl_root_node));

Linus Torvalds's avatar
Linus Torvalds committed
266 267 268 269 270 271 272
		prefix_node = acpi_gbl_root_node;
	}
	else {
		prefix_node = scope_info->scope.node;
	}

	/*
Linus Torvalds's avatar
Linus Torvalds committed
273
	 * This check is explicitly split to relax the Type_to_check_for
Linus Torvalds's avatar
Linus Torvalds committed
274 275 276 277 278
	 * conditions for Bank_field_defn. Originally, both Bank_field_defn and
	 * Def_field_defn caused Type_to_check_for to be set to ACPI_TYPE_REGION,
	 * but the Bank_field_defn may also check for a Field definition as well
	 * as an Operation_region.
	 */
Linus Torvalds's avatar
Linus Torvalds committed
279
	if (INTERNAL_TYPE_FIELD_DEFN == type) {
Linus Torvalds's avatar
Linus Torvalds committed
280 281 282 283 284 285 286 287 288 289 290 291 292
		/* Def_field_defn defines fields in a Region */

		type_to_check_for = ACPI_TYPE_REGION;
	}
	else if (INTERNAL_TYPE_BANK_FIELD_DEFN == type) {
		/* Bank_field_defn defines data fields in a Field Object */

		type_to_check_for = ACPI_TYPE_ANY;
	}
	else {
		type_to_check_for = type;
	}

Andy Grover's avatar
Andy Grover committed
293 294 295
	/*
	 * Begin examination of the actual pathname
	 */
Linus Torvalds's avatar
Linus Torvalds committed
296
	if (!pathname) {
Andy Grover's avatar
Andy Grover committed
297
		/* A Null Name_path is allowed and refers to the root */
Linus Torvalds's avatar
Linus Torvalds committed
298 299

		num_segments = 0;
Andy Grover's avatar
Andy Grover committed
300
		this_node    = acpi_gbl_root_node;
Linus Torvalds's avatar
Linus Torvalds committed
301

Linus Torvalds's avatar
Linus Torvalds committed
302
		ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
Andy Grover's avatar
Andy Grover committed
303
			"Null Pathname (Zero segments), Flags=%x\n", flags));
Linus Torvalds's avatar
Linus Torvalds committed
304 305 306
	}
	else {
		/*
Andy Grover's avatar
Andy Grover committed
307
		 * Name pointer is valid (and must be in internal name format)
Linus Torvalds's avatar
Linus Torvalds committed
308
		 *
Andy Grover's avatar
Andy Grover committed
309
		 * Check for scope prefixes:
Linus Torvalds's avatar
Linus Torvalds committed
310
		 *
Andy Grover's avatar
Andy Grover committed
311 312
		 * As represented in the AML stream, a namepath consists of an
		 * optional scope prefix followed by a name segment part.
Linus Torvalds's avatar
Linus Torvalds committed
313
		 *
Andy Grover's avatar
Andy Grover committed
314 315 316 317
		 * If present, the scope prefix is either a Root Prefix (in
		 * which case the name is fully qualified), or one or more
		 * Parent Prefixes (in which case the name's scope is relative
		 * to the current scope).
Linus Torvalds's avatar
Linus Torvalds committed
318 319
		 */
		if (*pathname == AML_ROOT_PREFIX) {
Andy Grover's avatar
Andy Grover committed
320
			/* Pathname is fully qualified, start from the root */
Linus Torvalds's avatar
Linus Torvalds committed
321

Andy Grover's avatar
Andy Grover committed
322
			this_node = acpi_gbl_root_node;
Linus Torvalds's avatar
Linus Torvalds committed
323

Andy Grover's avatar
Andy Grover committed
324
			/* Point to name segment part */
Linus Torvalds's avatar
Linus Torvalds committed
325 326 327

			pathname++;

Linus Torvalds's avatar
Linus Torvalds committed
328
			ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Searching from root [%p]\n",
Andy Grover's avatar
Andy Grover committed
329
				this_node));
Linus Torvalds's avatar
Linus Torvalds committed
330 331 332 333
		}
		else {
			/* Pathname is relative to current scope, start there */

Andy Grover's avatar
Andy Grover committed
334 335
			ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
				"Searching relative to pfx scope [%p]\n",
Linus Torvalds's avatar
Linus Torvalds committed
336 337
				prefix_node));

Linus Torvalds's avatar
Linus Torvalds committed
338
			/*
Andy Grover's avatar
Andy Grover committed
339 340
			 * Handle multiple Parent Prefixes (carat) by just getting
			 * the parent node for each prefix instance.
Linus Torvalds's avatar
Linus Torvalds committed
341
			 */
Andy Grover's avatar
Andy Grover committed
342
			this_node = prefix_node;
Linus Torvalds's avatar
Linus Torvalds committed
343
			while (*pathname == AML_PARENT_PREFIX) {
Andy Grover's avatar
Andy Grover committed
344 345 346 347
				/*
				 * Point past this prefix to the name segment
				 * part or the next Parent Prefix
				 */
Linus Torvalds's avatar
Linus Torvalds committed
348 349
				pathname++;

Andy Grover's avatar
Andy Grover committed
350
				/* Backup to the parent node */
Linus Torvalds's avatar
Linus Torvalds committed
351

Andy Grover's avatar
Andy Grover committed
352
				this_node = acpi_ns_get_parent_node (this_node);
Linus Torvalds's avatar
Linus Torvalds committed
353 354 355
				if (!this_node) {
					/* Current scope has no parent scope */

Andy Grover's avatar
Andy Grover committed
356 357
					ACPI_REPORT_ERROR (
						("ACPI path has too many parent prefixes (^) - reached beyond root node\n"));
Linus Torvalds's avatar
Linus Torvalds committed
358
					return_ACPI_STATUS (AE_NOT_FOUND);
Linus Torvalds's avatar
Linus Torvalds committed
359 360 361 362 363
				}
			}
		}

		/*
Andy Grover's avatar
Andy Grover committed
364 365 366 367 368 369 370 371 372 373 374
		 * Determine the number of ACPI name segments in this pathname.
		 *
		 * The segment part consists of either:
		 *  - A Null name segment (0)
		 *  - A Dual_name_prefix followed by two 4-byte name segments
		 *  - A Multi_name_prefix followed by a byte indicating the
		 *      number of segments and the segments themselves.
		 *  - A single 4-byte name segment
		 *
		 * Examine the name prefix opcode, if any, to determine the number of
		 * segments.
Linus Torvalds's avatar
Linus Torvalds committed
375
		 */
Andy Grover's avatar
Andy Grover committed
376 377 378 379 380 381 382
		switch (*pathname) {
		case 0:
			/*
			 * Null name after a root or parent prefixes. We already
			 * have the correct target node and there are no name segments.
			 */
			num_segments = 0;
Linus Torvalds's avatar
Linus Torvalds committed
383

Andy Grover's avatar
Andy Grover committed
384 385 386 387 388
			ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
				"Prefix-only Pathname (Zero name segments), Flags=%x\n", flags));
			break;

		case AML_DUAL_NAME_PREFIX:
Linus Torvalds's avatar
Linus Torvalds committed
389

Andy Grover's avatar
Andy Grover committed
390 391 392
			/* Two segments, point to first name segment */

			num_segments = 2;
Linus Torvalds's avatar
Linus Torvalds committed
393 394
			pathname++;

Linus Torvalds's avatar
Linus Torvalds committed
395 396
			ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
				"Dual Pathname (2 segments, Flags=%X)\n", flags));
Andy Grover's avatar
Andy Grover committed
397
			break;
Linus Torvalds's avatar
Linus Torvalds committed
398

Andy Grover's avatar
Andy Grover committed
399
		case AML_MULTI_NAME_PREFIX_OP:
Linus Torvalds's avatar
Linus Torvalds committed
400

Andy Grover's avatar
Andy Grover committed
401
			/* Extract segment count, point to first name segment */
Linus Torvalds's avatar
Linus Torvalds committed
402

Andy Grover's avatar
Andy Grover committed
403 404
			pathname++;
			num_segments = (u32) (u8) *pathname;
Linus Torvalds's avatar
Linus Torvalds committed
405 406
			pathname++;

Linus Torvalds's avatar
Linus Torvalds committed
407 408 409
			ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
				"Multi Pathname (%d Segments, Flags=%X) \n",
				num_segments, flags));
Andy Grover's avatar
Andy Grover committed
410
			break;
Linus Torvalds's avatar
Linus Torvalds committed
411

Andy Grover's avatar
Andy Grover committed
412
		default:
Linus Torvalds's avatar
Linus Torvalds committed
413
			/*
Andy Grover's avatar
Andy Grover committed
414 415
			 * Not a Null name, no Dual or Multi prefix, hence there is
			 * only one name segment and Pathname is already pointing to it.
Linus Torvalds's avatar
Linus Torvalds committed
416 417 418
			 */
			num_segments = 1;

Linus Torvalds's avatar
Linus Torvalds committed
419 420
			ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
				"Simple Pathname (1 segment, Flags=%X)\n", flags));
Andy Grover's avatar
Andy Grover committed
421
			break;
Linus Torvalds's avatar
Linus Torvalds committed
422 423
		}

Andy Grover's avatar
Andy Grover committed
424
		ACPI_DEBUG_EXEC (acpi_ns_print_pathname (num_segments, pathname));
Linus Torvalds's avatar
Linus Torvalds committed
425 426 427
	}

	/*
Andy Grover's avatar
Andy Grover committed
428 429
	 * Search namespace for each segment of the name.  Loop through and
	 * verify/add each name segment.
Linus Torvalds's avatar
Linus Torvalds committed
430
	 */
Andy Grover's avatar
Andy Grover committed
431 432
	current_node = this_node;
	while (num_segments && current_node) {
Linus Torvalds's avatar
Linus Torvalds committed
433 434
		/*
		 * Search for the current name segment under the current
Andy Grover's avatar
Andy Grover committed
435 436
		 * named object.  The Type is significant only at the last name
		 * segment.  (We don't care about the types along the path, only
Linus Torvalds's avatar
Linus Torvalds committed
437 438 439
		 * the type of the final target object.)
		 */
		this_search_type = ACPI_TYPE_ANY;
Andy Grover's avatar
Andy Grover committed
440
		num_segments--;
Linus Torvalds's avatar
Linus Torvalds committed
441 442
		if (!num_segments) {
			this_search_type = type;
Linus Torvalds's avatar
Linus Torvalds committed
443
			local_flags = flags;
Linus Torvalds's avatar
Linus Torvalds committed
444 445
		}

Andy Grover's avatar
Andy Grover committed
446
		/* Extract one ACPI name from the front of the pathname */
Linus Torvalds's avatar
Linus Torvalds committed
447

Andy Grover's avatar
Andy Grover committed
448
		ACPI_MOVE_UNALIGNED32_TO_32 (&simple_name, pathname);
Linus Torvalds's avatar
Linus Torvalds committed
449 450 451

		/* Try to find the ACPI name */

Andy Grover's avatar
Andy Grover committed
452 453
		status = acpi_ns_search_and_enter (simple_name, walk_state, current_node,
				  interpreter_mode, this_search_type, local_flags, &this_node);
Linus Torvalds's avatar
Linus Torvalds committed
454 455
		if (ACPI_FAILURE (status)) {
			if (status == AE_NOT_FOUND) {
Andy Grover's avatar
Andy Grover committed
456
				/* Name not found in ACPI namespace */
Linus Torvalds's avatar
Linus Torvalds committed
457

Linus Torvalds's avatar
Linus Torvalds committed
458
				ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
Andy Grover's avatar
Andy Grover committed
459 460
					"Name [%4.4s] not found in scope [%4.4s] %p\n",
					(char *) &simple_name, (char *) &current_node->name, current_node));
Linus Torvalds's avatar
Linus Torvalds committed
461 462
			}

Linus Torvalds's avatar
Linus Torvalds committed
463
			return_ACPI_STATUS (status);
Linus Torvalds's avatar
Linus Torvalds committed
464 465 466
		}

		/*
Andy Grover's avatar
Andy Grover committed
467 468
		 * Sanity typecheck of the target object:
		 *
Linus Torvalds's avatar
Linus Torvalds committed
469
		 * If 1) This is the last segment (Num_segments == 0)
Andy Grover's avatar
Andy Grover committed
470
		 *    2) And we are looking for a specific type
Linus Torvalds's avatar
Linus Torvalds committed
471 472
		 *       (Not checking for TYPE_ANY)
		 *    3) Which is not an alias
Andy Grover's avatar
Andy Grover committed
473 474 475 476 477
		 *    4) Which is not a local type (TYPE_DEF_ANY)
		 *    5) Which is not a local type (TYPE_SCOPE)
		 *    6) Which is not a local type (TYPE_INDEX_FIELD_DEFN)
		 *    7) And the type of target object is known (not TYPE_ANY)
		 *    8) And target object does not match what we are looking for
Linus Torvalds's avatar
Linus Torvalds committed
478 479 480 481 482 483 484 485 486 487
		 *
		 * Then we have a type mismatch.  Just warn and ignore it.
		 */
		if ((num_segments       == 0)                               &&
			(type_to_check_for  != ACPI_TYPE_ANY)                   &&
			(type_to_check_for  != INTERNAL_TYPE_ALIAS)             &&
			(type_to_check_for  != INTERNAL_TYPE_DEF_ANY)           &&
			(type_to_check_for  != INTERNAL_TYPE_SCOPE)             &&
			(type_to_check_for  != INTERNAL_TYPE_INDEX_FIELD_DEFN)  &&
			(this_node->type    != ACPI_TYPE_ANY)                   &&
Linus Torvalds's avatar
Linus Torvalds committed
488
			(this_node->type    != type_to_check_for)) {
Linus Torvalds's avatar
Linus Torvalds committed
489 490
			/* Complain about a type mismatch */

Andy Grover's avatar
Andy Grover committed
491
			ACPI_REPORT_WARNING (
Linus Torvalds's avatar
Linus Torvalds committed
492
				("Ns_lookup: %4.4s, type %X, checking for type %X\n",
Andy Grover's avatar
Andy Grover committed
493
				(char *) &simple_name, this_node->type, type_to_check_for));
Linus Torvalds's avatar
Linus Torvalds committed
494 495 496 497 498 499 500
		}

		/*
		 * If this is the last name segment and we are not looking for a
		 * specific type, but the type of found object is known, use that type
		 * to see if it opens a scope.
		 */
Andy Grover's avatar
Andy Grover committed
501
		if ((num_segments == 0) && (type == ACPI_TYPE_ANY)) {
Linus Torvalds's avatar
Linus Torvalds committed
502 503 504
			type = this_node->type;
		}

Andy Grover's avatar
Andy Grover committed
505
		/* Point to next name segment and make this node current */
Linus Torvalds's avatar
Linus Torvalds committed
506 507

		pathname += ACPI_NAME_SIZE;
Andy Grover's avatar
Andy Grover committed
508
		current_node = this_node;
Linus Torvalds's avatar
Linus Torvalds committed
509 510 511 512 513
	}

	/*
	 * Always check if we need to open a new scope
	 */
Andy Grover's avatar
Andy Grover committed
514
	if (!(flags & ACPI_NS_DONT_OPEN_SCOPE) && (walk_state)) {
Linus Torvalds's avatar
Linus Torvalds committed
515
		/*
Andy Grover's avatar
Andy Grover committed
516 517
		 * If entry is a type which opens a scope, push the new scope on the
		 * scope stack.
Linus Torvalds's avatar
Linus Torvalds committed
518 519
		 */
		if (acpi_ns_opens_scope (type_to_check_for)) {
Andy Grover's avatar
Andy Grover committed
520
			status = acpi_ds_scope_stack_push (this_node, type, walk_state);
Linus Torvalds's avatar
Linus Torvalds committed
521
			if (ACPI_FAILURE (status)) {
Linus Torvalds's avatar
Linus Torvalds committed
522
				return_ACPI_STATUS (status);
Linus Torvalds's avatar
Linus Torvalds committed
523 524
			}

Andy Grover's avatar
Andy Grover committed
525 526
			ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
				"Setting global scope to %p\n", this_node));
Linus Torvalds's avatar
Linus Torvalds committed
527 528 529 530
		}
	}

	*return_node = this_node;
Linus Torvalds's avatar
Linus Torvalds committed
531
	return_ACPI_STATUS (AE_OK);
Linus Torvalds's avatar
Linus Torvalds committed
532 533
}