cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

nsinit.c (19201B)


      1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
      2/******************************************************************************
      3 *
      4 * Module Name: nsinit - namespace initialization
      5 *
      6 * Copyright (C) 2000 - 2022, Intel Corp.
      7 *
      8 *****************************************************************************/
      9
     10#include <acpi/acpi.h>
     11#include "accommon.h"
     12#include "acnamesp.h"
     13#include "acdispat.h"
     14#include "acinterp.h"
     15#include "acevents.h"
     16
     17#define _COMPONENT          ACPI_NAMESPACE
     18ACPI_MODULE_NAME("nsinit")
     19
     20/* Local prototypes */
     21static acpi_status
     22acpi_ns_init_one_object(acpi_handle obj_handle,
     23			u32 level, void *context, void **return_value);
     24
     25static acpi_status
     26acpi_ns_init_one_device(acpi_handle obj_handle,
     27			u32 nesting_level, void *context, void **return_value);
     28
     29static acpi_status
     30acpi_ns_find_ini_methods(acpi_handle obj_handle,
     31			 u32 nesting_level, void *context, void **return_value);
     32
     33/*******************************************************************************
     34 *
     35 * FUNCTION:    acpi_ns_initialize_objects
     36 *
     37 * PARAMETERS:  None
     38 *
     39 * RETURN:      Status
     40 *
     41 * DESCRIPTION: Walk the entire namespace and perform any necessary
     42 *              initialization on the objects found therein
     43 *
     44 ******************************************************************************/
     45
     46acpi_status acpi_ns_initialize_objects(void)
     47{
     48	acpi_status status;
     49	struct acpi_init_walk_info info;
     50
     51	ACPI_FUNCTION_TRACE(ns_initialize_objects);
     52
     53	ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
     54			  "[Init] Completing Initialization of ACPI Objects\n"));
     55	ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
     56			  "**** Starting initialization of namespace objects ****\n"));
     57	ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT,
     58			      "Final data object initialization: "));
     59
     60	/* Clear the info block */
     61
     62	memset(&info, 0, sizeof(struct acpi_init_walk_info));
     63
     64	/* Walk entire namespace from the supplied root */
     65
     66	/*
     67	 * TBD: will become ACPI_TYPE_PACKAGE as this type object
     68	 * is now the only one that supports deferred initialization
     69	 * (forward references).
     70	 */
     71	status = acpi_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
     72				     ACPI_UINT32_MAX, acpi_ns_init_one_object,
     73				     NULL, &info, NULL);
     74	if (ACPI_FAILURE(status)) {
     75		ACPI_EXCEPTION((AE_INFO, status, "During WalkNamespace"));
     76	}
     77
     78	ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT,
     79			      "Namespace contains %u (0x%X) objects\n",
     80			      info.object_count, info.object_count));
     81
     82	ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
     83			  "%u Control Methods found\n%u Op Regions found\n",
     84			  info.method_count, info.op_region_count));
     85
     86	return_ACPI_STATUS(AE_OK);
     87}
     88
     89/*******************************************************************************
     90 *
     91 * FUNCTION:    acpi_ns_initialize_devices
     92 *
     93 * PARAMETERS:  None
     94 *
     95 * RETURN:      acpi_status
     96 *
     97 * DESCRIPTION: Walk the entire namespace and initialize all ACPI devices.
     98 *              This means running _INI on all present devices.
     99 *
    100 *              Note: We install PCI config space handler on region access,
    101 *              not here.
    102 *
    103 ******************************************************************************/
    104
    105acpi_status acpi_ns_initialize_devices(u32 flags)
    106{
    107	acpi_status status = AE_OK;
    108	struct acpi_device_walk_info info;
    109	acpi_handle handle;
    110
    111	ACPI_FUNCTION_TRACE(ns_initialize_devices);
    112
    113	if (!(flags & ACPI_NO_DEVICE_INIT)) {
    114		ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
    115				  "[Init] Initializing ACPI Devices\n"));
    116
    117		/* Init counters */
    118
    119		info.device_count = 0;
    120		info.num_STA = 0;
    121		info.num_INI = 0;
    122
    123		ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT,
    124				      "Initializing Device/Processor/Thermal objects "
    125				      "and executing _INI/_STA methods:\n"));
    126
    127		/* Tree analysis: find all subtrees that contain _INI methods */
    128
    129		status = acpi_ns_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
    130						ACPI_UINT32_MAX, FALSE,
    131						acpi_ns_find_ini_methods, NULL,
    132						&info, NULL);
    133		if (ACPI_FAILURE(status)) {
    134			goto error_exit;
    135		}
    136
    137		/* Allocate the evaluation information block */
    138
    139		info.evaluate_info =
    140		    ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info));
    141		if (!info.evaluate_info) {
    142			status = AE_NO_MEMORY;
    143			goto error_exit;
    144		}
    145
    146		/*
    147		 * Execute the "global" _INI method that may appear at the root.
    148		 * This support is provided for Windows compatibility (Vista+) and
    149		 * is not part of the ACPI specification.
    150		 */
    151		info.evaluate_info->prefix_node = acpi_gbl_root_node;
    152		info.evaluate_info->relative_pathname = METHOD_NAME__INI;
    153		info.evaluate_info->parameters = NULL;
    154		info.evaluate_info->flags = ACPI_IGNORE_RETURN_VALUE;
    155
    156		status = acpi_ns_evaluate(info.evaluate_info);
    157		if (ACPI_SUCCESS(status)) {
    158			info.num_INI++;
    159		}
    160
    161		/*
    162		 * Execute \_SB._INI.
    163		 * There appears to be a strict order requirement for \_SB._INI,
    164		 * which should be evaluated before any _REG evaluations.
    165		 */
    166		status = acpi_get_handle(NULL, "\\_SB", &handle);
    167		if (ACPI_SUCCESS(status)) {
    168			memset(info.evaluate_info, 0,
    169			       sizeof(struct acpi_evaluate_info));
    170			info.evaluate_info->prefix_node = handle;
    171			info.evaluate_info->relative_pathname =
    172			    METHOD_NAME__INI;
    173			info.evaluate_info->parameters = NULL;
    174			info.evaluate_info->flags = ACPI_IGNORE_RETURN_VALUE;
    175
    176			status = acpi_ns_evaluate(info.evaluate_info);
    177			if (ACPI_SUCCESS(status)) {
    178				info.num_INI++;
    179			}
    180		}
    181	}
    182
    183	/*
    184	 * Run all _REG methods
    185	 *
    186	 * Note: Any objects accessed by the _REG methods will be automatically
    187	 * initialized, even if they contain executable AML (see the call to
    188	 * acpi_ns_initialize_objects below).
    189	 *
    190	 * Note: According to the ACPI specification, we actually needn't execute
    191	 * _REG for system_memory/system_io operation regions, but for PCI_Config
    192	 * operation regions, it is required to evaluate _REG for those on a PCI
    193	 * root bus that doesn't contain _BBN object. So this code is kept here
    194	 * in order not to break things.
    195	 */
    196	if (!(flags & ACPI_NO_ADDRESS_SPACE_INIT)) {
    197		ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
    198				  "[Init] Executing _REG OpRegion methods\n"));
    199
    200		status = acpi_ev_initialize_op_regions();
    201		if (ACPI_FAILURE(status)) {
    202			goto error_exit;
    203		}
    204	}
    205
    206	if (!(flags & ACPI_NO_DEVICE_INIT)) {
    207
    208		/* Walk namespace to execute all _INIs on present devices */
    209
    210		status = acpi_ns_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
    211						ACPI_UINT32_MAX, FALSE,
    212						acpi_ns_init_one_device, NULL,
    213						&info, NULL);
    214
    215		/*
    216		 * Any _OSI requests should be completed by now. If the BIOS has
    217		 * requested any Windows OSI strings, we will always truncate
    218		 * I/O addresses to 16 bits -- for Windows compatibility.
    219		 */
    220		if (acpi_gbl_osi_data >= ACPI_OSI_WIN_2000) {
    221			acpi_gbl_truncate_io_addresses = TRUE;
    222		}
    223
    224		ACPI_FREE(info.evaluate_info);
    225		if (ACPI_FAILURE(status)) {
    226			goto error_exit;
    227		}
    228
    229		ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT,
    230				      "    Executed %u _INI methods requiring %u _STA executions "
    231				      "(examined %u objects)\n",
    232				      info.num_INI, info.num_STA,
    233				      info.device_count));
    234	}
    235
    236	return_ACPI_STATUS(status);
    237
    238error_exit:
    239	ACPI_EXCEPTION((AE_INFO, status, "During device initialization"));
    240	return_ACPI_STATUS(status);
    241}
    242
    243/*******************************************************************************
    244 *
    245 * FUNCTION:    acpi_ns_init_one_package
    246 *
    247 * PARAMETERS:  obj_handle      - Node
    248 *              level           - Current nesting level
    249 *              context         - Not used
    250 *              return_value    - Not used
    251 *
    252 * RETURN:      Status
    253 *
    254 * DESCRIPTION: Callback from acpi_walk_namespace. Invoked for every package
    255 *              within the namespace. Used during dynamic load of an SSDT.
    256 *
    257 ******************************************************************************/
    258
    259acpi_status
    260acpi_ns_init_one_package(acpi_handle obj_handle,
    261			 u32 level, void *context, void **return_value)
    262{
    263	acpi_status status;
    264	union acpi_operand_object *obj_desc;
    265	struct acpi_namespace_node *node =
    266	    (struct acpi_namespace_node *)obj_handle;
    267
    268	obj_desc = acpi_ns_get_attached_object(node);
    269	if (!obj_desc) {
    270		return (AE_OK);
    271	}
    272
    273	/* Exit if package is already initialized */
    274
    275	if (obj_desc->package.flags & AOPOBJ_DATA_VALID) {
    276		return (AE_OK);
    277	}
    278
    279	status = acpi_ds_get_package_arguments(obj_desc);
    280	if (ACPI_FAILURE(status)) {
    281		return (AE_OK);
    282	}
    283
    284	status =
    285	    acpi_ut_walk_package_tree(obj_desc, NULL,
    286				      acpi_ds_init_package_element, NULL);
    287	if (ACPI_FAILURE(status)) {
    288		return (AE_OK);
    289	}
    290
    291	obj_desc->package.flags |= AOPOBJ_DATA_VALID;
    292	return (AE_OK);
    293}
    294
    295/*******************************************************************************
    296 *
    297 * FUNCTION:    acpi_ns_init_one_object
    298 *
    299 * PARAMETERS:  obj_handle      - Node
    300 *              level           - Current nesting level
    301 *              context         - Points to a init info struct
    302 *              return_value    - Not used
    303 *
    304 * RETURN:      Status
    305 *
    306 * DESCRIPTION: Callback from acpi_walk_namespace. Invoked for every object
    307 *              within the namespace.
    308 *
    309 *              Currently, the only objects that require initialization are:
    310 *              1) Methods
    311 *              2) Op Regions
    312 *
    313 ******************************************************************************/
    314
    315static acpi_status
    316acpi_ns_init_one_object(acpi_handle obj_handle,
    317			u32 level, void *context, void **return_value)
    318{
    319	acpi_object_type type;
    320	acpi_status status = AE_OK;
    321	struct acpi_init_walk_info *info =
    322	    (struct acpi_init_walk_info *)context;
    323	struct acpi_namespace_node *node =
    324	    (struct acpi_namespace_node *)obj_handle;
    325	union acpi_operand_object *obj_desc;
    326
    327	ACPI_FUNCTION_NAME(ns_init_one_object);
    328
    329	info->object_count++;
    330
    331	/* And even then, we are only interested in a few object types */
    332
    333	type = acpi_ns_get_type(obj_handle);
    334	obj_desc = acpi_ns_get_attached_object(node);
    335	if (!obj_desc) {
    336		return (AE_OK);
    337	}
    338
    339	/* Increment counters for object types we are looking for */
    340
    341	switch (type) {
    342	case ACPI_TYPE_REGION:
    343
    344		info->op_region_count++;
    345		break;
    346
    347	case ACPI_TYPE_BUFFER_FIELD:
    348
    349		info->field_count++;
    350		break;
    351
    352	case ACPI_TYPE_LOCAL_BANK_FIELD:
    353
    354		info->field_count++;
    355		break;
    356
    357	case ACPI_TYPE_BUFFER:
    358
    359		info->buffer_count++;
    360		break;
    361
    362	case ACPI_TYPE_PACKAGE:
    363
    364		info->package_count++;
    365		break;
    366
    367	default:
    368
    369		/* No init required, just exit now */
    370
    371		return (AE_OK);
    372	}
    373
    374	/* If the object is already initialized, nothing else to do */
    375
    376	if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {
    377		return (AE_OK);
    378	}
    379
    380	/* Must lock the interpreter before executing AML code */
    381
    382	acpi_ex_enter_interpreter();
    383
    384	/*
    385	 * Only initialization of Package objects can be deferred, in order
    386	 * to support forward references.
    387	 */
    388	switch (type) {
    389	case ACPI_TYPE_LOCAL_BANK_FIELD:
    390
    391		/* TBD: bank_fields do not require deferred init, remove this code */
    392
    393		info->field_init++;
    394		status = acpi_ds_get_bank_field_arguments(obj_desc);
    395		break;
    396
    397	case ACPI_TYPE_PACKAGE:
    398
    399		/* Complete the initialization/resolution of the package object */
    400
    401		info->package_init++;
    402		status =
    403		    acpi_ns_init_one_package(obj_handle, level, NULL, NULL);
    404		break;
    405
    406	default:
    407
    408		/* No other types should get here */
    409
    410		status = AE_TYPE;
    411		ACPI_EXCEPTION((AE_INFO, status,
    412				"Opcode is not deferred [%4.4s] (%s)",
    413				acpi_ut_get_node_name(node),
    414				acpi_ut_get_type_name(type)));
    415		break;
    416	}
    417
    418	if (ACPI_FAILURE(status)) {
    419		ACPI_EXCEPTION((AE_INFO, status,
    420				"Could not execute arguments for [%4.4s] (%s)",
    421				acpi_ut_get_node_name(node),
    422				acpi_ut_get_type_name(type)));
    423	}
    424
    425	/*
    426	 * We ignore errors from above, and always return OK, since we don't want
    427	 * to abort the walk on any single error.
    428	 */
    429	acpi_ex_exit_interpreter();
    430	return (AE_OK);
    431}
    432
    433/*******************************************************************************
    434 *
    435 * FUNCTION:    acpi_ns_find_ini_methods
    436 *
    437 * PARAMETERS:  acpi_walk_callback
    438 *
    439 * RETURN:      acpi_status
    440 *
    441 * DESCRIPTION: Called during namespace walk. Finds objects named _INI under
    442 *              device/processor/thermal objects, and marks the entire subtree
    443 *              with a SUBTREE_HAS_INI flag. This flag is used during the
    444 *              subsequent device initialization walk to avoid entire subtrees
    445 *              that do not contain an _INI.
    446 *
    447 ******************************************************************************/
    448
    449static acpi_status
    450acpi_ns_find_ini_methods(acpi_handle obj_handle,
    451			 u32 nesting_level, void *context, void **return_value)
    452{
    453	struct acpi_device_walk_info *info =
    454	    ACPI_CAST_PTR(struct acpi_device_walk_info, context);
    455	struct acpi_namespace_node *node;
    456	struct acpi_namespace_node *parent_node;
    457
    458	/* Keep count of device/processor/thermal objects */
    459
    460	node = ACPI_CAST_PTR(struct acpi_namespace_node, obj_handle);
    461	if ((node->type == ACPI_TYPE_DEVICE) ||
    462	    (node->type == ACPI_TYPE_PROCESSOR) ||
    463	    (node->type == ACPI_TYPE_THERMAL)) {
    464		info->device_count++;
    465		return (AE_OK);
    466	}
    467
    468	/* We are only looking for methods named _INI */
    469
    470	if (!ACPI_COMPARE_NAMESEG(node->name.ascii, METHOD_NAME__INI)) {
    471		return (AE_OK);
    472	}
    473
    474	/*
    475	 * The only _INI methods that we care about are those that are
    476	 * present under Device, Processor, and Thermal objects.
    477	 */
    478	parent_node = node->parent;
    479	switch (parent_node->type) {
    480	case ACPI_TYPE_DEVICE:
    481	case ACPI_TYPE_PROCESSOR:
    482	case ACPI_TYPE_THERMAL:
    483
    484		/* Mark parent and bubble up the INI present flag to the root */
    485
    486		while (parent_node) {
    487			parent_node->flags |= ANOBJ_SUBTREE_HAS_INI;
    488			parent_node = parent_node->parent;
    489		}
    490		break;
    491
    492	default:
    493
    494		break;
    495	}
    496
    497	return (AE_OK);
    498}
    499
    500/*******************************************************************************
    501 *
    502 * FUNCTION:    acpi_ns_init_one_device
    503 *
    504 * PARAMETERS:  acpi_walk_callback
    505 *
    506 * RETURN:      acpi_status
    507 *
    508 * DESCRIPTION: This is called once per device soon after ACPI is enabled
    509 *              to initialize each device. It determines if the device is
    510 *              present, and if so, calls _INI.
    511 *
    512 ******************************************************************************/
    513
    514static acpi_status
    515acpi_ns_init_one_device(acpi_handle obj_handle,
    516			u32 nesting_level, void *context, void **return_value)
    517{
    518	struct acpi_device_walk_info *walk_info =
    519	    ACPI_CAST_PTR(struct acpi_device_walk_info, context);
    520	struct acpi_evaluate_info *info = walk_info->evaluate_info;
    521	u32 flags;
    522	acpi_status status;
    523	struct acpi_namespace_node *device_node;
    524
    525	ACPI_FUNCTION_TRACE(ns_init_one_device);
    526
    527	/* We are interested in Devices, Processors and thermal_zones only */
    528
    529	device_node = ACPI_CAST_PTR(struct acpi_namespace_node, obj_handle);
    530	if ((device_node->type != ACPI_TYPE_DEVICE) &&
    531	    (device_node->type != ACPI_TYPE_PROCESSOR) &&
    532	    (device_node->type != ACPI_TYPE_THERMAL)) {
    533		return_ACPI_STATUS(AE_OK);
    534	}
    535
    536	/*
    537	 * Because of an earlier namespace analysis, all subtrees that contain an
    538	 * _INI method are tagged.
    539	 *
    540	 * If this device subtree does not contain any _INI methods, we
    541	 * can exit now and stop traversing this entire subtree.
    542	 */
    543	if (!(device_node->flags & ANOBJ_SUBTREE_HAS_INI)) {
    544		return_ACPI_STATUS(AE_CTRL_DEPTH);
    545	}
    546
    547	/*
    548	 * Run _STA to determine if this device is present and functioning. We
    549	 * must know this information for two important reasons (from ACPI spec):
    550	 *
    551	 * 1) We can only run _INI if the device is present.
    552	 * 2) We must abort the device tree walk on this subtree if the device is
    553	 *    not present and is not functional (we will not examine the children)
    554	 *
    555	 * The _STA method is not required to be present under the device, we
    556	 * assume the device is present if _STA does not exist.
    557	 */
    558	ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname
    559			(ACPI_TYPE_METHOD, device_node, METHOD_NAME__STA));
    560
    561	status = acpi_ut_execute_STA(device_node, &flags);
    562	if (ACPI_FAILURE(status)) {
    563
    564		/* Ignore error and move on to next device */
    565
    566		return_ACPI_STATUS(AE_OK);
    567	}
    568
    569	/*
    570	 * Flags == -1 means that _STA was not found. In this case, we assume that
    571	 * the device is both present and functional.
    572	 *
    573	 * From the ACPI spec, description of _STA:
    574	 *
    575	 * "If a device object (including the processor object) does not have an
    576	 * _STA object, then OSPM assumes that all of the above bits are set (in
    577	 * other words, the device is present, ..., and functioning)"
    578	 */
    579	if (flags != ACPI_UINT32_MAX) {
    580		walk_info->num_STA++;
    581	}
    582
    583	/*
    584	 * Examine the PRESENT and FUNCTIONING status bits
    585	 *
    586	 * Note: ACPI spec does not seem to specify behavior for the present but
    587	 * not functioning case, so we assume functioning if present.
    588	 */
    589	if (!(flags & ACPI_STA_DEVICE_PRESENT)) {
    590
    591		/* Device is not present, we must examine the Functioning bit */
    592
    593		if (flags & ACPI_STA_DEVICE_FUNCTIONING) {
    594			/*
    595			 * Device is not present but is "functioning". In this case,
    596			 * we will not run _INI, but we continue to examine the children
    597			 * of this device.
    598			 *
    599			 * From the ACPI spec, description of _STA: (note - no mention
    600			 * of whether to run _INI or not on the device in question)
    601			 *
    602			 * "_STA may return bit 0 clear (not present) with bit 3 set
    603			 * (device is functional). This case is used to indicate a valid
    604			 * device for which no device driver should be loaded (for example,
    605			 * a bridge device.) Children of this device may be present and
    606			 * valid. OSPM should continue enumeration below a device whose
    607			 * _STA returns this bit combination"
    608			 */
    609			return_ACPI_STATUS(AE_OK);
    610		} else {
    611			/*
    612			 * Device is not present and is not functioning. We must abort the
    613			 * walk of this subtree immediately -- don't look at the children
    614			 * of such a device.
    615			 *
    616			 * From the ACPI spec, description of _INI:
    617			 *
    618			 * "If the _STA method indicates that the device is not present,
    619			 * OSPM will not run the _INI and will not examine the children
    620			 * of the device for _INI methods"
    621			 */
    622			return_ACPI_STATUS(AE_CTRL_DEPTH);
    623		}
    624	}
    625
    626	/*
    627	 * The device is present or is assumed present if no _STA exists.
    628	 * Run the _INI if it exists (not required to exist)
    629	 *
    630	 * Note: We know there is an _INI within this subtree, but it may not be
    631	 * under this particular device, it may be lower in the branch.
    632	 */
    633	if (!ACPI_COMPARE_NAMESEG(device_node->name.ascii, "_SB_") ||
    634	    device_node->parent != acpi_gbl_root_node) {
    635		ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname
    636				(ACPI_TYPE_METHOD, device_node,
    637				 METHOD_NAME__INI));
    638
    639		memset(info, 0, sizeof(struct acpi_evaluate_info));
    640		info->prefix_node = device_node;
    641		info->relative_pathname = METHOD_NAME__INI;
    642		info->parameters = NULL;
    643		info->flags = ACPI_IGNORE_RETURN_VALUE;
    644
    645		status = acpi_ns_evaluate(info);
    646		if (ACPI_SUCCESS(status)) {
    647			walk_info->num_INI++;
    648		}
    649#ifdef ACPI_DEBUG_OUTPUT
    650		else if (status != AE_NOT_FOUND) {
    651
    652			/* Ignore error and move on to next device */
    653
    654			char *scope_name =
    655			    acpi_ns_get_normalized_pathname(device_node, TRUE);
    656
    657			ACPI_EXCEPTION((AE_INFO, status,
    658					"during %s._INI execution",
    659					scope_name));
    660			ACPI_FREE(scope_name);
    661		}
    662#endif
    663	}
    664
    665	/* Ignore errors from above */
    666
    667	status = AE_OK;
    668
    669	/*
    670	 * The _INI method has been run if present; call the Global Initialization
    671	 * Handler for this device.
    672	 */
    673	if (acpi_gbl_init_handler) {
    674		status =
    675		    acpi_gbl_init_handler(device_node, ACPI_INIT_DEVICE_INI);
    676	}
    677
    678	return_ACPI_STATUS(status);
    679}