diff options
Diffstat (limited to 'drivers/acpi/tables/tbxfroot.c')
-rw-r--r-- | drivers/acpi/tables/tbxfroot.c | 552 |
1 files changed, 89 insertions, 463 deletions
diff --git a/drivers/acpi/tables/tbxfroot.c b/drivers/acpi/tables/tbxfroot.c index da2648bbdbc0..cf8fa514189f 100644 --- a/drivers/acpi/tables/tbxfroot.c +++ b/drivers/acpi/tables/tbxfroot.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2006, R. Byron Moore | 8 | * Copyright (C) 2000 - 2007, R. Byron Moore |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -48,16 +48,15 @@ | |||
48 | ACPI_MODULE_NAME("tbxfroot") | 48 | ACPI_MODULE_NAME("tbxfroot") |
49 | 49 | ||
50 | /* Local prototypes */ | 50 | /* Local prototypes */ |
51 | static acpi_status | ||
52 | acpi_tb_find_rsdp(struct acpi_table_desc *table_info, u32 flags); | ||
53 | |||
54 | static u8 *acpi_tb_scan_memory_for_rsdp(u8 * start_address, u32 length); | 51 | static u8 *acpi_tb_scan_memory_for_rsdp(u8 * start_address, u32 length); |
55 | 52 | ||
53 | static acpi_status acpi_tb_validate_rsdp(struct acpi_table_rsdp *rsdp); | ||
54 | |||
56 | /******************************************************************************* | 55 | /******************************************************************************* |
57 | * | 56 | * |
58 | * FUNCTION: acpi_tb_validate_rsdp | 57 | * FUNCTION: acpi_tb_validate_rsdp |
59 | * | 58 | * |
60 | * PARAMETERS: Rsdp - Pointer to unvalidated RSDP | 59 | * PARAMETERS: Rsdp - Pointer to unvalidated RSDP |
61 | * | 60 | * |
62 | * RETURN: Status | 61 | * RETURN: Status |
63 | * | 62 | * |
@@ -65,14 +64,18 @@ static u8 *acpi_tb_scan_memory_for_rsdp(u8 * start_address, u32 length); | |||
65 | * | 64 | * |
66 | ******************************************************************************/ | 65 | ******************************************************************************/ |
67 | 66 | ||
68 | acpi_status acpi_tb_validate_rsdp(struct rsdp_descriptor *rsdp) | 67 | static acpi_status acpi_tb_validate_rsdp(struct acpi_table_rsdp *rsdp) |
69 | { | 68 | { |
70 | ACPI_FUNCTION_ENTRY(); | 69 | ACPI_FUNCTION_ENTRY(); |
71 | 70 | ||
72 | /* | 71 | /* |
73 | * The signature and checksum must both be correct | 72 | * The signature and checksum must both be correct |
73 | * | ||
74 | * Note: Sometimes there exists more than one RSDP in memory; the valid | ||
75 | * RSDP has a valid checksum, all others have an invalid checksum. | ||
74 | */ | 76 | */ |
75 | if (ACPI_STRNCMP((char *)rsdp, RSDP_SIG, sizeof(RSDP_SIG) - 1) != 0) { | 77 | if (ACPI_STRNCMP((char *)rsdp, ACPI_SIG_RSDP, sizeof(ACPI_SIG_RSDP) - 1) |
78 | != 0) { | ||
76 | 79 | ||
77 | /* Nope, BAD Signature */ | 80 | /* Nope, BAD Signature */ |
78 | 81 | ||
@@ -81,14 +84,14 @@ acpi_status acpi_tb_validate_rsdp(struct rsdp_descriptor *rsdp) | |||
81 | 84 | ||
82 | /* Check the standard checksum */ | 85 | /* Check the standard checksum */ |
83 | 86 | ||
84 | if (acpi_tb_sum_table(rsdp, ACPI_RSDP_CHECKSUM_LENGTH) != 0) { | 87 | if (acpi_tb_checksum((u8 *) rsdp, ACPI_RSDP_CHECKSUM_LENGTH) != 0) { |
85 | return (AE_BAD_CHECKSUM); | 88 | return (AE_BAD_CHECKSUM); |
86 | } | 89 | } |
87 | 90 | ||
88 | /* Check extended checksum if table version >= 2 */ | 91 | /* Check extended checksum if table version >= 2 */ |
89 | 92 | ||
90 | if ((rsdp->revision >= 2) && | 93 | if ((rsdp->revision >= 2) && |
91 | (acpi_tb_sum_table(rsdp, ACPI_RSDP_XCHECKSUM_LENGTH) != 0)) { | 94 | (acpi_tb_checksum((u8 *) rsdp, ACPI_RSDP_XCHECKSUM_LENGTH) != 0)) { |
92 | return (AE_BAD_CHECKSUM); | 95 | return (AE_BAD_CHECKSUM); |
93 | } | 96 | } |
94 | 97 | ||
@@ -97,314 +100,123 @@ acpi_status acpi_tb_validate_rsdp(struct rsdp_descriptor *rsdp) | |||
97 | 100 | ||
98 | /******************************************************************************* | 101 | /******************************************************************************* |
99 | * | 102 | * |
100 | * FUNCTION: acpi_tb_find_table | 103 | * FUNCTION: acpi_tb_find_rsdp |
101 | * | ||
102 | * PARAMETERS: Signature - String with ACPI table signature | ||
103 | * oem_id - String with the table OEM ID | ||
104 | * oem_table_id - String with the OEM Table ID | ||
105 | * table_ptr - Where the table pointer is returned | ||
106 | * | ||
107 | * RETURN: Status | ||
108 | * | 104 | * |
109 | * DESCRIPTION: Find an ACPI table (in the RSDT/XSDT) that matches the | 105 | * PARAMETERS: table_address - Where the table pointer is returned |
110 | * Signature, OEM ID and OEM Table ID. | ||
111 | * | 106 | * |
112 | ******************************************************************************/ | 107 | * RETURN: Status, RSDP physical address |
113 | |||
114 | acpi_status | ||
115 | acpi_tb_find_table(char *signature, | ||
116 | char *oem_id, | ||
117 | char *oem_table_id, struct acpi_table_header ** table_ptr) | ||
118 | { | ||
119 | acpi_status status; | ||
120 | struct acpi_table_header *table; | ||
121 | |||
122 | ACPI_FUNCTION_TRACE(tb_find_table); | ||
123 | |||
124 | /* Validate string lengths */ | ||
125 | |||
126 | if ((ACPI_STRLEN(signature) > ACPI_NAME_SIZE) || | ||
127 | (ACPI_STRLEN(oem_id) > sizeof(table->oem_id)) || | ||
128 | (ACPI_STRLEN(oem_table_id) > sizeof(table->oem_table_id))) { | ||
129 | return_ACPI_STATUS(AE_AML_STRING_LIMIT); | ||
130 | } | ||
131 | |||
132 | if (ACPI_COMPARE_NAME(signature, DSDT_SIG)) { | ||
133 | /* | ||
134 | * The DSDT pointer is contained in the FADT, not the RSDT. | ||
135 | * This code should suffice, because the only code that would perform | ||
136 | * a "find" on the DSDT is the data_table_region() AML opcode -- in | ||
137 | * which case, the DSDT is guaranteed to be already loaded. | ||
138 | * If this becomes insufficient, the FADT will have to be found first. | ||
139 | */ | ||
140 | if (!acpi_gbl_DSDT) { | ||
141 | return_ACPI_STATUS(AE_NO_ACPI_TABLES); | ||
142 | } | ||
143 | table = acpi_gbl_DSDT; | ||
144 | } else { | ||
145 | /* Find the table */ | ||
146 | |||
147 | status = acpi_get_firmware_table(signature, 1, | ||
148 | ACPI_LOGICAL_ADDRESSING, | ||
149 | &table); | ||
150 | if (ACPI_FAILURE(status)) { | ||
151 | return_ACPI_STATUS(status); | ||
152 | } | ||
153 | } | ||
154 | |||
155 | /* Check oem_id and oem_table_id */ | ||
156 | |||
157 | if ((oem_id[0] && | ||
158 | ACPI_STRNCMP(oem_id, table->oem_id, | ||
159 | sizeof(table->oem_id))) || | ||
160 | (oem_table_id[0] && | ||
161 | ACPI_STRNCMP(oem_table_id, table->oem_table_id, | ||
162 | sizeof(table->oem_table_id)))) { | ||
163 | return_ACPI_STATUS(AE_AML_NAME_NOT_FOUND); | ||
164 | } | ||
165 | |||
166 | ACPI_DEBUG_PRINT((ACPI_DB_TABLES, "Found table [%4.4s]\n", | ||
167 | table->signature)); | ||
168 | |||
169 | *table_ptr = table; | ||
170 | return_ACPI_STATUS(AE_OK); | ||
171 | } | ||
172 | |||
173 | /******************************************************************************* | ||
174 | * | ||
175 | * FUNCTION: acpi_get_firmware_table | ||
176 | * | 108 | * |
177 | * PARAMETERS: Signature - Any ACPI table signature | 109 | * DESCRIPTION: Search lower 1_mbyte of memory for the root system descriptor |
178 | * Instance - the non zero instance of the table, allows | 110 | * pointer structure. If it is found, set *RSDP to point to it. |
179 | * support for multiple tables of the same type | ||
180 | * Flags - Physical/Virtual support | ||
181 | * table_pointer - Where a buffer containing the table is | ||
182 | * returned | ||
183 | * | 111 | * |
184 | * RETURN: Status | 112 | * NOTE1: The RSDP must be either in the first 1_k of the Extended |
113 | * BIOS Data Area or between E0000 and FFFFF (From ACPI Spec.) | ||
114 | * Only a 32-bit physical address is necessary. | ||
185 | * | 115 | * |
186 | * DESCRIPTION: This function is called to get an ACPI table. A buffer is | 116 | * NOTE2: This function is always available, regardless of the |
187 | * allocated for the table and returned in table_pointer. | 117 | * initialization state of the rest of ACPI. |
188 | * This table will be a complete table including the header. | ||
189 | * | 118 | * |
190 | ******************************************************************************/ | 119 | ******************************************************************************/ |
191 | 120 | ||
192 | acpi_status | 121 | acpi_status acpi_find_root_pointer(acpi_native_uint * table_address) |
193 | acpi_get_firmware_table(acpi_string signature, | ||
194 | u32 instance, | ||
195 | u32 flags, struct acpi_table_header **table_pointer) | ||
196 | { | 122 | { |
197 | acpi_status status; | 123 | u8 *table_ptr; |
198 | struct acpi_pointer address; | 124 | u8 *mem_rover; |
199 | struct acpi_table_header *header = NULL; | 125 | u32 physical_address; |
200 | struct acpi_table_desc *table_info = NULL; | ||
201 | struct acpi_table_desc *rsdt_info; | ||
202 | u32 table_count; | ||
203 | u32 i; | ||
204 | u32 j; | ||
205 | |||
206 | ACPI_FUNCTION_TRACE(acpi_get_firmware_table); | ||
207 | |||
208 | /* | ||
209 | * Ensure that at least the table manager is initialized. We don't | ||
210 | * require that the entire ACPI subsystem is up for this interface. | ||
211 | * If we have a buffer, we must have a length too | ||
212 | */ | ||
213 | if ((instance == 0) || (!signature) || (!table_pointer)) { | ||
214 | return_ACPI_STATUS(AE_BAD_PARAMETER); | ||
215 | } | ||
216 | |||
217 | /* Ensure that we have a RSDP */ | ||
218 | |||
219 | if (!acpi_gbl_RSDP) { | ||
220 | |||
221 | /* Get the RSDP */ | ||
222 | |||
223 | status = acpi_os_get_root_pointer(flags, &address); | ||
224 | if (ACPI_FAILURE(status)) { | ||
225 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "RSDP not found\n")); | ||
226 | return_ACPI_STATUS(AE_NO_ACPI_TABLES); | ||
227 | } | ||
228 | |||
229 | /* Map and validate the RSDP */ | ||
230 | |||
231 | if ((flags & ACPI_MEMORY_MODE) == ACPI_LOGICAL_ADDRESSING) { | ||
232 | status = acpi_os_map_memory(address.pointer.physical, | ||
233 | sizeof(struct | ||
234 | rsdp_descriptor), | ||
235 | (void *)&acpi_gbl_RSDP); | ||
236 | if (ACPI_FAILURE(status)) { | ||
237 | return_ACPI_STATUS(status); | ||
238 | } | ||
239 | } else { | ||
240 | acpi_gbl_RSDP = address.pointer.logical; | ||
241 | } | ||
242 | |||
243 | /* The RDSP signature and checksum must both be correct */ | ||
244 | |||
245 | status = acpi_tb_validate_rsdp(acpi_gbl_RSDP); | ||
246 | if (ACPI_FAILURE(status)) { | ||
247 | return_ACPI_STATUS(status); | ||
248 | } | ||
249 | } | ||
250 | |||
251 | /* Get the RSDT address via the RSDP */ | ||
252 | |||
253 | acpi_tb_get_rsdt_address(&address); | ||
254 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | ||
255 | "RSDP located at %p, RSDT physical=%8.8X%8.8X\n", | ||
256 | acpi_gbl_RSDP, | ||
257 | ACPI_FORMAT_UINT64(address.pointer.value))); | ||
258 | 126 | ||
259 | /* Insert processor_mode flags */ | 127 | ACPI_FUNCTION_TRACE(acpi_find_root_pointer); |
260 | 128 | ||
261 | address.pointer_type |= flags; | 129 | /* 1a) Get the location of the Extended BIOS Data Area (EBDA) */ |
262 | 130 | ||
263 | /* Get and validate the RSDT */ | 131 | table_ptr = acpi_os_map_memory((acpi_physical_address) |
132 | ACPI_EBDA_PTR_LOCATION, | ||
133 | ACPI_EBDA_PTR_LENGTH); | ||
134 | if (!table_ptr) { | ||
135 | ACPI_ERROR((AE_INFO, | ||
136 | "Could not map memory at %8.8X for length %X", | ||
137 | ACPI_EBDA_PTR_LOCATION, ACPI_EBDA_PTR_LENGTH)); | ||
264 | 138 | ||
265 | rsdt_info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_table_desc)); | ||
266 | if (!rsdt_info) { | ||
267 | return_ACPI_STATUS(AE_NO_MEMORY); | 139 | return_ACPI_STATUS(AE_NO_MEMORY); |
268 | } | 140 | } |
269 | 141 | ||
270 | status = acpi_tb_get_table(&address, rsdt_info); | 142 | ACPI_MOVE_16_TO_32(&physical_address, table_ptr); |
271 | if (ACPI_FAILURE(status)) { | ||
272 | goto cleanup; | ||
273 | } | ||
274 | |||
275 | status = acpi_tb_validate_rsdt(rsdt_info->pointer); | ||
276 | if (ACPI_FAILURE(status)) { | ||
277 | goto cleanup; | ||
278 | } | ||
279 | 143 | ||
280 | /* Allocate a scratch table header and table descriptor */ | 144 | /* Convert segment part to physical address */ |
281 | 145 | ||
282 | header = ACPI_ALLOCATE(sizeof(struct acpi_table_header)); | 146 | physical_address <<= 4; |
283 | if (!header) { | 147 | acpi_os_unmap_memory(table_ptr, ACPI_EBDA_PTR_LENGTH); |
284 | status = AE_NO_MEMORY; | ||
285 | goto cleanup; | ||
286 | } | ||
287 | 148 | ||
288 | table_info = ACPI_ALLOCATE(sizeof(struct acpi_table_desc)); | 149 | /* EBDA present? */ |
289 | if (!table_info) { | ||
290 | status = AE_NO_MEMORY; | ||
291 | goto cleanup; | ||
292 | } | ||
293 | 150 | ||
294 | /* Get the number of table pointers within the RSDT */ | 151 | if (physical_address > 0x400) { |
295 | |||
296 | table_count = | ||
297 | acpi_tb_get_table_count(acpi_gbl_RSDP, rsdt_info->pointer); | ||
298 | address.pointer_type = acpi_gbl_table_flags | flags; | ||
299 | |||
300 | /* | ||
301 | * Search the RSDT/XSDT for the correct instance of the | ||
302 | * requested table | ||
303 | */ | ||
304 | for (i = 0, j = 0; i < table_count; i++) { | ||
305 | /* | 152 | /* |
306 | * Get the next table pointer, handle RSDT vs. XSDT | 153 | * 1b) Search EBDA paragraphs (EBDA is required to be a |
307 | * RSDT pointers are 32 bits, XSDT pointers are 64 bits | 154 | * minimum of 1_k length) |
308 | */ | 155 | */ |
309 | if (acpi_gbl_root_table_type == ACPI_TABLE_TYPE_RSDT) { | 156 | table_ptr = acpi_os_map_memory((acpi_native_uint) |
310 | address.pointer.value = | 157 | physical_address, |
311 | (ACPI_CAST_PTR | 158 | ACPI_EBDA_WINDOW_SIZE); |
312 | (struct rsdt_descriptor, | 159 | if (!table_ptr) { |
313 | rsdt_info->pointer))->table_offset_entry[i]; | 160 | ACPI_ERROR((AE_INFO, |
314 | } else { | 161 | "Could not map memory at %8.8X for length %X", |
315 | address.pointer.value = | 162 | physical_address, ACPI_EBDA_WINDOW_SIZE)); |
316 | (ACPI_CAST_PTR | ||
317 | (struct xsdt_descriptor, | ||
318 | rsdt_info->pointer))->table_offset_entry[i]; | ||
319 | } | ||
320 | |||
321 | /* Get the table header */ | ||
322 | 163 | ||
323 | status = acpi_tb_get_table_header(&address, header); | 164 | return_ACPI_STATUS(AE_NO_MEMORY); |
324 | if (ACPI_FAILURE(status)) { | ||
325 | goto cleanup; | ||
326 | } | 165 | } |
327 | 166 | ||
328 | /* Compare table signatures and table instance */ | 167 | mem_rover = |
329 | 168 | acpi_tb_scan_memory_for_rsdp(table_ptr, | |
330 | if (ACPI_COMPARE_NAME(header->signature, signature)) { | 169 | ACPI_EBDA_WINDOW_SIZE); |
331 | 170 | acpi_os_unmap_memory(table_ptr, ACPI_EBDA_WINDOW_SIZE); | |
332 | /* An instance of the table was found */ | ||
333 | 171 | ||
334 | j++; | 172 | if (mem_rover) { |
335 | if (j >= instance) { | ||
336 | 173 | ||
337 | /* Found the correct instance, get the entire table */ | 174 | /* Return the physical address */ |
338 | 175 | ||
339 | status = | 176 | physical_address += |
340 | acpi_tb_get_table_body(&address, header, | 177 | (u32) ACPI_PTR_DIFF(mem_rover, table_ptr); |
341 | table_info); | ||
342 | if (ACPI_FAILURE(status)) { | ||
343 | goto cleanup; | ||
344 | } | ||
345 | 178 | ||
346 | *table_pointer = table_info->pointer; | 179 | *table_address = physical_address; |
347 | goto cleanup; | 180 | return_ACPI_STATUS(AE_OK); |
348 | } | ||
349 | } | 181 | } |
350 | } | 182 | } |
351 | 183 | ||
352 | /* Did not find the table */ | 184 | /* |
185 | * 2) Search upper memory: 16-byte boundaries in E0000h-FFFFFh | ||
186 | */ | ||
187 | table_ptr = acpi_os_map_memory((acpi_physical_address) | ||
188 | ACPI_HI_RSDP_WINDOW_BASE, | ||
189 | ACPI_HI_RSDP_WINDOW_SIZE); | ||
353 | 190 | ||
354 | status = AE_NOT_EXIST; | 191 | if (!table_ptr) { |
192 | ACPI_ERROR((AE_INFO, | ||
193 | "Could not map memory at %8.8X for length %X", | ||
194 | ACPI_HI_RSDP_WINDOW_BASE, | ||
195 | ACPI_HI_RSDP_WINDOW_SIZE)); | ||
355 | 196 | ||
356 | cleanup: | 197 | return_ACPI_STATUS(AE_NO_MEMORY); |
357 | if (rsdt_info->pointer) { | ||
358 | acpi_os_unmap_memory(rsdt_info->pointer, | ||
359 | (acpi_size) rsdt_info->pointer->length); | ||
360 | } | 198 | } |
361 | ACPI_FREE(rsdt_info); | ||
362 | 199 | ||
363 | if (header) { | 200 | mem_rover = |
364 | ACPI_FREE(header); | 201 | acpi_tb_scan_memory_for_rsdp(table_ptr, ACPI_HI_RSDP_WINDOW_SIZE); |
365 | } | 202 | acpi_os_unmap_memory(table_ptr, ACPI_HI_RSDP_WINDOW_SIZE); |
366 | if (table_info) { | ||
367 | ACPI_FREE(table_info); | ||
368 | } | ||
369 | return_ACPI_STATUS(status); | ||
370 | } | ||
371 | 203 | ||
372 | ACPI_EXPORT_SYMBOL(acpi_get_firmware_table) | 204 | if (mem_rover) { |
373 | 205 | ||
374 | /* TBD: Move to a new file */ | 206 | /* Return the physical address */ |
375 | #if ACPI_MACHINE_WIDTH != 16 | ||
376 | /******************************************************************************* | ||
377 | * | ||
378 | * FUNCTION: acpi_find_root_pointer | ||
379 | * | ||
380 | * PARAMETERS: Flags - Logical/Physical addressing | ||
381 | * rsdp_address - Where to place the RSDP address | ||
382 | * | ||
383 | * RETURN: Status, Physical address of the RSDP | ||
384 | * | ||
385 | * DESCRIPTION: Find the RSDP | ||
386 | * | ||
387 | ******************************************************************************/ | ||
388 | acpi_status acpi_find_root_pointer(u32 flags, struct acpi_pointer *rsdp_address) | ||
389 | { | ||
390 | struct acpi_table_desc table_info; | ||
391 | acpi_status status; | ||
392 | |||
393 | ACPI_FUNCTION_TRACE(acpi_find_root_pointer); | ||
394 | |||
395 | /* Get the RSDP */ | ||
396 | 207 | ||
397 | status = acpi_tb_find_rsdp(&table_info, flags); | 208 | physical_address = (u32) |
398 | if (ACPI_FAILURE(status)) { | 209 | (ACPI_HI_RSDP_WINDOW_BASE + |
399 | ACPI_EXCEPTION((AE_INFO, status, | 210 | ACPI_PTR_DIFF(mem_rover, table_ptr)); |
400 | "RSDP structure not found - Flags=%X", flags)); | ||
401 | 211 | ||
402 | return_ACPI_STATUS(AE_NO_ACPI_TABLES); | 212 | *table_address = physical_address; |
213 | return_ACPI_STATUS(AE_OK); | ||
403 | } | 214 | } |
404 | 215 | ||
405 | rsdp_address->pointer_type = ACPI_PHYSICAL_POINTER; | 216 | /* A valid RSDP was not found */ |
406 | rsdp_address->pointer.physical = table_info.physical_address; | 217 | |
407 | return_ACPI_STATUS(AE_OK); | 218 | ACPI_ERROR((AE_INFO, "A valid RSDP was not found")); |
219 | return_ACPI_STATUS(AE_NOT_FOUND); | ||
408 | } | 220 | } |
409 | 221 | ||
410 | ACPI_EXPORT_SYMBOL(acpi_find_root_pointer) | 222 | ACPI_EXPORT_SYMBOL(acpi_find_root_pointer) |
@@ -440,7 +252,7 @@ static u8 *acpi_tb_scan_memory_for_rsdp(u8 * start_address, u32 length) | |||
440 | 252 | ||
441 | status = | 253 | status = |
442 | acpi_tb_validate_rsdp(ACPI_CAST_PTR | 254 | acpi_tb_validate_rsdp(ACPI_CAST_PTR |
443 | (struct rsdp_descriptor, mem_rover)); | 255 | (struct acpi_table_rsdp, mem_rover)); |
444 | if (ACPI_SUCCESS(status)) { | 256 | if (ACPI_SUCCESS(status)) { |
445 | 257 | ||
446 | /* Sig and checksum valid, we have found a real RSDP */ | 258 | /* Sig and checksum valid, we have found a real RSDP */ |
@@ -461,189 +273,3 @@ static u8 *acpi_tb_scan_memory_for_rsdp(u8 * start_address, u32 length) | |||
461 | start_address)); | 273 | start_address)); |
462 | return_PTR(NULL); | 274 | return_PTR(NULL); |
463 | } | 275 | } |
464 | |||
465 | /******************************************************************************* | ||
466 | * | ||
467 | * FUNCTION: acpi_tb_find_rsdp | ||
468 | * | ||
469 | * PARAMETERS: table_info - Where the table info is returned | ||
470 | * Flags - Current memory mode (logical vs. | ||
471 | * physical addressing) | ||
472 | * | ||
473 | * RETURN: Status, RSDP physical address | ||
474 | * | ||
475 | * DESCRIPTION: Search lower 1_mbyte of memory for the root system descriptor | ||
476 | * pointer structure. If it is found, set *RSDP to point to it. | ||
477 | * | ||
478 | * NOTE1: The RSDP must be either in the first 1_k of the Extended | ||
479 | * BIOS Data Area or between E0000 and FFFFF (From ACPI Spec.) | ||
480 | * Only a 32-bit physical address is necessary. | ||
481 | * | ||
482 | * NOTE2: This function is always available, regardless of the | ||
483 | * initialization state of the rest of ACPI. | ||
484 | * | ||
485 | ******************************************************************************/ | ||
486 | |||
487 | static acpi_status | ||
488 | acpi_tb_find_rsdp(struct acpi_table_desc *table_info, u32 flags) | ||
489 | { | ||
490 | u8 *table_ptr; | ||
491 | u8 *mem_rover; | ||
492 | u32 physical_address; | ||
493 | acpi_status status; | ||
494 | |||
495 | ACPI_FUNCTION_TRACE(tb_find_rsdp); | ||
496 | |||
497 | /* | ||
498 | * Scan supports either logical addressing or physical addressing | ||
499 | */ | ||
500 | if ((flags & ACPI_MEMORY_MODE) == ACPI_LOGICAL_ADDRESSING) { | ||
501 | |||
502 | /* 1a) Get the location of the Extended BIOS Data Area (EBDA) */ | ||
503 | |||
504 | status = acpi_os_map_memory((acpi_physical_address) | ||
505 | ACPI_EBDA_PTR_LOCATION, | ||
506 | ACPI_EBDA_PTR_LENGTH, | ||
507 | (void *)&table_ptr); | ||
508 | if (ACPI_FAILURE(status)) { | ||
509 | ACPI_ERROR((AE_INFO, | ||
510 | "Could not map memory at %8.8X for length %X", | ||
511 | ACPI_EBDA_PTR_LOCATION, | ||
512 | ACPI_EBDA_PTR_LENGTH)); | ||
513 | |||
514 | return_ACPI_STATUS(status); | ||
515 | } | ||
516 | |||
517 | ACPI_MOVE_16_TO_32(&physical_address, table_ptr); | ||
518 | |||
519 | /* Convert segment part to physical address */ | ||
520 | |||
521 | physical_address <<= 4; | ||
522 | acpi_os_unmap_memory(table_ptr, ACPI_EBDA_PTR_LENGTH); | ||
523 | |||
524 | /* EBDA present? */ | ||
525 | |||
526 | if (physical_address > 0x400) { | ||
527 | /* | ||
528 | * 1b) Search EBDA paragraphs (EBDA is required to be a | ||
529 | * minimum of 1_k length) | ||
530 | */ | ||
531 | status = acpi_os_map_memory((acpi_physical_address) | ||
532 | physical_address, | ||
533 | ACPI_EBDA_WINDOW_SIZE, | ||
534 | (void *)&table_ptr); | ||
535 | if (ACPI_FAILURE(status)) { | ||
536 | ACPI_ERROR((AE_INFO, | ||
537 | "Could not map memory at %8.8X for length %X", | ||
538 | physical_address, | ||
539 | ACPI_EBDA_WINDOW_SIZE)); | ||
540 | |||
541 | return_ACPI_STATUS(status); | ||
542 | } | ||
543 | |||
544 | mem_rover = acpi_tb_scan_memory_for_rsdp(table_ptr, | ||
545 | ACPI_EBDA_WINDOW_SIZE); | ||
546 | acpi_os_unmap_memory(table_ptr, ACPI_EBDA_WINDOW_SIZE); | ||
547 | |||
548 | if (mem_rover) { | ||
549 | |||
550 | /* Return the physical address */ | ||
551 | |||
552 | physical_address += | ||
553 | (u32) ACPI_PTR_DIFF(mem_rover, table_ptr); | ||
554 | |||
555 | table_info->physical_address = | ||
556 | (acpi_physical_address) physical_address; | ||
557 | return_ACPI_STATUS(AE_OK); | ||
558 | } | ||
559 | } | ||
560 | |||
561 | /* | ||
562 | * 2) Search upper memory: 16-byte boundaries in E0000h-FFFFFh | ||
563 | */ | ||
564 | status = acpi_os_map_memory((acpi_physical_address) | ||
565 | ACPI_HI_RSDP_WINDOW_BASE, | ||
566 | ACPI_HI_RSDP_WINDOW_SIZE, | ||
567 | (void *)&table_ptr); | ||
568 | |||
569 | if (ACPI_FAILURE(status)) { | ||
570 | ACPI_ERROR((AE_INFO, | ||
571 | "Could not map memory at %8.8X for length %X", | ||
572 | ACPI_HI_RSDP_WINDOW_BASE, | ||
573 | ACPI_HI_RSDP_WINDOW_SIZE)); | ||
574 | |||
575 | return_ACPI_STATUS(status); | ||
576 | } | ||
577 | |||
578 | mem_rover = | ||
579 | acpi_tb_scan_memory_for_rsdp(table_ptr, | ||
580 | ACPI_HI_RSDP_WINDOW_SIZE); | ||
581 | acpi_os_unmap_memory(table_ptr, ACPI_HI_RSDP_WINDOW_SIZE); | ||
582 | |||
583 | if (mem_rover) { | ||
584 | |||
585 | /* Return the physical address */ | ||
586 | |||
587 | physical_address = (u32) | ||
588 | (ACPI_HI_RSDP_WINDOW_BASE + | ||
589 | ACPI_PTR_DIFF(mem_rover, table_ptr)); | ||
590 | |||
591 | table_info->physical_address = | ||
592 | (acpi_physical_address) physical_address; | ||
593 | return_ACPI_STATUS(AE_OK); | ||
594 | } | ||
595 | } | ||
596 | |||
597 | /* | ||
598 | * Physical addressing | ||
599 | */ | ||
600 | else { | ||
601 | /* 1a) Get the location of the EBDA */ | ||
602 | |||
603 | ACPI_MOVE_16_TO_32(&physical_address, ACPI_EBDA_PTR_LOCATION); | ||
604 | physical_address <<= 4; /* Convert segment to physical address */ | ||
605 | |||
606 | /* EBDA present? */ | ||
607 | |||
608 | if (physical_address > 0x400) { | ||
609 | /* | ||
610 | * 1b) Search EBDA paragraphs (EBDA is required to be a minimum of | ||
611 | * 1_k length) | ||
612 | */ | ||
613 | mem_rover = | ||
614 | acpi_tb_scan_memory_for_rsdp(ACPI_PHYSADDR_TO_PTR | ||
615 | (physical_address), | ||
616 | ACPI_EBDA_WINDOW_SIZE); | ||
617 | if (mem_rover) { | ||
618 | |||
619 | /* Return the physical address */ | ||
620 | |||
621 | table_info->physical_address = | ||
622 | ACPI_TO_INTEGER(mem_rover); | ||
623 | return_ACPI_STATUS(AE_OK); | ||
624 | } | ||
625 | } | ||
626 | |||
627 | /* 2) Search upper memory: 16-byte boundaries in E0000h-FFFFFh */ | ||
628 | |||
629 | mem_rover = | ||
630 | acpi_tb_scan_memory_for_rsdp(ACPI_PHYSADDR_TO_PTR | ||
631 | (ACPI_HI_RSDP_WINDOW_BASE), | ||
632 | ACPI_HI_RSDP_WINDOW_SIZE); | ||
633 | if (mem_rover) { | ||
634 | |||
635 | /* Found it, return the physical address */ | ||
636 | |||
637 | table_info->physical_address = | ||
638 | ACPI_TO_INTEGER(mem_rover); | ||
639 | return_ACPI_STATUS(AE_OK); | ||
640 | } | ||
641 | } | ||
642 | |||
643 | /* A valid RSDP was not found */ | ||
644 | |||
645 | ACPI_ERROR((AE_INFO, "No valid RSDP was found")); | ||
646 | return_ACPI_STATUS(AE_NOT_FOUND); | ||
647 | } | ||
648 | |||
649 | #endif | ||