nsrepair2.c 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979
  1. /******************************************************************************
  2. *
  3. * Module Name: nsrepair2 - Repair for objects returned by specific
  4. * predefined methods
  5. *
  6. *****************************************************************************/
  7. /*
  8. * Copyright (C) 2000 - 2015, 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 subpackage count of zero means _CST is meaningless
  362. * 4. Count must match the number of C state subpackages
  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)toupper((int)*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. union acpi_operand_object *sub_package;
  515. u32 element_count;
  516. u32 index;
  517. /* Each element in the _PRT package is a subpackage */
  518. top_object_list = package_object->package.elements;
  519. element_count = package_object->package.count;
  520. /* Examine each subpackage */
  521. for (index = 0; index < element_count; index++, top_object_list++) {
  522. sub_package = *top_object_list;
  523. sub_object_list = sub_package->package.elements;
  524. /* Check for minimum required element count */
  525. if (sub_package->package.count < 4) {
  526. continue;
  527. }
  528. /*
  529. * If the BIOS has erroneously reversed the _PRT source_name (index 2)
  530. * and the source_index (index 3), fix it. _PRT is important enough to
  531. * workaround this BIOS error. This also provides compatibility with
  532. * other ACPI implementations.
  533. */
  534. obj_desc = sub_object_list[3];
  535. if (!obj_desc || (obj_desc->common.type != ACPI_TYPE_INTEGER)) {
  536. sub_object_list[3] = sub_object_list[2];
  537. sub_object_list[2] = obj_desc;
  538. info->return_flags |= ACPI_OBJECT_REPAIRED;
  539. ACPI_WARN_PREDEFINED((AE_INFO,
  540. info->full_pathname,
  541. info->node_flags,
  542. "PRT[%X]: Fixed reversed SourceName and SourceIndex",
  543. index));
  544. }
  545. }
  546. return (AE_OK);
  547. }
  548. /******************************************************************************
  549. *
  550. * FUNCTION: acpi_ns_repair_PSS
  551. *
  552. * PARAMETERS: info - Method execution information block
  553. * return_object_ptr - Pointer to the object returned from the
  554. * evaluation of a method or object
  555. *
  556. * RETURN: Status. AE_OK if object is OK or was repaired successfully
  557. *
  558. * DESCRIPTION: Repair for the _PSS object. If necessary, sort the object list
  559. * by the CPU frequencies. Check that the power dissipation values
  560. * are all proportional to CPU frequency (i.e., sorting by
  561. * frequency should be the same as sorting by power.)
  562. *
  563. *****************************************************************************/
  564. static acpi_status
  565. acpi_ns_repair_PSS(struct acpi_evaluate_info *info,
  566. union acpi_operand_object **return_object_ptr)
  567. {
  568. union acpi_operand_object *return_object = *return_object_ptr;
  569. union acpi_operand_object **outer_elements;
  570. u32 outer_element_count;
  571. union acpi_operand_object **elements;
  572. union acpi_operand_object *obj_desc;
  573. u32 previous_value;
  574. acpi_status status;
  575. u32 i;
  576. /*
  577. * Entries (subpackages) in the _PSS Package must be sorted by power
  578. * dissipation, in descending order. If it appears that the list is
  579. * incorrectly sorted, sort it. We sort by cpu_frequency, since this
  580. * should be proportional to the power.
  581. */
  582. status = acpi_ns_check_sorted_list(info, return_object, 0, 6, 0,
  583. ACPI_SORT_DESCENDING,
  584. "CpuFrequency");
  585. if (ACPI_FAILURE(status)) {
  586. return (status);
  587. }
  588. /*
  589. * We now know the list is correctly sorted by CPU frequency. Check if
  590. * the power dissipation values are proportional.
  591. */
  592. previous_value = ACPI_UINT32_MAX;
  593. outer_elements = return_object->package.elements;
  594. outer_element_count = return_object->package.count;
  595. for (i = 0; i < outer_element_count; i++) {
  596. elements = (*outer_elements)->package.elements;
  597. obj_desc = elements[1]; /* Index1 = power_dissipation */
  598. if ((u32) obj_desc->integer.value > previous_value) {
  599. ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname,
  600. info->node_flags,
  601. "SubPackage[%u,%u] - suspicious power dissipation values",
  602. i - 1, i));
  603. }
  604. previous_value = (u32) obj_desc->integer.value;
  605. outer_elements++;
  606. }
  607. return (AE_OK);
  608. }
  609. /******************************************************************************
  610. *
  611. * FUNCTION: acpi_ns_repair_TSS
  612. *
  613. * PARAMETERS: info - Method execution information block
  614. * return_object_ptr - Pointer to the object returned from the
  615. * evaluation of a method or object
  616. *
  617. * RETURN: Status. AE_OK if object is OK or was repaired successfully
  618. *
  619. * DESCRIPTION: Repair for the _TSS object. If necessary, sort the object list
  620. * descending by the power dissipation values.
  621. *
  622. *****************************************************************************/
  623. static acpi_status
  624. acpi_ns_repair_TSS(struct acpi_evaluate_info *info,
  625. union acpi_operand_object **return_object_ptr)
  626. {
  627. union acpi_operand_object *return_object = *return_object_ptr;
  628. acpi_status status;
  629. struct acpi_namespace_node *node;
  630. /*
  631. * We can only sort the _TSS return package if there is no _PSS in the
  632. * same scope. This is because if _PSS is present, the ACPI specification
  633. * dictates that the _TSS Power Dissipation field is to be ignored, and
  634. * therefore some BIOSs leave garbage values in the _TSS Power field(s).
  635. * In this case, it is best to just return the _TSS package as-is.
  636. * (May, 2011)
  637. */
  638. status = acpi_ns_get_node(info->node, "^_PSS",
  639. ACPI_NS_NO_UPSEARCH, &node);
  640. if (ACPI_SUCCESS(status)) {
  641. return (AE_OK);
  642. }
  643. status = acpi_ns_check_sorted_list(info, return_object, 0, 5, 1,
  644. ACPI_SORT_DESCENDING,
  645. "PowerDissipation");
  646. return (status);
  647. }
  648. /******************************************************************************
  649. *
  650. * FUNCTION: acpi_ns_check_sorted_list
  651. *
  652. * PARAMETERS: info - Method execution information block
  653. * return_object - Pointer to the top-level returned object
  654. * start_index - Index of the first subpackage
  655. * expected_count - Minimum length of each subpackage
  656. * sort_index - Subpackage entry to sort on
  657. * sort_direction - Ascending or descending
  658. * sort_key_name - Name of the sort_index field
  659. *
  660. * RETURN: Status. AE_OK if the list is valid and is sorted correctly or
  661. * has been repaired by sorting the list.
  662. *
  663. * DESCRIPTION: Check if the package list is valid and sorted correctly by the
  664. * sort_index. If not, then sort the list.
  665. *
  666. *****************************************************************************/
  667. static acpi_status
  668. acpi_ns_check_sorted_list(struct acpi_evaluate_info *info,
  669. union acpi_operand_object *return_object,
  670. u32 start_index,
  671. u32 expected_count,
  672. u32 sort_index,
  673. u8 sort_direction, char *sort_key_name)
  674. {
  675. u32 outer_element_count;
  676. union acpi_operand_object **outer_elements;
  677. union acpi_operand_object **elements;
  678. union acpi_operand_object *obj_desc;
  679. u32 i;
  680. u32 previous_value;
  681. ACPI_FUNCTION_NAME(ns_check_sorted_list);
  682. /* The top-level object must be a package */
  683. if (return_object->common.type != ACPI_TYPE_PACKAGE) {
  684. return (AE_AML_OPERAND_TYPE);
  685. }
  686. /*
  687. * NOTE: assumes list of subpackages contains no NULL elements.
  688. * Any NULL elements should have been removed by earlier call
  689. * to acpi_ns_remove_null_elements.
  690. */
  691. outer_element_count = return_object->package.count;
  692. if (!outer_element_count || start_index >= outer_element_count) {
  693. return (AE_AML_PACKAGE_LIMIT);
  694. }
  695. outer_elements = &return_object->package.elements[start_index];
  696. outer_element_count -= start_index;
  697. previous_value = 0;
  698. if (sort_direction == ACPI_SORT_DESCENDING) {
  699. previous_value = ACPI_UINT32_MAX;
  700. }
  701. /* Examine each subpackage */
  702. for (i = 0; i < outer_element_count; i++) {
  703. /* Each element of the top-level package must also be a package */
  704. if ((*outer_elements)->common.type != ACPI_TYPE_PACKAGE) {
  705. return (AE_AML_OPERAND_TYPE);
  706. }
  707. /* Each subpackage must have the minimum length */
  708. if ((*outer_elements)->package.count < expected_count) {
  709. return (AE_AML_PACKAGE_LIMIT);
  710. }
  711. elements = (*outer_elements)->package.elements;
  712. obj_desc = elements[sort_index];
  713. if (obj_desc->common.type != ACPI_TYPE_INTEGER) {
  714. return (AE_AML_OPERAND_TYPE);
  715. }
  716. /*
  717. * The list must be sorted in the specified order. If we detect a
  718. * discrepancy, sort the entire list.
  719. */
  720. if (((sort_direction == ACPI_SORT_ASCENDING) &&
  721. (obj_desc->integer.value < previous_value)) ||
  722. ((sort_direction == ACPI_SORT_DESCENDING) &&
  723. (obj_desc->integer.value > previous_value))) {
  724. acpi_ns_sort_list(&return_object->package.
  725. elements[start_index],
  726. outer_element_count, sort_index,
  727. sort_direction);
  728. info->return_flags |= ACPI_OBJECT_REPAIRED;
  729. ACPI_DEBUG_PRINT((ACPI_DB_REPAIR,
  730. "%s: Repaired unsorted list - now sorted by %s\n",
  731. info->full_pathname, sort_key_name));
  732. return (AE_OK);
  733. }
  734. previous_value = (u32) obj_desc->integer.value;
  735. outer_elements++;
  736. }
  737. return (AE_OK);
  738. }
  739. /******************************************************************************
  740. *
  741. * FUNCTION: acpi_ns_sort_list
  742. *
  743. * PARAMETERS: elements - Package object element list
  744. * count - Element count for above
  745. * index - Sort by which package element
  746. * sort_direction - Ascending or Descending sort
  747. *
  748. * RETURN: None
  749. *
  750. * DESCRIPTION: Sort the objects that are in a package element list.
  751. *
  752. * NOTE: Assumes that all NULL elements have been removed from the package,
  753. * and that all elements have been verified to be of type Integer.
  754. *
  755. *****************************************************************************/
  756. static void
  757. acpi_ns_sort_list(union acpi_operand_object **elements,
  758. u32 count, u32 index, u8 sort_direction)
  759. {
  760. union acpi_operand_object *obj_desc1;
  761. union acpi_operand_object *obj_desc2;
  762. union acpi_operand_object *temp_obj;
  763. u32 i;
  764. u32 j;
  765. /* Simple bubble sort */
  766. for (i = 1; i < count; i++) {
  767. for (j = (count - 1); j >= i; j--) {
  768. obj_desc1 = elements[j - 1]->package.elements[index];
  769. obj_desc2 = elements[j]->package.elements[index];
  770. if (((sort_direction == ACPI_SORT_ASCENDING) &&
  771. (obj_desc1->integer.value >
  772. obj_desc2->integer.value))
  773. || ((sort_direction == ACPI_SORT_DESCENDING)
  774. && (obj_desc1->integer.value <
  775. obj_desc2->integer.value))) {
  776. temp_obj = elements[j - 1];
  777. elements[j - 1] = elements[j];
  778. elements[j] = temp_obj;
  779. }
  780. }
  781. }
  782. }
  783. /******************************************************************************
  784. *
  785. * FUNCTION: acpi_ns_remove_element
  786. *
  787. * PARAMETERS: obj_desc - Package object element list
  788. * index - Index of element to remove
  789. *
  790. * RETURN: None
  791. *
  792. * DESCRIPTION: Remove the requested element of a package and delete it.
  793. *
  794. *****************************************************************************/
  795. static void
  796. acpi_ns_remove_element(union acpi_operand_object *obj_desc, u32 index)
  797. {
  798. union acpi_operand_object **source;
  799. union acpi_operand_object **dest;
  800. u32 count;
  801. u32 new_count;
  802. u32 i;
  803. ACPI_FUNCTION_NAME(ns_remove_element);
  804. count = obj_desc->package.count;
  805. new_count = count - 1;
  806. source = obj_desc->package.elements;
  807. dest = source;
  808. /* Examine all elements of the package object, remove matched index */
  809. for (i = 0; i < count; i++) {
  810. if (i == index) {
  811. acpi_ut_remove_reference(*source); /* Remove one ref for being in pkg */
  812. acpi_ut_remove_reference(*source);
  813. } else {
  814. *dest = *source;
  815. dest++;
  816. }
  817. source++;
  818. }
  819. /* NULL terminate list and update the package count */
  820. *dest = NULL;
  821. obj_desc->package.count = new_count;
  822. }