Branch data Line data Source code
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 - 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("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 : 0 : u32 acpi_tb_get_rsdp_length(struct acpi_table_rsdp *rsdp)
29 : : {
30 : :
31 [ # # ]: 0 : 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 [ # # ]: 0 : if (rsdp->revision >= 2) {
41 : 0 : 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 : 0 : 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 [ # # ]: 0 : 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 [ # # ]: 0 : 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 [ # # # # ]: 0 : if ((rsdp->revision >= 2) &&
84 : 0 : (acpi_tb_checksum((u8 *) rsdp, ACPI_RSDP_XCHECKSUM_LENGTH) != 0)) {
85 : 0 : 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 : 0 : acpi_find_root_pointer(acpi_physical_address *table_address)
113 : : {
114 : 0 : u8 *table_ptr;
115 : 0 : u8 *mem_rover;
116 : 0 : u32 physical_address;
117 : :
118 : 0 : ACPI_FUNCTION_TRACE(acpi_find_root_pointer);
119 : :
120 : : /* 1a) Get the location of the Extended BIOS Data Area (EBDA) */
121 : :
122 : 0 : table_ptr = acpi_os_map_memory((acpi_physical_address)
123 : : ACPI_EBDA_PTR_LOCATION,
124 : : ACPI_EBDA_PTR_LENGTH);
125 [ # # ]: 0 : if (!table_ptr) {
126 : 0 : 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 : 0 : return_ACPI_STATUS(AE_NO_MEMORY);
131 : : }
132 : :
133 : 0 : ACPI_MOVE_16_TO_32(&physical_address, table_ptr);
134 : :
135 : : /* Convert segment part to physical address */
136 : :
137 : 0 : physical_address <<= 4;
138 : 0 : acpi_os_unmap_memory(table_ptr, ACPI_EBDA_PTR_LENGTH);
139 : :
140 : : /* EBDA present? */
141 : :
142 [ # # ]: 0 : if (physical_address > 0x400) {
143 : : /*
144 : : * 1b) Search EBDA paragraphs (EBDA is required to be a
145 : : * minimum of 1K length)
146 : : */
147 : 0 : table_ptr = acpi_os_map_memory((acpi_physical_address)
148 : : physical_address,
149 : : ACPI_EBDA_WINDOW_SIZE);
150 [ # # ]: 0 : if (!table_ptr) {
151 : 0 : 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 : 0 : return_ACPI_STATUS(AE_NO_MEMORY);
156 : : }
157 : :
158 : 0 : mem_rover =
159 : 0 : acpi_tb_scan_memory_for_rsdp(table_ptr,
160 : : ACPI_EBDA_WINDOW_SIZE);
161 : 0 : acpi_os_unmap_memory(table_ptr, ACPI_EBDA_WINDOW_SIZE);
162 : :
163 [ # # ]: 0 : if (mem_rover) {
164 : :
165 : : /* Return the physical address */
166 : :
167 : 0 : physical_address +=
168 : 0 : (u32) ACPI_PTR_DIFF(mem_rover, table_ptr);
169 : :
170 : 0 : *table_address =
171 : 0 : (acpi_physical_address)physical_address;
172 : 0 : return_ACPI_STATUS(AE_OK);
173 : : }
174 : : }
175 : :
176 : : /*
177 : : * 2) Search upper memory: 16-byte boundaries in E0000h-FFFFFh
178 : : */
179 : 0 : table_ptr = acpi_os_map_memory((acpi_physical_address)
180 : : ACPI_HI_RSDP_WINDOW_BASE,
181 : : ACPI_HI_RSDP_WINDOW_SIZE);
182 : :
183 [ # # ]: 0 : if (!table_ptr) {
184 : 0 : 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 : 0 : return_ACPI_STATUS(AE_NO_MEMORY);
190 : : }
191 : :
192 : 0 : mem_rover =
193 : 0 : acpi_tb_scan_memory_for_rsdp(table_ptr, ACPI_HI_RSDP_WINDOW_SIZE);
194 : 0 : acpi_os_unmap_memory(table_ptr, ACPI_HI_RSDP_WINDOW_SIZE);
195 : :
196 [ # # ]: 0 : if (mem_rover) {
197 : :
198 : : /* Return the physical address */
199 : :
200 : 0 : physical_address = (u32)
201 : : (ACPI_HI_RSDP_WINDOW_BASE +
202 : 0 : ACPI_PTR_DIFF(mem_rover, table_ptr));
203 : :
204 : 0 : *table_address = (acpi_physical_address)physical_address;
205 : 0 : return_ACPI_STATUS(AE_OK);
206 : : }
207 : :
208 : : /* A valid RSDP was not found */
209 : :
210 : 0 : ACPI_BIOS_ERROR((AE_INFO, "A valid RSDP was not found"));
211 : 0 : 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 : 0 : u8 *acpi_tb_scan_memory_for_rsdp(u8 *start_address, u32 length)
229 : : {
230 : 0 : acpi_status status;
231 : 0 : u8 *mem_rover;
232 : 0 : u8 *end_address;
233 : :
234 : 0 : ACPI_FUNCTION_TRACE(tb_scan_memory_for_rsdp);
235 : :
236 : 0 : end_address = start_address + length;
237 : :
238 : : /* Search from given start address for the requested length */
239 : :
240 [ # # ]: 0 : for (mem_rover = start_address; mem_rover < end_address;
241 : 0 : mem_rover += ACPI_RSDP_SCAN_STEP) {
242 : :
243 : : /* The RSDP signature and checksum must both be correct */
244 : :
245 : 0 : status =
246 : 0 : acpi_tb_validate_rsdp(ACPI_CAST_PTR
247 : : (struct acpi_table_rsdp, mem_rover));
248 [ # # ]: 0 : 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 : 0 : mem_rover));
255 : 0 : 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 : : }
|