ReactOS  0.4.14-dev-376-gaedba84
exmisc.c
Go to the documentation of this file.
1 /******************************************************************************
2  *
3  * Module Name: exmisc - ACPI AML (p-code) execution - specific opcodes
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2019, 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 
44 #include "acpi.h"
45 #include "accommon.h"
46 #include "acinterp.h"
47 #include "amlcode.h"
48 
49 
50 #define _COMPONENT ACPI_EXECUTER
51  ACPI_MODULE_NAME ("exmisc")
52 
53 
54 /*******************************************************************************
55  *
56  * FUNCTION: AcpiExGetObjectReference
57  *
58  * PARAMETERS: ObjDesc - Create a reference to this object
59  * ReturnDesc - Where to store the reference
60  * WalkState - Current state
61  *
62  * RETURN: Status
63  *
64  * DESCRIPTION: Obtain and return a "reference" to the target object
65  * Common code for the RefOfOp and the CondRefOfOp.
66  *
67  ******************************************************************************/
68 
71  ACPI_OPERAND_OBJECT *ObjDesc,
72  ACPI_OPERAND_OBJECT **ReturnDesc,
73  ACPI_WALK_STATE *WalkState)
74 {
75  ACPI_OPERAND_OBJECT *ReferenceObj;
76  ACPI_OPERAND_OBJECT *ReferencedObj;
77 
78 
79  ACPI_FUNCTION_TRACE_PTR (ExGetObjectReference, ObjDesc);
80 
81 
82  *ReturnDesc = NULL;
83 
84  switch (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc))
85  {
87 
88  if (ObjDesc->Common.Type != ACPI_TYPE_LOCAL_REFERENCE)
89  {
91  }
92 
93  /*
94  * Must be a reference to a Local or Arg
95  */
96  switch (ObjDesc->Reference.Class)
97  {
99  case ACPI_REFCLASS_ARG:
100  case ACPI_REFCLASS_DEBUG:
101 
102  /* The referenced object is the pseudo-node for the local/arg */
103 
104  ReferencedObj = ObjDesc->Reference.Object;
105  break;
106 
107  default:
108 
109  ACPI_ERROR ((AE_INFO, "Invalid Reference Class 0x%2.2X",
110  ObjDesc->Reference.Class));
112  }
113  break;
114 
116  /*
117  * A named reference that has already been resolved to a Node
118  */
119  ReferencedObj = ObjDesc;
120  break;
121 
122  default:
123 
124  ACPI_ERROR ((AE_INFO, "Invalid descriptor type 0x%X",
125  ACPI_GET_DESCRIPTOR_TYPE (ObjDesc)));
127  }
128 
129 
130  /* Create a new reference object */
131 
133  if (!ReferenceObj)
134  {
136  }
137 
138  ReferenceObj->Reference.Class = ACPI_REFCLASS_REFOF;
139  ReferenceObj->Reference.Object = ReferencedObj;
140  *ReturnDesc = ReferenceObj;
141 
143  "Object %p Type [%s], returning Reference %p\n",
144  ObjDesc, AcpiUtGetObjectTypeName (ObjDesc), *ReturnDesc));
145 
147 }
148 
149 
150 /*******************************************************************************
151  *
152  * FUNCTION: AcpiExDoMathOp
153  *
154  * PARAMETERS: Opcode - AML opcode
155  * Integer0 - Integer operand #0
156  * Integer1 - Integer operand #1
157  *
158  * RETURN: Integer result of the operation
159  *
160  * DESCRIPTION: Execute a math AML opcode. The purpose of having all of the
161  * math functions here is to prevent a lot of pointer dereferencing
162  * to obtain the operands.
163  *
164  ******************************************************************************/
165 
166 UINT64
168  UINT16 Opcode,
169  UINT64 Integer0,
170  UINT64 Integer1)
171 {
172 
174 
175 
176  switch (Opcode)
177  {
178  case AML_ADD_OP: /* Add (Integer0, Integer1, Result) */
179 
180  return (Integer0 + Integer1);
181 
182  case AML_BIT_AND_OP: /* And (Integer0, Integer1, Result) */
183 
184  return (Integer0 & Integer1);
185 
186  case AML_BIT_NAND_OP: /* NAnd (Integer0, Integer1, Result) */
187 
188  return (~(Integer0 & Integer1));
189 
190  case AML_BIT_OR_OP: /* Or (Integer0, Integer1, Result) */
191 
192  return (Integer0 | Integer1);
193 
194  case AML_BIT_NOR_OP: /* NOr (Integer0, Integer1, Result) */
195 
196  return (~(Integer0 | Integer1));
197 
198  case AML_BIT_XOR_OP: /* XOr (Integer0, Integer1, Result) */
199 
200  return (Integer0 ^ Integer1);
201 
202  case AML_MULTIPLY_OP: /* Multiply (Integer0, Integer1, Result) */
203 
204  return (Integer0 * Integer1);
205 
206  case AML_SHIFT_LEFT_OP: /* ShiftLeft (Operand, ShiftCount, Result)*/
207 
208  /*
209  * We need to check if the shiftcount is larger than the integer bit
210  * width since the behavior of this is not well-defined in the C language.
211  */
212  if (Integer1 >= AcpiGbl_IntegerBitWidth)
213  {
214  return (0);
215  }
216  return (Integer0 << Integer1);
217 
218  case AML_SHIFT_RIGHT_OP: /* ShiftRight (Operand, ShiftCount, Result) */
219 
220  /*
221  * We need to check if the shiftcount is larger than the integer bit
222  * width since the behavior of this is not well-defined in the C language.
223  */
224  if (Integer1 >= AcpiGbl_IntegerBitWidth)
225  {
226  return (0);
227  }
228  return (Integer0 >> Integer1);
229 
230  case AML_SUBTRACT_OP: /* Subtract (Integer0, Integer1, Result) */
231 
232  return (Integer0 - Integer1);
233 
234  default:
235 
236  return (0);
237  }
238 }
239 
240 
241 /*******************************************************************************
242  *
243  * FUNCTION: AcpiExDoLogicalNumericOp
244  *
245  * PARAMETERS: Opcode - AML opcode
246  * Integer0 - Integer operand #0
247  * Integer1 - Integer operand #1
248  * LogicalResult - TRUE/FALSE result of the operation
249  *
250  * RETURN: Status
251  *
252  * DESCRIPTION: Execute a logical "Numeric" AML opcode. For these Numeric
253  * operators (LAnd and LOr), both operands must be integers.
254  *
255  * Note: cleanest machine code seems to be produced by the code
256  * below, rather than using statements of the form:
257  * Result = (Integer0 && Integer1);
258  *
259  ******************************************************************************/
260 
263  UINT16 Opcode,
264  UINT64 Integer0,
265  UINT64 Integer1,
266  BOOLEAN *LogicalResult)
267 {
269  BOOLEAN LocalResult = FALSE;
270 
271 
272  ACPI_FUNCTION_TRACE (ExDoLogicalNumericOp);
273 
274 
275  switch (Opcode)
276  {
277  case AML_LOGICAL_AND_OP: /* LAnd (Integer0, Integer1) */
278 
279  if (Integer0 && Integer1)
280  {
281  LocalResult = TRUE;
282  }
283  break;
284 
285  case AML_LOGICAL_OR_OP: /* LOr (Integer0, Integer1) */
286 
287  if (Integer0 || Integer1)
288  {
289  LocalResult = TRUE;
290  }
291  break;
292 
293  default:
294 
296  "Invalid numeric logical opcode: %X", Opcode));
298  break;
299  }
300 
301  /* Return the logical result and status */
302 
303  *LogicalResult = LocalResult;
305 }
306 
307 
308 /*******************************************************************************
309  *
310  * FUNCTION: AcpiExDoLogicalOp
311  *
312  * PARAMETERS: Opcode - AML opcode
313  * Operand0 - operand #0
314  * Operand1 - operand #1
315  * LogicalResult - TRUE/FALSE result of the operation
316  *
317  * RETURN: Status
318  *
319  * DESCRIPTION: Execute a logical AML opcode. The purpose of having all of the
320  * functions here is to prevent a lot of pointer dereferencing
321  * to obtain the operands and to simplify the generation of the
322  * logical value. For the Numeric operators (LAnd and LOr), both
323  * operands must be integers. For the other logical operators,
324  * operands can be any combination of Integer/String/Buffer. The
325  * first operand determines the type to which the second operand
326  * will be converted.
327  *
328  * Note: cleanest machine code seems to be produced by the code
329  * below, rather than using statements of the form:
330  * Result = (Operand0 == Operand1);
331  *
332  ******************************************************************************/
333 
336  UINT16 Opcode,
337  ACPI_OPERAND_OBJECT *Operand0,
338  ACPI_OPERAND_OBJECT *Operand1,
339  BOOLEAN *LogicalResult)
340 {
341  ACPI_OPERAND_OBJECT *LocalOperand1 = Operand1;
342  UINT64 Integer0;
343  UINT64 Integer1;
344  UINT32 Length0;
345  UINT32 Length1;
347  BOOLEAN LocalResult = FALSE;
348  int Compare;
349 
350 
351  ACPI_FUNCTION_TRACE (ExDoLogicalOp);
352 
353 
354  /*
355  * Convert the second operand if necessary. The first operand
356  * determines the type of the second operand, (See the Data Types
357  * section of the ACPI 3.0+ specification.) Both object types are
358  * guaranteed to be either Integer/String/Buffer by the operand
359  * resolution mechanism.
360  */
361  switch (Operand0->Common.Type)
362  {
363  case ACPI_TYPE_INTEGER:
364 
365  Status = AcpiExConvertToInteger (Operand1, &LocalOperand1,
367  break;
368 
369  case ACPI_TYPE_STRING:
370 
372  Operand1, &LocalOperand1, ACPI_IMPLICIT_CONVERT_HEX);
373  break;
374 
375  case ACPI_TYPE_BUFFER:
376 
377  Status = AcpiExConvertToBuffer (Operand1, &LocalOperand1);
378  break;
379 
380  default:
381 
383  "Invalid object type for logical operator: %X",
384  Operand0->Common.Type));
386  break;
387  }
388 
389  if (ACPI_FAILURE (Status))
390  {
391  goto Cleanup;
392  }
393 
394  /*
395  * Two cases: 1) Both Integers, 2) Both Strings or Buffers
396  */
397  if (Operand0->Common.Type == ACPI_TYPE_INTEGER)
398  {
399  /*
400  * 1) Both operands are of type integer
401  * Note: LocalOperand1 may have changed above
402  */
403  Integer0 = Operand0->Integer.Value;
404  Integer1 = LocalOperand1->Integer.Value;
405 
406  switch (Opcode)
407  {
408  case AML_LOGICAL_EQUAL_OP: /* LEqual (Operand0, Operand1) */
409 
410  if (Integer0 == Integer1)
411  {
412  LocalResult = TRUE;
413  }
414  break;
415 
416  case AML_LOGICAL_GREATER_OP: /* LGreater (Operand0, Operand1) */
417 
418  if (Integer0 > Integer1)
419  {
420  LocalResult = TRUE;
421  }
422  break;
423 
424  case AML_LOGICAL_LESS_OP: /* LLess (Operand0, Operand1) */
425 
426  if (Integer0 < Integer1)
427  {
428  LocalResult = TRUE;
429  }
430  break;
431 
432  default:
433 
435  "Invalid comparison opcode: %X", Opcode));
437  break;
438  }
439  }
440  else
441  {
442  /*
443  * 2) Both operands are Strings or both are Buffers
444  * Note: Code below takes advantage of common Buffer/String
445  * object fields. LocalOperand1 may have changed above. Use
446  * memcmp to handle nulls in buffers.
447  */
448  Length0 = Operand0->Buffer.Length;
449  Length1 = LocalOperand1->Buffer.Length;
450 
451  /* Lexicographic compare: compare the data bytes */
452 
453  Compare = memcmp (Operand0->Buffer.Pointer,
454  LocalOperand1->Buffer.Pointer,
455  (Length0 > Length1) ? Length1 : Length0);
456 
457  switch (Opcode)
458  {
459  case AML_LOGICAL_EQUAL_OP: /* LEqual (Operand0, Operand1) */
460 
461  /* Length and all bytes must be equal */
462 
463  if ((Length0 == Length1) &&
464  (Compare == 0))
465  {
466  /* Length and all bytes match ==> TRUE */
467 
468  LocalResult = TRUE;
469  }
470  break;
471 
472  case AML_LOGICAL_GREATER_OP: /* LGreater (Operand0, Operand1) */
473 
474  if (Compare > 0)
475  {
476  LocalResult = TRUE;
477  goto Cleanup; /* TRUE */
478  }
479  if (Compare < 0)
480  {
481  goto Cleanup; /* FALSE */
482  }
483 
484  /* Bytes match (to shortest length), compare lengths */
485 
486  if (Length0 > Length1)
487  {
488  LocalResult = TRUE;
489  }
490  break;
491 
492  case AML_LOGICAL_LESS_OP: /* LLess (Operand0, Operand1) */
493 
494  if (Compare > 0)
495  {
496  goto Cleanup; /* FALSE */
497  }
498  if (Compare < 0)
499  {
500  LocalResult = TRUE;
501  goto Cleanup; /* TRUE */
502  }
503 
504  /* Bytes match (to shortest length), compare lengths */
505 
506  if (Length0 < Length1)
507  {
508  LocalResult = TRUE;
509  }
510  break;
511 
512  default:
513 
515  "Invalid comparison opcode: %X", Opcode));
517  break;
518  }
519  }
520 
521 Cleanup:
522 
523  /* New object was created if implicit conversion performed - delete */
524 
525  if (LocalOperand1 != Operand1)
526  {
527  AcpiUtRemoveReference (LocalOperand1);
528  }
529 
530  /* Return the logical result and status */
531 
532  *LogicalResult = LocalResult;
534 }
#define TRUE
Definition: types.h:120
#define AML_BIT_NOR_OP
Definition: amlcode.h:102
_In_ PVOID _In_ ULONG Opcode
Definition: hubbusif.h:330
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
#define AE_NO_MEMORY
Definition: acexcep.h:112
UINT64 AcpiExDoMathOp(UINT16 Opcode, UINT64 Integer0, UINT64 Integer1)
Definition: exmisc.c:167
#define AML_BIT_NAND_OP
Definition: amlcode.h:100
#define AML_LOGICAL_OR_OP
Definition: amlcode.h:121
ACPI_STATUS AcpiExDoLogicalOp(UINT16 Opcode, ACPI_OPERAND_OBJECT *Operand0, ACPI_OPERAND_OBJECT *Operand1, BOOLEAN *LogicalResult)
Definition: exmisc.c:335
#define ACPI_TYPE_BUFFER
Definition: actypes.h:681
#define ACPI_TYPE_INTEGER
Definition: actypes.h:679
#define AE_AML_INTERNAL
Definition: acexcep.h:194
#define ACPI_TYPE_LOCAL_REFERENCE
Definition: actypes.h:710
UINT32 ACPI_STATUS
Definition: actypes.h:460
#define AE_AML_OPERAND_TYPE
Definition: acexcep.h:182
#define AML_SHIFT_RIGHT_OP
Definition: amlcode.h:98
INT Length1
Definition: FsRtlDissect.c:15
#define ACPI_FAILURE(a)
Definition: acexcep.h:95
#define AML_BIT_AND_OP
Definition: amlcode.h:99
ACPI_OBJECT_COMMON_HEADER UINT8 Class
Definition: acobject.h:440
unsigned int UINT32
#define ACPI_MODULE_NAME(Name)
Definition: acoutput.h:216
unsigned char BOOLEAN
#define AML_LOGICAL_EQUAL_OP
Definition: amlcode.h:123
#define AE_INFO
Definition: acoutput.h:230
smooth NULL
Definition: ftsmooth.c:416
ACPI_OBJECT_REFERENCE Reference
Definition: acobject.h:537
#define AML_SHIFT_LEFT_OP
Definition: amlcode.h:97
#define ACPI_FUNCTION_ENTRY()
Definition: acoutput.h:484
#define ACPI_FUNCTION_TRACE_PTR(a, b)
Definition: acoutput.h:481
#define AML_BIT_OR_OP
Definition: amlcode.h:101
#define ACPI_DESC_TYPE_OPERAND
Definition: acobject.h:573
ACPI_OBJECT_BUFFER Buffer
Definition: acobject.h:519
#define AML_BIT_XOR_OP
Definition: amlcode.h:103
#define AML_ADD_OP
Definition: amlcode.h:90
#define ACPI_DEBUG_PRINT(pl)
Definition: acoutput.h:475
ACPI_STATUS AcpiExConvertToString(ACPI_OPERAND_OBJECT *ObjDesc, ACPI_OPERAND_OBJECT **ResultDesc, UINT32 Type)
Definition: exconvrt.c:440
#define AML_LOGICAL_AND_OP
Definition: amlcode.h:120
ACPI_STATUS AcpiExDoLogicalNumericOp(UINT16 Opcode, UINT64 Integer0, UINT64 Integer1, BOOLEAN *LogicalResult)
Definition: exmisc.c:262
ACPI_STATUS AcpiExConvertToInteger(ACPI_OPERAND_OBJECT *ObjDesc, ACPI_OPERAND_OBJECT **ResultDesc, UINT32 ImplicitConversion)
Definition: exconvrt.c:79
ACPI_OBJECT_INTEGER Integer
Definition: acobject.h:517
#define AE_TYPE
Definition: acexcep.h:116
static const WCHAR Cleanup[]
Definition: register.c:80
#define AML_SUBTRACT_OP
Definition: amlcode.h:92
#define AML_LOGICAL_GREATER_OP
Definition: amlcode.h:124
Status
Definition: gdiplustypes.h:24
#define ACPI_DB_EXEC
Definition: acoutput.h:165
#define return_ACPI_STATUS(s)
Definition: acoutput.h:496
#define ACPI_FUNCTION_TRACE(a)
Definition: acoutput.h:480
ACPI_OBJECT_COMMON Common
Definition: acobject.h:516
void AcpiUtRemoveReference(ACPI_OPERAND_OBJECT *Object)
Definition: utdelete.c:784
unsigned short UINT16
ACPI_STATUS AcpiExConvertToBuffer(ACPI_OPERAND_OBJECT *ObjDesc, ACPI_OPERAND_OBJECT **ResultDesc)
Definition: exconvrt.c:224
#define ACPI_ERROR(plist)
Definition: acoutput.h:240
#define AML_MULTIPLY_OP
Definition: amlcode.h:95
ACPI_STATUS AcpiExGetObjectReference(ACPI_OPERAND_OBJECT *ObjDesc, ACPI_OPERAND_OBJECT **ReturnDesc, ACPI_WALK_STATE *WalkState)
Definition: exmisc.c:70
#define ACPI_TYPE_STRING
Definition: actypes.h:680
#define AcpiUtCreateInternalObject(t)
Definition: acutils.h:655
#define ACPI_DESC_TYPE_NAMED
Definition: acobject.h:574
unsigned long long UINT64
const char * AcpiUtGetObjectTypeName(ACPI_OPERAND_OBJECT *ObjDesc)
Definition: utdecode.c:263
#define AML_LOGICAL_LESS_OP
Definition: amlcode.h:125
#define AE_OK
Definition: acexcep.h:97
#define ACPI_IMPLICIT_CONVERT_HEX
Definition: acinterp.h:126
#define ACPI_GET_DESCRIPTOR_TYPE(d)
Definition: acmacros.h:414
#define ACPI_IMPLICIT_CONVERSION
Definition: acutils.h:144