nsrepair2.c 30 KB

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