nsrepair2.c 30 KB

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