1 | /****************************************************************************** |
2 | * |
3 | * Module Name: nsprepkg - Validation of package objects for predefined names |
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 | #include "acpredef.h" |
48 | |
49 | |
50 | #define _COMPONENT ACPI_NAMESPACE |
51 | ACPI_MODULE_NAME ("nsprepkg" ) |
52 | |
53 | |
54 | /* Local prototypes */ |
55 | |
56 | static ACPI_STATUS |
57 | AcpiNsCheckPackageList ( |
58 | ACPI_EVALUATE_INFO *Info, |
59 | const ACPI_PREDEFINED_INFO *Package, |
60 | ACPI_OPERAND_OBJECT **Elements, |
61 | UINT32 Count); |
62 | |
63 | static ACPI_STATUS |
64 | AcpiNsCheckPackageElements ( |
65 | ACPI_EVALUATE_INFO *Info, |
66 | ACPI_OPERAND_OBJECT **Elements, |
67 | UINT8 Type1, |
68 | UINT32 Count1, |
69 | UINT8 Type2, |
70 | UINT32 Count2, |
71 | UINT32 StartIndex); |
72 | |
73 | static ACPI_STATUS |
74 | AcpiNsCustomPackage ( |
75 | ACPI_EVALUATE_INFO *Info, |
76 | ACPI_OPERAND_OBJECT **Elements, |
77 | UINT32 Count); |
78 | |
79 | |
80 | /******************************************************************************* |
81 | * |
82 | * FUNCTION: AcpiNsCheckPackage |
83 | * |
84 | * PARAMETERS: Info - Method execution information block |
85 | * ReturnObjectPtr - Pointer to the object returned from the |
86 | * evaluation of a method or object |
87 | * |
88 | * RETURN: Status |
89 | * |
90 | * DESCRIPTION: Check a returned package object for the correct count and |
91 | * correct type of all sub-objects. |
92 | * |
93 | ******************************************************************************/ |
94 | |
95 | ACPI_STATUS |
96 | AcpiNsCheckPackage ( |
97 | ACPI_EVALUATE_INFO *Info, |
98 | ACPI_OPERAND_OBJECT **ReturnObjectPtr) |
99 | { |
100 | ACPI_OPERAND_OBJECT *ReturnObject = *ReturnObjectPtr; |
101 | const ACPI_PREDEFINED_INFO *Package; |
102 | ACPI_OPERAND_OBJECT **Elements; |
103 | ACPI_STATUS Status = AE_OK; |
104 | UINT32 ExpectedCount; |
105 | UINT32 Count; |
106 | UINT32 i; |
107 | |
108 | |
109 | ACPI_FUNCTION_NAME (NsCheckPackage); |
110 | |
111 | |
112 | /* The package info for this name is in the next table entry */ |
113 | |
114 | Package = Info->Predefined + 1; |
115 | |
116 | ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, |
117 | "%s Validating return Package of Type %X, Count %X\n" , |
118 | Info->FullPathname, Package->RetInfo.Type, |
119 | ReturnObject->Package.Count)); |
120 | |
121 | /* |
122 | * For variable-length Packages, we can safely remove all embedded |
123 | * and trailing NULL package elements |
124 | */ |
125 | AcpiNsRemoveNullElements (Info, Package->RetInfo.Type, ReturnObject); |
126 | |
127 | /* Extract package count and elements array */ |
128 | |
129 | Elements = ReturnObject->Package.Elements; |
130 | Count = ReturnObject->Package.Count; |
131 | |
132 | /* |
133 | * Most packages must have at least one element. The only exception |
134 | * is the variable-length package (ACPI_PTYPE1_VAR). |
135 | */ |
136 | if (!Count) |
137 | { |
138 | if (Package->RetInfo.Type == ACPI_PTYPE1_VAR) |
139 | { |
140 | return (AE_OK); |
141 | } |
142 | |
143 | ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname, Info->NodeFlags, |
144 | "Return Package has no elements (empty)" )); |
145 | |
146 | return (AE_AML_OPERAND_VALUE); |
147 | } |
148 | |
149 | /* |
150 | * Decode the type of the expected package contents |
151 | * |
152 | * PTYPE1 packages contain no subpackages |
153 | * PTYPE2 packages contain subpackages |
154 | */ |
155 | switch (Package->RetInfo.Type) |
156 | { |
157 | case ACPI_PTYPE_CUSTOM: |
158 | |
159 | Status = AcpiNsCustomPackage (Info, Elements, Count); |
160 | break; |
161 | |
162 | case ACPI_PTYPE1_FIXED: |
163 | /* |
164 | * The package count is fixed and there are no subpackages |
165 | * |
166 | * If package is too small, exit. |
167 | * If package is larger than expected, issue warning but continue |
168 | */ |
169 | ExpectedCount = Package->RetInfo.Count1 + Package->RetInfo.Count2; |
170 | if (Count < ExpectedCount) |
171 | { |
172 | goto PackageTooSmall; |
173 | } |
174 | else if (Count > ExpectedCount) |
175 | { |
176 | ACPI_DEBUG_PRINT ((ACPI_DB_REPAIR, |
177 | "%s: Return Package is larger than needed - " |
178 | "found %u, expected %u\n" , |
179 | Info->FullPathname, Count, ExpectedCount)); |
180 | } |
181 | |
182 | /* Validate all elements of the returned package */ |
183 | |
184 | Status = AcpiNsCheckPackageElements (Info, Elements, |
185 | Package->RetInfo.ObjectType1, Package->RetInfo.Count1, |
186 | Package->RetInfo.ObjectType2, Package->RetInfo.Count2, 0); |
187 | break; |
188 | |
189 | case ACPI_PTYPE1_VAR: |
190 | /* |
191 | * The package count is variable, there are no subpackages, and all |
192 | * elements must be of the same type |
193 | */ |
194 | for (i = 0; i < Count; i++) |
195 | { |
196 | Status = AcpiNsCheckObjectType (Info, Elements, |
197 | Package->RetInfo.ObjectType1, i); |
198 | if (ACPI_FAILURE (Status)) |
199 | { |
200 | return (Status); |
201 | } |
202 | |
203 | Elements++; |
204 | } |
205 | break; |
206 | |
207 | case ACPI_PTYPE1_OPTION: |
208 | /* |
209 | * The package count is variable, there are no subpackages. There are |
210 | * a fixed number of required elements, and a variable number of |
211 | * optional elements. |
212 | * |
213 | * Check if package is at least as large as the minimum required |
214 | */ |
215 | ExpectedCount = Package->RetInfo3.Count; |
216 | if (Count < ExpectedCount) |
217 | { |
218 | goto PackageTooSmall; |
219 | } |
220 | |
221 | /* Variable number of sub-objects */ |
222 | |
223 | for (i = 0; i < Count; i++) |
224 | { |
225 | if (i < Package->RetInfo3.Count) |
226 | { |
227 | /* These are the required package elements (0, 1, or 2) */ |
228 | |
229 | Status = AcpiNsCheckObjectType (Info, Elements, |
230 | Package->RetInfo3.ObjectType[i], i); |
231 | if (ACPI_FAILURE (Status)) |
232 | { |
233 | return (Status); |
234 | } |
235 | } |
236 | else |
237 | { |
238 | /* These are the optional package elements */ |
239 | |
240 | Status = AcpiNsCheckObjectType (Info, Elements, |
241 | Package->RetInfo3.TailObjectType, i); |
242 | if (ACPI_FAILURE (Status)) |
243 | { |
244 | return (Status); |
245 | } |
246 | } |
247 | |
248 | Elements++; |
249 | } |
250 | break; |
251 | |
252 | case ACPI_PTYPE2_REV_FIXED: |
253 | |
254 | /* First element is the (Integer) revision */ |
255 | |
256 | Status = AcpiNsCheckObjectType ( |
257 | Info, Elements, ACPI_RTYPE_INTEGER, 0); |
258 | if (ACPI_FAILURE (Status)) |
259 | { |
260 | return (Status); |
261 | } |
262 | |
263 | Elements++; |
264 | Count--; |
265 | |
266 | /* Examine the subpackages */ |
267 | |
268 | Status = AcpiNsCheckPackageList (Info, Package, Elements, Count); |
269 | break; |
270 | |
271 | case ACPI_PTYPE2_PKG_COUNT: |
272 | |
273 | /* First element is the (Integer) count of subpackages to follow */ |
274 | |
275 | Status = AcpiNsCheckObjectType ( |
276 | Info, Elements, ACPI_RTYPE_INTEGER, 0); |
277 | if (ACPI_FAILURE (Status)) |
278 | { |
279 | return (Status); |
280 | } |
281 | |
282 | /* |
283 | * Count cannot be larger than the parent package length, but allow it |
284 | * to be smaller. The >= accounts for the Integer above. |
285 | */ |
286 | ExpectedCount = (UINT32) (*Elements)->Integer.Value; |
287 | if (ExpectedCount >= Count) |
288 | { |
289 | goto PackageTooSmall; |
290 | } |
291 | |
292 | Count = ExpectedCount; |
293 | Elements++; |
294 | |
295 | /* Examine the subpackages */ |
296 | |
297 | Status = AcpiNsCheckPackageList (Info, Package, Elements, Count); |
298 | break; |
299 | |
300 | case ACPI_PTYPE2: |
301 | case ACPI_PTYPE2_FIXED: |
302 | case ACPI_PTYPE2_MIN: |
303 | case ACPI_PTYPE2_COUNT: |
304 | case ACPI_PTYPE2_FIX_VAR: |
305 | /* |
306 | * These types all return a single Package that consists of a |
307 | * variable number of subpackages. |
308 | * |
309 | * First, ensure that the first element is a subpackage. If not, |
310 | * the BIOS may have incorrectly returned the object as a single |
311 | * package instead of a Package of Packages (a common error if |
312 | * there is only one entry). We may be able to repair this by |
313 | * wrapping the returned Package with a new outer Package. |
314 | */ |
315 | if (*Elements && ((*Elements)->Common.Type != ACPI_TYPE_PACKAGE)) |
316 | { |
317 | /* Create the new outer package and populate it */ |
318 | |
319 | Status = AcpiNsWrapWithPackage ( |
320 | Info, ReturnObject, ReturnObjectPtr); |
321 | if (ACPI_FAILURE (Status)) |
322 | { |
323 | return (Status); |
324 | } |
325 | |
326 | /* Update locals to point to the new package (of 1 element) */ |
327 | |
328 | ReturnObject = *ReturnObjectPtr; |
329 | Elements = ReturnObject->Package.Elements; |
330 | Count = 1; |
331 | } |
332 | |
333 | /* Examine the subpackages */ |
334 | |
335 | Status = AcpiNsCheckPackageList (Info, Package, Elements, Count); |
336 | break; |
337 | |
338 | case ACPI_PTYPE2_VAR_VAR: |
339 | /* |
340 | * Returns a variable list of packages, each with a variable list |
341 | * of objects. |
342 | */ |
343 | break; |
344 | |
345 | case ACPI_PTYPE2_UUID_PAIR: |
346 | |
347 | /* The package must contain pairs of (UUID + type) */ |
348 | |
349 | if (Count & 1) |
350 | { |
351 | ExpectedCount = Count + 1; |
352 | goto PackageTooSmall; |
353 | } |
354 | |
355 | while (Count > 0) |
356 | { |
357 | Status = AcpiNsCheckObjectType(Info, Elements, |
358 | Package->RetInfo.ObjectType1, 0); |
359 | if (ACPI_FAILURE(Status)) |
360 | { |
361 | return (Status); |
362 | } |
363 | |
364 | /* Validate length of the UUID buffer */ |
365 | |
366 | if ((*Elements)->Buffer.Length != 16) |
367 | { |
368 | ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname, |
369 | Info->NodeFlags, "Invalid length for UUID Buffer" )); |
370 | return (AE_AML_OPERAND_VALUE); |
371 | } |
372 | |
373 | Status = AcpiNsCheckObjectType(Info, Elements + 1, |
374 | Package->RetInfo.ObjectType2, 0); |
375 | if (ACPI_FAILURE(Status)) |
376 | { |
377 | return (Status); |
378 | } |
379 | |
380 | Elements += 2; |
381 | Count -= 2; |
382 | } |
383 | break; |
384 | |
385 | default: |
386 | |
387 | /* Should not get here if predefined info table is correct */ |
388 | |
389 | ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname, Info->NodeFlags, |
390 | "Invalid internal return type in table entry: %X" , |
391 | Package->RetInfo.Type)); |
392 | |
393 | return (AE_AML_INTERNAL); |
394 | } |
395 | |
396 | return (Status); |
397 | |
398 | |
399 | PackageTooSmall: |
400 | |
401 | /* Error exit for the case with an incorrect package count */ |
402 | |
403 | ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname, Info->NodeFlags, |
404 | "Return Package is too small - found %u elements, expected %u" , |
405 | Count, ExpectedCount)); |
406 | |
407 | return (AE_AML_OPERAND_VALUE); |
408 | } |
409 | |
410 | |
411 | /******************************************************************************* |
412 | * |
413 | * FUNCTION: AcpiNsCheckPackageList |
414 | * |
415 | * PARAMETERS: Info - Method execution information block |
416 | * Package - Pointer to package-specific info for method |
417 | * Elements - Element list of parent package. All elements |
418 | * of this list should be of type Package. |
419 | * Count - Count of subpackages |
420 | * |
421 | * RETURN: Status |
422 | * |
423 | * DESCRIPTION: Examine a list of subpackages |
424 | * |
425 | ******************************************************************************/ |
426 | |
427 | static ACPI_STATUS |
428 | AcpiNsCheckPackageList ( |
429 | ACPI_EVALUATE_INFO *Info, |
430 | const ACPI_PREDEFINED_INFO *Package, |
431 | ACPI_OPERAND_OBJECT **Elements, |
432 | UINT32 Count) |
433 | { |
434 | ACPI_OPERAND_OBJECT *SubPackage; |
435 | ACPI_OPERAND_OBJECT **SubElements; |
436 | ACPI_STATUS Status; |
437 | UINT32 ExpectedCount; |
438 | UINT32 i; |
439 | UINT32 j; |
440 | |
441 | |
442 | /* |
443 | * Validate each subpackage in the parent Package |
444 | * |
445 | * NOTE: assumes list of subpackages contains no NULL elements. |
446 | * Any NULL elements should have been removed by earlier call |
447 | * to AcpiNsRemoveNullElements. |
448 | */ |
449 | for (i = 0; i < Count; i++) |
450 | { |
451 | SubPackage = *Elements; |
452 | SubElements = SubPackage->Package.Elements; |
453 | Info->ParentPackage = SubPackage; |
454 | |
455 | /* Each sub-object must be of type Package */ |
456 | |
457 | Status = AcpiNsCheckObjectType (Info, &SubPackage, |
458 | ACPI_RTYPE_PACKAGE, i); |
459 | if (ACPI_FAILURE (Status)) |
460 | { |
461 | return (Status); |
462 | } |
463 | |
464 | /* Examine the different types of expected subpackages */ |
465 | |
466 | Info->ParentPackage = SubPackage; |
467 | switch (Package->RetInfo.Type) |
468 | { |
469 | case ACPI_PTYPE2: |
470 | case ACPI_PTYPE2_PKG_COUNT: |
471 | case ACPI_PTYPE2_REV_FIXED: |
472 | |
473 | /* Each subpackage has a fixed number of elements */ |
474 | |
475 | ExpectedCount = Package->RetInfo.Count1 + Package->RetInfo.Count2; |
476 | if (SubPackage->Package.Count < ExpectedCount) |
477 | { |
478 | goto PackageTooSmall; |
479 | } |
480 | |
481 | Status = AcpiNsCheckPackageElements (Info, SubElements, |
482 | Package->RetInfo.ObjectType1, |
483 | Package->RetInfo.Count1, |
484 | Package->RetInfo.ObjectType2, |
485 | Package->RetInfo.Count2, 0); |
486 | if (ACPI_FAILURE (Status)) |
487 | { |
488 | return (Status); |
489 | } |
490 | break; |
491 | |
492 | case ACPI_PTYPE2_FIX_VAR: |
493 | /* |
494 | * Each subpackage has a fixed number of elements and an |
495 | * optional element |
496 | */ |
497 | ExpectedCount = Package->RetInfo.Count1 + Package->RetInfo.Count2; |
498 | if (SubPackage->Package.Count < ExpectedCount) |
499 | { |
500 | goto PackageTooSmall; |
501 | } |
502 | |
503 | Status = AcpiNsCheckPackageElements (Info, SubElements, |
504 | Package->RetInfo.ObjectType1, |
505 | Package->RetInfo.Count1, |
506 | Package->RetInfo.ObjectType2, |
507 | SubPackage->Package.Count - Package->RetInfo.Count1, 0); |
508 | if (ACPI_FAILURE (Status)) |
509 | { |
510 | return (Status); |
511 | } |
512 | break; |
513 | |
514 | case ACPI_PTYPE2_VAR_VAR: |
515 | /* |
516 | * Each subpackage has a fixed or variable number of elements |
517 | */ |
518 | break; |
519 | |
520 | case ACPI_PTYPE2_FIXED: |
521 | |
522 | /* Each subpackage has a fixed length */ |
523 | |
524 | ExpectedCount = Package->RetInfo2.Count; |
525 | if (SubPackage->Package.Count < ExpectedCount) |
526 | { |
527 | goto PackageTooSmall; |
528 | } |
529 | |
530 | /* Check the type of each subpackage element */ |
531 | |
532 | for (j = 0; j < ExpectedCount; j++) |
533 | { |
534 | Status = AcpiNsCheckObjectType (Info, &SubElements[j], |
535 | Package->RetInfo2.ObjectType[j], j); |
536 | if (ACPI_FAILURE (Status)) |
537 | { |
538 | return (Status); |
539 | } |
540 | } |
541 | break; |
542 | |
543 | case ACPI_PTYPE2_MIN: |
544 | |
545 | /* Each subpackage has a variable but minimum length */ |
546 | |
547 | ExpectedCount = Package->RetInfo.Count1; |
548 | if (SubPackage->Package.Count < ExpectedCount) |
549 | { |
550 | goto PackageTooSmall; |
551 | } |
552 | |
553 | /* Check the type of each subpackage element */ |
554 | |
555 | Status = AcpiNsCheckPackageElements (Info, SubElements, |
556 | Package->RetInfo.ObjectType1, |
557 | SubPackage->Package.Count, 0, 0, 0); |
558 | if (ACPI_FAILURE (Status)) |
559 | { |
560 | return (Status); |
561 | } |
562 | break; |
563 | |
564 | case ACPI_PTYPE2_COUNT: |
565 | /* |
566 | * First element is the (Integer) count of elements, including |
567 | * the count field (the ACPI name is NumElements) |
568 | */ |
569 | Status = AcpiNsCheckObjectType (Info, SubElements, |
570 | ACPI_RTYPE_INTEGER, 0); |
571 | if (ACPI_FAILURE (Status)) |
572 | { |
573 | return (Status); |
574 | } |
575 | |
576 | /* |
577 | * Make sure package is large enough for the Count and is |
578 | * is as large as the minimum size |
579 | */ |
580 | ExpectedCount = (UINT32) (*SubElements)->Integer.Value; |
581 | if (SubPackage->Package.Count < ExpectedCount) |
582 | { |
583 | goto PackageTooSmall; |
584 | } |
585 | |
586 | if (SubPackage->Package.Count < Package->RetInfo.Count1) |
587 | { |
588 | ExpectedCount = Package->RetInfo.Count1; |
589 | goto PackageTooSmall; |
590 | } |
591 | |
592 | if (ExpectedCount == 0) |
593 | { |
594 | /* |
595 | * Either the NumEntries element was originally zero or it was |
596 | * a NULL element and repaired to an Integer of value zero. |
597 | * In either case, repair it by setting NumEntries to be the |
598 | * actual size of the subpackage. |
599 | */ |
600 | ExpectedCount = SubPackage->Package.Count; |
601 | (*SubElements)->Integer.Value = ExpectedCount; |
602 | } |
603 | |
604 | /* Check the type of each subpackage element */ |
605 | |
606 | Status = AcpiNsCheckPackageElements (Info, (SubElements + 1), |
607 | Package->RetInfo.ObjectType1, |
608 | (ExpectedCount - 1), 0, 0, 1); |
609 | if (ACPI_FAILURE (Status)) |
610 | { |
611 | return (Status); |
612 | } |
613 | break; |
614 | |
615 | default: /* Should not get here, type was validated by caller */ |
616 | |
617 | return (AE_AML_INTERNAL); |
618 | } |
619 | |
620 | Elements++; |
621 | } |
622 | |
623 | return (AE_OK); |
624 | |
625 | |
626 | PackageTooSmall: |
627 | |
628 | /* The subpackage count was smaller than required */ |
629 | |
630 | ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname, Info->NodeFlags, |
631 | "Return SubPackage[%u] is too small - found %u elements, expected %u" , |
632 | i, SubPackage->Package.Count, ExpectedCount)); |
633 | |
634 | return (AE_AML_OPERAND_VALUE); |
635 | } |
636 | |
637 | |
638 | /******************************************************************************* |
639 | * |
640 | * FUNCTION: AcpiNsCustomPackage |
641 | * |
642 | * PARAMETERS: Info - Method execution information block |
643 | * Elements - Pointer to the package elements array |
644 | * Count - Element count for the package |
645 | * |
646 | * RETURN: Status |
647 | * |
648 | * DESCRIPTION: Check a returned package object for the correct count and |
649 | * correct type of all sub-objects. |
650 | * |
651 | * NOTE: Currently used for the _BIX method only. When needed for two or more |
652 | * methods, probably a detect/dispatch mechanism will be required. |
653 | * |
654 | ******************************************************************************/ |
655 | |
656 | static ACPI_STATUS |
657 | AcpiNsCustomPackage ( |
658 | ACPI_EVALUATE_INFO *Info, |
659 | ACPI_OPERAND_OBJECT **Elements, |
660 | UINT32 Count) |
661 | { |
662 | UINT32 ExpectedCount; |
663 | UINT32 Version; |
664 | ACPI_STATUS Status = AE_OK; |
665 | |
666 | |
667 | ACPI_FUNCTION_NAME (NsCustomPackage); |
668 | |
669 | |
670 | /* Get version number, must be Integer */ |
671 | |
672 | if ((*Elements)->Common.Type != ACPI_TYPE_INTEGER) |
673 | { |
674 | ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname, Info->NodeFlags, |
675 | "Return Package has invalid object type for version number" )); |
676 | return_ACPI_STATUS (AE_AML_OPERAND_TYPE); |
677 | } |
678 | |
679 | Version = (UINT32) (*Elements)->Integer.Value; |
680 | ExpectedCount = 21; /* Version 1 */ |
681 | |
682 | if (Version == 0) |
683 | { |
684 | ExpectedCount = 20; /* Version 0 */ |
685 | } |
686 | |
687 | if (Count < ExpectedCount) |
688 | { |
689 | ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname, Info->NodeFlags, |
690 | "Return Package is too small - found %u elements, expected %u" , |
691 | Count, ExpectedCount)); |
692 | return_ACPI_STATUS (AE_AML_OPERAND_VALUE); |
693 | } |
694 | else if (Count > ExpectedCount) |
695 | { |
696 | ACPI_DEBUG_PRINT ((ACPI_DB_REPAIR, |
697 | "%s: Return Package is larger than needed - " |
698 | "found %u, expected %u\n" , |
699 | Info->FullPathname, Count, ExpectedCount)); |
700 | } |
701 | |
702 | /* Validate all elements of the returned package */ |
703 | |
704 | Status = AcpiNsCheckPackageElements (Info, Elements, |
705 | ACPI_RTYPE_INTEGER, 16, |
706 | ACPI_RTYPE_STRING, 4, 0); |
707 | if (ACPI_FAILURE (Status)) |
708 | { |
709 | return_ACPI_STATUS (Status); |
710 | } |
711 | |
712 | /* Version 1 has a single trailing integer */ |
713 | |
714 | if (Version > 0) |
715 | { |
716 | Status = AcpiNsCheckPackageElements (Info, Elements + 20, |
717 | ACPI_RTYPE_INTEGER, 1, 0, 0, 20); |
718 | } |
719 | |
720 | return_ACPI_STATUS (Status); |
721 | } |
722 | |
723 | |
724 | /******************************************************************************* |
725 | * |
726 | * FUNCTION: AcpiNsCheckPackageElements |
727 | * |
728 | * PARAMETERS: Info - Method execution information block |
729 | * Elements - Pointer to the package elements array |
730 | * Type1 - Object type for first group |
731 | * Count1 - Count for first group |
732 | * Type2 - Object type for second group |
733 | * Count2 - Count for second group |
734 | * StartIndex - Start of the first group of elements |
735 | * |
736 | * RETURN: Status |
737 | * |
738 | * DESCRIPTION: Check that all elements of a package are of the correct object |
739 | * type. Supports up to two groups of different object types. |
740 | * |
741 | ******************************************************************************/ |
742 | |
743 | static ACPI_STATUS |
744 | AcpiNsCheckPackageElements ( |
745 | ACPI_EVALUATE_INFO *Info, |
746 | ACPI_OPERAND_OBJECT **Elements, |
747 | UINT8 Type1, |
748 | UINT32 Count1, |
749 | UINT8 Type2, |
750 | UINT32 Count2, |
751 | UINT32 StartIndex) |
752 | { |
753 | ACPI_OPERAND_OBJECT **ThisElement = Elements; |
754 | ACPI_STATUS Status; |
755 | UINT32 i; |
756 | |
757 | |
758 | /* |
759 | * Up to two groups of package elements are supported by the data |
760 | * structure. All elements in each group must be of the same type. |
761 | * The second group can have a count of zero. |
762 | */ |
763 | for (i = 0; i < Count1; i++) |
764 | { |
765 | Status = AcpiNsCheckObjectType (Info, ThisElement, |
766 | Type1, i + StartIndex); |
767 | if (ACPI_FAILURE (Status)) |
768 | { |
769 | return (Status); |
770 | } |
771 | |
772 | ThisElement++; |
773 | } |
774 | |
775 | for (i = 0; i < Count2; i++) |
776 | { |
777 | Status = AcpiNsCheckObjectType (Info, ThisElement, |
778 | Type2, (i + Count1 + StartIndex)); |
779 | if (ACPI_FAILURE (Status)) |
780 | { |
781 | return (Status); |
782 | } |
783 | |
784 | ThisElement++; |
785 | } |
786 | |
787 | return (AE_OK); |
788 | } |
789 | |