linux/drivers/acpi/acpica/utids.c
<<
>>
Prefs
   1/******************************************************************************
   2 *
   3 * Module Name: utids - support for device Ids - HID, UID, CID, SUB, CLS
   4 *
   5 *****************************************************************************/
   6
   7/*
   8 * Copyright (C) 2000 - 2016, Intel Corp.
   9 * All rights reserved.
  10 *
  11 * Redistribution and use in source and binary forms, with or without
  12 * modification, are permitted provided that the following conditions
  13 * are met:
  14 * 1. Redistributions of source code must retain the above copyright
  15 *    notice, this list of conditions, and the following disclaimer,
  16 *    without modification.
  17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
  18 *    substantially similar to the "NO WARRANTY" disclaimer below
  19 *    ("Disclaimer") and any redistribution must be conditioned upon
  20 *    including a substantially similar Disclaimer requirement for further
  21 *    binary redistribution.
  22 * 3. Neither the names of the above-listed copyright holders nor the names
  23 *    of any contributors may be used to endorse or promote products derived
  24 *    from this software without specific prior written permission.
  25 *
  26 * Alternatively, this software may be distributed under the terms of the
  27 * GNU General Public License ("GPL") version 2 as published by the Free
  28 * Software Foundation.
  29 *
  30 * NO WARRANTY
  31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
  34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
  40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  41 * POSSIBILITY OF SUCH DAMAGES.
  42 */
  43
  44#include <acpi/acpi.h>
  45#include "accommon.h"
  46#include "acinterp.h"
  47
  48#define _COMPONENT          ACPI_UTILITIES
  49ACPI_MODULE_NAME("utids")
  50
  51/*******************************************************************************
  52 *
  53 * FUNCTION:    acpi_ut_execute_HID
  54 *
  55 * PARAMETERS:  device_node         - Node for the device
  56 *              return_id           - Where the string HID is returned
  57 *
  58 * RETURN:      Status
  59 *
  60 * DESCRIPTION: Executes the _HID control method that returns the hardware
  61 *              ID of the device. The HID is either an 32-bit encoded EISAID
  62 *              Integer or a String. A string is always returned. An EISAID
  63 *              is converted to a string.
  64 *
  65 *              NOTE: Internal function, no parameter validation
  66 *
  67 ******************************************************************************/
  68acpi_status
  69acpi_ut_execute_HID(struct acpi_namespace_node *device_node,
  70                    struct acpi_pnp_device_id **return_id)
  71{
  72        union acpi_operand_object *obj_desc;
  73        struct acpi_pnp_device_id *hid;
  74        u32 length;
  75        acpi_status status;
  76
  77        ACPI_FUNCTION_TRACE(ut_execute_HID);
  78
  79        status = acpi_ut_evaluate_object(device_node, METHOD_NAME__HID,
  80                                         ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING,
  81                                         &obj_desc);
  82        if (ACPI_FAILURE(status)) {
  83                return_ACPI_STATUS(status);
  84        }
  85
  86        /* Get the size of the String to be returned, includes null terminator */
  87
  88        if (obj_desc->common.type == ACPI_TYPE_INTEGER) {
  89                length = ACPI_EISAID_STRING_SIZE;
  90        } else {
  91                length = obj_desc->string.length + 1;
  92        }
  93
  94        /* Allocate a buffer for the HID */
  95
  96        hid =
  97            ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_pnp_device_id) +
  98                                 (acpi_size) length);
  99        if (!hid) {
 100                status = AE_NO_MEMORY;
 101                goto cleanup;
 102        }
 103
 104        /* Area for the string starts after PNP_DEVICE_ID struct */
 105
 106        hid->string =
 107            ACPI_ADD_PTR(char, hid, sizeof(struct acpi_pnp_device_id));
 108
 109        /* Convert EISAID to a string or simply copy existing string */
 110
 111        if (obj_desc->common.type == ACPI_TYPE_INTEGER) {
 112                acpi_ex_eisa_id_to_string(hid->string, obj_desc->integer.value);
 113        } else {
 114                strcpy(hid->string, obj_desc->string.pointer);
 115        }
 116
 117        hid->length = length;
 118        *return_id = hid;
 119
 120cleanup:
 121
 122        /* On exit, we must delete the return object */
 123
 124        acpi_ut_remove_reference(obj_desc);
 125        return_ACPI_STATUS(status);
 126}
 127
 128/*******************************************************************************
 129 *
 130 * FUNCTION:    acpi_ut_execute_UID
 131 *
 132 * PARAMETERS:  device_node         - Node for the device
 133 *              return_id           - Where the string UID is returned
 134 *
 135 * RETURN:      Status
 136 *
 137 * DESCRIPTION: Executes the _UID control method that returns the unique
 138 *              ID of the device. The UID is either a 64-bit Integer (NOT an
 139 *              EISAID) or a string. Always returns a string. A 64-bit integer
 140 *              is converted to a decimal string.
 141 *
 142 *              NOTE: Internal function, no parameter validation
 143 *
 144 ******************************************************************************/
 145
 146acpi_status
 147acpi_ut_execute_UID(struct acpi_namespace_node *device_node,
 148                    struct acpi_pnp_device_id **return_id)
 149{
 150        union acpi_operand_object *obj_desc;
 151        struct acpi_pnp_device_id *uid;
 152        u32 length;
 153        acpi_status status;
 154
 155        ACPI_FUNCTION_TRACE(ut_execute_UID);
 156
 157        status = acpi_ut_evaluate_object(device_node, METHOD_NAME__UID,
 158                                         ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING,
 159                                         &obj_desc);
 160        if (ACPI_FAILURE(status)) {
 161                return_ACPI_STATUS(status);
 162        }
 163
 164        /* Get the size of the String to be returned, includes null terminator */
 165
 166        if (obj_desc->common.type == ACPI_TYPE_INTEGER) {
 167                length = ACPI_MAX64_DECIMAL_DIGITS + 1;
 168        } else {
 169                length = obj_desc->string.length + 1;
 170        }
 171
 172        /* Allocate a buffer for the UID */
 173
 174        uid =
 175            ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_pnp_device_id) +
 176                                 (acpi_size) length);
 177        if (!uid) {
 178                status = AE_NO_MEMORY;
 179                goto cleanup;
 180        }
 181
 182        /* Area for the string starts after PNP_DEVICE_ID struct */
 183
 184        uid->string =
 185            ACPI_ADD_PTR(char, uid, sizeof(struct acpi_pnp_device_id));
 186
 187        /* Convert an Integer to string, or just copy an existing string */
 188
 189        if (obj_desc->common.type == ACPI_TYPE_INTEGER) {
 190                acpi_ex_integer_to_string(uid->string, obj_desc->integer.value);
 191        } else {
 192                strcpy(uid->string, obj_desc->string.pointer);
 193        }
 194
 195        uid->length = length;
 196        *return_id = uid;
 197
 198cleanup:
 199
 200        /* On exit, we must delete the return object */
 201
 202        acpi_ut_remove_reference(obj_desc);
 203        return_ACPI_STATUS(status);
 204}
 205
 206/*******************************************************************************
 207 *
 208 * FUNCTION:    acpi_ut_execute_CID
 209 *
 210 * PARAMETERS:  device_node         - Node for the device
 211 *              return_cid_list     - Where the CID list is returned
 212 *
 213 * RETURN:      Status, list of CID strings
 214 *
 215 * DESCRIPTION: Executes the _CID control method that returns one or more
 216 *              compatible hardware IDs for the device.
 217 *
 218 *              NOTE: Internal function, no parameter validation
 219 *
 220 * A _CID method can return either a single compatible ID or a package of
 221 * compatible IDs. Each compatible ID can be one of the following:
 222 * 1) Integer (32 bit compressed EISA ID) or
 223 * 2) String (PCI ID format, e.g. "PCI\VEN_vvvv&DEV_dddd&SUBSYS_ssssssss")
 224 *
 225 * The Integer CIDs are converted to string format by this function.
 226 *
 227 ******************************************************************************/
 228
 229acpi_status
 230acpi_ut_execute_CID(struct acpi_namespace_node *device_node,
 231                    struct acpi_pnp_device_id_list **return_cid_list)
 232{
 233        union acpi_operand_object **cid_objects;
 234        union acpi_operand_object *obj_desc;
 235        struct acpi_pnp_device_id_list *cid_list;
 236        char *next_id_string;
 237        u32 string_area_size;
 238        u32 length;
 239        u32 cid_list_size;
 240        acpi_status status;
 241        u32 count;
 242        u32 i;
 243
 244        ACPI_FUNCTION_TRACE(ut_execute_CID);
 245
 246        /* Evaluate the _CID method for this device */
 247
 248        status = acpi_ut_evaluate_object(device_node, METHOD_NAME__CID,
 249                                         ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING
 250                                         | ACPI_BTYPE_PACKAGE, &obj_desc);
 251        if (ACPI_FAILURE(status)) {
 252                return_ACPI_STATUS(status);
 253        }
 254
 255        /*
 256         * Get the count and size of the returned _CIDs. _CID can return either
 257         * a Package of Integers/Strings or a single Integer or String.
 258         * Note: This section also validates that all CID elements are of the
 259         * correct type (Integer or String).
 260         */
 261        if (obj_desc->common.type == ACPI_TYPE_PACKAGE) {
 262                count = obj_desc->package.count;
 263                cid_objects = obj_desc->package.elements;
 264        } else {                /* Single Integer or String CID */
 265
 266                count = 1;
 267                cid_objects = &obj_desc;
 268        }
 269
 270        string_area_size = 0;
 271        for (i = 0; i < count; i++) {
 272
 273                /* String lengths include null terminator */
 274
 275                switch (cid_objects[i]->common.type) {
 276                case ACPI_TYPE_INTEGER:
 277
 278                        string_area_size += ACPI_EISAID_STRING_SIZE;
 279                        break;
 280
 281                case ACPI_TYPE_STRING:
 282
 283                        string_area_size += cid_objects[i]->string.length + 1;
 284                        break;
 285
 286                default:
 287
 288                        status = AE_TYPE;
 289                        goto cleanup;
 290                }
 291        }
 292
 293        /*
 294         * Now that we know the length of the CIDs, allocate return buffer:
 295         * 1) Size of the base structure +
 296         * 2) Size of the CID PNP_DEVICE_ID array +
 297         * 3) Size of the actual CID strings
 298         */
 299        cid_list_size = sizeof(struct acpi_pnp_device_id_list) +
 300            ((count - 1) * sizeof(struct acpi_pnp_device_id)) +
 301            string_area_size;
 302
 303        cid_list = ACPI_ALLOCATE_ZEROED(cid_list_size);
 304        if (!cid_list) {
 305                status = AE_NO_MEMORY;
 306                goto cleanup;
 307        }
 308
 309        /* Area for CID strings starts after the CID PNP_DEVICE_ID array */
 310
 311        next_id_string = ACPI_CAST_PTR(char, cid_list->ids) +
 312            ((acpi_size) count * sizeof(struct acpi_pnp_device_id));
 313
 314        /* Copy/convert the CIDs to the return buffer */
 315
 316        for (i = 0; i < count; i++) {
 317                if (cid_objects[i]->common.type == ACPI_TYPE_INTEGER) {
 318
 319                        /* Convert the Integer (EISAID) CID to a string */
 320
 321                        acpi_ex_eisa_id_to_string(next_id_string,
 322                                                  cid_objects[i]->integer.
 323                                                  value);
 324                        length = ACPI_EISAID_STRING_SIZE;
 325                } else {        /* ACPI_TYPE_STRING */
 326
 327                        /* Copy the String CID from the returned object */
 328
 329                        strcpy(next_id_string, cid_objects[i]->string.pointer);
 330                        length = cid_objects[i]->string.length + 1;
 331                }
 332
 333                cid_list->ids[i].string = next_id_string;
 334                cid_list->ids[i].length = length;
 335                next_id_string += length;
 336        }
 337
 338        /* Finish the CID list */
 339
 340        cid_list->count = count;
 341        cid_list->list_size = cid_list_size;
 342        *return_cid_list = cid_list;
 343
 344cleanup:
 345
 346        /* On exit, we must delete the _CID return object */
 347
 348        acpi_ut_remove_reference(obj_desc);
 349        return_ACPI_STATUS(status);
 350}
 351
 352/*******************************************************************************
 353 *
 354 * FUNCTION:    acpi_ut_execute_CLS
 355 *
 356 * PARAMETERS:  device_node         - Node for the device
 357 *              return_id           - Where the _CLS is returned
 358 *
 359 * RETURN:      Status
 360 *
 361 * DESCRIPTION: Executes the _CLS control method that returns PCI-defined
 362 *              class code of the device. The _CLS value is always a package
 363 *              containing PCI class information as a list of integers.
 364 *              The returned string has format "BBSSPP", where:
 365 *                BB = Base-class code
 366 *                SS = Sub-class code
 367 *                PP = Programming Interface code
 368 *
 369 ******************************************************************************/
 370
 371acpi_status
 372acpi_ut_execute_CLS(struct acpi_namespace_node *device_node,
 373                    struct acpi_pnp_device_id **return_id)
 374{
 375        union acpi_operand_object *obj_desc;
 376        union acpi_operand_object **cls_objects;
 377        u32 count;
 378        struct acpi_pnp_device_id *cls;
 379        u32 length;
 380        acpi_status status;
 381        u8 class_code[3] = { 0, 0, 0 };
 382
 383        ACPI_FUNCTION_TRACE(ut_execute_CLS);
 384
 385        status = acpi_ut_evaluate_object(device_node, METHOD_NAME__CLS,
 386                                         ACPI_BTYPE_PACKAGE, &obj_desc);
 387        if (ACPI_FAILURE(status)) {
 388                return_ACPI_STATUS(status);
 389        }
 390
 391        /* Get the size of the String to be returned, includes null terminator */
 392
 393        length = ACPI_PCICLS_STRING_SIZE;
 394        cls_objects = obj_desc->package.elements;
 395        count = obj_desc->package.count;
 396
 397        if (obj_desc->common.type == ACPI_TYPE_PACKAGE) {
 398                if (count > 0
 399                    && cls_objects[0]->common.type == ACPI_TYPE_INTEGER) {
 400                        class_code[0] = (u8)cls_objects[0]->integer.value;
 401                }
 402                if (count > 1
 403                    && cls_objects[1]->common.type == ACPI_TYPE_INTEGER) {
 404                        class_code[1] = (u8)cls_objects[1]->integer.value;
 405                }
 406                if (count > 2
 407                    && cls_objects[2]->common.type == ACPI_TYPE_INTEGER) {
 408                        class_code[2] = (u8)cls_objects[2]->integer.value;
 409                }
 410        }
 411
 412        /* Allocate a buffer for the CLS */
 413
 414        cls =
 415            ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_pnp_device_id) +
 416                                 (acpi_size) length);
 417        if (!cls) {
 418                status = AE_NO_MEMORY;
 419                goto cleanup;
 420        }
 421
 422        /* Area for the string starts after PNP_DEVICE_ID struct */
 423
 424        cls->string =
 425            ACPI_ADD_PTR(char, cls, sizeof(struct acpi_pnp_device_id));
 426
 427        /* Simply copy existing string */
 428
 429        acpi_ex_pci_cls_to_string(cls->string, class_code);
 430        cls->length = length;
 431        *return_id = cls;
 432
 433cleanup:
 434
 435        /* On exit, we must delete the return object */
 436
 437        acpi_ut_remove_reference(obj_desc);
 438        return_ACPI_STATUS(status);
 439}
 440