Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  *  acpi_utils.c - ACPI Utility Functions ($Revision: 10 $)
0004  *
0005  *  Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
0006  *  Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
0007  */
0008 
0009 #define pr_fmt(fmt) "ACPI: utils: " fmt
0010 
0011 #include <linux/kernel.h>
0012 #include <linux/module.h>
0013 #include <linux/slab.h>
0014 #include <linux/init.h>
0015 #include <linux/types.h>
0016 #include <linux/hardirq.h>
0017 #include <linux/acpi.h>
0018 #include <linux/dynamic_debug.h>
0019 
0020 #include "internal.h"
0021 #include "sleep.h"
0022 
0023 /* --------------------------------------------------------------------------
0024                             Object Evaluation Helpers
0025    -------------------------------------------------------------------------- */
0026 static void acpi_util_eval_error(acpi_handle h, acpi_string p, acpi_status s)
0027 {
0028     acpi_handle_debug(h, "Evaluate [%s]: %s\n", p, acpi_format_exception(s));
0029 }
0030 
0031 acpi_status
0032 acpi_extract_package(union acpi_object *package,
0033              struct acpi_buffer *format, struct acpi_buffer *buffer)
0034 {
0035     u32 size_required = 0;
0036     u32 tail_offset = 0;
0037     char *format_string = NULL;
0038     u32 format_count = 0;
0039     u32 i = 0;
0040     u8 *head = NULL;
0041     u8 *tail = NULL;
0042 
0043 
0044     if (!package || (package->type != ACPI_TYPE_PACKAGE)
0045         || (package->package.count < 1)) {
0046         pr_debug("Invalid package argument\n");
0047         return AE_BAD_PARAMETER;
0048     }
0049 
0050     if (!format || !format->pointer || (format->length < 1)) {
0051         pr_debug("Invalid format argument\n");
0052         return AE_BAD_PARAMETER;
0053     }
0054 
0055     if (!buffer) {
0056         pr_debug("Invalid buffer argument\n");
0057         return AE_BAD_PARAMETER;
0058     }
0059 
0060     format_count = (format->length / sizeof(char)) - 1;
0061     if (format_count > package->package.count) {
0062         pr_debug("Format specifies more objects [%d] than present [%d]\n",
0063              format_count, package->package.count);
0064         return AE_BAD_DATA;
0065     }
0066 
0067     format_string = format->pointer;
0068 
0069     /*
0070      * Calculate size_required.
0071      */
0072     for (i = 0; i < format_count; i++) {
0073 
0074         union acpi_object *element = &(package->package.elements[i]);
0075 
0076         switch (element->type) {
0077 
0078         case ACPI_TYPE_INTEGER:
0079             switch (format_string[i]) {
0080             case 'N':
0081                 size_required += sizeof(u64);
0082                 tail_offset += sizeof(u64);
0083                 break;
0084             case 'S':
0085                 size_required +=
0086                     sizeof(char *) + sizeof(u64) +
0087                     sizeof(char);
0088                 tail_offset += sizeof(char *);
0089                 break;
0090             default:
0091                 pr_debug("Invalid package element [%d]: got number, expected [%c]\n",
0092                      i, format_string[i]);
0093                 return AE_BAD_DATA;
0094             }
0095             break;
0096 
0097         case ACPI_TYPE_STRING:
0098         case ACPI_TYPE_BUFFER:
0099             switch (format_string[i]) {
0100             case 'S':
0101                 size_required +=
0102                     sizeof(char *) +
0103                     (element->string.length * sizeof(char)) +
0104                     sizeof(char);
0105                 tail_offset += sizeof(char *);
0106                 break;
0107             case 'B':
0108                 size_required +=
0109                     sizeof(u8 *) + element->buffer.length;
0110                 tail_offset += sizeof(u8 *);
0111                 break;
0112             default:
0113                 pr_debug("Invalid package element [%d] got string/buffer, expected [%c]\n",
0114                      i, format_string[i]);
0115                 return AE_BAD_DATA;
0116             }
0117             break;
0118         case ACPI_TYPE_LOCAL_REFERENCE:
0119             switch (format_string[i]) {
0120             case 'R':
0121                 size_required += sizeof(void *);
0122                 tail_offset += sizeof(void *);
0123                 break;
0124             default:
0125                 pr_debug("Invalid package element [%d] got reference, expected [%c]\n",
0126                      i, format_string[i]);
0127                 return AE_BAD_DATA;
0128             }
0129             break;
0130 
0131         case ACPI_TYPE_PACKAGE:
0132         default:
0133             pr_debug("Unsupported element at index=%d\n", i);
0134             /* TBD: handle nested packages... */
0135             return AE_SUPPORT;
0136         }
0137     }
0138 
0139     /*
0140      * Validate output buffer.
0141      */
0142     if (buffer->length == ACPI_ALLOCATE_BUFFER) {
0143         buffer->pointer = ACPI_ALLOCATE_ZEROED(size_required);
0144         if (!buffer->pointer)
0145             return AE_NO_MEMORY;
0146         buffer->length = size_required;
0147     } else {
0148         if (buffer->length < size_required) {
0149             buffer->length = size_required;
0150             return AE_BUFFER_OVERFLOW;
0151         } else if (buffer->length != size_required ||
0152                !buffer->pointer) {
0153             return AE_BAD_PARAMETER;
0154         }
0155     }
0156 
0157     head = buffer->pointer;
0158     tail = buffer->pointer + tail_offset;
0159 
0160     /*
0161      * Extract package data.
0162      */
0163     for (i = 0; i < format_count; i++) {
0164 
0165         u8 **pointer = NULL;
0166         union acpi_object *element = &(package->package.elements[i]);
0167 
0168         switch (element->type) {
0169 
0170         case ACPI_TYPE_INTEGER:
0171             switch (format_string[i]) {
0172             case 'N':
0173                 *((u64 *) head) =
0174                     element->integer.value;
0175                 head += sizeof(u64);
0176                 break;
0177             case 'S':
0178                 pointer = (u8 **) head;
0179                 *pointer = tail;
0180                 *((u64 *) tail) =
0181                     element->integer.value;
0182                 head += sizeof(u64 *);
0183                 tail += sizeof(u64);
0184                 /* NULL terminate string */
0185                 *tail = (char)0;
0186                 tail += sizeof(char);
0187                 break;
0188             default:
0189                 /* Should never get here */
0190                 break;
0191             }
0192             break;
0193 
0194         case ACPI_TYPE_STRING:
0195         case ACPI_TYPE_BUFFER:
0196             switch (format_string[i]) {
0197             case 'S':
0198                 pointer = (u8 **) head;
0199                 *pointer = tail;
0200                 memcpy(tail, element->string.pointer,
0201                        element->string.length);
0202                 head += sizeof(char *);
0203                 tail += element->string.length * sizeof(char);
0204                 /* NULL terminate string */
0205                 *tail = (char)0;
0206                 tail += sizeof(char);
0207                 break;
0208             case 'B':
0209                 pointer = (u8 **) head;
0210                 *pointer = tail;
0211                 memcpy(tail, element->buffer.pointer,
0212                        element->buffer.length);
0213                 head += sizeof(u8 *);
0214                 tail += element->buffer.length;
0215                 break;
0216             default:
0217                 /* Should never get here */
0218                 break;
0219             }
0220             break;
0221         case ACPI_TYPE_LOCAL_REFERENCE:
0222             switch (format_string[i]) {
0223             case 'R':
0224                 *(void **)head =
0225                     (void *)element->reference.handle;
0226                 head += sizeof(void *);
0227                 break;
0228             default:
0229                 /* Should never get here */
0230                 break;
0231             }
0232             break;
0233         case ACPI_TYPE_PACKAGE:
0234             /* TBD: handle nested packages... */
0235         default:
0236             /* Should never get here */
0237             break;
0238         }
0239     }
0240 
0241     return AE_OK;
0242 }
0243 
0244 EXPORT_SYMBOL(acpi_extract_package);
0245 
0246 acpi_status
0247 acpi_evaluate_integer(acpi_handle handle,
0248               acpi_string pathname,
0249               struct acpi_object_list *arguments, unsigned long long *data)
0250 {
0251     acpi_status status = AE_OK;
0252     union acpi_object element;
0253     struct acpi_buffer buffer = { 0, NULL };
0254 
0255     if (!data)
0256         return AE_BAD_PARAMETER;
0257 
0258     buffer.length = sizeof(union acpi_object);
0259     buffer.pointer = &element;
0260     status = acpi_evaluate_object(handle, pathname, arguments, &buffer);
0261     if (ACPI_FAILURE(status)) {
0262         acpi_util_eval_error(handle, pathname, status);
0263         return status;
0264     }
0265 
0266     if (element.type != ACPI_TYPE_INTEGER) {
0267         acpi_util_eval_error(handle, pathname, AE_BAD_DATA);
0268         return AE_BAD_DATA;
0269     }
0270 
0271     *data = element.integer.value;
0272 
0273     acpi_handle_debug(handle, "Return value [%llu]\n", *data);
0274 
0275     return AE_OK;
0276 }
0277 
0278 EXPORT_SYMBOL(acpi_evaluate_integer);
0279 
0280 int acpi_get_local_address(acpi_handle handle, u32 *addr)
0281 {
0282     unsigned long long adr;
0283     acpi_status status;
0284 
0285     status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL, &adr);
0286     if (ACPI_FAILURE(status))
0287         return -ENODATA;
0288 
0289     *addr = (u32)adr;
0290     return 0;
0291 }
0292 EXPORT_SYMBOL(acpi_get_local_address);
0293 
0294 #define ACPI_MAX_SUB_BUF_SIZE   9
0295 
0296 const char *acpi_get_subsystem_id(acpi_handle handle)
0297 {
0298     struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
0299     union acpi_object *obj;
0300     acpi_status status;
0301     const char *sub;
0302     size_t len;
0303 
0304     status = acpi_evaluate_object(handle, METHOD_NAME__SUB, NULL, &buffer);
0305     if (ACPI_FAILURE(status)) {
0306         acpi_handle_debug(handle, "Reading ACPI _SUB failed: %#x\n", status);
0307         return ERR_PTR(-ENODATA);
0308     }
0309 
0310     obj = buffer.pointer;
0311     if (obj->type == ACPI_TYPE_STRING) {
0312         len = strlen(obj->string.pointer);
0313         if (len < ACPI_MAX_SUB_BUF_SIZE && len > 0) {
0314             sub = kstrdup(obj->string.pointer, GFP_KERNEL);
0315             if (!sub)
0316                 sub = ERR_PTR(-ENOMEM);
0317         } else {
0318             acpi_handle_err(handle, "ACPI _SUB Length %zu is Invalid\n", len);
0319             sub = ERR_PTR(-ENODATA);
0320         }
0321     } else {
0322         acpi_handle_warn(handle, "Warning ACPI _SUB did not return a string\n");
0323         sub = ERR_PTR(-ENODATA);
0324     }
0325 
0326     acpi_os_free(buffer.pointer);
0327 
0328     return sub;
0329 }
0330 EXPORT_SYMBOL_GPL(acpi_get_subsystem_id);
0331 
0332 acpi_status
0333 acpi_evaluate_reference(acpi_handle handle,
0334             acpi_string pathname,
0335             struct acpi_object_list *arguments,
0336             struct acpi_handle_list *list)
0337 {
0338     acpi_status status = AE_OK;
0339     union acpi_object *package = NULL;
0340     union acpi_object *element = NULL;
0341     struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
0342     u32 i = 0;
0343 
0344 
0345     if (!list) {
0346         return AE_BAD_PARAMETER;
0347     }
0348 
0349     /* Evaluate object. */
0350 
0351     status = acpi_evaluate_object(handle, pathname, arguments, &buffer);
0352     if (ACPI_FAILURE(status))
0353         goto end;
0354 
0355     package = buffer.pointer;
0356 
0357     if ((buffer.length == 0) || !package) {
0358         status = AE_BAD_DATA;
0359         acpi_util_eval_error(handle, pathname, status);
0360         goto end;
0361     }
0362     if (package->type != ACPI_TYPE_PACKAGE) {
0363         status = AE_BAD_DATA;
0364         acpi_util_eval_error(handle, pathname, status);
0365         goto end;
0366     }
0367     if (!package->package.count) {
0368         status = AE_BAD_DATA;
0369         acpi_util_eval_error(handle, pathname, status);
0370         goto end;
0371     }
0372 
0373     if (package->package.count > ACPI_MAX_HANDLES) {
0374         kfree(package);
0375         return AE_NO_MEMORY;
0376     }
0377     list->count = package->package.count;
0378 
0379     /* Extract package data. */
0380 
0381     for (i = 0; i < list->count; i++) {
0382 
0383         element = &(package->package.elements[i]);
0384 
0385         if (element->type != ACPI_TYPE_LOCAL_REFERENCE) {
0386             status = AE_BAD_DATA;
0387             acpi_util_eval_error(handle, pathname, status);
0388             break;
0389         }
0390 
0391         if (!element->reference.handle) {
0392             status = AE_NULL_ENTRY;
0393             acpi_util_eval_error(handle, pathname, status);
0394             break;
0395         }
0396         /* Get the  acpi_handle. */
0397 
0398         list->handles[i] = element->reference.handle;
0399         acpi_handle_debug(list->handles[i], "Found in reference list\n");
0400     }
0401 
0402       end:
0403     if (ACPI_FAILURE(status)) {
0404         list->count = 0;
0405         //kfree(list->handles);
0406     }
0407 
0408     kfree(buffer.pointer);
0409 
0410     return status;
0411 }
0412 
0413 EXPORT_SYMBOL(acpi_evaluate_reference);
0414 
0415 acpi_status
0416 acpi_get_physical_device_location(acpi_handle handle, struct acpi_pld_info **pld)
0417 {
0418     acpi_status status;
0419     struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
0420     union acpi_object *output;
0421 
0422     status = acpi_evaluate_object(handle, "_PLD", NULL, &buffer);
0423 
0424     if (ACPI_FAILURE(status))
0425         return status;
0426 
0427     output = buffer.pointer;
0428 
0429     if (!output || output->type != ACPI_TYPE_PACKAGE
0430         || !output->package.count
0431         || output->package.elements[0].type != ACPI_TYPE_BUFFER
0432         || output->package.elements[0].buffer.length < ACPI_PLD_REV1_BUFFER_SIZE) {
0433         status = AE_TYPE;
0434         goto out;
0435     }
0436 
0437     status = acpi_decode_pld_buffer(
0438             output->package.elements[0].buffer.pointer,
0439             output->package.elements[0].buffer.length,
0440             pld);
0441 
0442 out:
0443     kfree(buffer.pointer);
0444     return status;
0445 }
0446 EXPORT_SYMBOL(acpi_get_physical_device_location);
0447 
0448 /**
0449  * acpi_evaluate_ost: Evaluate _OST for hotplug operations
0450  * @handle: ACPI device handle
0451  * @source_event: source event code
0452  * @status_code: status code
0453  * @status_buf: optional detailed information (NULL if none)
0454  *
0455  * Evaluate _OST for hotplug operations. All ACPI hotplug handlers
0456  * must call this function when evaluating _OST for hotplug operations.
0457  * When the platform does not support _OST, this function has no effect.
0458  */
0459 acpi_status
0460 acpi_evaluate_ost(acpi_handle handle, u32 source_event, u32 status_code,
0461           struct acpi_buffer *status_buf)
0462 {
0463     union acpi_object params[3] = {
0464         {.type = ACPI_TYPE_INTEGER,},
0465         {.type = ACPI_TYPE_INTEGER,},
0466         {.type = ACPI_TYPE_BUFFER,}
0467     };
0468     struct acpi_object_list arg_list = {3, params};
0469 
0470     params[0].integer.value = source_event;
0471     params[1].integer.value = status_code;
0472     if (status_buf != NULL) {
0473         params[2].buffer.pointer = status_buf->pointer;
0474         params[2].buffer.length = status_buf->length;
0475     } else {
0476         params[2].buffer.pointer = NULL;
0477         params[2].buffer.length = 0;
0478     }
0479 
0480     return acpi_evaluate_object(handle, "_OST", &arg_list, NULL);
0481 }
0482 EXPORT_SYMBOL(acpi_evaluate_ost);
0483 
0484 /**
0485  * acpi_handle_path: Return the object path of handle
0486  * @handle: ACPI device handle
0487  *
0488  * Caller must free the returned buffer
0489  */
0490 static char *acpi_handle_path(acpi_handle handle)
0491 {
0492     struct acpi_buffer buffer = {
0493         .length = ACPI_ALLOCATE_BUFFER,
0494         .pointer = NULL
0495     };
0496 
0497     if (in_interrupt() ||
0498         acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer) != AE_OK)
0499         return NULL;
0500     return buffer.pointer;
0501 }
0502 
0503 /**
0504  * acpi_handle_printk: Print message with ACPI prefix and object path
0505  * @level: log level
0506  * @handle: ACPI device handle
0507  * @fmt: format string
0508  *
0509  * This function is called through acpi_handle_<level> macros and prints
0510  * a message with ACPI prefix and object path.  This function acquires
0511  * the global namespace mutex to obtain an object path.  In interrupt
0512  * context, it shows the object path as <n/a>.
0513  */
0514 void
0515 acpi_handle_printk(const char *level, acpi_handle handle, const char *fmt, ...)
0516 {
0517     struct va_format vaf;
0518     va_list args;
0519     const char *path;
0520 
0521     va_start(args, fmt);
0522     vaf.fmt = fmt;
0523     vaf.va = &args;
0524 
0525     path = acpi_handle_path(handle);
0526     printk("%sACPI: %s: %pV", level, path ? path : "<n/a>" , &vaf);
0527 
0528     va_end(args);
0529     kfree(path);
0530 }
0531 EXPORT_SYMBOL(acpi_handle_printk);
0532 
0533 #if defined(CONFIG_DYNAMIC_DEBUG)
0534 /**
0535  * __acpi_handle_debug: pr_debug with ACPI prefix and object path
0536  * @descriptor: Dynamic Debug descriptor
0537  * @handle: ACPI device handle
0538  * @fmt: format string
0539  *
0540  * This function is called through acpi_handle_debug macro and debug
0541  * prints a message with ACPI prefix and object path. This function
0542  * acquires the global namespace mutex to obtain an object path.  In
0543  * interrupt context, it shows the object path as <n/a>.
0544  */
0545 void
0546 __acpi_handle_debug(struct _ddebug *descriptor, acpi_handle handle,
0547             const char *fmt, ...)
0548 {
0549     struct va_format vaf;
0550     va_list args;
0551     const char *path;
0552 
0553     va_start(args, fmt);
0554     vaf.fmt = fmt;
0555     vaf.va = &args;
0556 
0557     path = acpi_handle_path(handle);
0558     __dynamic_pr_debug(descriptor, "ACPI: %s: %pV", path ? path : "<n/a>", &vaf);
0559 
0560     va_end(args);
0561     kfree(path);
0562 }
0563 EXPORT_SYMBOL(__acpi_handle_debug);
0564 #endif
0565 
0566 /**
0567  * acpi_evaluation_failure_warn - Log evaluation failure warning.
0568  * @handle: Parent object handle.
0569  * @name: Name of the object whose evaluation has failed.
0570  * @status: Status value returned by the failing object evaluation.
0571  */
0572 void acpi_evaluation_failure_warn(acpi_handle handle, const char *name,
0573                   acpi_status status)
0574 {
0575     acpi_handle_warn(handle, "%s evaluation failed: %s\n", name,
0576              acpi_format_exception(status));
0577 }
0578 EXPORT_SYMBOL_GPL(acpi_evaluation_failure_warn);
0579 
0580 /**
0581  * acpi_has_method: Check whether @handle has a method named @name
0582  * @handle: ACPI device handle
0583  * @name: name of object or method
0584  *
0585  * Check whether @handle has a method named @name.
0586  */
0587 bool acpi_has_method(acpi_handle handle, char *name)
0588 {
0589     acpi_handle tmp;
0590 
0591     return ACPI_SUCCESS(acpi_get_handle(handle, name, &tmp));
0592 }
0593 EXPORT_SYMBOL(acpi_has_method);
0594 
0595 acpi_status acpi_execute_simple_method(acpi_handle handle, char *method,
0596                        u64 arg)
0597 {
0598     union acpi_object obj = { .type = ACPI_TYPE_INTEGER };
0599     struct acpi_object_list arg_list = { .count = 1, .pointer = &obj, };
0600 
0601     obj.integer.value = arg;
0602 
0603     return acpi_evaluate_object(handle, method, &arg_list, NULL);
0604 }
0605 EXPORT_SYMBOL(acpi_execute_simple_method);
0606 
0607 /**
0608  * acpi_evaluate_ej0: Evaluate _EJ0 method for hotplug operations
0609  * @handle: ACPI device handle
0610  *
0611  * Evaluate device's _EJ0 method for hotplug operations.
0612  */
0613 acpi_status acpi_evaluate_ej0(acpi_handle handle)
0614 {
0615     acpi_status status;
0616 
0617     status = acpi_execute_simple_method(handle, "_EJ0", 1);
0618     if (status == AE_NOT_FOUND)
0619         acpi_handle_warn(handle, "No _EJ0 support for device\n");
0620     else if (ACPI_FAILURE(status))
0621         acpi_handle_warn(handle, "Eject failed (0x%x)\n", status);
0622 
0623     return status;
0624 }
0625 
0626 /**
0627  * acpi_evaluate_lck: Evaluate _LCK method to lock/unlock device
0628  * @handle: ACPI device handle
0629  * @lock: lock device if non-zero, otherwise unlock device
0630  *
0631  * Evaluate device's _LCK method if present to lock/unlock device
0632  */
0633 acpi_status acpi_evaluate_lck(acpi_handle handle, int lock)
0634 {
0635     acpi_status status;
0636 
0637     status = acpi_execute_simple_method(handle, "_LCK", !!lock);
0638     if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
0639         if (lock)
0640             acpi_handle_warn(handle,
0641                 "Locking device failed (0x%x)\n", status);
0642         else
0643             acpi_handle_warn(handle,
0644                 "Unlocking device failed (0x%x)\n", status);
0645     }
0646 
0647     return status;
0648 }
0649 
0650 /**
0651  * acpi_evaluate_reg: Evaluate _REG method to register OpRegion presence
0652  * @handle: ACPI device handle
0653  * @space_id: ACPI address space id to register OpRegion presence for
0654  * @function: Parameter to pass to _REG one of ACPI_REG_CONNECT or
0655  *            ACPI_REG_DISCONNECT
0656  *
0657  * Evaluate device's _REG method to register OpRegion presence.
0658  */
0659 acpi_status acpi_evaluate_reg(acpi_handle handle, u8 space_id, u32 function)
0660 {
0661     struct acpi_object_list arg_list;
0662     union acpi_object params[2];
0663 
0664     params[0].type = ACPI_TYPE_INTEGER;
0665     params[0].integer.value = space_id;
0666     params[1].type = ACPI_TYPE_INTEGER;
0667     params[1].integer.value = function;
0668     arg_list.count = 2;
0669     arg_list.pointer = params;
0670 
0671     return acpi_evaluate_object(handle, "_REG", &arg_list, NULL);
0672 }
0673 EXPORT_SYMBOL(acpi_evaluate_reg);
0674 
0675 /**
0676  * acpi_evaluate_dsm - evaluate device's _DSM method
0677  * @handle: ACPI device handle
0678  * @guid: GUID of requested functions, should be 16 bytes
0679  * @rev: revision number of requested function
0680  * @func: requested function number
0681  * @argv4: the function specific parameter
0682  *
0683  * Evaluate device's _DSM method with specified GUID, revision id and
0684  * function number. Caller needs to free the returned object.
0685  *
0686  * Though ACPI defines the fourth parameter for _DSM should be a package,
0687  * some old BIOSes do expect a buffer or an integer etc.
0688  */
0689 union acpi_object *
0690 acpi_evaluate_dsm(acpi_handle handle, const guid_t *guid, u64 rev, u64 func,
0691           union acpi_object *argv4)
0692 {
0693     acpi_status ret;
0694     struct acpi_buffer buf = {ACPI_ALLOCATE_BUFFER, NULL};
0695     union acpi_object params[4];
0696     struct acpi_object_list input = {
0697         .count = 4,
0698         .pointer = params,
0699     };
0700 
0701     params[0].type = ACPI_TYPE_BUFFER;
0702     params[0].buffer.length = 16;
0703     params[0].buffer.pointer = (u8 *)guid;
0704     params[1].type = ACPI_TYPE_INTEGER;
0705     params[1].integer.value = rev;
0706     params[2].type = ACPI_TYPE_INTEGER;
0707     params[2].integer.value = func;
0708     if (argv4) {
0709         params[3] = *argv4;
0710     } else {
0711         params[3].type = ACPI_TYPE_PACKAGE;
0712         params[3].package.count = 0;
0713         params[3].package.elements = NULL;
0714     }
0715 
0716     ret = acpi_evaluate_object(handle, "_DSM", &input, &buf);
0717     if (ACPI_SUCCESS(ret))
0718         return (union acpi_object *)buf.pointer;
0719 
0720     if (ret != AE_NOT_FOUND)
0721         acpi_handle_warn(handle,
0722                  "failed to evaluate _DSM %pUb (0x%x)\n", guid, ret);
0723 
0724     return NULL;
0725 }
0726 EXPORT_SYMBOL(acpi_evaluate_dsm);
0727 
0728 /**
0729  * acpi_check_dsm - check if _DSM method supports requested functions.
0730  * @handle: ACPI device handle
0731  * @guid: GUID of requested functions, should be 16 bytes at least
0732  * @rev: revision number of requested functions
0733  * @funcs: bitmap of requested functions
0734  *
0735  * Evaluate device's _DSM method to check whether it supports requested
0736  * functions. Currently only support 64 functions at maximum, should be
0737  * enough for now.
0738  */
0739 bool acpi_check_dsm(acpi_handle handle, const guid_t *guid, u64 rev, u64 funcs)
0740 {
0741     int i;
0742     u64 mask = 0;
0743     union acpi_object *obj;
0744 
0745     if (funcs == 0)
0746         return false;
0747 
0748     obj = acpi_evaluate_dsm(handle, guid, rev, 0, NULL);
0749     if (!obj)
0750         return false;
0751 
0752     /* For compatibility, old BIOSes may return an integer */
0753     if (obj->type == ACPI_TYPE_INTEGER)
0754         mask = obj->integer.value;
0755     else if (obj->type == ACPI_TYPE_BUFFER)
0756         for (i = 0; i < obj->buffer.length && i < 8; i++)
0757             mask |= (((u64)obj->buffer.pointer[i]) << (i * 8));
0758     ACPI_FREE(obj);
0759 
0760     /*
0761      * Bit 0 indicates whether there's support for any functions other than
0762      * function 0 for the specified GUID and revision.
0763      */
0764     if ((mask & 0x1) && (mask & funcs) == funcs)
0765         return true;
0766 
0767     return false;
0768 }
0769 EXPORT_SYMBOL(acpi_check_dsm);
0770 
0771 /**
0772  * acpi_dev_hid_uid_match - Match device by supplied HID and UID
0773  * @adev: ACPI device to match.
0774  * @hid2: Hardware ID of the device.
0775  * @uid2: Unique ID of the device, pass NULL to not check _UID.
0776  *
0777  * Matches HID and UID in @adev with given @hid2 and @uid2.
0778  * Returns true if matches.
0779  */
0780 bool acpi_dev_hid_uid_match(struct acpi_device *adev,
0781                 const char *hid2, const char *uid2)
0782 {
0783     const char *hid1 = acpi_device_hid(adev);
0784     const char *uid1 = acpi_device_uid(adev);
0785 
0786     if (strcmp(hid1, hid2))
0787         return false;
0788 
0789     if (!uid2)
0790         return true;
0791 
0792     return uid1 && !strcmp(uid1, uid2);
0793 }
0794 EXPORT_SYMBOL(acpi_dev_hid_uid_match);
0795 
0796 /**
0797  * acpi_dev_found - Detect presence of a given ACPI device in the namespace.
0798  * @hid: Hardware ID of the device.
0799  *
0800  * Return %true if the device was present at the moment of invocation.
0801  * Note that if the device is pluggable, it may since have disappeared.
0802  *
0803  * For this function to work, acpi_bus_scan() must have been executed
0804  * which happens in the subsys_initcall() subsection. Hence, do not
0805  * call from a subsys_initcall() or earlier (use acpi_get_devices()
0806  * instead). Calling from module_init() is fine (which is synonymous
0807  * with device_initcall()).
0808  */
0809 bool acpi_dev_found(const char *hid)
0810 {
0811     struct acpi_device_bus_id *acpi_device_bus_id;
0812     bool found = false;
0813 
0814     mutex_lock(&acpi_device_lock);
0815     list_for_each_entry(acpi_device_bus_id, &acpi_bus_id_list, node)
0816         if (!strcmp(acpi_device_bus_id->bus_id, hid)) {
0817             found = true;
0818             break;
0819         }
0820     mutex_unlock(&acpi_device_lock);
0821 
0822     return found;
0823 }
0824 EXPORT_SYMBOL(acpi_dev_found);
0825 
0826 struct acpi_dev_match_info {
0827     struct acpi_device_id hid[2];
0828     const char *uid;
0829     s64 hrv;
0830 };
0831 
0832 static int acpi_dev_match_cb(struct device *dev, const void *data)
0833 {
0834     struct acpi_device *adev = to_acpi_device(dev);
0835     const struct acpi_dev_match_info *match = data;
0836     unsigned long long hrv;
0837     acpi_status status;
0838 
0839     if (acpi_match_device_ids(adev, match->hid))
0840         return 0;
0841 
0842     if (match->uid && (!adev->pnp.unique_id ||
0843         strcmp(adev->pnp.unique_id, match->uid)))
0844         return 0;
0845 
0846     if (match->hrv == -1)
0847         return 1;
0848 
0849     status = acpi_evaluate_integer(adev->handle, "_HRV", NULL, &hrv);
0850     if (ACPI_FAILURE(status))
0851         return 0;
0852 
0853     return hrv == match->hrv;
0854 }
0855 
0856 /**
0857  * acpi_dev_present - Detect that a given ACPI device is present
0858  * @hid: Hardware ID of the device.
0859  * @uid: Unique ID of the device, pass NULL to not check _UID
0860  * @hrv: Hardware Revision of the device, pass -1 to not check _HRV
0861  *
0862  * Return %true if a matching device was present at the moment of invocation.
0863  * Note that if the device is pluggable, it may since have disappeared.
0864  *
0865  * Note that unlike acpi_dev_found() this function checks the status
0866  * of the device. So for devices which are present in the DSDT, but
0867  * which are disabled (their _STA callback returns 0) this function
0868  * will return false.
0869  *
0870  * For this function to work, acpi_bus_scan() must have been executed
0871  * which happens in the subsys_initcall() subsection. Hence, do not
0872  * call from a subsys_initcall() or earlier (use acpi_get_devices()
0873  * instead). Calling from module_init() is fine (which is synonymous
0874  * with device_initcall()).
0875  */
0876 bool acpi_dev_present(const char *hid, const char *uid, s64 hrv)
0877 {
0878     struct acpi_dev_match_info match = {};
0879     struct device *dev;
0880 
0881     strlcpy(match.hid[0].id, hid, sizeof(match.hid[0].id));
0882     match.uid = uid;
0883     match.hrv = hrv;
0884 
0885     dev = bus_find_device(&acpi_bus_type, NULL, &match, acpi_dev_match_cb);
0886     put_device(dev);
0887     return !!dev;
0888 }
0889 EXPORT_SYMBOL(acpi_dev_present);
0890 
0891 /**
0892  * acpi_dev_get_next_match_dev - Return the next match of ACPI device
0893  * @adev: Pointer to the previous ACPI device matching this @hid, @uid and @hrv
0894  * @hid: Hardware ID of the device.
0895  * @uid: Unique ID of the device, pass NULL to not check _UID
0896  * @hrv: Hardware Revision of the device, pass -1 to not check _HRV
0897  *
0898  * Return the next match of ACPI device if another matching device was present
0899  * at the moment of invocation, or NULL otherwise.
0900  *
0901  * The caller is responsible for invoking acpi_dev_put() on the returned device.
0902  * On the other hand the function invokes  acpi_dev_put() on the given @adev
0903  * assuming that its reference counter had been increased beforehand.
0904  *
0905  * See additional information in acpi_dev_present() as well.
0906  */
0907 struct acpi_device *
0908 acpi_dev_get_next_match_dev(struct acpi_device *adev, const char *hid, const char *uid, s64 hrv)
0909 {
0910     struct device *start = adev ? &adev->dev : NULL;
0911     struct acpi_dev_match_info match = {};
0912     struct device *dev;
0913 
0914     strlcpy(match.hid[0].id, hid, sizeof(match.hid[0].id));
0915     match.uid = uid;
0916     match.hrv = hrv;
0917 
0918     dev = bus_find_device(&acpi_bus_type, start, &match, acpi_dev_match_cb);
0919     acpi_dev_put(adev);
0920     return dev ? to_acpi_device(dev) : NULL;
0921 }
0922 EXPORT_SYMBOL(acpi_dev_get_next_match_dev);
0923 
0924 /**
0925  * acpi_dev_get_first_match_dev - Return the first match of ACPI device
0926  * @hid: Hardware ID of the device.
0927  * @uid: Unique ID of the device, pass NULL to not check _UID
0928  * @hrv: Hardware Revision of the device, pass -1 to not check _HRV
0929  *
0930  * Return the first match of ACPI device if a matching device was present
0931  * at the moment of invocation, or NULL otherwise.
0932  *
0933  * The caller is responsible for invoking acpi_dev_put() on the returned device.
0934  *
0935  * See additional information in acpi_dev_present() as well.
0936  */
0937 struct acpi_device *
0938 acpi_dev_get_first_match_dev(const char *hid, const char *uid, s64 hrv)
0939 {
0940     return acpi_dev_get_next_match_dev(NULL, hid, uid, hrv);
0941 }
0942 EXPORT_SYMBOL(acpi_dev_get_first_match_dev);
0943 
0944 /**
0945  * acpi_reduced_hardware - Return if this is an ACPI-reduced-hw machine
0946  *
0947  * Return true when running on an ACPI-reduced-hw machine, false otherwise.
0948  */
0949 bool acpi_reduced_hardware(void)
0950 {
0951     return acpi_gbl_reduced_hardware;
0952 }
0953 EXPORT_SYMBOL_GPL(acpi_reduced_hardware);
0954 
0955 /*
0956  * acpi_backlight= handling, this is done here rather then in video_detect.c
0957  * because __setup cannot be used in modules.
0958  */
0959 char acpi_video_backlight_string[16];
0960 EXPORT_SYMBOL(acpi_video_backlight_string);
0961 
0962 static int __init acpi_backlight(char *str)
0963 {
0964     strlcpy(acpi_video_backlight_string, str,
0965         sizeof(acpi_video_backlight_string));
0966     return 1;
0967 }
0968 __setup("acpi_backlight=", acpi_backlight);
0969 
0970 /**
0971  * acpi_match_platform_list - Check if the system matches with a given list
0972  * @plat: pointer to acpi_platform_list table terminated by a NULL entry
0973  *
0974  * Return the matched index if the system is found in the platform list.
0975  * Otherwise, return a negative error code.
0976  */
0977 int acpi_match_platform_list(const struct acpi_platform_list *plat)
0978 {
0979     struct acpi_table_header hdr;
0980     int idx = 0;
0981 
0982     if (acpi_disabled)
0983         return -ENODEV;
0984 
0985     for (; plat->oem_id[0]; plat++, idx++) {
0986         if (ACPI_FAILURE(acpi_get_table_header(plat->table, 0, &hdr)))
0987             continue;
0988 
0989         if (strncmp(plat->oem_id, hdr.oem_id, ACPI_OEM_ID_SIZE))
0990             continue;
0991 
0992         if (strncmp(plat->oem_table_id, hdr.oem_table_id, ACPI_OEM_TABLE_ID_SIZE))
0993             continue;
0994 
0995         if ((plat->pred == all_versions) ||
0996             (plat->pred == less_than_or_equal && hdr.oem_revision <= plat->oem_revision) ||
0997             (plat->pred == greater_than_or_equal && hdr.oem_revision >= plat->oem_revision) ||
0998             (plat->pred == equal && hdr.oem_revision == plat->oem_revision))
0999             return idx;
1000     }
1001 
1002     return -ENODEV;
1003 }
1004 EXPORT_SYMBOL(acpi_match_platform_list);