nsaccess.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:15k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*******************************************************************************
  2.  *
  3.  * Module Name: nsaccess - Top-level functions for accessing ACPI namespace
  4.  *              $Revision: 135 $
  5.  *
  6.  ******************************************************************************/
  7. /*
  8.  *  Copyright (C) 2000, 2001 R. Byron Moore
  9.  *
  10.  *  This program is free software; you can redistribute it and/or modify
  11.  *  it under the terms of the GNU General Public License as published by
  12.  *  the Free Software Foundation; either version 2 of the License, or
  13.  *  (at your option) any later version.
  14.  *
  15.  *  This program is distributed in the hope that it will be useful,
  16.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18.  *  GNU General Public License for more details.
  19.  *
  20.  *  You should have received a copy of the GNU General Public License
  21.  *  along with this program; if not, write to the Free Software
  22.  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  23.  */
  24. #include "acpi.h"
  25. #include "amlcode.h"
  26. #include "acinterp.h"
  27. #include "acnamesp.h"
  28. #include "acdispat.h"
  29. #define _COMPONENT          ACPI_NAMESPACE
  30.  MODULE_NAME         ("nsaccess")
  31. /*******************************************************************************
  32.  *
  33.  * FUNCTION:    Acpi_ns_root_initialize
  34.  *
  35.  * PARAMETERS:  None
  36.  *
  37.  * RETURN:      Status
  38.  *
  39.  * DESCRIPTION: Allocate and initialize the default root named objects
  40.  *
  41.  * MUTEX:       Locks namespace for entire execution
  42.  *
  43.  ******************************************************************************/
  44. acpi_status
  45. acpi_ns_root_initialize (void)
  46. {
  47. acpi_status             status = AE_OK;
  48. const predefined_names  *init_val = NULL;
  49. acpi_namespace_node     *new_node;
  50. acpi_operand_object     *obj_desc;
  51. FUNCTION_TRACE ("Ns_root_initialize");
  52. acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
  53. /*
  54.  * The global root ptr is initially NULL, so a non-NULL value indicates
  55.  * that Acpi_ns_root_initialize() has already been called; just return.
  56.  */
  57. if (acpi_gbl_root_node) {
  58. status = AE_OK;
  59. goto unlock_and_exit;
  60. }
  61. /*
  62.  * Tell the rest of the subsystem that the root is initialized
  63.  * (This is OK because the namespace is locked)
  64.  */
  65. acpi_gbl_root_node = &acpi_gbl_root_node_struct;
  66. /* Enter the pre-defined names in the name table */
  67. ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Entering predefined entries into namespacen"));
  68. for (init_val = acpi_gbl_pre_defined_names; init_val->name; init_val++) {
  69. status = acpi_ns_lookup (NULL, init_val->name, init_val->type,
  70.  IMODE_LOAD_PASS2, NS_NO_UPSEARCH,
  71.  NULL, &new_node);
  72. if (ACPI_FAILURE (status) || (!new_node)) /* Must be on same line for code converter */ {
  73. ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
  74. "Could not create predefined name %s, %sn",
  75. init_val->name, acpi_format_exception (status)));
  76. }
  77. /*
  78.  * Name entered successfully.
  79.  * If entry in Pre_defined_names[] specifies an
  80.  * initial value, create the initial value.
  81.  */
  82. if (init_val->val) {
  83. /*
  84.  * Entry requests an initial value, allocate a
  85.  * descriptor for it.
  86.  */
  87. obj_desc = acpi_ut_create_internal_object (init_val->type);
  88. if (!obj_desc) {
  89. status = AE_NO_MEMORY;
  90. goto unlock_and_exit;
  91. }
  92. /*
  93.  * Convert value string from table entry to
  94.  * internal representation. Only types actually
  95.  * used for initial values are implemented here.
  96.  */
  97. switch (init_val->type) {
  98. case ACPI_TYPE_INTEGER:
  99. obj_desc->integer.value =
  100. (acpi_integer) STRTOUL (init_val->val, NULL, 10);
  101. break;
  102. case ACPI_TYPE_STRING:
  103. /*
  104.  * Build an object around the static string
  105.  */
  106. obj_desc->string.length = STRLEN (init_val->val);
  107. obj_desc->string.pointer = init_val->val;
  108. obj_desc->common.flags |= AOPOBJ_STATIC_POINTER;
  109. break;
  110. case ACPI_TYPE_MUTEX:
  111. obj_desc->mutex.sync_level =
  112.  (u16) STRTOUL (init_val->val, NULL, 10);
  113. if (STRCMP (init_val->name, "_GL_") == 0) {
  114. /*
  115.  * Create a counting semaphore for the
  116.  * global lock
  117.  */
  118. status = acpi_os_create_semaphore (ACPI_NO_UNIT_LIMIT,
  119.  1, &obj_desc->mutex.semaphore);
  120. if (ACPI_FAILURE (status)) {
  121. goto unlock_and_exit;
  122. }
  123. /*
  124.  * We just created the mutex for the
  125.  * global lock, save it
  126.  */
  127. acpi_gbl_global_lock_semaphore = obj_desc->mutex.semaphore;
  128. }
  129. else {
  130. /* Create a mutex */
  131. status = acpi_os_create_semaphore (1, 1,
  132.    &obj_desc->mutex.semaphore);
  133. if (ACPI_FAILURE (status)) {
  134. goto unlock_and_exit;
  135. }
  136. }
  137. break;
  138. default:
  139. REPORT_ERROR (("Unsupported initial type value %Xn",
  140. init_val->type));
  141. acpi_ut_remove_reference (obj_desc);
  142. obj_desc = NULL;
  143. continue;
  144. }
  145. /* Store pointer to value descriptor in the Node */
  146. acpi_ns_attach_object (new_node, obj_desc, obj_desc->common.type);
  147. /* Remove local reference to the object */
  148. acpi_ut_remove_reference (obj_desc);
  149. }
  150. }
  151. unlock_and_exit:
  152. acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
  153. return_ACPI_STATUS (status);
  154. }
  155. /*******************************************************************************
  156.  *
  157.  * FUNCTION:    Acpi_ns_lookup
  158.  *
  159.  * PARAMETERS:  Prefix_node     - Search scope if name is not fully qualified
  160.  *              Pathname        - Search pathname, in internal format
  161.  *                                (as represented in the AML stream)
  162.  *              Type            - Type associated with name
  163.  *              Interpreter_mode - IMODE_LOAD_PASS2 => add name if not found
  164.  *              Flags           - Flags describing the search restrictions
  165.  *              Walk_state      - Current state of the walk
  166.  *              Return_node     - Where the Node is placed (if found
  167.  *                                or created successfully)
  168.  *
  169.  * RETURN:      Status
  170.  *
  171.  * DESCRIPTION: Find or enter the passed name in the name space.
  172.  *              Log an error if name not found in Exec mode.
  173.  *
  174.  * MUTEX:       Assumes namespace is locked.
  175.  *
  176.  ******************************************************************************/
  177. acpi_status
  178. acpi_ns_lookup (
  179. acpi_generic_state      *scope_info,
  180. NATIVE_CHAR             *pathname,
  181. acpi_object_type8       type,
  182. operating_mode          interpreter_mode,
  183. u32                     flags,
  184. acpi_walk_state         *walk_state,
  185. acpi_namespace_node     **return_node)
  186. {
  187. acpi_status             status;
  188. acpi_namespace_node     *prefix_node;
  189. acpi_namespace_node     *current_node = NULL;
  190. acpi_namespace_node     *scope_to_push = NULL;
  191. acpi_namespace_node     *this_node = NULL;
  192. u32                     num_segments;
  193. acpi_name               simple_name;
  194. u8                      null_name_path = FALSE;
  195. acpi_object_type8       type_to_check_for;
  196. acpi_object_type8       this_search_type;
  197. u32                     local_flags = flags & ~NS_ERROR_IF_FOUND;
  198. DEBUG_EXEC              (u32 i;)
  199. FUNCTION_TRACE ("Ns_lookup");
  200. if (!return_node) {
  201. return_ACPI_STATUS (AE_BAD_PARAMETER);
  202. }
  203. acpi_gbl_ns_lookup_count++;
  204. *return_node = ENTRY_NOT_FOUND;
  205. if (!acpi_gbl_root_node) {
  206. return (AE_NO_NAMESPACE);
  207. }
  208. /*
  209.  * Get the prefix scope.
  210.  * A null scope means use the root scope
  211.  */
  212. if ((!scope_info) ||
  213. (!scope_info->scope.node)) {
  214. ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Null scope prefix, using root node (%p)n",
  215. acpi_gbl_root_node));
  216. prefix_node = acpi_gbl_root_node;
  217. }
  218. else {
  219. prefix_node = scope_info->scope.node;
  220. }
  221. /*
  222.  * This check is explicitly split to relax the Type_to_check_for
  223.  * conditions for Bank_field_defn. Originally, both Bank_field_defn and
  224.  * Def_field_defn caused Type_to_check_for to be set to ACPI_TYPE_REGION,
  225.  * but the Bank_field_defn may also check for a Field definition as well
  226.  * as an Operation_region.
  227.  */
  228. if (INTERNAL_TYPE_FIELD_DEFN == type) {
  229. /* Def_field_defn defines fields in a Region */
  230. type_to_check_for = ACPI_TYPE_REGION;
  231. }
  232. else if (INTERNAL_TYPE_BANK_FIELD_DEFN == type) {
  233. /* Bank_field_defn defines data fields in a Field Object */
  234. type_to_check_for = ACPI_TYPE_ANY;
  235. }
  236. else {
  237. type_to_check_for = type;
  238. }
  239. /* TBD: [Restructure] - Move the pathname stuff into a new procedure */
  240. /* Examine the name pointer */
  241. if (!pathname) {
  242. /*  8-12-98 ASL Grammar Update supports null Name_path  */
  243. null_name_path = TRUE;
  244. num_segments = 0;
  245. this_node = acpi_gbl_root_node;
  246. ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
  247. "Null Pathname (Zero segments),  Flags=%xn", flags));
  248. }
  249. else {
  250. /*
  251.  * Valid name pointer (Internal name format)
  252.  *
  253.  * Check for prefixes.  As represented in the AML stream, a
  254.  * Pathname consists of an optional scope prefix followed by
  255.  * a segment part.
  256.  *
  257.  * If present, the scope prefix is either a Root_prefix (in
  258.  * which case the name is fully qualified), or zero or more
  259.  * Parent_prefixes (in which case the name's scope is relative
  260.  * to the current scope).
  261.  *
  262.  * The segment part consists of either:
  263.  *  - A single 4-byte name segment, or
  264.  *  - A Dual_name_prefix followed by two 4-byte name segments, or
  265.  *  - A Multi_name_prefix_op, followed by a byte indicating the
  266.  *    number of segments and the segments themselves.
  267.  */
  268. if (*pathname == AML_ROOT_PREFIX) {
  269. /* Pathname is fully qualified, look in root name table */
  270. current_node = acpi_gbl_root_node;
  271. /* point to segment part */
  272. pathname++;
  273. ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Searching from root [%p]n",
  274. current_node));
  275. /* Direct reference to root, "" */
  276. if (!(*pathname)) {
  277. this_node = acpi_gbl_root_node;
  278. goto check_for_new_scope_and_exit;
  279. }
  280. }
  281. else {
  282. /* Pathname is relative to current scope, start there */
  283. current_node = prefix_node;
  284. ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Searching relative to pfx scope [%p]n",
  285. prefix_node));
  286. /*
  287.  * Handle up-prefix (carat).  More than one prefix
  288.  * is supported
  289.  */
  290. while (*pathname == AML_PARENT_PREFIX) {
  291. /* Point to segment part or next Parent_prefix */
  292. pathname++;
  293. /*  Backup to the parent's scope  */
  294. this_node = acpi_ns_get_parent_object (current_node);
  295. if (!this_node) {
  296. /* Current scope has no parent scope */
  297. REPORT_ERROR (
  298. ("Too many parent prefixes (^) - reached rootn"));
  299. return_ACPI_STATUS (AE_NOT_FOUND);
  300. }
  301. current_node = this_node;
  302. }
  303. }
  304. /*
  305.  * Examine the name prefix opcode, if any,
  306.  * to determine the number of segments
  307.  */
  308. if (*pathname == AML_DUAL_NAME_PREFIX) {
  309. num_segments = 2;
  310. /* point to first segment */
  311. pathname++;
  312. ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
  313. "Dual Pathname (2 segments, Flags=%X)n", flags));
  314. }
  315. else if (*pathname == AML_MULTI_NAME_PREFIX_OP) {
  316. num_segments = (u32)* (u8 *) ++pathname;
  317. /* point to first segment */
  318. pathname++;
  319. ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
  320. "Multi Pathname (%d Segments, Flags=%X) n",
  321. num_segments, flags));
  322. }
  323. else {
  324. /*
  325.  * No Dual or Multi prefix, hence there is only one
  326.  * segment and Pathname is already pointing to it.
  327.  */
  328. num_segments = 1;
  329. ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
  330. "Simple Pathname (1 segment, Flags=%X)n", flags));
  331. }
  332. #ifdef ACPI_DEBUG
  333. /* TBD: [Restructure] Make this a procedure */
  334. /* Debug only: print the entire name that we are about to lookup */
  335. ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "["));
  336. for (i = 0; i < num_segments; i++) {
  337. ACPI_DEBUG_PRINT_RAW ((ACPI_DB_NAMES, "%4.4s/", (char*)&pathname[i * 4]));
  338. }
  339. ACPI_DEBUG_PRINT_RAW ((ACPI_DB_NAMES, "]n"));
  340. #endif
  341. }
  342. /*
  343.  * Search namespace for each segment of the name.
  344.  * Loop through and verify/add each name segment.
  345.  */
  346. while (num_segments-- && current_node) {
  347. /*
  348.  * Search for the current name segment under the current
  349.  * named object.  The Type is significant only at the last (topmost)
  350.  * level.  (We don't care about the types along the path, only
  351.  * the type of the final target object.)
  352.  */
  353. this_search_type = ACPI_TYPE_ANY;
  354. if (!num_segments) {
  355. this_search_type = type;
  356. local_flags = flags;
  357. }
  358. /* Pluck one ACPI name from the front of the pathname */
  359. MOVE_UNALIGNED32_TO_32 (&simple_name, pathname);
  360. /* Try to find the ACPI name */
  361. status = acpi_ns_search_and_enter (simple_name, walk_state,
  362.    current_node, interpreter_mode,
  363.    this_search_type, local_flags,
  364.    &this_node);
  365. if (ACPI_FAILURE (status)) {
  366. if (status == AE_NOT_FOUND) {
  367. /* Name not found in ACPI namespace  */
  368. ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
  369. "Name [%4.4s] not found in scope %pn",
  370. (char*)&simple_name, current_node));
  371. }
  372. return_ACPI_STATUS (status);
  373. }
  374. /*
  375.  * If 1) This is the last segment (Num_segments == 0)
  376.  *    2) and looking for a specific type
  377.  *       (Not checking for TYPE_ANY)
  378.  *    3) Which is not an alias
  379.  *    4) which is not a local type (TYPE_DEF_ANY)
  380.  *    5) which is not a local type (TYPE_SCOPE)
  381.  *    6) which is not a local type (TYPE_INDEX_FIELD_DEFN)
  382.  *    7) and type of object is known (not TYPE_ANY)
  383.  *    8) and object does not match request
  384.  *
  385.  * Then we have a type mismatch.  Just warn and ignore it.
  386.  */
  387. if ((num_segments       == 0)                               &&
  388. (type_to_check_for  != ACPI_TYPE_ANY)                   &&
  389. (type_to_check_for  != INTERNAL_TYPE_ALIAS)             &&
  390. (type_to_check_for  != INTERNAL_TYPE_DEF_ANY)           &&
  391. (type_to_check_for  != INTERNAL_TYPE_SCOPE)             &&
  392. (type_to_check_for  != INTERNAL_TYPE_INDEX_FIELD_DEFN)  &&
  393. (this_node->type    != ACPI_TYPE_ANY)                   &&
  394. (this_node->type    != type_to_check_for)) {
  395. /* Complain about a type mismatch */
  396. REPORT_WARNING (
  397. ("Ns_lookup: %4.4s, type %X, checking for type %Xn",
  398. (char*)&simple_name, this_node->type, type_to_check_for));
  399. }
  400. /*
  401.  * If this is the last name segment and we are not looking for a
  402.  * specific type, but the type of found object is known, use that type
  403.  * to see if it opens a scope.
  404.  */
  405. if ((0 == num_segments) && (ACPI_TYPE_ANY == type)) {
  406. type = this_node->type;
  407. }
  408. if ((num_segments || acpi_ns_opens_scope (type)) &&
  409. (this_node->child == NULL)) {
  410. /*
  411.  * More segments or the type implies enclosed scope,
  412.  * and the next scope has not been allocated.
  413.  */
  414. ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Load mode=%X  This_node=%pn",
  415. interpreter_mode, this_node));
  416. }
  417. current_node = this_node;
  418. /* point to next name segment */
  419. pathname += ACPI_NAME_SIZE;
  420. }
  421. /*
  422.  * Always check if we need to open a new scope
  423.  */
  424. check_for_new_scope_and_exit:
  425. if (!(flags & NS_DONT_OPEN_SCOPE) && (walk_state)) {
  426. /*
  427.  * If entry is a type which opens a scope,
  428.  * push the new scope on the scope stack.
  429.  */
  430. if (acpi_ns_opens_scope (type_to_check_for)) {
  431. /*  8-12-98 ASL Grammar Update supports null Name_path  */
  432. if (null_name_path) {
  433. /* TBD: [Investigate] - is this the correct thing to do? */
  434. scope_to_push = NULL;
  435. }
  436. else {
  437. scope_to_push = this_node;
  438. }
  439. status = acpi_ds_scope_stack_push (scope_to_push, type,
  440.    walk_state);
  441. if (ACPI_FAILURE (status)) {
  442. return_ACPI_STATUS (status);
  443. }
  444. ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Set global scope to %pn", scope_to_push));
  445. }
  446. }
  447. *return_node = this_node;
  448. return_ACPI_STATUS (AE_OK);
  449. }