Commit 091f4d718620a79698e1c8ca3e9acbf78eb62da3

Authored by Bob Moore
Committed by Len Brown
1 parent 5f8902acf8

ACPICA: Predefined name repair: fix NULL package elements

For the predefined methods that return fixed-length packages
(or subpackages), attempt repair for a NULL element. Create an
Integer of value 0, a NULL String, or a zero-length buffer as
appropriate.

http://www.acpica.org/bugzilla/show_bug.cgi?id=818

Signed-off-by: Bob Moore <robert.moore@intel.com>
Signed-off-by: Lin Ming <ming.m.lin@intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>

Showing 5 changed files with 209 additions and 92 deletions Side-by-side Diff

drivers/acpi/acpica/aclocal.h
... ... @@ -374,6 +374,7 @@
374 374 struct acpi_predefined_data {
375 375 char *pathname;
376 376 const union acpi_predefined_info *predefined;
  377 + union acpi_operand_object *parent_package;
377 378 u32 flags;
378 379 u8 node_flags;
379 380 };
drivers/acpi/acpica/acnamesp.h
... ... @@ -286,6 +286,17 @@
286 286 acpi_ns_repair_package_list(struct acpi_predefined_data *data,
287 287 union acpi_operand_object **obj_desc_ptr);
288 288  
  289 +acpi_status
  290 +acpi_ns_repair_null_element(struct acpi_predefined_data *data,
  291 + u32 expected_btypes,
  292 + u32 package_index,
  293 + union acpi_operand_object **return_object_ptr);
  294 +
  295 +void
  296 +acpi_ns_remove_null_elements(struct acpi_predefined_data *data,
  297 + u8 package_type,
  298 + union acpi_operand_object *obj_desc);
  299 +
