nsrepair2.c 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981
  1. /******************************************************************************
  2. *
  3. * Module Name: nsrepair2 - Repair for objects returned by specific
  4. * predefined methods
  5. *
  6. *****************************************************************************/
  7. /*
  8. * Copyright (C) 2000 - 2017, 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,
  260. info->full_pathname,
  261. info->node_flags,
  262. "Incorrect return buffer length %u, expected %u",
  263. return_object->buffer.length,
  264. ACPI_FDE_DWORD_BUFFER_SIZE));
  265. return (AE_AML_OPERAND_TYPE);
  266. }
  267. /* Create the new (larger) buffer object */
  268. buffer_object =
  269. acpi_ut_create_buffer_object(ACPI_FDE_DWORD_BUFFER_SIZE);
  270. if (!buffer_object) {
  271. return (AE_NO_MEMORY);
  272. }
  273. /* Expand each byte to a DWORD */
  274. byte_buffer = return_object->buffer.pointer;
  275. dword_buffer = ACPI_CAST_PTR(u32,
  276. buffer_object->buffer.pointer);
  277. for (i = 0; i < ACPI_FDE_FIELD_COUNT; i++) {
  278. *dword_buffer = (u32) *byte_buffer;
  279. dword_buffer++;
  280. byte_buffer++;
  281. }
  282. ACPI_DEBUG_PRINT((ACPI_DB_REPAIR,
  283. "%s Expanded Byte Buffer to expected DWord Buffer\n",
  284. info->full_pathname));
  285. break;
  286. default:
  287. return (AE_AML_OPERAND_TYPE);
  288. }
  289. /* Delete the original return object, return the new buffer object */
  290. acpi_ut_remove_reference(return_object);
  291. *return_object_ptr = buffer_object;
  292. info->return_flags |= ACPI_OBJECT_REPAIRED;
  293. return (AE_OK);
  294. }
  295. /******************************************************************************
  296. *
  297. * FUNCTION: acpi_ns_repair_CID
  298. *
  299. * PARAMETERS: info - Method execution information block
  300. * return_object_ptr - Pointer to the object returned from the
  301. * evaluation of a method or object
  302. *
  303. * RETURN: Status. AE_OK if object is OK or was repaired successfully
  304. *
  305. * DESCRIPTION: Repair for the _CID object. If a string, ensure that all
  306. * letters are uppercase and that there is no leading asterisk.
  307. * If a Package, ensure same for all string elements.
  308. *
  309. *****************************************************************************/
  310. static acpi_status
  311. acpi_ns_repair_CID(struct acpi_evaluate_info *info,
  312. union acpi_operand_object **return_object_ptr)
  313. {
  314. acpi_status status;
  315. union acpi_operand_object *return_object = *return_object_ptr;
  316. union acpi_operand_object **element_ptr;
  317. union acpi_operand_object *original_element;
  318. u16 original_ref_count;
  319. u32 i;
  320. /* Check for _CID as a simple string */
  321. if (return_object->common.type == ACPI_TYPE_STRING) {
  322. status = acpi_ns_repair_HID(info, return_object_ptr);
  323. return (status);
  324. }
  325. /* Exit if not a Package */
  326. if (return_object->common.type != ACPI_TYPE_PACKAGE) {
  327. return (AE_OK);
  328. }
  329. /* Examine each element of the _CID package */
  330. element_ptr = return_object->package.elements;
  331. for (i = 0; i < return_object->package.count; i++) {
  332. original_element = *element_ptr;
  333. original_ref_count = original_element->common.reference_count;
  334. status = acpi_ns_repair_HID(info, element_ptr);
  335. if (ACPI_FAILURE(status)) {
  336. return (status);
  337. }
  338. if (original_element != *element_ptr) {
  339. /* Update reference count of new object */
  340. (*element_ptr)->common.reference_count =
  341. original_ref_count;
  342. }
  343. element_ptr++;
  344. }
  345. return (AE_OK);
  346. }
  347. /******************************************************************************
  348. *
  349. * FUNCTION: acpi_ns_repair_CST
  350. *
  351. * PARAMETERS: info - Method execution information block
  352. * return_object_ptr - Pointer to the object returned from the
  353. * evaluation of a method or object
  354. *
  355. * RETURN: Status. AE_OK if object is OK or was repaired successfully
  356. *
  357. * DESCRIPTION: Repair for the _CST object:
  358. * 1. Sort the list ascending by C state type
  359. * 2. Ensure type cannot be zero
  360. * 3. A subpackage count of zero means _CST is meaningless
  361. * 4. Count must match the number of C state subpackages
  362. *
  363. *****************************************************************************/
  364. static acpi_status
  365. acpi_ns_repair_CST(struct acpi_evaluate_info *info,
  366. union acpi_operand_object **return_object_ptr)
  367. {
  368. union acpi_operand_object *return_object = *return_object_ptr;
  369. union acpi_operand_object **outer_elements;
  370. u32 outer_element_count;
  371. union acpi_operand_object *obj_desc;
  372. acpi_status status;
  373. u8 removing;
  374. u32 i;
  375. ACPI_FUNCTION_NAME(ns_repair_CST);
  376. /*
  377. * Check if the C-state type values are proportional.
  378. */
  379. outer_element_count = return_object->package.count - 1;
  380. i = 0;
  381. while (i < outer_element_count) {
  382. outer_elements = &return_object->package.elements[i + 1];
  383. removing = FALSE;
  384. if ((*outer_elements)->package.count == 0) {
  385. ACPI_WARN_PREDEFINED((AE_INFO,
  386. 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,
  396. info->full_pathname,
  397. info->node_flags,
  398. "SubPackage[%u] - removing entry due to invalid Type(0)",
  399. i));
  400. removing = TRUE;
  401. }
  402. remove_element:
  403. if (removing) {
  404. acpi_ns_remove_element(return_object, i + 1);
  405. outer_element_count--;
  406. } else {
  407. i++;
  408. }
  409. }
  410. /* Update top-level package count, Type "Integer" checked elsewhere */
  411. obj_desc = return_object->package.elements[0];
  412. obj_desc->integer.value = outer_element_count;
  413. /*
  414. * Entries (subpackages) in the _CST Package must be sorted by the
  415. * C-state type, in ascending order.
  416. */
  417. status = acpi_ns_check_sorted_list(info, return_object, 1, 4, 1,
  418. ACPI_SORT_ASCENDING, "C-State Type");
  419. if (ACPI_FAILURE(status)) {
  420. return (status);
  421. }
  422. return (AE_OK);
  423. }
  424. /******************************************************************************
  425. *
  426. * FUNCTION: acpi_ns_repair_HID
  427. *
  428. * PARAMETERS: info - Method execution information block
  429. * return_object_ptr - Pointer to the object returned from the
  430. * evaluation of a method or object
  431. *
  432. * RETURN: Status. AE_OK if object is OK or was repaired successfully
  433. *
  434. * DESCRIPTION: Repair for the _HID object. If a string, ensure that all
  435. * letters are uppercase and that there is no leading asterisk.
  436. *
  437. *****************************************************************************/
  438. static acpi_status
  439. acpi_ns_repair_HID(struct acpi_evaluate_info *info,
  440. union acpi_operand_object **return_object_ptr)
  441. {
  442. union acpi_operand_object *return_object = *return_object_ptr;
  443. union acpi_operand_object *new_string;
  444. char *source;
  445. char *dest;
  446. ACPI_FUNCTION_NAME(ns_repair_HID);
  447. /* We only care about string _HID objects (not integers) */
  448. if (return_object->common.type != ACPI_TYPE_STRING) {
  449. return (AE_OK);
  450. }
  451. if (return_object->string.length == 0) {
  452. ACPI_WARN_PREDEFINED((AE_INFO,
  453. info->full_pathname, info->node_flags,
  454. "Invalid zero-length _HID or _CID string"));
  455. /* Return AE_OK anyway, let driver handle it */
  456. info->return_flags |= ACPI_OBJECT_REPAIRED;
  457. return (AE_OK);
  458. }
  459. /* It is simplest to always create a new string object */
  460. new_string = acpi_ut_create_string_object(return_object->string.length);
  461. if (!new_string) {
  462. return (AE_NO_MEMORY);
  463. }
  464. /*
  465. * Remove a leading asterisk if present. For some unknown reason, there
  466. * are many machines in the field that contains IDs like this.
  467. *
  468. * Examples: "*PNP0C03", "*ACPI0003"
  469. */
  470. source = return_object->string.pointer;
  471. if (*source == '*') {
  472. source++;
  473. new_string->string.length--;
  474. ACPI_DEBUG_PRINT((ACPI_DB_REPAIR,
  475. "%s: Removed invalid leading asterisk\n",
  476. info->full_pathname));
  477. }
  478. /*
  479. * Copy and uppercase the string. From the ACPI 5.0 specification:
  480. *
  481. * A valid PNP ID must be of the form "AAA####" where A is an uppercase
  482. * letter and # is a hex digit. A valid ACPI ID must be of the form
  483. * "NNNN####" where N is an uppercase letter or decimal digit, and
  484. * # is a hex digit.
  485. */
  486. for (dest = new_string->string.pointer; *source; dest++, source++) {
  487. *dest = (char)toupper((int)*source);
  488. }
  489. acpi_ut_remove_reference(return_object);
  490. *return_object_ptr = new_string;
  491. return (AE_OK);
  492. }
  493. /******************************************************************************
  494. *
  495. * FUNCTION: acpi_ns_repair_PRT
  496. *
  497. * PARAMETERS: info - Method execution information block
  498. * return_object_ptr - Pointer to the object returned from the
  499. * evaluation of a method or object
  500. *
  501. * RETURN: Status. AE_OK if object is OK or was repaired successfully
  502. *
  503. * DESCRIPTION: Repair for the _PRT object. If necessary, fix reversed
  504. * source_name and source_index field, a common BIOS bug.
  505. *
  506. *****************************************************************************/
  507. static acpi_status
  508. acpi_ns_repair_PRT(struct acpi_evaluate_info *info,
  509. union acpi_operand_object **return_object_ptr)
  510. {
  511. union acpi_operand_object *package_object = *return_object_ptr;
  512. union acpi_operand_object **top_object_list;
  513. union acpi_operand_object **sub_object_list;
  514. union acpi_operand_object *obj_desc;
  515. union acpi_operand_object *sub_package;
  516. u32 element_count;
  517. u32 index;
  518. /* Each element in the _PRT package is a subpackage */
  519. top_object_list = package_object->package.elements;
  520. element_count = package_object->package.count;
  521. /* Examine each subpackage */
  522. for (index = 0; index < element_count; index++, top_object_list++) {
  523. sub_package = *top_object_list;
  524. sub_object_list = sub_package->package.elements;
  525. /* Check for minimum required element count */
  526. if (sub_package->package.count < 4) {
  527. continue;
  528. }
  529. /*
  530. * If the BIOS has erroneously reversed the _PRT source_name (index 2)
  531. * and the source_index (index 3), fix it. _PRT is important enough to
  532. * workaround this BIOS error. This also provides compatibility with
  533. * other ACPI implementations.
  534. */
  535. obj_desc = sub_object_list[3];
  536. if (!obj_desc || (obj_desc->common.type != ACPI_TYPE_INTEGER)) {
  537. sub_object_list[3] = sub_object_list[2];
  538. sub_object_list[2] = obj_desc;
  539. info->return_flags |= ACPI_OBJECT_REPAIRED;
  540. ACPI_WARN_PREDEFINED((AE_INFO,
  541. info->full_pathname,
  542. info->node_flags,
  543. "PRT[%X]: Fixed reversed SourceName and SourceIndex",
  544. index));
  545. }
  546. }
  547. return (AE_OK);
  548. }
  549. /******************************************************************************
  550. *
  551. * FUNCTION: acpi_ns_repair_PSS
  552. *
  553. * PARAMETERS: info - Method execution information block
  554. * return_object_ptr - Pointer to the object returned from the
  555. * evaluation of a method or object
  556. *
  557. * RETURN: Status. AE_OK if object is OK or was repaired successfully
  558. *
  559. * DESCRIPTION: Repair for the _PSS object. If necessary, sort the object list
  560. * by the CPU frequencies. Check that the power dissipation values
  561. * are all proportional to CPU frequency (i.e., sorting by
  562. * frequency should be the same as sorting by power.)
  563. *
  564. *****************************************************************************/
  565. static acpi_status
  566. acpi_ns_repair_PSS(struct acpi_evaluate_info *info,
  567. union acpi_operand_object **return_object_ptr)
  568. {
  569. union acpi_operand_object *return_object = *return_object_ptr;
  570. union acpi_operand_object **outer_elements;
  571. u32 outer_element_count;
  572. union acpi_operand_object **elements;
  573. union acpi_operand_object *obj_desc;
  574. u32 previous_value;
  575. acpi_status status;
  576. u32 i;
  577. /*
  578. * Entries (subpackages) in the _PSS Package must be sorted by power
  579. * dissipation, in descending order. If it appears that the list is
  580. * incorrectly sorted, sort it. We sort by cpu_frequency, since this
  581. * should be proportional to the power.
  582. */
  583. status = acpi_ns_check_sorted_list(info, return_object, 0, 6, 0,
  584. ACPI_SORT_DESCENDING,
  585. "CpuFrequency");
  586. if (ACPI_FAILURE(status)) {
  587. return (status);
  588. }
  589. /*
  590. * We now know the list is correctly sorted by CPU frequency. Check if
  591. * the power dissipation values are proportional.
  592. */
  593. previous_value = ACPI_UINT32_MAX;
  594. outer_elements = return_object->package.elements;
  595. outer_element_count = return_object->package.count;
  596. for (i = 0; i < outer_element_count; i++) {
  597. elements = (*outer_elements)->package.elements;
  598. obj_desc = elements[1]; /* Index1 = power_dissipation */
  599. if ((u32)obj_desc->integer.value > previous_value) {
  600. ACPI_WARN_PREDEFINED((AE_INFO,
  601. info->full_pathname,
  602. info->node_flags,
  603. "SubPackage[%u,%u] - suspicious power dissipation values",
  604. i - 1, i));
  605. }
  606. previous_value = (u32) obj_desc->integer.value;
  607. outer_elements++;
  608. }
  609. return (AE_OK);
  610. }
  611. /******************************************************************************
  612. *
  613. * FUNCTION: acpi_ns_repair_TSS
  614. *
  615. * PARAMETERS: info - Method execution information block
  616. * return_object_ptr - Pointer to the object returned from the
  617. * evaluation of a method or object
  618. *
  619. * RETURN: Status. AE_OK if object is OK or was repaired successfully
  620. *
  621. * DESCRIPTION: Repair for the _TSS object. If necessary, sort the object list
  622. * descending by the power dissipation values.
  623. *
  624. *****************************************************************************/
  625. static acpi_status
  626. acpi_ns_repair_TSS(struct acpi_evaluate_info *info,
  627. union acpi_operand_object **return_object_ptr)
  628. {
  629. union acpi_operand_object *return_object = *return_object_ptr;
  630. acpi_status status;
  631. struct acpi_namespace_node *node;
  632. /*
  633. * We can only sort the _TSS return package if there is no _PSS in the
  634. * same scope. This is because if _PSS is present, the ACPI specification
  635. * dictates that the _TSS Power Dissipation field is to be ignored, and
  636. * therefore some BIOSs leave garbage values in the _TSS Power field(s).
  637. * In this case, it is best to just return the _TSS package as-is.
  638. * (May, 2011)
  639. */
  640. status = acpi_ns_get_node(info->node, "^_PSS",
  641. ACPI_NS_NO_UPSEARCH, &node);
  642. if (ACPI_SUCCESS(status)) {
  643. return (AE_OK);
  644. }
  645. status = acpi_ns_check_sorted_list(info, return_object, 0, 5, 1,
  646. ACPI_SORT_DESCENDING,
  647. "PowerDissipation");
  648. return (status);
  649. }
  650. /******************************************************************************
  651. *
  652. * FUNCTION: acpi_ns_check_sorted_list
  653. *
  654. * PARAMETERS: info - Method execution information block
  655. * return_object - Pointer to the top-level returned object
  656. * start_index - Index of the first subpackage
  657. * expected_count - Minimum length of each subpackage
  658. * sort_index - Subpackage entry to sort on
  659. * sort_direction - Ascending or descending
  660. * sort_key_name - Name of the sort_index field
  661. *
  662. * RETURN: Status. AE_OK if the list is valid and is sorted correctly or
  663. * has been repaired by sorting the list.
  664. *
  665. * DESCRIPTION: Check if the package list is valid and sorted correctly by the
  666. * sort_index. If not, then sort the list.
  667. *
  668. *****************************************************************************/
  669. static acpi_status
  670. acpi_ns_check_sorted_list(struct acpi_evaluate_info *info,
  671. union acpi_operand_object *return_object,
  672. u32 start_index,
  673. u32 expected_count,
  674. u32 sort_index,
  675. u8 sort_direction, char *sort_key_name)
  676. {
  677. u32 outer_element_count;
  678. union acpi_operand_object **outer_elements;
  679. union acpi_operand_object **elements;
  680. union acpi_operand_object *obj_desc;
  681. u32 i;
  682. u32 previous_value;
  683. ACPI_FUNCTION_NAME(ns_check_sorted_list);
  684. /* The top-level object must be a package */
  685. if (return_object->common.type != ACPI_TYPE_PACKAGE) {
  686. return (AE_AML_OPERAND_TYPE);
  687. }
  688. /*
  689. * NOTE: assumes list of subpackages contains no NULL elements.
  690. * Any NULL elements should have been removed by earlier call
  691. * to acpi_ns_remove_null_elements.
  692. */
  693. outer_element_count = return_object->package.count;
  694. if (!outer_element_count || start_index >= outer_element_count) {
  695. return (AE_AML_PACKAGE_LIMIT);
  696. }
  697. outer_elements = &return_object->package.elements[start_index];
  698. outer_element_count -= start_index;
  699. previous_value = 0;
  700. if (sort_direction == ACPI_SORT_DESCENDING) {
  701. previous_value = ACPI_UINT32_MAX;
  702. }
  703. /* Examine each subpackage */
  704. for (i = 0; i < outer_element_count; i++) {
  705. /* Each element of the top-level package must also be a package */
  706. if ((*outer_elements)->common.type != ACPI_TYPE_PACKAGE) {
  707. return (AE_AML_OPERAND_TYPE);
  708. }
  709. /* Each subpackage must have the minimum length */
  710. if ((*outer_elements)->package.count < expected_count) {
  711. return (AE_AML_PACKAGE_LIMIT);
  712. }
  713. elements = (*outer_elements)->package.elements;
  714. obj_desc = elements[sort_index];
  715. if (obj_desc->common.type != ACPI_TYPE_INTEGER) {
  716. return (AE_AML_OPERAND_TYPE);
  717. }
  718. /*
  719. * The list must be sorted in the specified order. If we detect a
  720. * discrepancy, sort the entire list.
  721. */
  722. if (((sort_direction == ACPI_SORT_ASCENDING) &&
  723. (obj_desc->integer.value < previous_value)) ||
  724. ((sort_direction == ACPI_SORT_DESCENDING) &&
  725. (obj_desc->integer.value > previous_value))) {
  726. acpi_ns_sort_list(&return_object->package.
  727. elements[start_index],
  728. outer_element_count, sort_index,
  729. sort_direction);
  730. info->return_flags |= ACPI_OBJECT_REPAIRED;
  731. ACPI_DEBUG_PRINT((ACPI_DB_REPAIR,
  732. "%s: Repaired unsorted list - now sorted by %s\n",
  733. info->full_pathname, sort_key_name));
  734. return (AE_OK);
  735. }
  736. previous_value = (u32) obj_desc->integer.value;
  737. outer_elements++;
  738. }
  739. return (AE_OK);
  740. }
  741. /******************************************************************************
  742. *
  743. * FUNCTION: acpi_ns_sort_list
  744. *
  745. * PARAMETERS: elements - Package object element list
  746. * count - Element count for above
  747. * index - Sort by which package element
  748. * sort_direction - Ascending or Descending sort
  749. *
  750. * RETURN: None
  751. *
  752. * DESCRIPTION: Sort the objects that are in a package element list.
  753. *
  754. * NOTE: Assumes that all NULL elements have been removed from the package,
  755. * and that all elements have been verified to be of type Integer.
  756. *
  757. *****************************************************************************/
  758. static void
  759. acpi_ns_sort_list(union acpi_operand_object **elements,
  760. u32 count, u32 index, u8 sort_direction)
  761. {
  762. union acpi_operand_object *obj_desc1;
  763. union acpi_operand_object *obj_desc2;
  764. union acpi_operand_object *temp_obj;
  765. u32 i;
  766. u32 j;
  767. /* Simple bubble sort */
  768. for (i = 1; i < count; i++) {
  769. for (j = (count - 1); j >= i; j--) {
  770. obj_desc1 = elements[j - 1]->package.elements[index];
  771. obj_desc2 = elements[j]->package.elements[index];
  772. if (((sort_direction == ACPI_SORT_ASCENDING) &&
  773. (obj_desc1->integer.value >
  774. obj_desc2->integer.value))
  775. || ((sort_direction == ACPI_SORT_DESCENDING)
  776. && (obj_desc1->integer.value <
  777. obj_desc2->integer.value))) {
  778. temp_obj = elements[j - 1];
  779. elements[j - 1] = elements[j];
  780. elements[j] = temp_obj;
  781. }
  782. }
  783. }
  784. }
  785. /******************************************************************************
  786. *
  787. * FUNCTION: acpi_ns_remove_element
  788. *
  789. * PARAMETERS: obj_desc - Package object element list
  790. * index - Index of element to remove
  791. *
  792. * RETURN: None
  793. *
  794. * DESCRIPTION: Remove the requested element of a package and delete it.
  795. *
  796. *****************************************************************************/
  797. static void
  798. acpi_ns_remove_element(union acpi_operand_object *obj_desc, u32 index)
  799. {
  800. union acpi_operand_object **source;
  801. union acpi_operand_object **dest;
  802. u32 count;
  803. u32 new_count;
  804. u32 i;
  805. ACPI_FUNCTION_NAME(ns_remove_element);
  806. count = obj_desc->package.count;
  807. new_count = count - 1;
  808. source = obj_desc->package.elements;
  809. dest = source;
  810. /* Examine all elements of the package object, remove matched index */
  811. for (i = 0; i < count; i++) {
  812. if (i == index) {
  813. acpi_ut_remove_reference(*source); /* Remove one ref for being in pkg */
  814. acpi_ut_remove_reference(*source);
  815. } else {
  816. *dest = *source;
  817. dest++;
  818. }
  819. source++;
  820. }
  821. /* NULL terminate list and update the package count */
  822. *dest = NULL;
  823. obj_desc->package.count = new_count;
  824. }