1
1

exmisc.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534
  1. /******************************************************************************
  2. *
  3. * Module Name: exmisc - ACPI AML (p-code) execution - specific opcodes
  4. *
  5. *****************************************************************************/
  6. /*
  7. * Copyright (C) 2000 - 2019, Intel Corp.
  8. * All rights reserved.
  9. *
  10. * Redistribution and use in source and binary forms, with or without
  11. * modification, are permitted provided that the following conditions
  12. * are met:
  13. * 1. Redistributions of source code must retain the above copyright
  14. * notice, this list of conditions, and the following disclaimer,
  15. * without modification.
  16. * 2. Redistributions in binary form must reproduce at minimum a disclaimer
  17. * substantially similar to the "NO WARRANTY" disclaimer below
  18. * ("Disclaimer") and any redistribution must be conditioned upon
  19. * including a substantially similar Disclaimer requirement for further
  20. * binary redistribution.
  21. * 3. Neither the names of the above-listed copyright holders nor the names
  22. * of any contributors may be used to endorse or promote products derived
  23. * from this software without specific prior written permission.
  24. *
  25. * Alternatively, this software may be distributed under the terms of the
  26. * GNU General Public License ("GPL") version 2 as published by the Free
  27. * Software Foundation.
  28. *
  29. * NO WARRANTY
  30. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  31. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  32. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
  33. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  34. * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  35. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  36. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  37. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  38. * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
  39. * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  40. * POSSIBILITY OF SUCH DAMAGES.
  41. */
  42. #include "acpi.h"
  43. #include "accommon.h"
  44. #include "acinterp.h"
  45. #include "amlcode.h"
  46. #define _COMPONENT ACPI_EXECUTER
  47. ACPI_MODULE_NAME ("exmisc")
  48. /*******************************************************************************
  49. *
  50. * FUNCTION: AcpiExGetObjectReference
  51. *
  52. * PARAMETERS: ObjDesc - Create a reference to this object
  53. * ReturnDesc - Where to store the reference
  54. * WalkState - Current state
  55. *
  56. * RETURN: Status
  57. *
  58. * DESCRIPTION: Obtain and return a "reference" to the target object
  59. * Common code for the RefOfOp and the CondRefOfOp.
  60. *
  61. ******************************************************************************/
  62. ACPI_STATUS
  63. AcpiExGetObjectReference (
  64. ACPI_OPERAND_OBJECT *ObjDesc,
  65. ACPI_OPERAND_OBJECT **ReturnDesc,
  66. ACPI_WALK_STATE *WalkState)
  67. {
  68. ACPI_OPERAND_OBJECT *ReferenceObj;
  69. ACPI_OPERAND_OBJECT *ReferencedObj;
  70. ACPI_FUNCTION_TRACE_PTR (ExGetObjectReference, ObjDesc);
  71. *ReturnDesc = NULL;
  72. switch (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc))
  73. {
  74. case ACPI_DESC_TYPE_OPERAND:
  75. if (ObjDesc->Common.Type != ACPI_TYPE_LOCAL_REFERENCE)
  76. {
  77. return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
  78. }
  79. /*
  80. * Must be a reference to a Local or Arg
  81. */
  82. switch (ObjDesc->Reference.Class)
  83. {
  84. case ACPI_REFCLASS_LOCAL:
  85. case ACPI_REFCLASS_ARG:
  86. case ACPI_REFCLASS_DEBUG:
  87. /* The referenced object is the pseudo-node for the local/arg */
  88. ReferencedObj = ObjDesc->Reference.Object;
  89. break;
  90. default:
  91. ACPI_ERROR ((AE_INFO, "Invalid Reference Class 0x%2.2X",
  92. ObjDesc->Reference.Class));
  93. return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
  94. }
  95. break;
  96. case ACPI_DESC_TYPE_NAMED:
  97. /*
  98. * A named reference that has already been resolved to a Node
  99. */
  100. ReferencedObj = ObjDesc;
  101. break;
  102. default:
  103. ACPI_ERROR ((AE_INFO, "Invalid descriptor type 0x%X",
  104. ACPI_GET_DESCRIPTOR_TYPE (ObjDesc)));
  105. return_ACPI_STATUS (AE_TYPE);
  106. }
  107. /* Create a new reference object */
  108. ReferenceObj = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_REFERENCE);
  109. if (!ReferenceObj)
  110. {
  111. return_ACPI_STATUS (AE_NO_MEMORY);
  112. }
  113. ReferenceObj->Reference.Class = ACPI_REFCLASS_REFOF;
  114. ReferenceObj->Reference.Object = ReferencedObj;
  115. *ReturnDesc = ReferenceObj;
  116. ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
  117. "Object %p Type [%s], returning Reference %p\n",
  118. ObjDesc, AcpiUtGetObjectTypeName (ObjDesc), *ReturnDesc));
  119. return_ACPI_STATUS (AE_OK);
  120. }
  121. /*******************************************************************************
  122. *
  123. * FUNCTION: AcpiExDoMathOp
  124. *
  125. * PARAMETERS: Opcode - AML opcode
  126. * Integer0 - Integer operand #0
  127. * Integer1 - Integer operand #1
  128. *
  129. * RETURN: Integer result of the operation
  130. *
  131. * DESCRIPTION: Execute a math AML opcode. The purpose of having all of the
  132. * math functions here is to prevent a lot of pointer dereferencing
  133. * to obtain the operands.
  134. *
  135. ******************************************************************************/
  136. UINT64
  137. AcpiExDoMathOp (
  138. UINT16 Opcode,
  139. UINT64 Integer0,
  140. UINT64 Integer1)
  141. {
  142. ACPI_FUNCTION_ENTRY ();
  143. switch (Opcode)
  144. {
  145. case AML_ADD_OP: /* Add (Integer0, Integer1, Result) */
  146. return (Integer0 + Integer1);
  147. case AML_BIT_AND_OP: /* And (Integer0, Integer1, Result) */
  148. return (Integer0 & Integer1);
  149. case AML_BIT_NAND_OP: /* NAnd (Integer0, Integer1, Result) */
  150. return (~(Integer0 & Integer1));
  151. case AML_BIT_OR_OP: /* Or (Integer0, Integer1, Result) */
  152. return (Integer0 | Integer1);
  153. case AML_BIT_NOR_OP: /* NOr (Integer0, Integer1, Result) */
  154. return (~(Integer0 | Integer1));
  155. case AML_BIT_XOR_OP: /* XOr (Integer0, Integer1, Result) */
  156. return (Integer0 ^ Integer1);
  157. case AML_MULTIPLY_OP: /* Multiply (Integer0, Integer1, Result) */
  158. return (Integer0 * Integer1);
  159. case AML_SHIFT_LEFT_OP: /* ShiftLeft (Operand, ShiftCount, Result)*/
  160. /*
  161. * We need to check if the shiftcount is larger than the integer bit
  162. * width since the behavior of this is not well-defined in the C language.
  163. */
  164. if (Integer1 >= AcpiGbl_IntegerBitWidth)
  165. {
  166. return (0);
  167. }
  168. return (Integer0 << Integer1);
  169. case AML_SHIFT_RIGHT_OP: /* ShiftRight (Operand, ShiftCount, Result) */
  170. /*
  171. * We need to check if the shiftcount is larger than the integer bit
  172. * width since the behavior of this is not well-defined in the C language.
  173. */
  174. if (Integer1 >= AcpiGbl_IntegerBitWidth)
  175. {
  176. return (0);
  177. }
  178. return (Integer0 >> Integer1);
  179. case AML_SUBTRACT_OP: /* Subtract (Integer0, Integer1, Result) */
  180. return (Integer0 - Integer1);
  181. default:
  182. return (0);
  183. }
  184. }
  185. /*******************************************************************************
  186. *
  187. * FUNCTION: AcpiExDoLogicalNumericOp
  188. *
  189. * PARAMETERS: Opcode - AML opcode
  190. * Integer0 - Integer operand #0
  191. * Integer1 - Integer operand #1
  192. * LogicalResult - TRUE/FALSE result of the operation
  193. *
  194. * RETURN: Status
  195. *
  196. * DESCRIPTION: Execute a logical "Numeric" AML opcode. For these Numeric
  197. * operators (LAnd and LOr), both operands must be integers.
  198. *
  199. * Note: cleanest machine code seems to be produced by the code
  200. * below, rather than using statements of the form:
  201. * Result = (Integer0 && Integer1);
  202. *
  203. ******************************************************************************/
  204. ACPI_STATUS
  205. AcpiExDoLogicalNumericOp (
  206. UINT16 Opcode,
  207. UINT64 Integer0,
  208. UINT64 Integer1,
  209. BOOLEAN *LogicalResult)
  210. {
  211. ACPI_STATUS Status = AE_OK;
  212. BOOLEAN LocalResult = FALSE;
  213. ACPI_FUNCTION_TRACE (ExDoLogicalNumericOp);
  214. switch (Opcode)
  215. {
  216. case AML_LOGICAL_AND_OP: /* LAnd (Integer0, Integer1) */
  217. if (Integer0 && Integer1)
  218. {
  219. LocalResult = TRUE;
  220. }
  221. break;
  222. case AML_LOGICAL_OR_OP: /* LOr (Integer0, Integer1) */
  223. if (Integer0 || Integer1)
  224. {
  225. LocalResult = TRUE;
  226. }
  227. break;
  228. default:
  229. ACPI_ERROR ((AE_INFO,
  230. "Invalid numeric logical opcode: %X", Opcode));
  231. Status = AE_AML_INTERNAL;
  232. break;
  233. }
  234. /* Return the logical result and status */
  235. *LogicalResult = LocalResult;
  236. return_ACPI_STATUS (Status);
  237. }
  238. /*******************************************************************************
  239. *
  240. * FUNCTION: AcpiExDoLogicalOp
  241. *
  242. * PARAMETERS: Opcode - AML opcode
  243. * Operand0 - operand #0
  244. * Operand1 - operand #1
  245. * LogicalResult - TRUE/FALSE result of the operation
  246. *
  247. * RETURN: Status
  248. *
  249. * DESCRIPTION: Execute a logical AML opcode. The purpose of having all of the
  250. * functions here is to prevent a lot of pointer dereferencing
  251. * to obtain the operands and to simplify the generation of the
  252. * logical value. For the Numeric operators (LAnd and LOr), both
  253. * operands must be integers. For the other logical operators,
  254. * operands can be any combination of Integer/String/Buffer. The
  255. * first operand determines the type to which the second operand
  256. * will be converted.
  257. *
  258. * Note: cleanest machine code seems to be produced by the code
  259. * below, rather than using statements of the form:
  260. * Result = (Operand0 == Operand1);
  261. *
  262. ******************************************************************************/
  263. ACPI_STATUS
  264. AcpiExDoLogicalOp (
  265. UINT16 Opcode,
  266. ACPI_OPERAND_OBJECT *Operand0,
  267. ACPI_OPERAND_OBJECT *Operand1,
  268. BOOLEAN *LogicalResult)
  269. {
  270. ACPI_OPERAND_OBJECT *LocalOperand1 = Operand1;
  271. UINT64 Integer0;
  272. UINT64 Integer1;
  273. UINT32 Length0;
  274. UINT32 Length1;
  275. ACPI_STATUS Status = AE_OK;
  276. BOOLEAN LocalResult = FALSE;
  277. int Compare;
  278. ACPI_FUNCTION_TRACE (ExDoLogicalOp);
  279. /*
  280. * Convert the second operand if necessary. The first operand
  281. * determines the type of the second operand, (See the Data Types
  282. * section of the ACPI 3.0+ specification.) Both object types are
  283. * guaranteed to be either Integer/String/Buffer by the operand
  284. * resolution mechanism.
  285. */
  286. switch (Operand0->Common.Type)
  287. {
  288. case ACPI_TYPE_INTEGER:
  289. Status = AcpiExConvertToInteger (Operand1, &LocalOperand1,
  290. ACPI_IMPLICIT_CONVERSION);
  291. break;
  292. case ACPI_TYPE_STRING:
  293. Status = AcpiExConvertToString (
  294. Operand1, &LocalOperand1, ACPI_IMPLICIT_CONVERT_HEX);
  295. break;
  296. case ACPI_TYPE_BUFFER:
  297. Status = AcpiExConvertToBuffer (Operand1, &LocalOperand1);
  298. break;
  299. default:
  300. ACPI_ERROR ((AE_INFO,
  301. "Invalid object type for logical operator: %X",
  302. Operand0->Common.Type));
  303. Status = AE_AML_INTERNAL;
  304. break;
  305. }
  306. if (ACPI_FAILURE (Status))
  307. {
  308. goto Cleanup;
  309. }
  310. /*
  311. * Two cases: 1) Both Integers, 2) Both Strings or Buffers
  312. */
  313. if (Operand0->Common.Type == ACPI_TYPE_INTEGER)
  314. {
  315. /*
  316. * 1) Both operands are of type integer
  317. * Note: LocalOperand1 may have changed above
  318. */
  319. Integer0 = Operand0->Integer.Value;
  320. Integer1 = LocalOperand1->Integer.Value;
  321. switch (Opcode)
  322. {
  323. case AML_LOGICAL_EQUAL_OP: /* LEqual (Operand0, Operand1) */
  324. if (Integer0 == Integer1)
  325. {
  326. LocalResult = TRUE;
  327. }
  328. break;
  329. case AML_LOGICAL_GREATER_OP: /* LGreater (Operand0, Operand1) */
  330. if (Integer0 > Integer1)
  331. {
  332. LocalResult = TRUE;
  333. }
  334. break;
  335. case AML_LOGICAL_LESS_OP: /* LLess (Operand0, Operand1) */
  336. if (Integer0 < Integer1)
  337. {
  338. LocalResult = TRUE;
  339. }
  340. break;
  341. default:
  342. ACPI_ERROR ((AE_INFO,
  343. "Invalid comparison opcode: %X", Opcode));
  344. Status = AE_AML_INTERNAL;
  345. break;
  346. }
  347. }
  348. else
  349. {
  350. /*
  351. * 2) Both operands are Strings or both are Buffers
  352. * Note: Code below takes advantage of common Buffer/String
  353. * object fields. LocalOperand1 may have changed above. Use
  354. * memcmp to handle nulls in buffers.
  355. */
  356. Length0 = Operand0->Buffer.Length;
  357. Length1 = LocalOperand1->Buffer.Length;
  358. /* Lexicographic compare: compare the data bytes */
  359. Compare = memcmp (Operand0->Buffer.Pointer,
  360. LocalOperand1->Buffer.Pointer,
  361. (Length0 > Length1) ? Length1 : Length0);
  362. switch (Opcode)
  363. {
  364. case AML_LOGICAL_EQUAL_OP: /* LEqual (Operand0, Operand1) */
  365. /* Length and all bytes must be equal */
  366. if ((Length0 == Length1) &&
  367. (Compare == 0))
  368. {
  369. /* Length and all bytes match ==> TRUE */
  370. LocalResult = TRUE;
  371. }
  372. break;
  373. case AML_LOGICAL_GREATER_OP: /* LGreater (Operand0, Operand1) */
  374. if (Compare > 0)
  375. {
  376. LocalResult = TRUE;
  377. goto Cleanup; /* TRUE */
  378. }
  379. if (Compare < 0)
  380. {
  381. goto Cleanup; /* FALSE */
  382. }
  383. /* Bytes match (to shortest length), compare lengths */
  384. if (Length0 > Length1)
  385. {
  386. LocalResult = TRUE;
  387. }
  388. break;
  389. case AML_LOGICAL_LESS_OP: /* LLess (Operand0, Operand1) */
  390. if (Compare > 0)
  391. {
  392. goto Cleanup; /* FALSE */
  393. }
  394. if (Compare < 0)
  395. {
  396. LocalResult = TRUE;
  397. goto Cleanup; /* TRUE */
  398. }
  399. /* Bytes match (to shortest length), compare lengths */
  400. if (Length0 < Length1)
  401. {
  402. LocalResult = TRUE;
  403. }
  404. break;
  405. default:
  406. ACPI_ERROR ((AE_INFO,
  407. "Invalid comparison opcode: %X", Opcode));
  408. Status = AE_AML_INTERNAL;
  409. break;
  410. }
  411. }
  412. Cleanup:
  413. /* New object was created if implicit conversion performed - delete */
  414. if (LocalOperand1 != Operand1)
  415. {
  416. AcpiUtRemoveReference (LocalOperand1);
  417. }
  418. /* Return the logical result and status */
  419. *LogicalResult = LocalResult;
  420. return_ACPI_STATUS (Status);
  421. }