1 /****************************************************************************** 2 * 3 * Module Name: nsrepair2 - Repair for objects returned by specific 4 * predefined methods 5 * 6 *****************************************************************************/ 7 8 /* 9 * Copyright (C) 2000 - 2012, Intel Corp. 10 * All rights reserved. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions, and the following disclaimer, 17 * without modification. 18 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 19 * substantially similar to the "NO WARRANTY" disclaimer below 20 * ("Disclaimer") and any redistribution must be conditioned upon 21 * including a substantially similar Disclaimer requirement for further 22 * binary redistribution. 23 * 3. Neither the names of the above-listed copyright holders nor the names 24 * of any contributors may be used to endorse or promote products derived 25 * from this software without specific prior written permission. 26 * 27 * Alternatively, this software may be distributed under the terms of the 28 * GNU General Public License ("GPL") version 2 as published by the Free 29 * Software Foundation. 30 * 31 * NO WARRANTY 32 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 33 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 34 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 35 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 36 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 40 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 41 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 42 * POSSIBILITY OF SUCH DAMAGES. 43 */ 44 45 #include <acpi/acpi.h> 46 #include "accommon.h" 47 #include "acnamesp.h" 48 49 #define _COMPONENT ACPI_NAMESPACE 50 ACPI_MODULE_NAME("nsrepair2") 51 52 /* 53 * Information structure and handler for ACPI predefined names that can 54 * be repaired on a per-name basis. 55 */ 56 typedef 57 acpi_status(*acpi_repair_function) (struct acpi_predefined_data *data, 58 union acpi_operand_object **return_object_ptr); 59 60 typedef struct acpi_repair_info { 61 char name[ACPI_NAME_SIZE]; 62 acpi_repair_function repair_function; 63 64 } acpi_repair_info; 65 66 /* Local prototypes */ 67 68 static const struct acpi_repair_info *acpi_ns_match_repairable_name(struct 69 acpi_namespace_node 70 *node); 71 72 static acpi_status 73 acpi_ns_repair_ALR(struct acpi_predefined_data *data, 74 union acpi_operand_object **return_object_ptr); 75 76 static acpi_status 77 acpi_ns_repair_CID(struct acpi_predefined_data *data, 78 union acpi_operand_object **return_object_ptr); 79 80 static acpi_status 81 acpi_ns_repair_FDE(struct acpi_predefined_data *data, 82 union acpi_operand_object **return_object_ptr); 83 84 static acpi_status 85 acpi_ns_repair_HID(struct acpi_predefined_data *data, 86 union acpi_operand_object **return_object_ptr); 87 88 static acpi_status 89 acpi_ns_repair_PSS(struct acpi_predefined_data *data, 90 union acpi_operand_object **return_object_ptr); 91 92 static acpi_status 93 acpi_ns_repair_TSS(struct acpi_predefined_data *data, 94 union acpi_operand_object **return_object_ptr); 95 96 static acpi_status 97 acpi_ns_check_sorted_list(struct acpi_predefined_data *data, 98 union acpi_operand_object *return_object, 99 u32 expected_count, 100 u32 sort_index, 101 u8 sort_direction, char *sort_key_name); 102 103 static void 104 acpi_ns_sort_list(union acpi_operand_object **elements, 105 u32 count, u32 index, u8 sort_direction); 106 107 /* Values for sort_direction above */ 108 109 #define ACPI_SORT_ASCENDING 0 110 #define ACPI_SORT_DESCENDING 1 111 112 /* 113 * This table contains the names of the predefined methods for which we can 114 * perform more complex repairs. 115 * 116 * As necessary: 117 * 118 * _ALR: Sort the list ascending by ambient_illuminance 119 * _CID: Strings: uppercase all, remove any leading asterisk 120 * _FDE: Convert Buffer of BYTEs to a Buffer of DWORDs 121 * _GTM: Convert Buffer of BYTEs to a Buffer of DWORDs 122 * _HID: Strings: uppercase all, remove any leading asterisk 123 * _PSS: Sort the list descending by Power 124 * _TSS: Sort the list descending by Power 125 * 126 * Names that must be packages, but cannot be sorted: 127 * 128 * _BCL: Values are tied to the Package index where they appear, and cannot 129 * be moved or sorted. These index values are used for _BQC and _BCM. 130 * However, we can fix the case where a buffer is returned, by converting 131 * it to a Package of integers. 132 */ 133 static const struct acpi_repair_info acpi_ns_repairable_names[] = { 134 {"_ALR", acpi_ns_repair_ALR}, 135 {"_CID", acpi_ns_repair_CID}, 136 {"_FDE", acpi_ns_repair_FDE}, 137 {"_GTM", acpi_ns_repair_FDE}, /* _GTM has same repair as _FDE */ 138 {"_HID", acpi_ns_repair_HID}, 139 {"_PSS", acpi_ns_repair_PSS}, 140 {"_TSS", acpi_ns_repair_TSS}, 141 {{0, 0, 0, 0}, NULL} /* Table terminator */ 142 }; 143 144 #define ACPI_FDE_FIELD_COUNT 5 145 #define ACPI_FDE_BYTE_BUFFER_SIZE 5 146 #define ACPI_FDE_DWORD_BUFFER_SIZE (ACPI_FDE_FIELD_COUNT * sizeof (u32)) 147 148 /****************************************************************************** 149 * 150 * FUNCTION: acpi_ns_complex_repairs 151 * 152 * PARAMETERS: data - Pointer to validation data structure 153 * node - Namespace node for the method/object 154 * validate_status - Original status of earlier validation 155 * return_object_ptr - Pointer to the object returned from the 156 * evaluation of a method or object 157 * 158 * RETURN: Status. AE_OK if repair was successful. If name is not 159 * matched, validate_status is returned. 160 * 161 * DESCRIPTION: Attempt to repair/convert a return object of a type that was 162 * not expected. 163 * 164 *****************************************************************************/ 165 166 acpi_status 167 acpi_ns_complex_repairs(struct acpi_predefined_data *data, 168 struct acpi_namespace_node *node, 169 acpi_status validate_status, 170 union acpi_operand_object **return_object_ptr) 171 { 172 const struct acpi_repair_info *predefined; 173 acpi_status status; 174 175 /* Check if this name is in the list of repairable names */ 176 177 predefined = acpi_ns_match_repairable_name(node); 178 if (!predefined) { 179 return (validate_status); 180 } 181 182 status = predefined->repair_function(data, return_object_ptr); 183 return (status); 184 } 185 186 /****************************************************************************** 187 * 188 * FUNCTION: acpi_ns_match_repairable_name 189 * 190 * PARAMETERS: node - Namespace node for the method/object 191 * 192 * RETURN: Pointer to entry in repair table. NULL indicates not found. 193 * 194 * DESCRIPTION: Check an object name against the repairable object list. 195 * 196 *****************************************************************************/ 197 198 static const struct acpi_repair_info *acpi_ns_match_repairable_name(struct 199 acpi_namespace_node 200 *node) 201 { 202 const struct acpi_repair_info *this_name; 203 204 /* Search info table for a repairable predefined method/object name */ 205 206 this_name = acpi_ns_repairable_names; 207 while (this_name->repair_function) { 208 if (ACPI_COMPARE_NAME(node->name.ascii, this_name->name)) { 209 return (this_name); 210 } 211 this_name++; 212 } 213 214 return (NULL); /* Not found */ 215 } 216 217 /****************************************************************************** 218 * 219 * FUNCTION: acpi_ns_repair_ALR 220 * 221 * PARAMETERS: data - Pointer to validation data structure 222 * return_object_ptr - Pointer to the object returned from the 223 * evaluation of a method or object 224 * 225 * RETURN: Status. AE_OK if object is OK or was repaired successfully 226 * 227 * DESCRIPTION: Repair for the _ALR object. If necessary, sort the object list 228 * ascending by the ambient illuminance values. 229 * 230 *****************************************************************************/ 231 232 static acpi_status 233 acpi_ns_repair_ALR(struct acpi_predefined_data *data, 234 union acpi_operand_object **return_object_ptr) 235 { 236 union acpi_operand_object *return_object = *return_object_ptr; 237 acpi_status status; 238 239 status = acpi_ns_check_sorted_list(data, return_object, 2, 1, 240 ACPI_SORT_ASCENDING, 241 "AmbientIlluminance"); 242 243 return (status); 244 } 245 246 /****************************************************************************** 247 * 248 * FUNCTION: acpi_ns_repair_FDE 249 * 250 * PARAMETERS: data - Pointer to validation data structure 251 * return_object_ptr - Pointer to the object returned from the 252 * evaluation of a method or object 253 * 254 * RETURN: Status. AE_OK if object is OK or was repaired successfully 255 * 256 * DESCRIPTION: Repair for the _FDE and _GTM objects. The expected return 257 * value is a Buffer of 5 DWORDs. This function repairs a common 258 * problem where the return value is a Buffer of BYTEs, not 259 * DWORDs. 260 * 261 *****************************************************************************/ 262 263 static acpi_status 264 acpi_ns_repair_FDE(struct acpi_predefined_data *data, 265 union acpi_operand_object **return_object_ptr) 266 { 267 union acpi_operand_object *return_object = *return_object_ptr; 268 union acpi_operand_object *buffer_object; 269 u8 *byte_buffer; 270 u32 *dword_buffer; 271 u32 i; 272 273 ACPI_FUNCTION_NAME(ns_repair_FDE); 274 275 switch (return_object->common.type) { 276 case ACPI_TYPE_BUFFER: 277 278 /* This is the expected type. Length should be (at least) 5 DWORDs */ 279 280 if (return_object->buffer.length >= ACPI_FDE_DWORD_BUFFER_SIZE) { 281 return (AE_OK); 282 } 283 284 /* We can only repair if we have exactly 5 BYTEs */ 285 286 if (return_object->buffer.length != ACPI_FDE_BYTE_BUFFER_SIZE) { 287 ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, 288 data->node_flags, 289 "Incorrect return buffer length %u, expected %u", 290 return_object->buffer.length, 291 ACPI_FDE_DWORD_BUFFER_SIZE)); 292 293 return (AE_AML_OPERAND_TYPE); 294 } 295 296 /* Create the new (larger) buffer object */ 297 298 buffer_object = 299 acpi_ut_create_buffer_object(ACPI_FDE_DWORD_BUFFER_SIZE); 300 if (!buffer_object) { 301 return (AE_NO_MEMORY); 302 } 303 304 /* Expand each byte to a DWORD */ 305 306 byte_buffer = return_object->buffer.pointer; 307 dword_buffer = 308 ACPI_CAST_PTR(u32, buffer_object->buffer.pointer); 309 310 for (i = 0; i < ACPI_FDE_FIELD_COUNT; i++) { 311 *dword_buffer = (u32) *byte_buffer; 312 dword_buffer++; 313 byte_buffer++; 314 } 315 316 ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, 317 "%s Expanded Byte Buffer to expected DWord Buffer\n", 318 data->pathname)); 319 break; 320 321 default: 322 return (AE_AML_OPERAND_TYPE); 323 } 324 325 /* Delete the original return object, return the new buffer object */ 326 327 acpi_ut_remove_reference(return_object); 328 *return_object_ptr = buffer_object; 329 330 data->flags |= ACPI_OBJECT_REPAIRED; 331 return (AE_OK); 332 } 333 334 /****************************************************************************** 335 * 336 * FUNCTION: acpi_ns_repair_CID 337 * 338 * PARAMETERS: data - Pointer to validation data structure 339 * return_object_ptr - Pointer to the object returned from the 340 * evaluation of a method or object 341 * 342 * RETURN: Status. AE_OK if object is OK or was repaired successfully 343 * 344 * DESCRIPTION: Repair for the _CID object. If a string, ensure that all 345 * letters are uppercase and that there is no leading asterisk. 346 * If a Package, ensure same for all string elements. 347 * 348 *****************************************************************************/ 349 350 static acpi_status 351 acpi_ns_repair_CID(struct acpi_predefined_data *data, 352 union acpi_operand_object **return_object_ptr) 353 { 354 acpi_status status; 355 union acpi_operand_object *return_object = *return_object_ptr; 356 union acpi_operand_object **element_ptr; 357 union acpi_operand_object *original_element; 358 u16 original_ref_count; 359 u32 i; 360 361 /* Check for _CID as a simple string */ 362 363 if (return_object->common.type == ACPI_TYPE_STRING) { 364 status = acpi_ns_repair_HID(data, return_object_ptr); 365 return (status); 366 } 367 368 /* Exit if not a Package */ 369 370 if (return_object->common.type != ACPI_TYPE_PACKAGE) { 371 return (AE_OK); 372 } 373 374 /* Examine each element of the _CID package */ 375 376 element_ptr = return_object->package.elements; 377 for (i = 0; i < return_object->package.count; i++) { 378 original_element = *element_ptr; 379 original_ref_count = original_element->common.reference_count; 380 381 status = acpi_ns_repair_HID(data, element_ptr); 382 if (ACPI_FAILURE(status)) { 383 return (status); 384 } 385 386 /* Take care with reference counts */ 387 388 if (original_element != *element_ptr) { 389 390 /* Element was replaced */ 391 392 (*element_ptr)->common.reference_count = 393 original_ref_count; 394 395 acpi_ut_remove_reference(original_element); 396 } 397 398 element_ptr++; 399 } 400 401 return (AE_OK); 402 } 403 404 /****************************************************************************** 405 * 406 * FUNCTION: acpi_ns_repair_HID 407 * 408 * PARAMETERS: data - Pointer to validation data structure 409 * return_object_ptr - Pointer to the object returned from the 410 * evaluation of a method or object 411 * 412 * RETURN: Status. AE_OK if object is OK or was repaired successfully 413 * 414 * DESCRIPTION: Repair for the _HID object. If a string, ensure that all 415 * letters are uppercase and that there is no leading asterisk. 416 * 417 *****************************************************************************/ 418 419 static acpi_status 420 acpi_ns_repair_HID(struct acpi_predefined_data *data, 421 union acpi_operand_object **return_object_ptr) 422 { 423 union acpi_operand_object *return_object = *return_object_ptr; 424 union acpi_operand_object *new_string; 425 char *source; 426 char *dest; 427 428 ACPI_FUNCTION_NAME(ns_repair_HID); 429 430 /* We only care about string _HID objects (not integers) */ 431 432 if (return_object->common.type != ACPI_TYPE_STRING) { 433 return (AE_OK); 434 } 435 436 if (return_object->string.length == 0) { 437 ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, data->node_flags, 438 "Invalid zero-length _HID or _CID string")); 439 440 /* Return AE_OK anyway, let driver handle it */ 441 442 data->flags |= ACPI_OBJECT_REPAIRED; 443 return (AE_OK); 444 } 445 446 /* It is simplest to always create a new string object */ 447 448 new_string = acpi_ut_create_string_object(return_object->string.length); 449 if (!new_string) { 450 return (AE_NO_MEMORY); 451 } 452 453 /* 454 * Remove a leading asterisk if present. For some unknown reason, there 455 * are many machines in the field that contains IDs like this. 456 * 457 * Examples: "*PNP0C03", "*ACPI0003" 458 */ 459 source = return_object->string.pointer; 460 if (*source == '*') { 461 source++; 462 new_string->string.length--; 463 464 ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, 465 "%s: Removed invalid leading asterisk\n", 466 data->pathname)); 467 } 468 469 /* 470 * Copy and uppercase the string. From the ACPI 5.0 specification: 471 * 472 * A valid PNP ID must be of the form "AAA####" where A is an uppercase 473 * letter and # is a hex digit. A valid ACPI ID must be of the form 474 * "NNNN####" where N is an uppercase letter or decimal digit, and 475 * # is a hex digit. 476 */ 477 for (dest = new_string->string.pointer; *source; dest++, source++) { 478 *dest = (char)ACPI_TOUPPER(*source); 479 } 480 481 acpi_ut_remove_reference(return_object); 482 *return_object_ptr = new_string; 483 return (AE_OK); 484 } 485 486 /****************************************************************************** 487 * 488 * FUNCTION: acpi_ns_repair_TSS 489 * 490 * PARAMETERS: data - Pointer to validation data structure 491 * return_object_ptr - Pointer to the object returned from the 492 * evaluation of a method or object 493 * 494 * RETURN: Status. AE_OK if object is OK or was repaired successfully 495 * 496 * DESCRIPTION: Repair for the _TSS object. If necessary, sort the object list 497 * descending by the power dissipation values. 498 * 499 *****************************************************************************/ 500 501 static acpi_status 502 acpi_ns_repair_TSS(struct acpi_predefined_data *data, 503 union acpi_operand_object **return_object_ptr) 504 { 505 union acpi_operand_object *return_object = *return_object_ptr; 506 acpi_status status; 507 struct acpi_namespace_node *node; 508 509 /* 510 * We can only sort the _TSS return package if there is no _PSS in the 511 * same scope. This is because if _PSS is present, the ACPI specification 512 * dictates that the _TSS Power Dissipation field is to be ignored, and 513 * therefore some BIOSs leave garbage values in the _TSS Power field(s). 514 * In this case, it is best to just return the _TSS package as-is. 515 * (May, 2011) 516 */ 517 status = 518 acpi_ns_get_node(data->node, "^_PSS", ACPI_NS_NO_UPSEARCH, &node); 519 if (ACPI_SUCCESS(status)) { 520 return (AE_OK); 521 } 522 523 status = acpi_ns_check_sorted_list(data, return_object, 5, 1, 524 ACPI_SORT_DESCENDING, 525 "PowerDissipation"); 526 527 return (status); 528 } 529 530 /****************************************************************************** 531 * 532 * FUNCTION: acpi_ns_repair_PSS 533 * 534 * PARAMETERS: data - Pointer to validation data structure 535 * return_object_ptr - Pointer to the object returned from the 536 * evaluation of a method or object 537 * 538 * RETURN: Status. AE_OK if object is OK or was repaired successfully 539 * 540 * DESCRIPTION: Repair for the _PSS object. If necessary, sort the object list 541 * by the CPU frequencies. Check that the power dissipation values 542 * are all proportional to CPU frequency (i.e., sorting by 543 * frequency should be the same as sorting by power.) 544 * 545 *****************************************************************************/ 546 547 static acpi_status 548 acpi_ns_repair_PSS(struct acpi_predefined_data *data, 549 union acpi_operand_object **return_object_ptr) 550 { 551 union acpi_operand_object *return_object = *return_object_ptr; 552 union acpi_operand_object **outer_elements; 553 u32 outer_element_count; 554 union acpi_operand_object **elements; 555 union acpi_operand_object *obj_desc; 556 u32 previous_value; 557 acpi_status status; 558 u32 i; 559 560 /* 561 * Entries (sub-packages) in the _PSS Package must be sorted by power 562 * dissipation, in descending order. If it appears that the list is 563 * incorrectly sorted, sort it. We sort by cpu_frequency, since this 564 * should be proportional to the power. 565 */ 566 status = acpi_ns_check_sorted_list(data, return_object, 6, 0, 567 ACPI_SORT_DESCENDING, 568 "CpuFrequency"); 569 if (ACPI_FAILURE(status)) { 570 return (status); 571 } 572 573 /* 574 * We now know the list is correctly sorted by CPU frequency. Check if 575 * the power dissipation values are proportional. 576 */ 577 previous_value = ACPI_UINT32_MAX; 578 outer_elements = return_object->package.elements; 579 outer_element_count = return_object->package.count; 580 581 for (i = 0; i < outer_element_count; i++) { 582 elements = (*outer_elements)->package.elements; 583 obj_desc = elements[1]; /* Index1 = power_dissipation */ 584 585 if ((u32) obj_desc->integer.value > previous_value) { 586 ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, 587 data->node_flags, 588 "SubPackage[%u,%u] - suspicious power dissipation values", 589 i - 1, i)); 590 } 591 592 previous_value = (u32) obj_desc->integer.value; 593 outer_elements++; 594 } 595 596 return (AE_OK); 597 } 598 599 /****************************************************************************** 600 * 601 * FUNCTION: acpi_ns_check_sorted_list 602 * 603 * PARAMETERS: data - Pointer to validation data structure 604 * return_object - Pointer to the top-level returned object 605 * expected_count - Minimum length of each sub-package 606 * sort_index - Sub-package entry to sort on 607 * sort_direction - Ascending or descending 608 * sort_key_name - Name of the sort_index field 609 * 610 * RETURN: Status. AE_OK if the list is valid and is sorted correctly or 611 * has been repaired by sorting the list. 612 * 613 * DESCRIPTION: Check if the package list is valid and sorted correctly by the 614 * sort_index. If not, then sort the list. 615 * 616 *****************************************************************************/ 617 618 static acpi_status 619 acpi_ns_check_sorted_list(struct acpi_predefined_data *data, 620 union acpi_operand_object *return_object, 621 u32 expected_count, 622 u32 sort_index, 623 u8 sort_direction, char *sort_key_name) 624 { 625 u32 outer_element_count; 626 union acpi_operand_object **outer_elements; 627 union acpi_operand_object **elements; 628 union acpi_operand_object *obj_desc; 629 u32 i; 630 u32 previous_value; 631 632 ACPI_FUNCTION_NAME(ns_check_sorted_list); 633 634 /* The top-level object must be a package */ 635 636 if (return_object->common.type != ACPI_TYPE_PACKAGE) { 637 return (AE_AML_OPERAND_TYPE); 638 } 639 640 /* 641 * NOTE: assumes list of sub-packages contains no NULL elements. 642 * Any NULL elements should have been removed by earlier call 643 * to acpi_ns_remove_null_elements. 644 */ 645 outer_elements = return_object->package.elements; 646 outer_element_count = return_object->package.count; 647 if (!outer_element_count) { 648 return (AE_AML_PACKAGE_LIMIT); 649 } 650 651 previous_value = 0; 652 if (sort_direction == ACPI_SORT_DESCENDING) { 653 previous_value = ACPI_UINT32_MAX; 654 } 655 656 /* Examine each subpackage */ 657 658 for (i = 0; i < outer_element_count; i++) { 659 660 /* Each element of the top-level package must also be a package */ 661 662 if ((*outer_elements)->common.type != ACPI_TYPE_PACKAGE) { 663 return (AE_AML_OPERAND_TYPE); 664 } 665 666 /* Each sub-package must have the minimum length */ 667 668 if ((*outer_elements)->package.count < expected_count) { 669 return (AE_AML_PACKAGE_LIMIT); 670 } 671 672 elements = (*outer_elements)->package.elements; 673 obj_desc = elements[sort_index]; 674 675 if (obj_desc->common.type != ACPI_TYPE_INTEGER) { 676 return (AE_AML_OPERAND_TYPE); 677 } 678 679 /* 680 * The list must be sorted in the specified order. If we detect a 681 * discrepancy, sort the entire list. 682 */ 683 if (((sort_direction == ACPI_SORT_ASCENDING) && 684 (obj_desc->integer.value < previous_value)) || 685 ((sort_direction == ACPI_SORT_DESCENDING) && 686 (obj_desc->integer.value > previous_value))) { 687 acpi_ns_sort_list(return_object->package.elements, 688 outer_element_count, sort_index, 689 sort_direction); 690 691 data->flags |= ACPI_OBJECT_REPAIRED; 692 693 ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, 694 "%s: Repaired unsorted list - now sorted by %s\n", 695 data->pathname, sort_key_name)); 696 return (AE_OK); 697 } 698 699 previous_value = (u32) obj_desc->integer.value; 700 outer_elements++; 701 } 702 703 return (AE_OK); 704 } 705 706 /****************************************************************************** 707 * 708 * FUNCTION: acpi_ns_sort_list 709 * 710 * PARAMETERS: elements - Package object element list 711 * count - Element count for above 712 * index - Sort by which package element 713 * sort_direction - Ascending or Descending sort 714 * 715 * RETURN: None 716 * 717 * DESCRIPTION: Sort the objects that are in a package element list. 718 * 719 * NOTE: Assumes that all NULL elements have been removed from the package, 720 * and that all elements have been verified to be of type Integer. 721 * 722 *****************************************************************************/ 723 724 static void 725 acpi_ns_sort_list(union acpi_operand_object **elements, 726 u32 count, u32 index, u8 sort_direction) 727 { 728 union acpi_operand_object *obj_desc1; 729 union acpi_operand_object *obj_desc2; 730 union acpi_operand_object *temp_obj; 731 u32 i; 732 u32 j; 733 734 /* Simple bubble sort */ 735 736 for (i = 1; i < count; i++) { 737 for (j = (count - 1); j >= i; j--) { 738 obj_desc1 = elements[j - 1]->package.elements[index]; 739 obj_desc2 = elements[j]->package.elements[index]; 740 741 if (((sort_direction == ACPI_SORT_ASCENDING) && 742 (obj_desc1->integer.value > 743 obj_desc2->integer.value)) 744 || ((sort_direction == ACPI_SORT_DESCENDING) 745 && (obj_desc1->integer.value < 746 obj_desc2->integer.value))) { 747 temp_obj = elements[j - 1]; 748 elements[j - 1] = elements[j]; 749 elements[j] = temp_obj; 750 } 751 } 752 } 753 } 754