1 /****************************************************************************** 2 * 3 * Module Name: nsrepair2 - Repair for objects returned by specific 4 * predefined methods 5 * 6 *****************************************************************************/ 7 8 /* 9 * Copyright (C) 2000 - 2011, 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 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 * "ACPI####" where # is a hex digit. 475 */ 476 for (dest = new_string->string.pointer; *source; dest++, source++) { 477 *dest = (char)ACPI_TOUPPER(*source); 478 } 479 480 acpi_ut_remove_reference(return_object); 481 *return_object_ptr = new_string; 482 return (AE_OK); 483 } 484 485 /****************************************************************************** 486 * 487 * FUNCTION: acpi_ns_repair_TSS 488 * 489 * PARAMETERS: Data - Pointer to validation data structure 490 * return_object_ptr - Pointer to the object returned from the 491 * evaluation of a method or object 492 * 493 * RETURN: Status. AE_OK if object is OK or was repaired successfully 494 * 495 * DESCRIPTION: Repair for the _TSS object. If necessary, sort the object list 496 * descending by the power dissipation values. 497 * 498 *****************************************************************************/ 499 500 static acpi_status 501 acpi_ns_repair_TSS(struct acpi_predefined_data *data, 502 union acpi_operand_object **return_object_ptr) 503 { 504 union acpi_operand_object *return_object = *return_object_ptr; 505 acpi_status status; 506 507 status = acpi_ns_check_sorted_list(data, return_object, 5, 1, 508 ACPI_SORT_DESCENDING, 509 "PowerDissipation"); 510 511 return (status); 512 } 513 514 /****************************************************************************** 515 * 516 * FUNCTION: acpi_ns_repair_PSS 517 * 518 * PARAMETERS: Data - Pointer to validation data structure 519 * return_object_ptr - Pointer to the object returned from the 520 * evaluation of a method or object 521 * 522 * RETURN: Status. AE_OK if object is OK or was repaired successfully 523 * 524 * DESCRIPTION: Repair for the _PSS object. If necessary, sort the object list 525 * by the CPU frequencies. Check that the power dissipation values 526 * are all proportional to CPU frequency (i.e., sorting by 527 * frequency should be the same as sorting by power.) 528 * 529 *****************************************************************************/ 530 531 static acpi_status 532 acpi_ns_repair_PSS(struct acpi_predefined_data *data, 533 union acpi_operand_object **return_object_ptr) 534 { 535 union acpi_operand_object *return_object = *return_object_ptr; 536 union acpi_operand_object **outer_elements; 537 u32 outer_element_count; 538 union acpi_operand_object **elements; 539 union acpi_operand_object *obj_desc; 540 u32 previous_value; 541 acpi_status status; 542 u32 i; 543 544 /* 545 * Entries (sub-packages) in the _PSS Package must be sorted by power 546 * dissipation, in descending order. If it appears that the list is 547 * incorrectly sorted, sort it. We sort by cpu_frequency, since this 548 * should be proportional to the power. 549 */ 550 status = acpi_ns_check_sorted_list(data, return_object, 6, 0, 551 ACPI_SORT_DESCENDING, 552 "CpuFrequency"); 553 if (ACPI_FAILURE(status)) { 554 return (status); 555 } 556 557 /* 558 * We now know the list is correctly sorted by CPU frequency. Check if 559 * the power dissipation values are proportional. 560 */ 561 previous_value = ACPI_UINT32_MAX; 562 outer_elements = return_object->package.elements; 563 outer_element_count = return_object->package.count; 564 565 for (i = 0; i < outer_element_count; i++) { 566 elements = (*outer_elements)->package.elements; 567 obj_desc = elements[1]; /* Index1 = power_dissipation */ 568 569 if ((u32) obj_desc->integer.value > previous_value) { 570 ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, 571 data->node_flags, 572 "SubPackage[%u,%u] - suspicious power dissipation values", 573 i - 1, i)); 574 } 575 576 previous_value = (u32) obj_desc->integer.value; 577 outer_elements++; 578 } 579 580 return (AE_OK); 581 } 582 583 /****************************************************************************** 584 * 585 * FUNCTION: acpi_ns_check_sorted_list 586 * 587 * PARAMETERS: Data - Pointer to validation data structure 588 * return_object - Pointer to the top-level returned object 589 * expected_count - Minimum length of each sub-package 590 * sort_index - Sub-package entry to sort on 591 * sort_direction - Ascending or descending 592 * sort_key_name - Name of the sort_index field 593 * 594 * RETURN: Status. AE_OK if the list is valid and is sorted correctly or 595 * has been repaired by sorting the list. 596 * 597 * DESCRIPTION: Check if the package list is valid and sorted correctly by the 598 * sort_index. If not, then sort the list. 599 * 600 *****************************************************************************/ 601 602 static acpi_status 603 acpi_ns_check_sorted_list(struct acpi_predefined_data *data, 604 union acpi_operand_object *return_object, 605 u32 expected_count, 606 u32 sort_index, 607 u8 sort_direction, char *sort_key_name) 608 { 609 u32 outer_element_count; 610 union acpi_operand_object **outer_elements; 611 union acpi_operand_object **elements; 612 union acpi_operand_object *obj_desc; 613 u32 i; 614 u32 previous_value; 615 616 ACPI_FUNCTION_NAME(ns_check_sorted_list); 617 618 /* The top-level object must be a package */ 619 620 if (return_object->common.type != ACPI_TYPE_PACKAGE) { 621 return (AE_AML_OPERAND_TYPE); 622 } 623 624 /* 625 * NOTE: assumes list of sub-packages contains no NULL elements. 626 * Any NULL elements should have been removed by earlier call 627 * to acpi_ns_remove_null_elements. 628 */ 629 outer_elements = return_object->package.elements; 630 outer_element_count = return_object->package.count; 631 if (!outer_element_count) { 632 return (AE_AML_PACKAGE_LIMIT); 633 } 634 635 previous_value = 0; 636 if (sort_direction == ACPI_SORT_DESCENDING) { 637 previous_value = ACPI_UINT32_MAX; 638 } 639 640 /* Examine each subpackage */ 641 642 for (i = 0; i < outer_element_count; i++) { 643 644 /* Each element of the top-level package must also be a package */ 645 646 if ((*outer_elements)->common.type != ACPI_TYPE_PACKAGE) { 647 return (AE_AML_OPERAND_TYPE); 648 } 649 650 /* Each sub-package must have the minimum length */ 651 652 if ((*outer_elements)->package.count < expected_count) { 653 return (AE_AML_PACKAGE_LIMIT); 654 } 655 656 elements = (*outer_elements)->package.elements; 657 obj_desc = elements[sort_index]; 658 659 if (obj_desc->common.type != ACPI_TYPE_INTEGER) { 660 return (AE_AML_OPERAND_TYPE); 661 } 662 663 /* 664 * The list must be sorted in the specified order. If we detect a 665 * discrepancy, sort the entire list. 666 */ 667 if (((sort_direction == ACPI_SORT_ASCENDING) && 668 (obj_desc->integer.value < previous_value)) || 669 ((sort_direction == ACPI_SORT_DESCENDING) && 670 (obj_desc->integer.value > previous_value))) { 671 acpi_ns_sort_list(return_object->package.elements, 672 outer_element_count, sort_index, 673 sort_direction); 674 675 data->flags |= ACPI_OBJECT_REPAIRED; 676 677 ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, 678 "%s: Repaired unsorted list - now sorted by %s\n", 679 data->pathname, sort_key_name)); 680 return (AE_OK); 681 } 682 683 previous_value = (u32) obj_desc->integer.value; 684 outer_elements++; 685 } 686 687 return (AE_OK); 688 } 689 690 /****************************************************************************** 691 * 692 * FUNCTION: acpi_ns_sort_list 693 * 694 * PARAMETERS: Elements - Package object element list 695 * Count - Element count for above 696 * Index - Sort by which package element 697 * sort_direction - Ascending or Descending sort 698 * 699 * RETURN: None 700 * 701 * DESCRIPTION: Sort the objects that are in a package element list. 702 * 703 * NOTE: Assumes that all NULL elements have been removed from the package, 704 * and that all elements have been verified to be of type Integer. 705 * 706 *****************************************************************************/ 707 708 static void 709 acpi_ns_sort_list(union acpi_operand_object **elements, 710 u32 count, u32 index, u8 sort_direction) 711 { 712 union acpi_operand_object *obj_desc1; 713 union acpi_operand_object *obj_desc2; 714 union acpi_operand_object *temp_obj; 715 u32 i; 716 u32 j; 717 718 /* Simple bubble sort */ 719 720 for (i = 1; i < count; i++) { 721 for (j = (count - 1); j >= i; j--) { 722 obj_desc1 = elements[j - 1]->package.elements[index]; 723 obj_desc2 = elements[j]->package.elements[index]; 724 725 if (((sort_direction == ACPI_SORT_ASCENDING) && 726 (obj_desc1->integer.value > 727 obj_desc2->integer.value)) 728 || ((sort_direction == ACPI_SORT_DESCENDING) 729 && (obj_desc1->integer.value < 730 obj_desc2->integer.value))) { 731 temp_obj = elements[j - 1]; 732 elements[j - 1] = elements[j]; 733 elements[j] = temp_obj; 734 } 735 } 736 } 737 } 738