linux/drivers/acpi/property.c
<<
>>
Prefs
   1/*
   2 * ACPI device specific properties support.
   3 *
   4 * Copyright (C) 2014, Intel Corporation
   5 * All rights reserved.
   6 *
   7 * Authors: Mika Westerberg <mika.westerberg@linux.intel.com>
   8 *          Darren Hart <dvhart@linux.intel.com>
   9 *          Rafael J. Wysocki <rafael.j.wysocki@intel.com>
  10 *
  11 * This program is free software; you can redistribute it and/or modify
  12 * it under the terms of the GNU General Public License version 2 as
  13 * published by the Free Software Foundation.
  14 */
  15
  16#include <linux/acpi.h>
  17#include <linux/device.h>
  18#include <linux/export.h>
  19
  20#include "internal.h"
  21
  22static int acpi_data_get_property_array(struct acpi_device_data *data,
  23                                        const char *name,
  24                                        acpi_object_type type,
  25                                        const union acpi_object **obj);
  26
  27/* ACPI _DSD device properties UUID: daffd814-6eba-4d8c-8a91-bc9bbf4aa301 */
  28static const u8 prp_uuid[16] = {
  29        0x14, 0xd8, 0xff, 0xda, 0xba, 0x6e, 0x8c, 0x4d,
  30        0x8a, 0x91, 0xbc, 0x9b, 0xbf, 0x4a, 0xa3, 0x01
  31};
  32/* ACPI _DSD data subnodes UUID: dbb8e3e6-5886-4ba6-8795-1319f52a966b */
  33static const u8 ads_uuid[16] = {
  34        0xe6, 0xe3, 0xb8, 0xdb, 0x86, 0x58, 0xa6, 0x4b,
  35        0x87, 0x95, 0x13, 0x19, 0xf5, 0x2a, 0x96, 0x6b
  36};
  37
  38static bool acpi_enumerate_nondev_subnodes(acpi_handle scope,
  39                                           const union acpi_object *desc,
  40                                           struct acpi_device_data *data);
  41static bool acpi_extract_properties(const union acpi_object *desc,
  42                                    struct acpi_device_data *data);
  43
  44static bool acpi_nondev_subnode_ok(acpi_handle scope,
  45                                   const union acpi_object *link,
  46                                   struct list_head *list)
  47{
  48        struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER };
  49        struct acpi_data_node *dn;
  50        acpi_handle handle;
  51        acpi_status status;
  52
  53        dn = kzalloc(sizeof(*dn), GFP_KERNEL);
  54        if (!dn)
  55                return false;
  56
  57        dn->name = link->package.elements[0].string.pointer;
  58        dn->fwnode.type = FWNODE_ACPI_DATA;
  59        INIT_LIST_HEAD(&dn->data.subnodes);
  60
  61        status = acpi_get_handle(scope, link->package.elements[1].string.pointer,
  62                                 &handle);
  63        if (ACPI_FAILURE(status))
  64                goto fail;
  65
  66        status = acpi_evaluate_object_typed(handle, NULL, NULL, &buf,
  67                                            ACPI_TYPE_PACKAGE);
  68        if (ACPI_FAILURE(status))
  69                goto fail;
  70
  71        if (acpi_extract_properties(buf.pointer, &dn->data))
  72                dn->handle = handle;
  73
  74        /*
  75         * The scope for the subnode object lookup is the one of the namespace
  76         * node (device) containing the object that has returned the package.
  77         * That is, it's the scope of that object's parent.
  78         */
  79        status = acpi_get_parent(handle, &scope);
  80        if (ACPI_SUCCESS(status)
  81            && acpi_enumerate_nondev_subnodes(scope, buf.pointer, &dn->data))
  82                dn->handle = handle;
  83
  84        if (dn->handle) {
  85                dn->data.pointer = buf.pointer;
  86                list_add_tail(&dn->sibling, list);
  87                return true;
  88        }
  89
  90        acpi_handle_debug(handle, "Invalid properties/subnodes data, skipping\n");
  91
  92 fail:
  93        ACPI_FREE(buf.pointer);
  94        kfree(dn);
  95        return false;
  96}
  97
  98static int acpi_add_nondev_subnodes(acpi_handle scope,
  99                                    const union acpi_object *links,
 100                                    struct list_head *list)
 101{
 102        bool ret = false;
 103        int i;
 104
 105        for (i = 0; i < links->package.count; i++) {
 106                const union acpi_object *link;
 107
 108                link = &links->package.elements[i];
 109                /* Only two elements allowed, both must be strings. */
 110                if (link->package.count == 2
 111                    && link->package.elements[0].type == ACPI_TYPE_STRING
 112                    && link->package.elements[1].type == ACPI_TYPE_STRING
 113                    && acpi_nondev_subnode_ok(scope, link, list))
 114                        ret = true;
 115        }
 116
 117        return ret;
 118}
 119
 120static bool acpi_enumerate_nondev_subnodes(acpi_handle scope,
 121                                           const union acpi_object *desc,
 122                                           struct acpi_device_data *data)
 123{
 124        int i;
 125
 126        /* Look for the ACPI data subnodes UUID. */
 127        for (i = 0; i < desc->package.count; i += 2) {
 128                const union acpi_object *uuid, *links;
 129
 130                uuid = &desc->package.elements[i];
 131                links = &desc->package.elements[i + 1];
 132
 133                /*
 134                 * The first element must be a UUID and the second one must be
 135                 * a package.
 136                 */
 137                if (uuid->type != ACPI_TYPE_BUFFER || uuid->buffer.length != 16
 138                    || links->type != ACPI_TYPE_PACKAGE)
 139                        break;
 140
 141                if (memcmp(uuid->buffer.pointer, ads_uuid, sizeof(ads_uuid)))
 142                        continue;
 143
 144                return acpi_add_nondev_subnodes(scope, links, &data->subnodes);
 145        }
 146
 147        return false;
 148}
 149
 150static bool acpi_property_value_ok(const union acpi_object *value)
 151{
 152        int j;
 153
 154        /*
 155         * The value must be an integer, a string, a reference, or a package
 156         * whose every element must be an integer, a string, or a reference.
 157         */
 158        switch (value->type) {
 159        case ACPI_TYPE_INTEGER:
 160        case ACPI_TYPE_STRING:
 161        case ACPI_TYPE_LOCAL_REFERENCE:
 162                return true;
 163
 164        case ACPI_TYPE_PACKAGE:
 165                for (j = 0; j < value->package.count; j++)
 166                        switch (value->package.elements[j].type) {
 167                        case ACPI_TYPE_INTEGER:
 168                        case ACPI_TYPE_STRING:
 169                        case ACPI_TYPE_LOCAL_REFERENCE:
 170                                continue;
 171
 172                        default:
 173                                return false;
 174                        }
 175
 176                return true;
 177        }
 178        return false;
 179}
 180
 181static bool acpi_properties_format_valid(const union acpi_object *properties)
 182{
 183        int i;
 184
 185        for (i = 0; i < properties->package.count; i++) {
 186                const union acpi_object *property;
 187
 188                property = &properties->package.elements[i];
 189                /*
 190                 * Only two elements allowed, the first one must be a string and
 191                 * the second one has to satisfy certain conditions.
 192                 */
 193                if (property->package.count != 2
 194                    || property->package.elements[0].type != ACPI_TYPE_STRING
 195                    || !acpi_property_value_ok(&property->package.elements[1]))
 196                        return false;
 197        }
 198        return true;
 199}
 200
 201static void acpi_init_of_compatible(struct acpi_device *adev)
 202{
 203        const union acpi_object *of_compatible;
 204        int ret;
 205
 206        ret = acpi_data_get_property_array(&adev->data, "compatible",
 207                                           ACPI_TYPE_STRING, &of_compatible);
 208        if (ret) {
 209                ret = acpi_dev_get_property(adev, "compatible",
 210                                            ACPI_TYPE_STRING, &of_compatible);
 211                if (ret) {
 212                        if (adev->parent
 213                            && adev->parent->flags.of_compatible_ok)
 214                                goto out;
 215
 216                        return;
 217                }
 218        }
 219        adev->data.of_compatible = of_compatible;
 220
 221 out:
 222        adev->flags.of_compatible_ok = 1;
 223}
 224
 225static bool acpi_extract_properties(const union acpi_object *desc,
 226                                    struct acpi_device_data *data)
 227{
 228        int i;
 229
 230        if (desc->package.count % 2)
 231                return false;
 232
 233        /* Look for the device properties UUID. */
 234        for (i = 0; i < desc->package.count; i += 2) {
 235                const union acpi_object *uuid, *properties;
 236
 237                uuid = &desc->package.elements[i];
 238                properties = &desc->package.elements[i + 1];
 239
 240                /*
 241                 * The first element must be a UUID and the second one must be
 242                 * a package.
 243                 */
 244                if (uuid->type != ACPI_TYPE_BUFFER || uuid->buffer.length != 16
 245                    || properties->type != ACPI_TYPE_PACKAGE)
 246                        break;
 247
 248                if (memcmp(uuid->buffer.pointer, prp_uuid, sizeof(prp_uuid)))
 249                        continue;
 250
 251                /*
 252                 * We found the matching UUID. Now validate the format of the
 253                 * package immediately following it.
 254                 */
 255                if (!acpi_properties_format_valid(properties))
 256                        break;
 257
 258                data->properties = properties;
 259                return true;
 260        }
 261
 262        return false;
 263}
 264
 265void acpi_init_properties(struct acpi_device *adev)
 266{
 267        struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER };
 268        struct acpi_hardware_id *hwid;
 269        acpi_status status;
 270        bool acpi_of = false;
 271
 272        INIT_LIST_HEAD(&adev->data.subnodes);
 273
 274        /*
 275         * Check if ACPI_DT_NAMESPACE_HID is present and inthat case we fill in
 276         * Device Tree compatible properties for this device.
 277         */
 278        list_for_each_entry(hwid, &adev->pnp.ids, list) {
 279                if (!strcmp(hwid->id, ACPI_DT_NAMESPACE_HID)) {
 280                        acpi_of = true;
 281                        break;
 282                }
 283        }
 284
 285        status = acpi_evaluate_object_typed(adev->handle, "_DSD", NULL, &buf,
 286                                            ACPI_TYPE_PACKAGE);
 287        if (ACPI_FAILURE(status))
 288                goto out;
 289
 290        if (acpi_extract_properties(buf.pointer, &adev->data)) {
 291                adev->data.pointer = buf.pointer;
 292                if (acpi_of)
 293                        acpi_init_of_compatible(adev);
 294        }
 295        if (acpi_enumerate_nondev_subnodes(adev->handle, buf.pointer, &adev->data))
 296                adev->data.pointer = buf.pointer;
 297
 298        if (!adev->data.pointer) {
 299                acpi_handle_debug(adev->handle, "Invalid _DSD data, skipping\n");
 300                ACPI_FREE(buf.pointer);
 301        }
 302
 303 out:
 304        if (acpi_of && !adev->flags.of_compatible_ok)
 305                acpi_handle_info(adev->handle,
 306                         ACPI_DT_NAMESPACE_HID " requires 'compatible' property\n");
 307}
 308
 309static void acpi_destroy_nondev_subnodes(struct list_head *list)
 310{
 311        struct acpi_data_node *dn, *next;
 312
 313        if (list_empty(list))
 314                return;
 315
 316        list_for_each_entry_safe_reverse(dn, next, list, sibling) {
 317                acpi_destroy_nondev_subnodes(&dn->data.subnodes);
 318                wait_for_completion(&dn->kobj_done);
 319                list_del(&dn->sibling);
 320                ACPI_FREE((void *)dn->data.pointer);
 321                kfree(dn);
 322        }
 323}
 324
 325void acpi_free_properties(struct acpi_device *adev)
 326{
 327        acpi_destroy_nondev_subnodes(&adev->data.subnodes);
 328        ACPI_FREE((void *)adev->data.pointer);
 329        adev->data.of_compatible = NULL;
 330        adev->data.pointer = NULL;
 331        adev->data.properties = NULL;
 332}
 333
 334/**
 335 * acpi_data_get_property - return an ACPI property with given name
 336 * @data: ACPI device deta object to get the property from
 337 * @name: Name of the property
 338 * @type: Expected property type
 339 * @obj: Location to store the property value (if not %NULL)
 340 *
 341 * Look up a property with @name and store a pointer to the resulting ACPI
 342 * object at the location pointed to by @obj if found.
 343 *
 344 * Callers must not attempt to free the returned objects.  These objects will be
 345 * freed by the ACPI core automatically during the removal of @data.
 346 *
 347 * Return: %0 if property with @name has been found (success),
 348 *         %-EINVAL if the arguments are invalid,
 349 *         %-EINVAL if the property doesn't exist,
 350 *         %-EPROTO if the property value type doesn't match @type.
 351 */
 352static int acpi_data_get_property(struct acpi_device_data *data,
 353                                  const char *name, acpi_object_type type,
 354                                  const union acpi_object **obj)
 355{
 356        const union acpi_object *properties;
 357        int i;
 358
 359        if (!data || !name)
 360                return -EINVAL;
 361
 362        if (!data->pointer || !data->properties)
 363                return -EINVAL;
 364
 365        properties = data->properties;
 366        for (i = 0; i < properties->package.count; i++) {
 367                const union acpi_object *propname, *propvalue;
 368                const union acpi_object *property;
 369
 370                property = &properties->package.elements[i];
 371
 372                propname = &property->package.elements[0];
 373                propvalue = &property->package.elements[1];
 374
 375                if (!strcmp(name, propname->string.pointer)) {
 376                        if (type != ACPI_TYPE_ANY && propvalue->type != type)
 377                                return -EPROTO;
 378                        if (obj)
 379                                *obj = propvalue;
 380
 381                        return 0;
 382                }
 383        }
 384        return -EINVAL;
 385}
 386
 387/**
 388 * acpi_dev_get_property - return an ACPI property with given name.
 389 * @adev: ACPI device to get the property from.
 390 * @name: Name of the property.
 391 * @type: Expected property type.
 392 * @obj: Location to store the property value (if not %NULL).
 393 */
 394int acpi_dev_get_property(struct acpi_device *adev, const char *name,
 395                          acpi_object_type type, const union acpi_object **obj)
 396{
 397        return adev ? acpi_data_get_property(&adev->data, name, type, obj) : -EINVAL;
 398}
 399EXPORT_SYMBOL_GPL(acpi_dev_get_property);
 400
 401static struct acpi_device_data *acpi_device_data_of_node(struct fwnode_handle *fwnode)
 402{
 403        if (fwnode->type == FWNODE_ACPI) {
 404                struct acpi_device *adev = to_acpi_device_node(fwnode);
 405                return &adev->data;
 406        } else if (fwnode->type == FWNODE_ACPI_DATA) {
 407                struct acpi_data_node *dn = to_acpi_data_node(fwnode);
 408                return &dn->data;
 409        }
 410        return NULL;
 411}
 412
 413/**
 414 * acpi_node_prop_get - return an ACPI property with given name.
 415 * @fwnode: Firmware node to get the property from.
 416 * @propname: Name of the property.
 417 * @valptr: Location to store a pointer to the property value (if not %NULL).
 418 */
 419int acpi_node_prop_get(struct fwnode_handle *fwnode, const char *propname,
 420                       void **valptr)
 421{
 422        return acpi_data_get_property(acpi_device_data_of_node(fwnode),
 423                                      propname, ACPI_TYPE_ANY,
 424                                      (const union acpi_object **)valptr);
 425}
 426
 427/**
 428 * acpi_data_get_property_array - return an ACPI array property with given name
 429 * @adev: ACPI data object to get the property from
 430 * @name: Name of the property
 431 * @type: Expected type of array elements
 432 * @obj: Location to store a pointer to the property value (if not NULL)
 433 *
 434 * Look up an array property with @name and store a pointer to the resulting
 435 * ACPI object at the location pointed to by @obj if found.
 436 *
 437 * Callers must not attempt to free the returned objects.  Those objects will be
 438 * freed by the ACPI core automatically during the removal of @data.
 439 *
 440 * Return: %0 if array property (package) with @name has been found (success),
 441 *         %-EINVAL if the arguments are invalid,
 442 *         %-EINVAL if the property doesn't exist,
 443 *         %-EPROTO if the property is not a package or the type of its elements
 444 *           doesn't match @type.
 445 */
 446static int acpi_data_get_property_array(struct acpi_device_data *data,
 447                                        const char *name,
 448                                        acpi_object_type type,
 449                                        const union acpi_object **obj)
 450{
 451        const union acpi_object *prop;
 452        int ret, i;
 453
 454        ret = acpi_data_get_property(data, name, ACPI_TYPE_PACKAGE, &prop);
 455        if (ret)
 456                return ret;
 457
 458        if (type != ACPI_TYPE_ANY) {
 459                /* Check that all elements are of correct type. */
 460                for (i = 0; i < prop->package.count; i++)
 461                        if (prop->package.elements[i].type != type)
 462                                return -EPROTO;
 463        }
 464        if (obj)
 465                *obj = prop;
 466
 467        return 0;
 468}
 469
 470/**
 471 * acpi_data_get_property_reference - returns handle to the referenced object
 472 * @data: ACPI device data object containing the property
 473 * @propname: Name of the property
 474 * @index: Index of the reference to return
 475 * @args: Location to store the returned reference with optional arguments
 476 *
 477 * Find property with @name, verifify that it is a package containing at least
 478 * one object reference and if so, store the ACPI device object pointer to the
 479 * target object in @args->adev.  If the reference includes arguments, store
 480 * them in the @args->args[] array.
 481 *
 482 * If there's more than one reference in the property value package, @index is
 483 * used to select the one to return.
 484 *
 485 * Return: %0 on success, negative error code on failure.
 486 */
 487static int acpi_data_get_property_reference(struct acpi_device_data *data,
 488                                            const char *propname, size_t index,
 489                                            struct acpi_reference_args *args)
 490{
 491        const union acpi_object *element, *end;
 492        const union acpi_object *obj;
 493        struct acpi_device *device;
 494        int ret, idx = 0;
 495
 496        ret = acpi_data_get_property(data, propname, ACPI_TYPE_ANY, &obj);
 497        if (ret)
 498                return ret;
 499
 500        /*
 501         * The simplest case is when the value is a single reference.  Just
 502         * return that reference then.
 503         */
 504        if (obj->type == ACPI_TYPE_LOCAL_REFERENCE) {
 505                if (index)
 506                        return -EINVAL;
 507
 508                ret = acpi_bus_get_device(obj->reference.handle, &device);
 509                if (ret)
 510                        return ret;
 511
 512                args->adev = device;
 513                args->nargs = 0;
 514                return 0;
 515        }
 516
 517        /*
 518         * If it is not a single reference, then it is a package of
 519         * references followed by number of ints as follows:
 520         *
 521         *  Package () { REF, INT, REF, INT, INT }
 522         *
 523         * The index argument is then used to determine which reference
 524         * the caller wants (along with the arguments).
 525         */
 526        if (obj->type != ACPI_TYPE_PACKAGE || index >= obj->package.count)
 527                return -EPROTO;
 528
 529        element = obj->package.elements;
 530        end = element + obj->package.count;
 531
 532        while (element < end) {
 533                u32 nargs, i;
 534
 535                if (element->type != ACPI_TYPE_LOCAL_REFERENCE)
 536                        return -EPROTO;
 537
 538                ret = acpi_bus_get_device(element->reference.handle, &device);
 539                if (ret)
 540                        return -ENODEV;
 541
 542                element++;
 543                nargs = 0;
 544
 545                /* assume following integer elements are all args */
 546                for (i = 0; element + i < end; i++) {
 547                        int type = element[i].type;
 548
 549                        if (type == ACPI_TYPE_INTEGER)
 550                                nargs++;
 551                        else if (type == ACPI_TYPE_LOCAL_REFERENCE)
 552                                break;
 553                        else
 554                                return -EPROTO;
 555                }
 556
 557                if (idx++ == index) {
 558                        args->adev = device;
 559                        args->nargs = nargs;
 560                        for (i = 0; i < nargs; i++)
 561                                args->args[i] = element[i].integer.value;
 562
 563                        return 0;
 564                }
 565
 566                element += nargs;
 567        }
 568
 569        return -EPROTO;
 570}
 571
 572/**
 573 * acpi_node_get_property_reference - get a handle to the referenced object.
 574 * @fwnode: Firmware node to get the property from.
 575 * @propname: Name of the property.
 576 * @index: Index of the reference to return.
 577 * @args: Location to store the returned reference with optional arguments.
 578 */
 579int acpi_node_get_property_reference(struct fwnode_handle *fwnode,
 580                                     const char *name, size_t index,
 581                                     struct acpi_reference_args *args)
 582{
 583        struct acpi_device_data *data = acpi_device_data_of_node(fwnode);
 584
 585        return data ? acpi_data_get_property_reference(data, name, index, args) : -EINVAL;
 586}
 587EXPORT_SYMBOL_GPL(acpi_node_get_property_reference);
 588
 589static int acpi_data_prop_read_single(struct acpi_device_data *data,
 590                                      const char *propname,
 591                                      enum dev_prop_type proptype, void *val)
 592{
 593        const union acpi_object *obj;
 594        int ret;
 595
 596        if (!val)
 597                return -EINVAL;
 598
 599        if (proptype >= DEV_PROP_U8 && proptype <= DEV_PROP_U64) {
 600                ret = acpi_data_get_property(data, propname, ACPI_TYPE_INTEGER, &obj);
 601                if (ret)
 602                        return ret;
 603
 604                switch (proptype) {
 605                case DEV_PROP_U8:
 606                        if (obj->integer.value > U8_MAX)
 607                                return -EOVERFLOW;
 608                        *(u8 *)val = obj->integer.value;
 609                        break;
 610                case DEV_PROP_U16:
 611                        if (obj->integer.value > U16_MAX)
 612                                return -EOVERFLOW;
 613                        *(u16 *)val = obj->integer.value;
 614                        break;
 615                case DEV_PROP_U32:
 616                        if (obj->integer.value > U32_MAX)
 617                                return -EOVERFLOW;
 618                        *(u32 *)val = obj->integer.value;
 619                        break;
 620                default:
 621                        *(u64 *)val = obj->integer.value;
 622                        break;
 623                }
 624        } else if (proptype == DEV_PROP_STRING) {
 625                ret = acpi_data_get_property(data, propname, ACPI_TYPE_STRING, &obj);
 626                if (ret)
 627                        return ret;
 628
 629                *(char **)val = obj->string.pointer;
 630        } else {
 631                ret = -EINVAL;
 632        }
 633        return ret;
 634}
 635
 636int acpi_dev_prop_read_single(struct acpi_device *adev, const char *propname,
 637                              enum dev_prop_type proptype, void *val)
 638{
 639        return adev ? acpi_data_prop_read_single(&adev->data, propname, proptype, val) : -EINVAL;
 640}
 641
 642static int acpi_copy_property_array_u8(const union acpi_object *items, u8 *val,
 643                                       size_t nval)
 644{
 645        int i;
 646
 647        for (i = 0; i < nval; i++) {
 648                if (items[i].type != ACPI_TYPE_INTEGER)
 649                        return -EPROTO;
 650                if (items[i].integer.value > U8_MAX)
 651                        return -EOVERFLOW;
 652
 653                val[i] = items[i].integer.value;
 654        }
 655        return 0;
 656}
 657
 658static int acpi_copy_property_array_u16(const union acpi_object *items,
 659                                        u16 *val, size_t nval)
 660{
 661        int i;
 662
 663        for (i = 0; i < nval; i++) {
 664                if (items[i].type != ACPI_TYPE_INTEGER)
 665                        return -EPROTO;
 666                if (items[i].integer.value > U16_MAX)
 667                        return -EOVERFLOW;
 668
 669                val[i] = items[i].integer.value;
 670        }
 671        return 0;
 672}
 673
 674static int acpi_copy_property_array_u32(const union acpi_object *items,
 675                                        u32 *val, size_t nval)
 676{
 677        int i;
 678
 679        for (i = 0; i < nval; i++) {
 680                if (items[i].type != ACPI_TYPE_INTEGER)
 681                        return -EPROTO;
 682                if (items[i].integer.value > U32_MAX)
 683                        return -EOVERFLOW;
 684
 685                val[i] = items[i].integer.value;
 686        }
 687        return 0;
 688}
 689
 690static int acpi_copy_property_array_u64(const union acpi_object *items,
 691                                        u64 *val, size_t nval)
 692{
 693        int i;
 694
 695        for (i = 0; i < nval; i++) {
 696                if (items[i].type != ACPI_TYPE_INTEGER)
 697                        return -EPROTO;
 698
 699                val[i] = items[i].integer.value;
 700        }
 701        return 0;
 702}
 703
 704static int acpi_copy_property_array_string(const union acpi_object *items,
 705                                           char **val, size_t nval)
 706{
 707        int i;
 708
 709        for (i = 0; i < nval; i++) {
 710                if (items[i].type != ACPI_TYPE_STRING)
 711                        return -EPROTO;
 712
 713                val[i] = items[i].string.pointer;
 714        }
 715        return 0;
 716}
 717
 718static int acpi_data_prop_read(struct acpi_device_data *data,
 719                               const char *propname,
 720                               enum dev_prop_type proptype,
 721                               void *val, size_t nval)
 722{
 723        const union acpi_object *obj;
 724        const union acpi_object *items;
 725        int ret;
 726
 727        if (val && nval == 1) {
 728                ret = acpi_data_prop_read_single(data, propname, proptype, val);
 729                if (!ret)
 730                        return ret;
 731        }
 732
 733        ret = acpi_data_get_property_array(data, propname, ACPI_TYPE_ANY, &obj);
 734        if (ret)
 735                return ret;
 736
 737        if (!val)
 738                return obj->package.count;
 739
 740        if (nval > obj->package.count)
 741                return -EOVERFLOW;
 742        else if (nval <= 0)
 743                return -EINVAL;
 744
 745        items = obj->package.elements;
 746
 747        switch (proptype) {
 748        case DEV_PROP_U8:
 749                ret = acpi_copy_property_array_u8(items, (u8 *)val, nval);
 750                break;
 751        case DEV_PROP_U16:
 752                ret = acpi_copy_property_array_u16(items, (u16 *)val, nval);
 753                break;
 754        case DEV_PROP_U32:
 755                ret = acpi_copy_property_array_u32(items, (u32 *)val, nval);
 756                break;
 757        case DEV_PROP_U64:
 758                ret = acpi_copy_property_array_u64(items, (u64 *)val, nval);
 759                break;
 760        case DEV_PROP_STRING:
 761                ret = acpi_copy_property_array_string(items, (char **)val, nval);
 762                break;
 763        default:
 764                ret = -EINVAL;
 765                break;
 766        }
 767        return ret;
 768}
 769
 770int acpi_dev_prop_read(struct acpi_device *adev, const char *propname,
 771                       enum dev_prop_type proptype, void *val, size_t nval)
 772{
 773        return adev ? acpi_data_prop_read(&adev->data, propname, proptype, val, nval) : -EINVAL;
 774}
 775
 776/**
 777 * acpi_node_prop_read - retrieve the value of an ACPI property with given name.
 778 * @fwnode: Firmware node to get the property from.
 779 * @propname: Name of the property.
 780 * @proptype: Expected property type.
 781 * @val: Location to store the property value (if not %NULL).
 782 * @nval: Size of the array pointed to by @val.
 783 *
 784 * If @val is %NULL, return the number of array elements comprising the value
 785 * of the property.  Otherwise, read at most @nval values to the array at the
 786 * location pointed to by @val.
 787 */
 788int acpi_node_prop_read(struct fwnode_handle *fwnode,  const char *propname,
 789                        enum dev_prop_type proptype, void *val, size_t nval)
 790{
 791        return acpi_data_prop_read(acpi_device_data_of_node(fwnode),
 792                                   propname, proptype, val, nval);
 793}
 794
 795/**
 796 * acpi_get_next_subnode - Return the next child node handle for a device.
 797 * @dev: Device to find the next child node for.
 798 * @child: Handle to one of the device's child nodes or a null handle.
 799 */
 800struct fwnode_handle *acpi_get_next_subnode(struct device *dev,
 801                                            struct fwnode_handle *child)
 802{
 803        struct acpi_device *adev = ACPI_COMPANION(dev);
 804        struct list_head *head, *next;
 805
 806        if (!adev)
 807                return NULL;
 808
 809        if (!child || child->type == FWNODE_ACPI) {
 810                head = &adev->children;
 811                if (list_empty(head))
 812                        goto nondev;
 813
 814                if (child) {
 815                        adev = to_acpi_device_node(child);
 816                        next = adev->node.next;
 817                        if (next == head) {
 818                                child = NULL;
 819                                adev = ACPI_COMPANION(dev);
 820                                goto nondev;
 821                        }
 822                        adev = list_entry(next, struct acpi_device, node);
 823                } else {
 824                        adev = list_first_entry(head, struct acpi_device, node);
 825                }
 826                return acpi_fwnode_handle(adev);
 827        }
 828
 829 nondev:
 830        if (!child || child->type == FWNODE_ACPI_DATA) {
 831                struct acpi_data_node *dn;
 832
 833                head = &adev->data.subnodes;
 834                if (list_empty(head))
 835                        return NULL;
 836
 837                if (child) {
 838                        dn = to_acpi_data_node(child);
 839                        next = dn->sibling.next;
 840                        if (next == head)
 841                                return NULL;
 842
 843                        dn = list_entry(next, struct acpi_data_node, sibling);
 844                } else {
 845                        dn = list_first_entry(head, struct acpi_data_node, sibling);
 846                }
 847                return &dn->fwnode;
 848        }
 849        return NULL;
 850}
 851