Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
0002 /******************************************************************************
0003  *
0004  * Module Name: nsinit - namespace initialization
0005  *
0006  * Copyright (C) 2000 - 2022, Intel Corp.
0007  *
0008  *****************************************************************************/
0009 
0010 #include <acpi/acpi.h>
0011 #include "accommon.h"
0012 #include "acnamesp.h"
0013 #include "acdispat.h"
0014 #include "acinterp.h"
0015 #include "acevents.h"
0016 
0017 #define _COMPONENT          ACPI_NAMESPACE
0018 ACPI_MODULE_NAME("nsinit")
0019 
0020 /* Local prototypes */
0021 static acpi_status
0022 acpi_ns_init_one_object(acpi_handle obj_handle,
0023             u32 level, void *context, void **return_value);
0024 
0025 static acpi_status
0026 acpi_ns_init_one_device(acpi_handle obj_handle,
0027             u32 nesting_level, void *context, void **return_value);
0028 
0029 static acpi_status
0030 acpi_ns_find_ini_methods(acpi_handle obj_handle,
0031              u32 nesting_level, void *context, void **return_value);
0032 
0033 /*******************************************************************************
0034  *
0035  * FUNCTION:    acpi_ns_initialize_objects
0036  *
0037  * PARAMETERS:  None
0038  *
0039  * RETURN:      Status
0040  *
0041  * DESCRIPTION: Walk the entire namespace and perform any necessary
0042  *              initialization on the objects found therein
0043  *
0044  ******************************************************************************/
0045 
0046 acpi_status acpi_ns_initialize_objects(void)
0047 {
0048     acpi_status status;
0049     struct acpi_init_walk_info info;
0050 
0051     ACPI_FUNCTION_TRACE(ns_initialize_objects);
0052 
0053     ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
0054               "[Init] Completing Initialization of ACPI Objects\n"));
0055     ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
0056               "**** Starting initialization of namespace objects ****\n"));
0057     ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT,
0058                   "Final data object initialization: "));
0059 
0060     /* Clear the info block */
0061 
0062     memset(&info, 0, sizeof(struct acpi_init_walk_info));
0063 
0064     /* Walk entire namespace from the supplied root */
0065 
0066     /*
0067      * TBD: will become ACPI_TYPE_PACKAGE as this type object
0068      * is now the only one that supports deferred initialization
0069      * (forward references).
0070      */
0071     status = acpi_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
0072                      ACPI_UINT32_MAX, acpi_ns_init_one_object,
0073                      NULL, &info, NULL);
0074     if (ACPI_FAILURE(status)) {
0075         ACPI_EXCEPTION((AE_INFO, status, "During WalkNamespace"));
0076     }
0077 
0078     ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT,
0079                   "Namespace contains %u (0x%X) objects\n",
0080                   info.object_count, info.object_count));
0081 
0082     ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
0083               "%u Control Methods found\n%u Op Regions found\n",
0084               info.method_count, info.op_region_count));
0085 
0086     return_ACPI_STATUS(AE_OK);
0087 }
0088 
0089 /*******************************************************************************
0090  *
0091  * FUNCTION:    acpi_ns_initialize_devices
0092  *
0093  * PARAMETERS:  None
0094  *
0095  * RETURN:      acpi_status
0096  *
0097  * DESCRIPTION: Walk the entire namespace and initialize all ACPI devices.
0098  *              This means running _INI on all present devices.
0099  *
0100  *              Note: We install PCI config space handler on region access,
0101  *              not here.
0102  *
0103  ******************************************************************************/
0104 
0105 acpi_status acpi_ns_initialize_devices(u32 flags)
0106 {
0107     acpi_status status = AE_OK;
0108     struct acpi_device_walk_info info;
0109     acpi_handle handle;
0110 
0111     ACPI_FUNCTION_TRACE(ns_initialize_devices);
0112 
0113     if (!(flags & ACPI_NO_DEVICE_INIT)) {
0114         ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
0115                   "[Init] Initializing ACPI Devices\n"));
0116 
0117         /* Init counters */
0118 
0119         info.device_count = 0;
0120         info.num_STA = 0;
0121         info.num_INI = 0;
0122 
0123         ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT,
0124                       "Initializing Device/Processor/Thermal objects "
0125                       "and executing _INI/_STA methods:\n"));
0126 
0127         /* Tree analysis: find all subtrees that contain _INI methods */
0128 
0129         status = acpi_ns_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
0130                         ACPI_UINT32_MAX, FALSE,
0131                         acpi_ns_find_ini_methods, NULL,
0132                         &info, NULL);
0133         if (ACPI_FAILURE(status)) {
0134             goto error_exit;
0135         }
0136 
0137         /* Allocate the evaluation information block */
0138 
0139         info.evaluate_info =
0140             ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info));
0141         if (!info.evaluate_info) {
0142             status = AE_NO_MEMORY;
0143             goto error_exit;
0144         }
0145 
0146         /*
0147          * Execute the "global" _INI method that may appear at the root.
0148          * This support is provided for Windows compatibility (Vista+) and
0149          * is not part of the ACPI specification.
0150          */
0151         info.evaluate_info->prefix_node = acpi_gbl_root_node;
0152         info.evaluate_info->relative_pathname = METHOD_NAME__INI;
0153         info.evaluate_info->parameters = NULL;
0154         info.evaluate_info->flags = ACPI_IGNORE_RETURN_VALUE;
0155 
0156         status = acpi_ns_evaluate(info.evaluate_info);
0157         if (ACPI_SUCCESS(status)) {
0158             info.num_INI++;
0159         }
0160 
0161         /*
0162          * Execute \_SB._INI.
0163          * There appears to be a strict order requirement for \_SB._INI,
0164          * which should be evaluated before any _REG evaluations.
0165          */
0166         status = acpi_get_handle(NULL, "\\_SB", &handle);
0167         if (ACPI_SUCCESS(status)) {
0168             memset(info.evaluate_info, 0,
0169                    sizeof(struct acpi_evaluate_info));
0170             info.evaluate_info->prefix_node = handle;
0171             info.evaluate_info->relative_pathname =
0172                 METHOD_NAME__INI;
0173             info.evaluate_info->parameters = NULL;
0174             info.evaluate_info->flags = ACPI_IGNORE_RETURN_VALUE;
0175 
0176             status = acpi_ns_evaluate(info.evaluate_info);
0177             if (ACPI_SUCCESS(status)) {
0178                 info.num_INI++;
0179             }
0180         }
0181     }
0182 
0183     /*
0184      * Run all _REG methods
0185      *
0186      * Note: Any objects accessed by the _REG methods will be automatically
0187      * initialized, even if they contain executable AML (see the call to
0188      * acpi_ns_initialize_objects below).
0189      *
0190      * Note: According to the ACPI specification, we actually needn't execute
0191      * _REG for system_memory/system_io operation regions, but for PCI_Config
0192      * operation regions, it is required to evaluate _REG for those on a PCI
0193      * root bus that doesn't contain _BBN object. So this code is kept here
0194      * in order not to break things.
0195      */
0196     if (!(flags & ACPI_NO_ADDRESS_SPACE_INIT)) {
0197         ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
0198                   "[Init] Executing _REG OpRegion methods\n"));
0199 
0200         status = acpi_ev_initialize_op_regions();
0201         if (ACPI_FAILURE(status)) {
0202             goto error_exit;
0203         }
0204     }
0205 
0206     if (!(flags & ACPI_NO_DEVICE_INIT)) {
0207 
0208         /* Walk namespace to execute all _INIs on present devices */
0209 
0210         status = acpi_ns_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
0211                         ACPI_UINT32_MAX, FALSE,
0212                         acpi_ns_init_one_device, NULL,
0213                         &info, NULL);
0214 
0215         /*
0216          * Any _OSI requests should be completed by now. If the BIOS has
0217          * requested any Windows OSI strings, we will always truncate
0218          * I/O addresses to 16 bits -- for Windows compatibility.
0219          */
0220         if (acpi_gbl_osi_data >= ACPI_OSI_WIN_2000) {
0221             acpi_gbl_truncate_io_addresses = TRUE;
0222         }
0223 
0224         ACPI_FREE(info.evaluate_info);
0225         if (ACPI_FAILURE(status)) {
0226             goto error_exit;
0227         }
0228 
0229         ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT,
0230                       "    Executed %u _INI methods requiring %u _STA executions "
0231                       "(examined %u objects)\n",
0232                       info.num_INI, info.num_STA,
0233                       info.device_count));
0234     }
0235 
0236     return_ACPI_STATUS(status);
0237 
0238 error_exit:
0239     ACPI_EXCEPTION((AE_INFO, status, "During device initialization"));
0240     return_ACPI_STATUS(status);
0241 }
0242 
0243 /*******************************************************************************
0244  *
0245  * FUNCTION:    acpi_ns_init_one_package
0246  *
0247  * PARAMETERS:  obj_handle      - Node
0248  *              level           - Current nesting level
0249  *              context         - Not used
0250  *              return_value    - Not used
0251  *
0252  * RETURN:      Status
0253  *
0254  * DESCRIPTION: Callback from acpi_walk_namespace. Invoked for every package
0255  *              within the namespace. Used during dynamic load of an SSDT.
0256  *
0257  ******************************************************************************/
0258 
0259 acpi_status
0260 acpi_ns_init_one_package(acpi_handle obj_handle,
0261              u32 level, void *context, void **return_value)
0262 {
0263     acpi_status status;
0264     union acpi_operand_object *obj_desc;
0265     struct acpi_namespace_node *node =
0266         (struct acpi_namespace_node *)obj_handle;
0267 
0268     obj_desc = acpi_ns_get_attached_object(node);
0269     if (!obj_desc) {
0270         return (AE_OK);
0271     }
0272 
0273     /* Exit if package is already initialized */
0274 
0275     if (obj_desc->package.flags & AOPOBJ_DATA_VALID) {
0276         return (AE_OK);
0277     }
0278 
0279     status = acpi_ds_get_package_arguments(obj_desc);
0280     if (ACPI_FAILURE(status)) {
0281         return (AE_OK);
0282     }
0283 
0284     status =
0285         acpi_ut_walk_package_tree(obj_desc, NULL,
0286                       acpi_ds_init_package_element, NULL);
0287     if (ACPI_FAILURE(status)) {
0288         return (AE_OK);
0289     }
0290 
0291     obj_desc->package.flags |= AOPOBJ_DATA_VALID;
0292     return (AE_OK);
0293 }
0294 
0295 /*******************************************************************************
0296  *
0297  * FUNCTION:    acpi_ns_init_one_object
0298  *
0299  * PARAMETERS:  obj_handle      - Node
0300  *              level           - Current nesting level
0301  *              context         - Points to a init info struct
0302  *              return_value    - Not used
0303  *
0304  * RETURN:      Status
0305  *
0306  * DESCRIPTION: Callback from acpi_walk_namespace. Invoked for every object
0307  *              within the namespace.
0308  *
0309  *              Currently, the only objects that require initialization are:
0310  *              1) Methods
0311  *              2) Op Regions
0312  *
0313  ******************************************************************************/
0314 
0315 static acpi_status
0316 acpi_ns_init_one_object(acpi_handle obj_handle,
0317             u32 level, void *context, void **return_value)
0318 {
0319     acpi_object_type type;
0320     acpi_status status = AE_OK;
0321     struct acpi_init_walk_info *info =
0322         (struct acpi_init_walk_info *)context;
0323     struct acpi_namespace_node *node =
0324         (struct acpi_namespace_node *)obj_handle;
0325     union acpi_operand_object *obj_desc;
0326 
0327     ACPI_FUNCTION_NAME(ns_init_one_object);
0328 
0329     info->object_count++;
0330 
0331     /* And even then, we are only interested in a few object types */
0332 
0333     type = acpi_ns_get_type(obj_handle);
0334     obj_desc = acpi_ns_get_attached_object(node);
0335     if (!obj_desc) {
0336         return (AE_OK);
0337     }
0338 
0339     /* Increment counters for object types we are looking for */
0340 
0341     switch (type) {
0342     case ACPI_TYPE_REGION:
0343 
0344         info->op_region_count++;
0345         break;
0346 
0347     case ACPI_TYPE_BUFFER_FIELD:
0348 
0349         info->field_count++;
0350         break;
0351 
0352     case ACPI_TYPE_LOCAL_BANK_FIELD:
0353 
0354         info->field_count++;
0355         break;
0356 
0357     case ACPI_TYPE_BUFFER:
0358 
0359         info->buffer_count++;
0360         break;
0361 
0362     case ACPI_TYPE_PACKAGE:
0363 
0364         info->package_count++;
0365         break;
0366 
0367     default:
0368 
0369         /* No init required, just exit now */
0370 
0371         return (AE_OK);
0372     }
0373 
0374     /* If the object is already initialized, nothing else to do */
0375 
0376     if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {
0377         return (AE_OK);
0378     }
0379 
0380     /* Must lock the interpreter before executing AML code */
0381 
0382     acpi_ex_enter_interpreter();
0383 
0384     /*
0385      * Only initialization of Package objects can be deferred, in order
0386      * to support forward references.
0387      */
0388     switch (type) {
0389     case ACPI_TYPE_LOCAL_BANK_FIELD:
0390 
0391         /* TBD: bank_fields do not require deferred init, remove this code */
0392 
0393         info->field_init++;
0394         status = acpi_ds_get_bank_field_arguments(obj_desc);
0395         break;
0396 
0397     case ACPI_TYPE_PACKAGE:
0398 
0399         /* Complete the initialization/resolution of the package object */
0400 
0401         info->package_init++;
0402         status =
0403             acpi_ns_init_one_package(obj_handle, level, NULL, NULL);
0404         break;
0405 
0406     default:
0407 
0408         /* No other types should get here */
0409 
0410         status = AE_TYPE;
0411         ACPI_EXCEPTION((AE_INFO, status,
0412                 "Opcode is not deferred [%4.4s] (%s)",
0413                 acpi_ut_get_node_name(node),
0414                 acpi_ut_get_type_name(type)));
0415         break;
0416     }
0417 
0418     if (ACPI_FAILURE(status)) {
0419         ACPI_EXCEPTION((AE_INFO, status,
0420                 "Could not execute arguments for [%4.4s] (%s)",
0421                 acpi_ut_get_node_name(node),
0422                 acpi_ut_get_type_name(type)));
0423     }
0424 
0425     /*
0426      * We ignore errors from above, and always return OK, since we don't want
0427      * to abort the walk on any single error.
0428      */
0429     acpi_ex_exit_interpreter();
0430     return (AE_OK);
0431 }
0432 
0433 /*******************************************************************************
0434  *
0435  * FUNCTION:    acpi_ns_find_ini_methods
0436  *
0437  * PARAMETERS:  acpi_walk_callback
0438  *
0439  * RETURN:      acpi_status
0440  *
0441  * DESCRIPTION: Called during namespace walk. Finds objects named _INI under
0442  *              device/processor/thermal objects, and marks the entire subtree
0443  *              with a SUBTREE_HAS_INI flag. This flag is used during the
0444  *              subsequent device initialization walk to avoid entire subtrees
0445  *              that do not contain an _INI.
0446  *
0447  ******************************************************************************/
0448 
0449 static acpi_status
0450 acpi_ns_find_ini_methods(acpi_handle obj_handle,
0451              u32 nesting_level, void *context, void **return_value)
0452 {
0453     struct acpi_device_walk_info *info =
0454         ACPI_CAST_PTR(struct acpi_device_walk_info, context);
0455     struct acpi_namespace_node *node;
0456     struct acpi_namespace_node *parent_node;
0457 
0458     /* Keep count of device/processor/thermal objects */
0459 
0460     node = ACPI_CAST_PTR(struct acpi_namespace_node, obj_handle);
0461     if ((node->type == ACPI_TYPE_DEVICE) ||
0462         (node->type == ACPI_TYPE_PROCESSOR) ||
0463         (node->type == ACPI_TYPE_THERMAL)) {
0464         info->device_count++;
0465         return (AE_OK);
0466     }
0467 
0468     /* We are only looking for methods named _INI */
0469 
0470     if (!ACPI_COMPARE_NAMESEG(node->name.ascii, METHOD_NAME__INI)) {
0471         return (AE_OK);
0472     }
0473 
0474     /*
0475      * The only _INI methods that we care about are those that are
0476      * present under Device, Processor, and Thermal objects.
0477      */
0478     parent_node = node->parent;
0479     switch (parent_node->type) {
0480     case ACPI_TYPE_DEVICE:
0481     case ACPI_TYPE_PROCESSOR:
0482     case ACPI_TYPE_THERMAL:
0483 
0484         /* Mark parent and bubble up the INI present flag to the root */
0485 
0486         while (parent_node) {
0487             parent_node->flags |= ANOBJ_SUBTREE_HAS_INI;
0488             parent_node = parent_node->parent;
0489         }
0490         break;
0491 
0492     default:
0493 
0494         break;
0495     }
0496 
0497     return (AE_OK);
0498 }
0499 
0500 /*******************************************************************************
0501  *
0502  * FUNCTION:    acpi_ns_init_one_device
0503  *
0504  * PARAMETERS:  acpi_walk_callback
0505  *
0506  * RETURN:      acpi_status
0507  *
0508  * DESCRIPTION: This is called once per device soon after ACPI is enabled
0509  *              to initialize each device. It determines if the device is
0510  *              present, and if so, calls _INI.
0511  *
0512  ******************************************************************************/
0513 
0514 static acpi_status
0515 acpi_ns_init_one_device(acpi_handle obj_handle,
0516             u32 nesting_level, void *context, void **return_value)
0517 {
0518     struct acpi_device_walk_info *walk_info =
0519         ACPI_CAST_PTR(struct acpi_device_walk_info, context);
0520     struct acpi_evaluate_info *info = walk_info->evaluate_info;
0521     u32 flags;
0522     acpi_status status;
0523     struct acpi_namespace_node *device_node;
0524 
0525     ACPI_FUNCTION_TRACE(ns_init_one_device);
0526 
0527     /* We are interested in Devices, Processors and thermal_zones only */
0528 
0529     device_node = ACPI_CAST_PTR(struct acpi_namespace_node, obj_handle);
0530     if ((device_node->type != ACPI_TYPE_DEVICE) &&
0531         (device_node->type != ACPI_TYPE_PROCESSOR) &&
0532         (device_node->type != ACPI_TYPE_THERMAL)) {
0533         return_ACPI_STATUS(AE_OK);
0534     }
0535 
0536     /*
0537      * Because of an earlier namespace analysis, all subtrees that contain an
0538      * _INI method are tagged.
0539      *
0540      * If this device subtree does not contain any _INI methods, we
0541      * can exit now and stop traversing this entire subtree.
0542      */
0543     if (!(device_node->flags & ANOBJ_SUBTREE_HAS_INI)) {
0544         return_ACPI_STATUS(AE_CTRL_DEPTH);
0545     }
0546 
0547     /*
0548      * Run _STA to determine if this device is present and functioning. We
0549      * must know this information for two important reasons (from ACPI spec):
0550      *
0551      * 1) We can only run _INI if the device is present.
0552      * 2) We must abort the device tree walk on this subtree if the device is
0553      *    not present and is not functional (we will not examine the children)
0554      *
0555      * The _STA method is not required to be present under the device, we
0556      * assume the device is present if _STA does not exist.
0557      */
0558     ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname
0559             (ACPI_TYPE_METHOD, device_node, METHOD_NAME__STA));
0560 
0561     status = acpi_ut_execute_STA(device_node, &flags);
0562     if (ACPI_FAILURE(status)) {
0563 
0564         /* Ignore error and move on to next device */
0565 
0566         return_ACPI_STATUS(AE_OK);
0567     }
0568 
0569     /*
0570      * Flags == -1 means that _STA was not found. In this case, we assume that
0571      * the device is both present and functional.
0572      *
0573      * From the ACPI spec, description of _STA:
0574      *
0575      * "If a device object (including the processor object) does not have an
0576      * _STA object, then OSPM assumes that all of the above bits are set (in
0577      * other words, the device is present, ..., and functioning)"
0578      */
0579     if (flags != ACPI_UINT32_MAX) {
0580         walk_info->num_STA++;
0581     }
0582 
0583     /*
0584      * Examine the PRESENT and FUNCTIONING status bits
0585      *
0586      * Note: ACPI spec does not seem to specify behavior for the present but
0587      * not functioning case, so we assume functioning if present.
0588      */
0589     if (!(flags & ACPI_STA_DEVICE_PRESENT)) {
0590 
0591         /* Device is not present, we must examine the Functioning bit */
0592 
0593         if (flags & ACPI_STA_DEVICE_FUNCTIONING) {
0594             /*
0595              * Device is not present but is "functioning". In this case,
0596              * we will not run _INI, but we continue to examine the children
0597              * of this device.
0598              *
0599              * From the ACPI spec, description of _STA: (note - no mention
0600              * of whether to run _INI or not on the device in question)
0601              *
0602              * "_STA may return bit 0 clear (not present) with bit 3 set
0603              * (device is functional). This case is used to indicate a valid
0604              * device for which no device driver should be loaded (for example,
0605              * a bridge device.) Children of this device may be present and
0606              * valid. OSPM should continue enumeration below a device whose
0607              * _STA returns this bit combination"
0608              */
0609             return_ACPI_STATUS(AE_OK);
0610         } else {
0611             /*
0612              * Device is not present and is not functioning. We must abort the
0613              * walk of this subtree immediately -- don't look at the children
0614              * of such a device.
0615              *
0616              * From the ACPI spec, description of _INI:
0617              *
0618              * "If the _STA method indicates that the device is not present,
0619              * OSPM will not run the _INI and will not examine the children
0620              * of the device for _INI methods"
0621              */
0622             return_ACPI_STATUS(AE_CTRL_DEPTH);
0623         }
0624     }
0625 
0626     /*
0627      * The device is present or is assumed present if no _STA exists.
0628      * Run the _INI if it exists (not required to exist)
0629      *
0630      * Note: We know there is an _INI within this subtree, but it may not be
0631      * under this particular device, it may be lower in the branch.
0632      */
0633     if (!ACPI_COMPARE_NAMESEG(device_node->name.ascii, "_SB_") ||
0634         device_node->parent != acpi_gbl_root_node) {
0635         ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname
0636                 (ACPI_TYPE_METHOD, device_node,
0637                  METHOD_NAME__INI));
0638 
0639         memset(info, 0, sizeof(struct acpi_evaluate_info));
0640         info->prefix_node = device_node;
0641         info->relative_pathname = METHOD_NAME__INI;
0642         info->parameters = NULL;
0643         info->flags = ACPI_IGNORE_RETURN_VALUE;
0644 
0645         status = acpi_ns_evaluate(info);
0646         if (ACPI_SUCCESS(status)) {
0647             walk_info->num_INI++;
0648         }
0649 #ifdef ACPI_DEBUG_OUTPUT
0650         else if (status != AE_NOT_FOUND) {
0651 
0652             /* Ignore error and move on to next device */
0653 
0654             char *scope_name =
0655                 acpi_ns_get_normalized_pathname(device_node, TRUE);
0656 
0657             ACPI_EXCEPTION((AE_INFO, status,
0658                     "during %s._INI execution",
0659                     scope_name));
0660             ACPI_FREE(scope_name);
0661         }
0662 #endif
0663     }
0664 
0665     /* Ignore errors from above */
0666 
0667     status = AE_OK;
0668 
0669     /*
0670      * The _INI method has been run if present; call the Global Initialization
0671      * Handler for this device.
0672      */
0673     if (acpi_gbl_init_handler) {
0674         status =
0675             acpi_gbl_init_handler(device_node, ACPI_INIT_DEVICE_INI);
0676     }
0677 
0678     return_ACPI_STATUS(status);
0679 }