xref: /linux/drivers/acpi/acpica/tbfind.c (revision f86fd32d)
1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2 /******************************************************************************
3  *
4  * Module Name: tbfind   - find table
5  *
6  * Copyright (C) 2000 - 2020, Intel Corp.
7  *
8  *****************************************************************************/
9 
10 #include <acpi/acpi.h>
11 #include "accommon.h"
12 #include "actables.h"
13 
14 #define _COMPONENT          ACPI_TABLES
15 ACPI_MODULE_NAME("tbfind")
16 
17 /*******************************************************************************
18  *
19  * FUNCTION:    acpi_tb_find_table
20  *
21  * PARAMETERS:  signature           - String with ACPI table signature
22  *              oem_id              - String with the table OEM ID
23  *              oem_table_id        - String with the OEM Table ID
24  *              table_index         - Where the table index is returned
25  *
26  * RETURN:      Status and table index
27  *
28  * DESCRIPTION: Find an ACPI table (in the RSDT/XSDT) that matches the
29  *              Signature, OEM ID and OEM Table ID. Returns an index that can
30  *              be used to get the table header or entire table.
31  *
32  ******************************************************************************/
33 acpi_status
34 acpi_tb_find_table(char *signature,
35 		   char *oem_id, char *oem_table_id, u32 *table_index)
36 {
37 	acpi_status status = AE_OK;
38 	struct acpi_table_header header;
39 	u32 i;
40 
41 	ACPI_FUNCTION_TRACE(tb_find_table);
42 
43 	/* Validate the input table signature */
44 
45 	if (!acpi_ut_valid_nameseg(signature)) {
46 		return_ACPI_STATUS(AE_BAD_SIGNATURE);
47 	}
48 
49 	/* Don't allow the OEM strings to be too long */
50 
51 	if ((strlen(oem_id) > ACPI_OEM_ID_SIZE) ||
52 	    (strlen(oem_table_id) > ACPI_OEM_TABLE_ID_SIZE)) {
53 		return_ACPI_STATUS(AE_AML_STRING_LIMIT);
54 	}
55 
56 	/* Normalize the input strings */
57 
58 	memset(&header, 0, sizeof(struct acpi_table_header));
59 	ACPI_COPY_NAMESEG(header.signature, signature);
60 	strncpy(header.oem_id, oem_id, ACPI_OEM_ID_SIZE);
61 	strncpy(header.oem_table_id, oem_table_id, ACPI_OEM_TABLE_ID_SIZE);
62 
63 	/* Search for the table */
64 
65 	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
66 	for (i = 0; i < acpi_gbl_root_table_list.current_table_count; ++i) {
67 		if (memcmp(&(acpi_gbl_root_table_list.tables[i].signature),
68 			   header.signature, ACPI_NAMESEG_SIZE)) {
69 
70 			/* Not the requested table */
71 
72 			continue;
73 		}
74 
75 		/* Table with matching signature has been found */
76 
77 		if (!acpi_gbl_root_table_list.tables[i].pointer) {
78 
79 			/* Table is not currently mapped, map it */
80 
81 			status =
82 			    acpi_tb_validate_table(&acpi_gbl_root_table_list.
83 						   tables[i]);
84 			if (ACPI_FAILURE(status)) {
85 				goto unlock_and_exit;
86 			}
87 
88 			if (!acpi_gbl_root_table_list.tables[i].pointer) {
89 				continue;
90 			}
91 		}
92 
93 		/* Check for table match on all IDs */
94 
95 		if (!memcmp
96 		    (acpi_gbl_root_table_list.tables[i].pointer->signature,
97 		     header.signature, ACPI_NAMESEG_SIZE) && (!oem_id[0]
98 							      ||
99 							      !memcmp
100 							      (acpi_gbl_root_table_list.
101 							       tables[i].
102 							       pointer->oem_id,
103 							       header.oem_id,
104 							       ACPI_OEM_ID_SIZE))
105 		    && (!oem_table_id[0]
106 			|| !memcmp(acpi_gbl_root_table_list.tables[i].pointer->
107 				   oem_table_id, header.oem_table_id,
108 				   ACPI_OEM_TABLE_ID_SIZE))) {
109 			*table_index = i;
110 
111 			ACPI_DEBUG_PRINT((ACPI_DB_TABLES,
112 					  "Found table [%4.4s]\n",
113 					  header.signature));
114 			goto unlock_and_exit;
115 		}
116 	}
117 	status = AE_NOT_FOUND;
118 
119 unlock_and_exit:
120 	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
121 	return_ACPI_STATUS(status);
122 }
123