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