1 | /****************************************************************************** |
2 | * |
3 | * Module Name: nsconvert - Object conversions for objects returned by |
4 | * predefined methods |
5 | * |
6 | *****************************************************************************/ |
7 | |
8 | /* |
9 | * Copyright (C) 2000 - 2016, Intel Corp. |
10 | * All rights reserved. |
11 | * |
12 | * Redistribution and use in source and binary forms, with or without |
13 | * modification, are permitted provided that the following conditions |
14 | * are met: |
15 | * 1. Redistributions of source code must retain the above copyright |
16 | * notice, this list of conditions, and the following disclaimer, |
17 | * without modification. |
18 | * 2. Redistributions in binary form must reproduce at minimum a disclaimer |
19 | * substantially similar to the "NO WARRANTY" disclaimer below |
20 | * ("Disclaimer") and any redistribution must be conditioned upon |
21 | * including a substantially similar Disclaimer requirement for further |
22 | * binary redistribution. |
23 | * 3. Neither the names of the above-listed copyright holders nor the names |
24 | * of any contributors may be used to endorse or promote products derived |
25 | * from this software without specific prior written permission. |
26 | * |
27 | * Alternatively, this software may be distributed under the terms of the |
28 | * GNU General Public License ("GPL") version 2 as published by the Free |
29 | * Software Foundation. |
30 | * |
31 | * NO WARRANTY |
32 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
33 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
34 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR |
35 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
36 | * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
37 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
38 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
39 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, |
40 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING |
41 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
42 | * POSSIBILITY OF SUCH DAMAGES. |
43 | */ |
44 | |
45 | #include "acpi.h" |
46 | #include "accommon.h" |
47 | #include "acnamesp.h" |
48 | #include "acinterp.h" |
49 | #include "acpredef.h" |
50 | #include "amlresrc.h" |
51 | |
52 | #define _COMPONENT ACPI_NAMESPACE |
53 | ACPI_MODULE_NAME ("nsconvert" ) |
54 | |
55 | |
56 | /******************************************************************************* |
57 | * |
58 | * FUNCTION: AcpiNsConvertToInteger |
59 | * |
60 | * PARAMETERS: OriginalObject - Object to be converted |
61 | * ReturnObject - Where the new converted object is returned |
62 | * |
63 | * RETURN: Status. AE_OK if conversion was successful. |
64 | * |
65 | * DESCRIPTION: Attempt to convert a String/Buffer object to an Integer. |
66 | * |
67 | ******************************************************************************/ |
68 | |
69 | ACPI_STATUS |
70 | AcpiNsConvertToInteger ( |
71 | ACPI_OPERAND_OBJECT *OriginalObject, |
72 | ACPI_OPERAND_OBJECT **ReturnObject) |
73 | { |
74 | ACPI_OPERAND_OBJECT *NewObject; |
75 | ACPI_STATUS Status; |
76 | UINT64 Value = 0; |
77 | UINT32 i; |
78 | |
79 | |
80 | switch (OriginalObject->Common.Type) |
81 | { |
82 | case ACPI_TYPE_STRING: |
83 | |
84 | /* String-to-Integer conversion */ |
85 | |
86 | Status = AcpiUtStrtoul64 (OriginalObject->String.Pointer, |
87 | AcpiGbl_IntegerByteWidth, &Value); |
88 | if (ACPI_FAILURE (Status)) |
89 | { |
90 | return (Status); |
91 | } |
92 | break; |
93 | |
94 | case ACPI_TYPE_BUFFER: |
95 | |
96 | /* Buffer-to-Integer conversion. Max buffer size is 64 bits. */ |
97 | |
98 | if (OriginalObject->Buffer.Length > 8) |
99 | { |
100 | return (AE_AML_OPERAND_TYPE); |
101 | } |
102 | |
103 | /* Extract each buffer byte to create the integer */ |
104 | |
105 | for (i = 0; i < OriginalObject->Buffer.Length; i++) |
106 | { |
107 | Value |= ((UINT64) |
108 | OriginalObject->Buffer.Pointer[i] << (i * 8)); |
109 | } |
110 | break; |
111 | |
112 | default: |
113 | |
114 | return (AE_AML_OPERAND_TYPE); |
115 | } |
116 | |
117 | NewObject = AcpiUtCreateIntegerObject (Value); |
118 | if (!NewObject) |
119 | { |
120 | return (AE_NO_MEMORY); |
121 | } |
122 | |
123 | *ReturnObject = NewObject; |
124 | return (AE_OK); |
125 | } |
126 | |
127 | |
128 | /******************************************************************************* |
129 | * |
130 | * FUNCTION: AcpiNsConvertToString |
131 | * |
132 | * PARAMETERS: OriginalObject - Object to be converted |
133 | * ReturnObject - Where the new converted object is returned |
134 | * |
135 | * RETURN: Status. AE_OK if conversion was successful. |
136 | * |
137 | * DESCRIPTION: Attempt to convert a Integer/Buffer object to a String. |
138 | * |
139 | ******************************************************************************/ |
140 | |
141 | ACPI_STATUS |
142 | AcpiNsConvertToString ( |
143 | ACPI_OPERAND_OBJECT *OriginalObject, |
144 | ACPI_OPERAND_OBJECT **ReturnObject) |
145 | { |
146 | ACPI_OPERAND_OBJECT *NewObject; |
147 | ACPI_SIZE Length; |
148 | ACPI_STATUS Status; |
149 | |
150 | |
151 | switch (OriginalObject->Common.Type) |
152 | { |
153 | case ACPI_TYPE_INTEGER: |
154 | /* |
155 | * Integer-to-String conversion. Commonly, convert |
156 | * an integer of value 0 to a NULL string. The last element of |
157 | * _BIF and _BIX packages occasionally need this fix. |
158 | */ |
159 | if (OriginalObject->Integer.Value == 0) |
160 | { |
161 | /* Allocate a new NULL string object */ |
162 | |
163 | NewObject = AcpiUtCreateStringObject (0); |
164 | if (!NewObject) |
165 | { |
166 | return (AE_NO_MEMORY); |
167 | } |
168 | } |
169 | else |
170 | { |
171 | Status = AcpiExConvertToString (OriginalObject, |
172 | &NewObject, ACPI_IMPLICIT_CONVERT_HEX); |
173 | if (ACPI_FAILURE (Status)) |
174 | { |
175 | return (Status); |
176 | } |
177 | } |
178 | break; |
179 | |
180 | case ACPI_TYPE_BUFFER: |
181 | /* |
182 | * Buffer-to-String conversion. Use a ToString |
183 | * conversion, no transform performed on the buffer data. The best |
184 | * example of this is the _BIF method, where the string data from |
185 | * the battery is often (incorrectly) returned as buffer object(s). |
186 | */ |
187 | Length = 0; |
188 | while ((Length < OriginalObject->Buffer.Length) && |
189 | (OriginalObject->Buffer.Pointer[Length])) |
190 | { |
191 | Length++; |
192 | } |
193 | |
194 | /* Allocate a new string object */ |
195 | |
196 | NewObject = AcpiUtCreateStringObject (Length); |
197 | if (!NewObject) |
198 | { |
199 | return (AE_NO_MEMORY); |
200 | } |
201 | |
202 | /* |
203 | * Copy the raw buffer data with no transform. String is already NULL |
204 | * terminated at Length+1. |
205 | */ |
206 | memcpy (NewObject->String.Pointer, |
207 | OriginalObject->Buffer.Pointer, Length); |
208 | break; |
209 | |
210 | default: |
211 | |
212 | return (AE_AML_OPERAND_TYPE); |
213 | } |
214 | |
215 | *ReturnObject = NewObject; |
216 | return (AE_OK); |
217 | } |
218 | |
219 | |
220 | /******************************************************************************* |
221 | * |
222 | * FUNCTION: AcpiNsConvertToBuffer |
223 | * |
224 | * PARAMETERS: OriginalObject - Object to be converted |
225 | * ReturnObject - Where the new converted object is returned |
226 | * |
227 | * RETURN: Status. AE_OK if conversion was successful. |
228 | * |
229 | * DESCRIPTION: Attempt to convert a Integer/String/Package object to a Buffer. |
230 | * |
231 | ******************************************************************************/ |
232 | |
233 | ACPI_STATUS |
234 | AcpiNsConvertToBuffer ( |
235 | ACPI_OPERAND_OBJECT *OriginalObject, |
236 | ACPI_OPERAND_OBJECT **ReturnObject) |
237 | { |
238 | ACPI_OPERAND_OBJECT *NewObject; |
239 | ACPI_STATUS Status; |
240 | ACPI_OPERAND_OBJECT **Elements; |
241 | UINT32 *DwordBuffer; |
242 | UINT32 Count; |
243 | UINT32 i; |
244 | |
245 | |
246 | switch (OriginalObject->Common.Type) |
247 | { |
248 | case ACPI_TYPE_INTEGER: |
249 | /* |
250 | * Integer-to-Buffer conversion. |
251 | * Convert the Integer to a packed-byte buffer. _MAT and other |
252 | * objects need this sometimes, if a read has been performed on a |
253 | * Field object that is less than or equal to the global integer |
254 | * size (32 or 64 bits). |
255 | */ |
256 | Status = AcpiExConvertToBuffer (OriginalObject, &NewObject); |
257 | if (ACPI_FAILURE (Status)) |
258 | { |
259 | return (Status); |
260 | } |
261 | break; |
262 | |
263 | case ACPI_TYPE_STRING: |
264 | |
265 | /* String-to-Buffer conversion. Simple data copy */ |
266 | |
267 | NewObject = AcpiUtCreateBufferObject |
268 | (OriginalObject->String.Length); |
269 | if (!NewObject) |
270 | { |
271 | return (AE_NO_MEMORY); |
272 | } |
273 | |
274 | memcpy (NewObject->Buffer.Pointer, |
275 | OriginalObject->String.Pointer, OriginalObject->String.Length); |
276 | break; |
277 | |
278 | case ACPI_TYPE_PACKAGE: |
279 | /* |
280 | * This case is often seen for predefined names that must return a |
281 | * Buffer object with multiple DWORD integers within. For example, |
282 | * _FDE and _GTM. The Package can be converted to a Buffer. |
283 | */ |
284 | |
285 | /* All elements of the Package must be integers */ |
286 | |
287 | Elements = OriginalObject->Package.Elements; |
288 | Count = OriginalObject->Package.Count; |
289 | |
290 | for (i = 0; i < Count; i++) |
291 | { |
292 | if ((!*Elements) || |
293 | ((*Elements)->Common.Type != ACPI_TYPE_INTEGER)) |
294 | { |
295 | return (AE_AML_OPERAND_TYPE); |
296 | } |
297 | Elements++; |
298 | } |
299 | |
300 | /* Create the new buffer object to replace the Package */ |
301 | |
302 | NewObject = AcpiUtCreateBufferObject (ACPI_MUL_4 (Count)); |
303 | if (!NewObject) |
304 | { |
305 | return (AE_NO_MEMORY); |
306 | } |
307 | |
308 | /* Copy the package elements (integers) to the buffer as DWORDs */ |
309 | |
310 | Elements = OriginalObject->Package.Elements; |
311 | DwordBuffer = ACPI_CAST_PTR (UINT32, NewObject->Buffer.Pointer); |
312 | |
313 | for (i = 0; i < Count; i++) |
314 | { |
315 | *DwordBuffer = (UINT32) (*Elements)->Integer.Value; |
316 | DwordBuffer++; |
317 | Elements++; |
318 | } |
319 | break; |
320 | |
321 | default: |
322 | |
323 | return (AE_AML_OPERAND_TYPE); |
324 | } |
325 | |
326 | *ReturnObject = NewObject; |
327 | return (AE_OK); |
328 | } |
329 | |
330 | |
331 | /******************************************************************************* |
332 | * |
333 | * FUNCTION: AcpiNsConvertToUnicode |
334 | * |
335 | * PARAMETERS: Scope - Namespace node for the method/object |
336 | * OriginalObject - ASCII String Object to be converted |
337 | * ReturnObject - Where the new converted object is returned |
338 | * |
339 | * RETURN: Status. AE_OK if conversion was successful. |
340 | * |
341 | * DESCRIPTION: Attempt to convert a String object to a Unicode string Buffer. |
342 | * |
343 | ******************************************************************************/ |
344 | |
345 | ACPI_STATUS |
346 | AcpiNsConvertToUnicode ( |
347 | ACPI_NAMESPACE_NODE *Scope, |
348 | ACPI_OPERAND_OBJECT *OriginalObject, |
349 | ACPI_OPERAND_OBJECT **ReturnObject) |
350 | { |
351 | ACPI_OPERAND_OBJECT *NewObject; |
352 | char *AsciiString; |
353 | UINT16 *UnicodeBuffer; |
354 | UINT32 UnicodeLength; |
355 | UINT32 i; |
356 | |
357 | |
358 | if (!OriginalObject) |
359 | { |
360 | return (AE_OK); |
361 | } |
362 | |
363 | /* If a Buffer was returned, it must be at least two bytes long */ |
364 | |
365 | if (OriginalObject->Common.Type == ACPI_TYPE_BUFFER) |
366 | { |
367 | if (OriginalObject->Buffer.Length < 2) |
368 | { |
369 | return (AE_AML_OPERAND_VALUE); |
370 | } |
371 | |
372 | *ReturnObject = NULL; |
373 | return (AE_OK); |
374 | } |
375 | |
376 | /* |
377 | * The original object is an ASCII string. Convert this string to |
378 | * a unicode buffer. |
379 | */ |
380 | AsciiString = OriginalObject->String.Pointer; |
381 | UnicodeLength = (OriginalObject->String.Length * 2) + 2; |
382 | |
383 | /* Create a new buffer object for the Unicode data */ |
384 | |
385 | NewObject = AcpiUtCreateBufferObject (UnicodeLength); |
386 | if (!NewObject) |
387 | { |
388 | return (AE_NO_MEMORY); |
389 | } |
390 | |
391 | UnicodeBuffer = ACPI_CAST_PTR (UINT16, NewObject->Buffer.Pointer); |
392 | |
393 | /* Convert ASCII to Unicode */ |
394 | |
395 | for (i = 0; i < OriginalObject->String.Length; i++) |
396 | { |
397 | UnicodeBuffer[i] = (UINT16) AsciiString[i]; |
398 | } |
399 | |
400 | *ReturnObject = NewObject; |
401 | return (AE_OK); |
402 | } |
403 | |
404 | |
405 | /******************************************************************************* |
406 | * |
407 | * FUNCTION: AcpiNsConvertToResource |
408 | * |
409 | * PARAMETERS: Scope - Namespace node for the method/object |
410 | * OriginalObject - Object to be converted |
411 | * ReturnObject - Where the new converted object is returned |
412 | * |
413 | * RETURN: Status. AE_OK if conversion was successful |
414 | * |
415 | * DESCRIPTION: Attempt to convert a Integer object to a ResourceTemplate |
416 | * Buffer. |
417 | * |
418 | ******************************************************************************/ |
419 | |
420 | ACPI_STATUS |
421 | AcpiNsConvertToResource ( |
422 | ACPI_NAMESPACE_NODE *Scope, |
423 | ACPI_OPERAND_OBJECT *OriginalObject, |
424 | ACPI_OPERAND_OBJECT **ReturnObject) |
425 | { |
426 | ACPI_OPERAND_OBJECT *NewObject; |
427 | UINT8 *Buffer; |
428 | |
429 | |
430 | /* |
431 | * We can fix the following cases for an expected resource template: |
432 | * 1. No return value (interpreter slack mode is disabled) |
433 | * 2. A "Return (Zero)" statement |
434 | * 3. A "Return empty buffer" statement |
435 | * |
436 | * We will return a buffer containing a single EndTag |
437 | * resource descriptor. |
438 | */ |
439 | if (OriginalObject) |
440 | { |
441 | switch (OriginalObject->Common.Type) |
442 | { |
443 | case ACPI_TYPE_INTEGER: |
444 | |
445 | /* We can only repair an Integer==0 */ |
446 | |
447 | if (OriginalObject->Integer.Value) |
448 | { |
449 | return (AE_AML_OPERAND_TYPE); |
450 | } |
451 | break; |
452 | |
453 | case ACPI_TYPE_BUFFER: |
454 | |
455 | if (OriginalObject->Buffer.Length) |
456 | { |
457 | /* Additional checks can be added in the future */ |
458 | |
459 | *ReturnObject = NULL; |
460 | return (AE_OK); |
461 | } |
462 | break; |
463 | |
464 | case ACPI_TYPE_STRING: |
465 | default: |
466 | |
467 | return (AE_AML_OPERAND_TYPE); |
468 | } |
469 | } |
470 | |
471 | /* Create the new buffer object for the resource descriptor */ |
472 | |
473 | NewObject = AcpiUtCreateBufferObject (2); |
474 | if (!NewObject) |
475 | { |
476 | return (AE_NO_MEMORY); |
477 | } |
478 | |
479 | Buffer = ACPI_CAST_PTR (UINT8, NewObject->Buffer.Pointer); |
480 | |
481 | /* Initialize the Buffer with a single EndTag descriptor */ |
482 | |
483 | Buffer[0] = (ACPI_RESOURCE_NAME_END_TAG | ASL_RDESC_END_TAG_SIZE); |
484 | Buffer[1] = 0x00; |
485 | |
486 | *ReturnObject = NewObject; |
487 | return (AE_OK); |
488 | } |
489 | |
490 | |
491 | /******************************************************************************* |
492 | * |
493 | * FUNCTION: AcpiNsConvertToReference |
494 | * |
495 | * PARAMETERS: Scope - Namespace node for the method/object |
496 | * OriginalObject - Object to be converted |
497 | * ReturnObject - Where the new converted object is returned |
498 | * |
499 | * RETURN: Status. AE_OK if conversion was successful |
500 | * |
501 | * DESCRIPTION: Attempt to convert a Integer object to a ObjectReference. |
502 | * Buffer. |
503 | * |
504 | ******************************************************************************/ |
505 | |
506 | ACPI_STATUS |
507 | AcpiNsConvertToReference ( |
508 | ACPI_NAMESPACE_NODE *Scope, |
509 | ACPI_OPERAND_OBJECT *OriginalObject, |
510 | ACPI_OPERAND_OBJECT **ReturnObject) |
511 | { |
512 | ACPI_OPERAND_OBJECT *NewObject = NULL; |
513 | ACPI_STATUS Status; |
514 | ACPI_NAMESPACE_NODE *Node; |
515 | ACPI_GENERIC_STATE ScopeInfo; |
516 | char *Name; |
517 | |
518 | |
519 | ACPI_FUNCTION_NAME (NsConvertToReference); |
520 | |
521 | |
522 | /* Convert path into internal presentation */ |
523 | |
524 | Status = AcpiNsInternalizeName (OriginalObject->String.Pointer, &Name); |
525 | if (ACPI_FAILURE (Status)) |
526 | { |
527 | return_ACPI_STATUS (Status); |
528 | } |
529 | |
530 | /* Find the namespace node */ |
531 | |
532 | ScopeInfo.Scope.Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Scope); |
533 | Status = AcpiNsLookup (&ScopeInfo, Name, |
534 | ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, |
535 | ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE, NULL, &Node); |
536 | if (ACPI_FAILURE (Status)) |
537 | { |
538 | /* Check if we are resolving a named reference within a package */ |
539 | |
540 | ACPI_ERROR_NAMESPACE (OriginalObject->String.Pointer, Status); |
541 | goto ErrorExit; |
542 | } |
543 | |
544 | /* Create and init a new internal ACPI object */ |
545 | |
546 | NewObject = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_REFERENCE); |
547 | if (!NewObject) |
548 | { |
549 | Status = AE_NO_MEMORY; |
550 | goto ErrorExit; |
551 | } |
552 | NewObject->Reference.Node = Node; |
553 | NewObject->Reference.Object = Node->Object; |
554 | NewObject->Reference.Class = ACPI_REFCLASS_NAME; |
555 | |
556 | /* |
557 | * Increase reference of the object if needed (the object is likely a |
558 | * null for device nodes). |
559 | */ |
560 | AcpiUtAddReference (Node->Object); |
561 | |
562 | ErrorExit: |
563 | ACPI_FREE (Name); |
564 | *ReturnObject = NewObject; |
565 | return (AE_OK); |
566 | } |
567 | |