Linux-libre 5.3.12-gnu
[librecmc/linux-libre.git] / drivers / acpi / acpica / tbxfroot.c
1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2 /******************************************************************************
3  *
4  * Module Name: tbxfroot - Find the root ACPI table (RSDT)
5  *
6  * Copyright (C) 2000 - 2019, 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("tbxfroot")
16
17 /*******************************************************************************
18  *
19  * FUNCTION:    acpi_tb_get_rsdp_length
20  *
21  * PARAMETERS:  rsdp                - Pointer to RSDP
22  *
23  * RETURN:      Table length
24  *
25  * DESCRIPTION: Get the length of the RSDP
26  *
27  ******************************************************************************/
28 u32 acpi_tb_get_rsdp_length(struct acpi_table_rsdp *rsdp)
29 {
30
31         if (!ACPI_VALIDATE_RSDP_SIG(rsdp->signature)) {
32
33                 /* BAD Signature */
34
35                 return (0);
36         }
37
38         /* "Length" field is available if table version >= 2 */
39
40         if (rsdp->revision >= 2) {
41                 return (rsdp->length);
42         } else {
43                 return (ACPI_RSDP_CHECKSUM_LENGTH);
44         }
45 }
46
47 /*******************************************************************************
48  *
49  * FUNCTION:    acpi_tb_validate_rsdp
50  *
51  * PARAMETERS:  rsdp                - Pointer to unvalidated RSDP
52  *
53  * RETURN:      Status
54  *
55  * DESCRIPTION: Validate the RSDP (ptr)
56  *
57  ******************************************************************************/
58
59 acpi_status acpi_tb_validate_rsdp(struct acpi_table_rsdp *rsdp)
60 {
61
62         /*
63          * The signature and checksum must both be correct
64          *
65          * Note: Sometimes there exists more than one RSDP in memory; the valid
66          * RSDP has a valid checksum, all others have an invalid checksum.
67          */
68         if (!ACPI_VALIDATE_RSDP_SIG(rsdp->signature)) {
69
70                 /* Nope, BAD Signature */
71
72                 return (AE_BAD_SIGNATURE);
73         }
74
75         /* Check the standard checksum */
76
77         if (acpi_tb_checksum((u8 *) rsdp, ACPI_RSDP_CHECKSUM_LENGTH) != 0) {
78                 return (AE_BAD_CHECKSUM);
79         }
80
81         /* Check extended checksum if table version >= 2 */
82
83         if ((rsdp->revision >= 2) &&
84             (acpi_tb_checksum((u8 *) rsdp, ACPI_RSDP_XCHECKSUM_LENGTH) != 0)) {
85                 return (AE_BAD_CHECKSUM);
86         }
87
88         return (AE_OK);
89 }
90
91 /*******************************************************************************
92  *
93  * FUNCTION:    acpi_find_root_pointer
94  *
95  * PARAMETERS:  table_address           - Where the table pointer is returned
96  *
97  * RETURN:      Status, RSDP physical address
98  *
99  * DESCRIPTION: Search lower 1Mbyte of memory for the root system descriptor
100  *              pointer structure. If it is found, set *RSDP to point to it.
101  *
102  * NOTE1:       The RSDP must be either in the first 1K of the Extended
103  *              BIOS Data Area or between E0000 and FFFFF (From ACPI Spec.)
104  *              Only a 32-bit physical address is necessary.
105  *
106  * NOTE2:       This function is always available, regardless of the
107  *              initialization state of the rest of ACPI.
108  *
109  ******************************************************************************/
110
111 acpi_status ACPI_INIT_FUNCTION
112 acpi_find_root_pointer(acpi_physical_address *table_address)
113 {
114         u8 *table_ptr;
115         u8 *mem_rover;
116         u32 physical_address;
117
118         ACPI_FUNCTION_TRACE(acpi_find_root_pointer);
119
120         /* 1a) Get the location of the Extended BIOS Data Area (EBDA) */
121
122         table_ptr = acpi_os_map_memory((acpi_physical_address)
123                                        ACPI_EBDA_PTR_LOCATION,
124                                        ACPI_EBDA_PTR_LENGTH);
125         if (!table_ptr) {
126                 ACPI_ERROR((AE_INFO,
127                             "Could not map memory at 0x%8.8X for length %u",
128                             ACPI_EBDA_PTR_LOCATION, ACPI_EBDA_PTR_LENGTH));
129
130                 return_ACPI_STATUS(AE_NO_MEMORY);
131         }
132
133         ACPI_MOVE_16_TO_32(&physical_address, table_ptr);
134
135         /* Convert segment part to physical address */
136
137         physical_address <<= 4;
138         acpi_os_unmap_memory(table_ptr, ACPI_EBDA_PTR_LENGTH);
139
140         /* EBDA present? */
141
142         if (physical_address > 0x400) {
143                 /*
144                  * 1b) Search EBDA paragraphs (EBDA is required to be a
145                  *     minimum of 1K length)
146                  */
147                 table_ptr = acpi_os_map_memory((acpi_physical_address)
148                                                physical_address,
149                                                ACPI_EBDA_WINDOW_SIZE);
150                 if (!table_ptr) {
151                         ACPI_ERROR((AE_INFO,
152                                     "Could not map memory at 0x%8.8X for length %u",
153                                     physical_address, ACPI_EBDA_WINDOW_SIZE));
154
155                         return_ACPI_STATUS(AE_NO_MEMORY);
156                 }
157
158                 mem_rover =
159                     acpi_tb_scan_memory_for_rsdp(table_ptr,
160                                                  ACPI_EBDA_WINDOW_SIZE);
161                 acpi_os_unmap_memory(table_ptr, ACPI_EBDA_WINDOW_SIZE);
162
163                 if (mem_rover) {
164
165                         /* Return the physical address */
166
167                         physical_address +=
168                             (u32) ACPI_PTR_DIFF(mem_rover, table_ptr);
169
170                         *table_address =
171                             (acpi_physical_address)physical_address;
172                         return_ACPI_STATUS(AE_OK);
173                 }
174         }
175
176         /*
177          * 2) Search upper memory: 16-byte boundaries in E0000h-FFFFFh
178          */
179         table_ptr = acpi_os_map_memory((acpi_physical_address)
180                                        ACPI_HI_RSDP_WINDOW_BASE,
181                                        ACPI_HI_RSDP_WINDOW_SIZE);
182
183         if (!table_ptr) {
184                 ACPI_ERROR((AE_INFO,
185                             "Could not map memory at 0x%8.8X for length %u",
186                             ACPI_HI_RSDP_WINDOW_BASE,
187                             ACPI_HI_RSDP_WINDOW_SIZE));
188
189                 return_ACPI_STATUS(AE_NO_MEMORY);
190         }
191
192         mem_rover =
193             acpi_tb_scan_memory_for_rsdp(table_ptr, ACPI_HI_RSDP_WINDOW_SIZE);
194         acpi_os_unmap_memory(table_ptr, ACPI_HI_RSDP_WINDOW_SIZE);
195
196         if (mem_rover) {
197
198                 /* Return the physical address */
199
200                 physical_address = (u32)
201                     (ACPI_HI_RSDP_WINDOW_BASE +
202                      ACPI_PTR_DIFF(mem_rover, table_ptr));
203
204                 *table_address = (acpi_physical_address)physical_address;
205                 return_ACPI_STATUS(AE_OK);
206         }
207
208         /* A valid RSDP was not found */
209
210         ACPI_BIOS_ERROR((AE_INFO, "A valid RSDP was not found"));
211         return_ACPI_STATUS(AE_NOT_FOUND);
212 }
213
214 ACPI_EXPORT_SYMBOL_INIT(acpi_find_root_pointer)
215
216 /*******************************************************************************
217  *
218  * FUNCTION:    acpi_tb_scan_memory_for_rsdp
219  *
220  * PARAMETERS:  start_address       - Starting pointer for search
221  *              length              - Maximum length to search
222  *
223  * RETURN:      Pointer to the RSDP if found, otherwise NULL.
224  *
225  * DESCRIPTION: Search a block of memory for the RSDP signature
226  *
227  ******************************************************************************/
228 u8 *acpi_tb_scan_memory_for_rsdp(u8 *start_address, u32 length)
229 {
230         acpi_status status;
231         u8 *mem_rover;
232         u8 *end_address;
233
234         ACPI_FUNCTION_TRACE(tb_scan_memory_for_rsdp);
235
236         end_address = start_address + length;
237
238         /* Search from given start address for the requested length */
239
240         for (mem_rover = start_address; mem_rover < end_address;
241              mem_rover += ACPI_RSDP_SCAN_STEP) {
242
243                 /* The RSDP signature and checksum must both be correct */
244
245                 status =
246                     acpi_tb_validate_rsdp(ACPI_CAST_PTR
247                                           (struct acpi_table_rsdp, mem_rover));
248                 if (ACPI_SUCCESS(status)) {
249
250                         /* Sig and checksum valid, we have found a real RSDP */
251
252                         ACPI_DEBUG_PRINT((ACPI_DB_INFO,
253                                           "RSDP located at physical address %p\n",
254                                           mem_rover));
255                         return_PTR(mem_rover);
256                 }
257
258                 /* No sig match or bad checksum, keep searching */
259         }
260
261         /* Searched entire block, no RSDP was found */
262
263         ACPI_DEBUG_PRINT((ACPI_DB_INFO,
264                           "Searched entire block from %p, valid RSDP was not found\n",
265                           start_address));
266         return_PTR(NULL);
267 }