289 300 /*
290 301 * nsrepair2 - Return object repair for specific
291 302 * predefined methods/objects
... ... @@ -295,11 +306,6 @@
295 306 struct acpi_namespace_node *node,
296 307 acpi_status validate_status,
297 308 union acpi_operand_object **return_object_ptr);
298   -
299   -void
300   -acpi_ns_remove_null_elements(struct acpi_predefined_data *data,
301   - u8 package_type,
302   - union acpi_operand_object *obj_desc);
303 309  
304 310 /*
305 311 * nssearch - Namespace searching and entry
drivers/acpi/acpica/nspredef.c
... ... @@ -231,6 +231,7 @@
231 231 * Note: Package may have been newly created by call above.
232 232 */
233 233 if ((*return_object_ptr)->common.type == ACPI_TYPE_PACKAGE) {
  234 + data->parent_package = *return_object_ptr;
234 235 status = acpi_ns_check_package(data, return_object_ptr);
235 236 if (ACPI_FAILURE(status)) {
236 237 goto exit;
... ... @@ -710,6 +711,7 @@
710 711 for (i = 0; i < count; i++) {
711 712 sub_package = *elements;
712 713 sub_elements = sub_package->package.elements;
  714 + data->parent_package = sub_package;
713 715  
714 716 /* Each sub-object must be of type Package */
715 717  
... ... @@ -721,6 +723,7 @@
721 723  
722 724 /* Examine the different types of expected sub-packages */
723 725  
  726 + data->parent_package = sub_package;
724 727 switch (package->ret_info.type) {
725 728 case ACPI_PTYPE2:
726 729 case ACPI_PTYPE2_PKG_COUNT:
... ... @@ -800,7 +803,7 @@
800 803  
801 804 /*
802 805 * First element is the (Integer) count of elements, including
803   - * the count field.
  806 + * the count field (the ACPI name is num_elements)
804 807 */
805 808 status = acpi_ns_check_object_type(data, sub_elements,
806 809 ACPI_RTYPE_INTEGER,
... ... @@ -822,6 +825,16 @@
822 825 expected_count = package->ret_info.count1;
823 826 goto package_too_small;
824 827 }
  828 + if (expected_count == 0) {
  829 + /*
  830 + * Either the num_entries element was originally zero or it was
  831 + * a NULL element and repaired to an Integer of value zero.
  832 + * In either case, repair it by setting num_entries to be the
  833 + * actual size of the subpackage.
  834 + */
  835 + expected_count = sub_package->package.count;
  836 + (*sub_elements)->integer.value = expected_count;
  837 + }
825 838  
826 839 /* Check the type of each sub-package element */
827 840  
828 841  
... ... @@ -945,10 +958,18 @@
945 958 char type_buffer[48]; /* Room for 5 types */
946 959  
947 960 /*
948   - * If we get a NULL return_object here, it is a NULL package element,
949   - * and this is always an error.
  961 + * If we get a NULL return_object here, it is a NULL package element.
  962 + * Since all extraneous NULL package elements were removed earlier by a
  963 + * call to acpi_ns_remove_null_elements, this is an unexpected NULL element.
  964 + * We will attempt to repair it.
950 965 */
951 966 if (!return_object) {
  967 + status = acpi_ns_repair_null_element(data, expected_btypes,
  968 + package_index,
  969 + return_object_ptr);
  970 + if (ACPI_SUCCESS(status)) {
  971 + return (AE_OK); /* Repair was successful */
  972 + }
952 973 goto type_error_exit;
953 974 }
954 975  
drivers/acpi/acpica/nsrepair.c
... ... @@ -45,6 +45,7 @@
45 45 #include "accommon.h"
46 46 #include "acnamesp.h"
47 47 #include "acinterp.h"
  48 +#include "acpredef.h"
48 49  
49 50 #define _COMPONENT ACPI_NAMESPACE
50 51 ACPI_MODULE_NAME("nsrepair")
... ... @@ -71,6 +72,12 @@
71 72 * Buffer -> Package of Integers
72 73 * Package -> Package of one Package
73 74 *
  75 + * Additional possible repairs:
  76 + *
  77 + * Optional/unnecessary NULL package elements removed
  78 + * Required package elements that are NULL replaced by Integer/String/Buffer
  79 + * Incorrect standalone package wrapped with required outer package
  80 + *
74 81 ******************************************************************************/
75 82 /* Local prototypes */
76 83 static acpi_status
... ... @@ -502,6 +509,172 @@
502 509  
503 510 *return_object = new_object;
504 511 return (AE_OK);
  512 +}
  513 +
  514 +/*******************************************************************************
  515 + *
  516 + * FUNCTION: acpi_ns_repair_null_element
  517 + *
  518 + * PARAMETERS: Data - Pointer to validation data structure
  519 + * expected_btypes - Object types expected
  520 + * package_index - Index of object within parent package (if
  521 + * applicable - ACPI_NOT_PACKAGE_ELEMENT
  522 + * otherwise)
  523 + * return_object_ptr - Pointer to the object returned from the
  524 + * evaluation of a method or object
  525 + *
  526 + * RETURN: Status. AE_OK if repair was successful.
  527 + *
  528 + * DESCRIPTION: Attempt to repair a NULL element of a returned Package object.
  529 + *
  530 + ******************************************************************************/
  531 +
  532 +acpi_status
  533 +acpi_ns_repair_null_element(struct acpi_predefined_data *data,
  534 + u32 expected_btypes,
  535 + u32 package_index,
  536 + union acpi_operand_object **return_object_ptr)
  537 +{
  538 + union acpi_operand_object *return_object = *return_object_ptr;
  539 + union acpi_operand_object *new_object;
  540 +
  541 + ACPI_FUNCTION_NAME(ns_repair_null_element);
  542 +
  543 + /* No repair needed if return object is non-NULL */
  544 +
  545 + if (return_object) {
  546 + return (AE_OK);
  547 + }
  548 +
  549 + /*
  550 + * Attempt to repair a NULL element of a Package object. This applies to
  551 + * predefined names that return a fixed-length package and each element
  552 + * is required. It does not apply to variable-length packages where NULL
  553 + * elements are allowed, especially at the end of the package.
  554 + */
  555 + if (expected_btypes & ACPI_RTYPE_INTEGER) {
  556 +
  557 + /* Need an Integer - create a zero-value integer */
  558 +
  559 + new_object = acpi_ut_create_integer_object(0);
  560 + } else if (expected_btypes & ACPI_RTYPE_STRING) {
  561 +
  562 + /* Need a String - create a NULL string */
  563 +
  564 + new_object = acpi_ut_create_string_object(0);
  565 + } else if (expected_btypes & ACPI_RTYPE_BUFFER) {
  566 +
  567 + /* Need a Buffer - create a zero-length buffer */
  568 +
  569 + new_object = acpi_ut_create_buffer_object(0);
  570 + } else {
  571 + /* Error for all other expected types */
  572 +
  573 + return (AE_AML_OPERAND_TYPE);
  574 + }
  575 +
  576 + if (!new_object) {
  577 + return (AE_NO_MEMORY);
  578 + }
  579 +
  580 + /* Set the reference count according to the parent Package object */
  581 +
  582 + new_object->common.reference_count =
  583 + data->parent_package->common.reference_count;
  584 +
  585 + ACPI_DEBUG_PRINT((ACPI_DB_REPAIR,
  586 + "%s: Converted NULL package element to expected %s at index %u\n",
  587 + data->pathname,
  588 + acpi_ut_get_object_type_name(new_object),
  589 + package_index));
  590 +
  591 + *return_object_ptr = new_object;
  592 + data->flags |= ACPI_OBJECT_REPAIRED;
  593 + return (AE_OK);
  594 +}
  595 +
  596 +/******************************************************************************
  597 + *
  598 + * FUNCTION: acpi_ns_remove_null_elements
  599 + *
  600 + * PARAMETERS: Data - Pointer to validation data structure
  601 + * package_type - An acpi_return_package_types value
  602 + * obj_desc - A Package object
  603 + *
  604 + * RETURN: None.
  605 + *
  606 + * DESCRIPTION: Remove all NULL package elements from packages that contain
  607 + * a variable number of sub-packages. For these types of
  608 + * packages, NULL elements can be safely removed.
  609 + *
  610 + *****************************************************************************/
  611 +
  612 +void
  613 +acpi_ns_remove_null_elements(struct acpi_predefined_data *data,
  614 + u8 package_type,
  615 + union acpi_operand_object *obj_desc)
  616 +{
  617 + union acpi_operand_object **source;
  618 + union acpi_operand_object **dest;
  619 + u32 count;
  620 + u32 new_count;
  621 + u32 i;
  622 +
  623 + ACPI_FUNCTION_NAME(ns_remove_null_elements);
  624 +
  625 + /*
  626 + * PTYPE1 packages contain no subpackages.
  627 + * PTYPE2 packages contain a variable number of sub-packages. We can
  628 + * safely remove all NULL elements from the PTYPE2 packages.
  629 + */
  630 + switch (package_type) {
  631 + case ACPI_PTYPE1_FIXED:
  632 + case ACPI_PTYPE1_VAR:
  633 + case ACPI_PTYPE1_OPTION:
  634 + return;
  635 +
  636 + case ACPI_PTYPE2:
  637 + case ACPI_PTYPE2_COUNT:
  638 + case ACPI_PTYPE2_PKG_COUNT:
  639 + case ACPI_PTYPE2_FIXED:
  640 + case ACPI_PTYPE2_MIN:
  641 + case ACPI_PTYPE2_REV_FIXED:
  642 + break;
  643 +
  644 + default:
  645 + return;
  646 + }
  647 +
  648 + count = obj_desc->package.count;
  649 + new_count = count;
  650 +
  651 + source = obj_desc->package.elements;
  652 + dest = source;
  653 +
  654 + /* Examine all elements of the package object, remove nulls */
  655 +
  656 + for (i = 0; i < count; i++) {
  657 + if (!*source) {
  658 + new_count--;
  659 + } else {
  660 + *dest = *source;
  661 + dest++;
  662 + }
  663 + source++;
  664 + }
  665 +
  666 + /* Update parent package if any null elements were removed */
  667 +
  668 + if (new_count < count) {
  669 + ACPI_DEBUG_PRINT((ACPI_DB_REPAIR,
  670 + "%s: Found and removed %u NULL elements\n",
  671 + data->pathname, (count - new_count)));
  672 +
  673 + /* NULL terminate list and update the package count */
  674 +
  675 + *dest = NULL;
  676 + obj_desc->package.count = new_count;
  677 + }
505 678 }
506 679  
507 680 /*******************************************************************************
drivers/acpi/acpica/nsrepair2.c
... ... @@ -45,7 +45,6 @@
45 45 #include <acpi/acpi.h>
46 46 #include "accommon.h"
47 47 #include "acnamesp.h"
48   -#include "acpredef.h"
49 48  
50 49 #define _COMPONENT ACPI_NAMESPACE
51 50 ACPI_MODULE_NAME("nsrepair2")
... ... @@ -516,89 +515,6 @@
516 515 }
517 516  
518 517 return (AE_OK);
519   -}
520   -
521   -/******************************************************************************
522   - *
523   - * FUNCTION: acpi_ns_remove_null_elements
524   - *
525   - * PARAMETERS: Data - Pointer to validation data structure
526   - * package_type - An acpi_return_package_types value
527   - * obj_desc - A Package object
528   - *
529   - * RETURN: None.
530   - *
531   - * DESCRIPTION: Remove all NULL package elements from packages that contain
532   - * a variable number of sub-packages.
533   - *
534   - *****************************************************************************/
535   -
536   -void
537   -acpi_ns_remove_null_elements(struct acpi_predefined_data *data,
538   - u8 package_type,
539   - union acpi_operand_object *obj_desc)
540   -{
541   - union acpi_operand_object **source;
542   - union acpi_operand_object **dest;
543   - u32 count;
544   - u32 new_count;
545   - u32 i;
546   -
547   - ACPI_FUNCTION_NAME(ns_remove_null_elements);
548   -
549   - /*
550   - * PTYPE1 packages contain no subpackages.
551   - * PTYPE2 packages contain a variable number of sub-packages. We can
552   - * safely remove all NULL elements from the PTYPE2 packages.
553   - */
554   - switch (package_type) {
555   - case ACPI_PTYPE1_FIXED:
556   - case ACPI_PTYPE1_VAR:
557   - case ACPI_PTYPE1_OPTION:
558   - return;
559   -
560   - case ACPI_PTYPE2:
561   - case ACPI_PTYPE2_COUNT:
562   - case ACPI_PTYPE2_PKG_COUNT:
563   - case ACPI_PTYPE2_FIXED:
564   - case ACPI_PTYPE2_MIN:
565   - case ACPI_PTYPE2_REV_FIXED:
566   - break;
567   -
568   - default:
569   - return;
570   - }
571   -
572   - count = obj_desc->package.count;
573   - new_count = count;
574   -
575   - source = obj_desc->package.elements;
576   - dest = source;
577   -
578   - /* Examine all elements of the package object, remove nulls */
579   -
580   - for (i = 0; i < count; i++) {
581   - if (!*source) {
582   - new_count--;
583   - } else {
584   - *dest = *source;
585   - dest++;
586   - }
587   - source++;
588   - }
589   -
590   - /* Update parent package if any null elements were removed */
591   -
592   - if (new_count < count) {
593   - ACPI_DEBUG_PRINT((ACPI_DB_REPAIR,
594   - "%s: Found and removed %u NULL elements\n",
595   - data->pathname, (count - new_count)));
596   -
597   - /* NULL terminate list and update the package count */
598   -
599   - *dest = NULL;
600   - obj_desc->package.count = new_count;
601   - }
602 518 }
603 519  
604 520 /******************************************************************************