nsrepair2.c 29 KB

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