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