1 | /****************************************************************************** |
2 | * |
3 | * Module Name: utobject - ACPI object create/delete/size/cache routines |
4 | * |
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 | |
44 | #include "acpi.h" |
45 | #include "accommon.h" |
46 | #include "acnamesp.h" |
47 | |
48 | |
49 | #define _COMPONENT ACPI_UTILITIES |
50 | ACPI_MODULE_NAME ("utobject" ) |
51 | |
52 | /* Local prototypes */ |
53 | |
54 | static ACPI_STATUS |
55 | AcpiUtGetSimpleObjectSize ( |
56 | ACPI_OPERAND_OBJECT *Obj, |
57 | ACPI_SIZE *ObjLength); |
58 | |
59 | static ACPI_STATUS |
60 | AcpiUtGetPackageObjectSize ( |
61 | ACPI_OPERAND_OBJECT *Obj, |
62 | ACPI_SIZE *ObjLength); |
63 | |
64 | static ACPI_STATUS |
65 | AcpiUtGetElementLength ( |
66 | UINT8 ObjectType, |
67 | ACPI_OPERAND_OBJECT *SourceObject, |
68 | ACPI_GENERIC_STATE *State, |
69 | void *Context); |
70 | |
71 | |
72 | /******************************************************************************* |
73 | * |
74 | * FUNCTION: AcpiUtCreateInternalObjectDbg |
75 | * |
76 | * PARAMETERS: ModuleName - Source file name of caller |
77 | * LineNumber - Line number of caller |
78 | * ComponentId - Component type of caller |
79 | * Type - ACPI Type of the new object |
80 | * |
81 | * RETURN: A new internal object, null on failure |
82 | * |
83 | * DESCRIPTION: Create and initialize a new internal object. |
84 | * |
85 | * NOTE: We always allocate the worst-case object descriptor because |
86 | * these objects are cached, and we want them to be |
87 | * one-size-satisifies-any-request. This in itself may not be |
88 | * the most memory efficient, but the efficiency of the object |
89 | * cache should more than make up for this! |
90 | * |
91 | ******************************************************************************/ |
92 | |
93 | ACPI_OPERAND_OBJECT * |
94 | AcpiUtCreateInternalObjectDbg ( |
95 | const char *ModuleName, |
96 | UINT32 LineNumber, |
97 | UINT32 ComponentId, |
98 | ACPI_OBJECT_TYPE Type) |
99 | { |
100 | ACPI_OPERAND_OBJECT *Object; |
101 | ACPI_OPERAND_OBJECT *SecondObject; |
102 | |
103 | |
104 | ACPI_FUNCTION_TRACE_STR (UtCreateInternalObjectDbg, |
105 | __UNCONST(AcpiUtGetTypeName (Type))); |
106 | |
107 | |
108 | /* Allocate the raw object descriptor */ |
109 | |
110 | Object = AcpiUtAllocateObjectDescDbg ( |
111 | ModuleName, LineNumber, ComponentId); |
112 | if (!Object) |
113 | { |
114 | return_PTR (NULL); |
115 | } |
116 | |
117 | switch (Type) |
118 | { |
119 | case ACPI_TYPE_REGION: |
120 | case ACPI_TYPE_BUFFER_FIELD: |
121 | case ACPI_TYPE_LOCAL_BANK_FIELD: |
122 | |
123 | /* These types require a secondary object */ |
124 | |
125 | SecondObject = AcpiUtAllocateObjectDescDbg ( |
126 | ModuleName, LineNumber, ComponentId); |
127 | if (!SecondObject) |
128 | { |
129 | AcpiUtDeleteObjectDesc (Object); |
130 | return_PTR (NULL); |
131 | } |
132 | |
133 | SecondObject->Common.Type = ACPI_TYPE_LOCAL_EXTRA; |
134 | SecondObject->Common.ReferenceCount = 1; |
135 | |
136 | /* Link the second object to the first */ |
137 | |
138 | Object->Common.NextObject = SecondObject; |
139 | break; |
140 | |
141 | default: |
142 | |
143 | /* All others have no secondary object */ |
144 | break; |
145 | } |
146 | |
147 | /* Save the object type in the object descriptor */ |
148 | |
149 | Object->Common.Type = (UINT8) Type; |
150 | |
151 | /* Init the reference count */ |
152 | |
153 | Object->Common.ReferenceCount = 1; |
154 | |
155 | /* Any per-type initialization should go here */ |
156 | |
157 | return_PTR (Object); |
158 | } |
159 | |
160 | |
161 | /******************************************************************************* |
162 | * |
163 | * FUNCTION: AcpiUtCreatePackageObject |
164 | * |
165 | * PARAMETERS: Count - Number of package elements |
166 | * |
167 | * RETURN: Pointer to a new Package object, null on failure |
168 | * |
169 | * DESCRIPTION: Create a fully initialized package object |
170 | * |
171 | ******************************************************************************/ |
172 | |
173 | ACPI_OPERAND_OBJECT * |
174 | AcpiUtCreatePackageObject ( |
175 | UINT32 Count) |
176 | { |
177 | ACPI_OPERAND_OBJECT *PackageDesc; |
178 | ACPI_OPERAND_OBJECT **PackageElements; |
179 | |
180 | |
181 | ACPI_FUNCTION_TRACE_U32 (UtCreatePackageObject, Count); |
182 | |
183 | |
184 | /* Create a new Package object */ |
185 | |
186 | PackageDesc = AcpiUtCreateInternalObject (ACPI_TYPE_PACKAGE); |
187 | if (!PackageDesc) |
188 | { |
189 | return_PTR (NULL); |
190 | } |
191 | |
192 | /* |
193 | * Create the element array. Count+1 allows the array to be null |
194 | * terminated. |
195 | */ |
196 | PackageElements = ACPI_ALLOCATE_ZEROED ( |
197 | ((ACPI_SIZE) Count + 1) * sizeof (void *)); |
198 | if (!PackageElements) |
199 | { |
200 | ACPI_FREE (PackageDesc); |
201 | return_PTR (NULL); |
202 | } |
203 | |
204 | PackageDesc->Package.Count = Count; |
205 | PackageDesc->Package.Elements = PackageElements; |
206 | return_PTR (PackageDesc); |
207 | } |
208 | |
209 | |
210 | /******************************************************************************* |
211 | * |
212 | * FUNCTION: AcpiUtCreateIntegerObject |
213 | * |
214 | * PARAMETERS: InitialValue - Initial value for the integer |
215 | * |
216 | * RETURN: Pointer to a new Integer object, null on failure |
217 | * |
218 | * DESCRIPTION: Create an initialized integer object |
219 | * |
220 | ******************************************************************************/ |
221 | |
222 | ACPI_OPERAND_OBJECT * |
223 | AcpiUtCreateIntegerObject ( |
224 | UINT64 InitialValue) |
225 | { |
226 | ACPI_OPERAND_OBJECT *IntegerDesc; |
227 | |
228 | |
229 | ACPI_FUNCTION_TRACE (UtCreateIntegerObject); |
230 | |
231 | |
232 | /* Create and initialize a new integer object */ |
233 | |
234 | IntegerDesc = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER); |
235 | if (!IntegerDesc) |
236 | { |
237 | return_PTR (NULL); |
238 | } |
239 | |
240 | IntegerDesc->Integer.Value = InitialValue; |
241 | return_PTR (IntegerDesc); |
242 | } |
243 | |
244 | |
245 | /******************************************************************************* |
246 | * |
247 | * FUNCTION: AcpiUtCreateBufferObject |
248 | * |
249 | * PARAMETERS: BufferSize - Size of buffer to be created |
250 | * |
251 | * RETURN: Pointer to a new Buffer object, null on failure |
252 | * |
253 | * DESCRIPTION: Create a fully initialized buffer object |
254 | * |
255 | ******************************************************************************/ |
256 | |
257 | ACPI_OPERAND_OBJECT * |
258 | AcpiUtCreateBufferObject ( |
259 | ACPI_SIZE BufferSize) |
260 | { |
261 | ACPI_OPERAND_OBJECT *BufferDesc; |
262 | UINT8 *Buffer = NULL; |
263 | |
264 | |
265 | ACPI_FUNCTION_TRACE_U32 (UtCreateBufferObject, BufferSize); |
266 | |
267 | |
268 | /* Create a new Buffer object */ |
269 | |
270 | BufferDesc = AcpiUtCreateInternalObject (ACPI_TYPE_BUFFER); |
271 | if (!BufferDesc) |
272 | { |
273 | return_PTR (NULL); |
274 | } |
275 | |
276 | /* Create an actual buffer only if size > 0 */ |
277 | |
278 | if (BufferSize > 0) |
279 | { |
280 | /* Allocate the actual buffer */ |
281 | |
282 | Buffer = ACPI_ALLOCATE_ZEROED (BufferSize); |
283 | if (!Buffer) |
284 | { |
285 | ACPI_ERROR ((AE_INFO, "Could not allocate size %u" , |
286 | (UINT32) BufferSize)); |
287 | |
288 | AcpiUtRemoveReference (BufferDesc); |
289 | return_PTR (NULL); |
290 | } |
291 | } |
292 | |
293 | /* Complete buffer object initialization */ |
294 | |
295 | BufferDesc->Buffer.Flags |= AOPOBJ_DATA_VALID; |
296 | BufferDesc->Buffer.Pointer = Buffer; |
297 | BufferDesc->Buffer.Length = (UINT32) BufferSize; |
298 | |
299 | /* Return the new buffer descriptor */ |
300 | |
301 | return_PTR (BufferDesc); |
302 | } |
303 | |
304 | |
305 | /******************************************************************************* |
306 | * |
307 | * FUNCTION: AcpiUtCreateStringObject |
308 | * |
309 | * PARAMETERS: StringSize - Size of string to be created. Does not |
310 | * include NULL terminator, this is added |
311 | * automatically. |
312 | * |
313 | * RETURN: Pointer to a new String object |
314 | * |
315 | * DESCRIPTION: Create a fully initialized string object |
316 | * |
317 | ******************************************************************************/ |
318 | |
319 | ACPI_OPERAND_OBJECT * |
320 | AcpiUtCreateStringObject ( |
321 | ACPI_SIZE StringSize) |
322 | { |
323 | ACPI_OPERAND_OBJECT *StringDesc; |
324 | char *String; |
325 | |
326 | |
327 | ACPI_FUNCTION_TRACE_U32 (UtCreateStringObject, StringSize); |
328 | |
329 | |
330 | /* Create a new String object */ |
331 | |
332 | StringDesc = AcpiUtCreateInternalObject (ACPI_TYPE_STRING); |
333 | if (!StringDesc) |
334 | { |
335 | return_PTR (NULL); |
336 | } |
337 | |
338 | /* |
339 | * Allocate the actual string buffer -- (Size + 1) for NULL terminator. |
340 | * NOTE: Zero-length strings are NULL terminated |
341 | */ |
342 | String = ACPI_ALLOCATE_ZEROED (StringSize + 1); |
343 | if (!String) |
344 | { |
345 | ACPI_ERROR ((AE_INFO, "Could not allocate size %u" , |
346 | (UINT32) StringSize)); |
347 | |
348 | AcpiUtRemoveReference (StringDesc); |
349 | return_PTR (NULL); |
350 | } |
351 | |
352 | /* Complete string object initialization */ |
353 | |
354 | StringDesc->String.Pointer = String; |
355 | StringDesc->String.Length = (UINT32) StringSize; |
356 | |
357 | /* Return the new string descriptor */ |
358 | |
359 | return_PTR (StringDesc); |
360 | } |
361 | |
362 | |
363 | /******************************************************************************* |
364 | * |
365 | * FUNCTION: AcpiUtValidInternalObject |
366 | * |
367 | * PARAMETERS: Object - Object to be validated |
368 | * |
369 | * RETURN: TRUE if object is valid, FALSE otherwise |
370 | * |
371 | * DESCRIPTION: Validate a pointer to be of type ACPI_OPERAND_OBJECT |
372 | * |
373 | ******************************************************************************/ |
374 | |
375 | BOOLEAN |
376 | AcpiUtValidInternalObject ( |
377 | void *Object) |
378 | { |
379 | |
380 | ACPI_FUNCTION_NAME (UtValidInternalObject); |
381 | |
382 | |
383 | /* Check for a null pointer */ |
384 | |
385 | if (!Object) |
386 | { |
387 | ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "**** Null Object Ptr\n" )); |
388 | return (FALSE); |
389 | } |
390 | |
391 | /* Check the descriptor type field */ |
392 | |
393 | switch (ACPI_GET_DESCRIPTOR_TYPE (Object)) |
394 | { |
395 | case ACPI_DESC_TYPE_OPERAND: |
396 | |
397 | /* The object appears to be a valid ACPI_OPERAND_OBJECT */ |
398 | |
399 | return (TRUE); |
400 | |
401 | default: |
402 | |
403 | ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, |
404 | "%p is not an ACPI operand obj [%s]\n" , |
405 | Object, AcpiUtGetDescriptorName (Object))); |
406 | break; |
407 | } |
408 | |
409 | return (FALSE); |
410 | } |
411 | |
412 | |
413 | /******************************************************************************* |
414 | * |
415 | * FUNCTION: AcpiUtAllocateObjectDescDbg |
416 | * |
417 | * PARAMETERS: ModuleName - Caller's module name (for error output) |
418 | * LineNumber - Caller's line number (for error output) |
419 | * ComponentId - Caller's component ID (for error output) |
420 | * |
421 | * RETURN: Pointer to newly allocated object descriptor. Null on error |
422 | * |
423 | * DESCRIPTION: Allocate a new object descriptor. Gracefully handle |
424 | * error conditions. |
425 | * |
426 | ******************************************************************************/ |
427 | |
428 | void * |
429 | AcpiUtAllocateObjectDescDbg ( |
430 | const char *ModuleName, |
431 | UINT32 LineNumber, |
432 | UINT32 ComponentId) |
433 | { |
434 | ACPI_OPERAND_OBJECT *Object; |
435 | |
436 | |
437 | ACPI_FUNCTION_TRACE (UtAllocateObjectDescDbg); |
438 | |
439 | |
440 | Object = AcpiOsAcquireObject (AcpiGbl_OperandCache); |
441 | if (!Object) |
442 | { |
443 | ACPI_ERROR ((ModuleName, LineNumber, |
444 | "Could not allocate an object descriptor" )); |
445 | |
446 | return_PTR (NULL); |
447 | } |
448 | |
449 | /* Mark the descriptor type */ |
450 | |
451 | ACPI_SET_DESCRIPTOR_TYPE (Object, ACPI_DESC_TYPE_OPERAND); |
452 | |
453 | ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "%p Size %X\n" , |
454 | Object, (UINT32) sizeof (ACPI_OPERAND_OBJECT))); |
455 | |
456 | return_PTR (Object); |
457 | } |
458 | |
459 | |
460 | /******************************************************************************* |
461 | * |
462 | * FUNCTION: AcpiUtDeleteObjectDesc |
463 | * |
464 | * PARAMETERS: Object - An Acpi internal object to be deleted |
465 | * |
466 | * RETURN: None. |
467 | * |
468 | * DESCRIPTION: Free an ACPI object descriptor or add it to the object cache |
469 | * |
470 | ******************************************************************************/ |
471 | |
472 | void |
473 | AcpiUtDeleteObjectDesc ( |
474 | ACPI_OPERAND_OBJECT *Object) |
475 | { |
476 | ACPI_FUNCTION_TRACE_PTR (UtDeleteObjectDesc, Object); |
477 | |
478 | |
479 | /* Object must be of type ACPI_OPERAND_OBJECT */ |
480 | |
481 | if (ACPI_GET_DESCRIPTOR_TYPE (Object) != ACPI_DESC_TYPE_OPERAND) |
482 | { |
483 | ACPI_ERROR ((AE_INFO, |
484 | "%p is not an ACPI Operand object [%s]" , Object, |
485 | AcpiUtGetDescriptorName (Object))); |
486 | return_VOID; |
487 | } |
488 | |
489 | (void) AcpiOsReleaseObject (AcpiGbl_OperandCache, Object); |
490 | return_VOID; |
491 | } |
492 | |
493 | |
494 | /******************************************************************************* |
495 | * |
496 | * FUNCTION: AcpiUtGetSimpleObjectSize |
497 | * |
498 | * PARAMETERS: InternalObject - An ACPI operand object |
499 | * ObjLength - Where the length is returned |
500 | * |
501 | * RETURN: Status |
502 | * |
503 | * DESCRIPTION: This function is called to determine the space required to |
504 | * contain a simple object for return to an external user. |
505 | * |
506 | * The length includes the object structure plus any additional |
507 | * needed space. |
508 | * |
509 | ******************************************************************************/ |
510 | |
511 | static ACPI_STATUS |
512 | AcpiUtGetSimpleObjectSize ( |
513 | ACPI_OPERAND_OBJECT *InternalObject, |
514 | ACPI_SIZE *ObjLength) |
515 | { |
516 | ACPI_SIZE Length; |
517 | ACPI_SIZE Size; |
518 | ACPI_STATUS Status = AE_OK; |
519 | |
520 | |
521 | ACPI_FUNCTION_TRACE_PTR (UtGetSimpleObjectSize, InternalObject); |
522 | |
523 | |
524 | /* Start with the length of the (external) Acpi object */ |
525 | |
526 | Length = sizeof (ACPI_OBJECT); |
527 | |
528 | /* A NULL object is allowed, can be a legal uninitialized package element */ |
529 | |
530 | if (!InternalObject) |
531 | { |
532 | /* |
533 | * Object is NULL, just return the length of ACPI_OBJECT |
534 | * (A NULL ACPI_OBJECT is an object of all zeroes.) |
535 | */ |
536 | *ObjLength = ACPI_ROUND_UP_TO_NATIVE_WORD (Length); |
537 | return_ACPI_STATUS (AE_OK); |
538 | } |
539 | |
540 | /* A Namespace Node should never appear here */ |
541 | |
542 | if (ACPI_GET_DESCRIPTOR_TYPE (InternalObject) == ACPI_DESC_TYPE_NAMED) |
543 | { |
544 | /* A namespace node should never get here */ |
545 | |
546 | return_ACPI_STATUS (AE_AML_INTERNAL); |
547 | } |
548 | |
549 | /* |
550 | * The final length depends on the object type |
551 | * Strings and Buffers are packed right up against the parent object and |
552 | * must be accessed bytewise or there may be alignment problems on |
553 | * certain processors |
554 | */ |
555 | switch (InternalObject->Common.Type) |
556 | { |
557 | case ACPI_TYPE_STRING: |
558 | |
559 | Length += (ACPI_SIZE) InternalObject->String.Length + 1; |
560 | break; |
561 | |
562 | case ACPI_TYPE_BUFFER: |
563 | |
564 | Length += (ACPI_SIZE) InternalObject->Buffer.Length; |
565 | break; |
566 | |
567 | case ACPI_TYPE_INTEGER: |
568 | case ACPI_TYPE_PROCESSOR: |
569 | case ACPI_TYPE_POWER: |
570 | |
571 | /* No extra data for these types */ |
572 | |
573 | break; |
574 | |
575 | case ACPI_TYPE_LOCAL_REFERENCE: |
576 | |
577 | switch (InternalObject->Reference.Class) |
578 | { |
579 | case ACPI_REFCLASS_NAME: |
580 | /* |
581 | * Get the actual length of the full pathname to this object. |
582 | * The reference will be converted to the pathname to the object |
583 | */ |
584 | Size = AcpiNsGetPathnameLength (InternalObject->Reference.Node); |
585 | if (!Size) |
586 | { |
587 | return_ACPI_STATUS (AE_BAD_PARAMETER); |
588 | } |
589 | |
590 | Length += ACPI_ROUND_UP_TO_NATIVE_WORD (Size); |
591 | break; |
592 | |
593 | default: |
594 | /* |
595 | * No other reference opcodes are supported. |
596 | * Notably, Locals and Args are not supported, but this may be |
597 | * required eventually. |
598 | */ |
599 | ACPI_ERROR ((AE_INFO, "Cannot convert to external object - " |
600 | "unsupported Reference Class [%s] 0x%X in object %p" , |
601 | AcpiUtGetReferenceName (InternalObject), |
602 | InternalObject->Reference.Class, InternalObject)); |
603 | Status = AE_TYPE; |
604 | break; |
605 | } |
606 | break; |
607 | |
608 | default: |
609 | |
610 | ACPI_ERROR ((AE_INFO, "Cannot convert to external object - " |
611 | "unsupported type [%s] 0x%X in object %p" , |
612 | AcpiUtGetObjectTypeName (InternalObject), |
613 | InternalObject->Common.Type, InternalObject)); |
614 | Status = AE_TYPE; |
615 | break; |
616 | } |
617 | |
618 | /* |
619 | * Account for the space required by the object rounded up to the next |
620 | * multiple of the machine word size. This keeps each object aligned |
621 | * on a machine word boundary. (preventing alignment faults on some |
622 | * machines.) |
623 | */ |
624 | *ObjLength = ACPI_ROUND_UP_TO_NATIVE_WORD (Length); |
625 | return_ACPI_STATUS (Status); |
626 | } |
627 | |
628 | |
629 | /******************************************************************************* |
630 | * |
631 | * FUNCTION: AcpiUtGetElementLength |
632 | * |
633 | * PARAMETERS: ACPI_PKG_CALLBACK |
634 | * |
635 | * RETURN: Status |
636 | * |
637 | * DESCRIPTION: Get the length of one package element. |
638 | * |
639 | ******************************************************************************/ |
640 | |
641 | static ACPI_STATUS |
642 | AcpiUtGetElementLength ( |
643 | UINT8 ObjectType, |
644 | ACPI_OPERAND_OBJECT *SourceObject, |
645 | ACPI_GENERIC_STATE *State, |
646 | void *Context) |
647 | { |
648 | ACPI_STATUS Status = AE_OK; |
649 | ACPI_PKG_INFO *Info = (ACPI_PKG_INFO *) Context; |
650 | ACPI_SIZE ObjectSpace; |
651 | |
652 | |
653 | switch (ObjectType) |
654 | { |
655 | case ACPI_COPY_TYPE_SIMPLE: |
656 | /* |
657 | * Simple object - just get the size (Null object/entry is handled |
658 | * here also) and sum it into the running package length |
659 | */ |
660 | Status = AcpiUtGetSimpleObjectSize (SourceObject, &ObjectSpace); |
661 | if (ACPI_FAILURE (Status)) |
662 | { |
663 | return (Status); |
664 | } |
665 | |
666 | Info->Length += ObjectSpace; |
667 | break; |
668 | |
669 | case ACPI_COPY_TYPE_PACKAGE: |
670 | |
671 | /* Package object - nothing much to do here, let the walk handle it */ |
672 | |
673 | Info->NumPackages++; |
674 | State->Pkg.ThisTargetObj = NULL; |
675 | break; |
676 | |
677 | default: |
678 | |
679 | /* No other types allowed */ |
680 | |
681 | return (AE_BAD_PARAMETER); |
682 | } |
683 | |
684 | return (Status); |
685 | } |
686 | |
687 | |
688 | /******************************************************************************* |
689 | * |
690 | * FUNCTION: AcpiUtGetPackageObjectSize |
691 | * |
692 | * PARAMETERS: InternalObject - An ACPI internal object |
693 | * ObjLength - Where the length is returned |
694 | * |
695 | * RETURN: Status |
696 | * |
697 | * DESCRIPTION: This function is called to determine the space required to |
698 | * contain a package object for return to an external user. |
699 | * |
700 | * This is moderately complex since a package contains other |
701 | * objects including packages. |
702 | * |
703 | ******************************************************************************/ |
704 | |
705 | static ACPI_STATUS |
706 | AcpiUtGetPackageObjectSize ( |
707 | ACPI_OPERAND_OBJECT *InternalObject, |
708 | ACPI_SIZE *ObjLength) |
709 | { |
710 | ACPI_STATUS Status; |
711 | ACPI_PKG_INFO Info; |
712 | |
713 | |
714 | ACPI_FUNCTION_TRACE_PTR (UtGetPackageObjectSize, InternalObject); |
715 | |
716 | |
717 | Info.Length = 0; |
718 | Info.ObjectSpace = 0; |
719 | Info.NumPackages = 1; |
720 | |
721 | Status = AcpiUtWalkPackageTree ( |
722 | InternalObject, NULL, AcpiUtGetElementLength, &Info); |
723 | if (ACPI_FAILURE (Status)) |
724 | { |
725 | return_ACPI_STATUS (Status); |
726 | } |
727 | |
728 | /* |
729 | * We have handled all of the objects in all levels of the package. |
730 | * just add the length of the package objects themselves. |
731 | * Round up to the next machine word. |
732 | */ |
733 | Info.Length += ACPI_ROUND_UP_TO_NATIVE_WORD ( |
734 | sizeof (ACPI_OBJECT)) * (ACPI_SIZE) Info.NumPackages; |
735 | |
736 | /* Return the total package length */ |
737 | |
738 | *ObjLength = Info.Length; |
739 | return_ACPI_STATUS (Status); |
740 | } |
741 | |
742 | |
743 | /******************************************************************************* |
744 | * |
745 | * FUNCTION: AcpiUtGetObjectSize |
746 | * |
747 | * PARAMETERS: InternalObject - An ACPI internal object |
748 | * ObjLength - Where the length will be returned |
749 | * |
750 | * RETURN: Status |
751 | * |
752 | * DESCRIPTION: This function is called to determine the space required to |
753 | * contain an object for return to an API user. |
754 | * |
755 | ******************************************************************************/ |
756 | |
757 | ACPI_STATUS |
758 | AcpiUtGetObjectSize ( |
759 | ACPI_OPERAND_OBJECT *InternalObject, |
760 | ACPI_SIZE *ObjLength) |
761 | { |
762 | ACPI_STATUS Status; |
763 | |
764 | |
765 | ACPI_FUNCTION_ENTRY (); |
766 | |
767 | |
768 | if ((ACPI_GET_DESCRIPTOR_TYPE (InternalObject) == |
769 | ACPI_DESC_TYPE_OPERAND) && |
770 | (InternalObject->Common.Type == ACPI_TYPE_PACKAGE)) |
771 | { |
772 | Status = AcpiUtGetPackageObjectSize (InternalObject, ObjLength); |
773 | } |
774 | else |
775 | { |
776 | Status = AcpiUtGetSimpleObjectSize (InternalObject, ObjLength); |
777 | } |
778 | |
779 | return (Status); |
780 | } |
781 | |