diff options
author | Len Brown <len.brown@intel.com> | 2007-02-06 15:31:00 -0500 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2007-02-06 15:31:00 -0500 |
commit | 57e1c5c87db512629dd44ddeb882a5aaf0e4299e (patch) | |
tree | e71e8a132d4f696beeae1bdab59efeed9517ba66 /drivers/acpi/tables | |
parent | 62d0cfcb27cf755cebdc93ca95dabc83608007cd (diff) | |
parent | 76a2e849df47697706024262a8bbb83432b8bde7 (diff) |
Pull test into release branch
Diffstat (limited to 'drivers/acpi/tables')
-rw-r--r-- | drivers/acpi/tables/Makefile | 3 | ||||
-rw-r--r-- | drivers/acpi/tables/tbconvrt.c | 622 | ||||
-rw-r--r-- | drivers/acpi/tables/tbfadt.c | 434 | ||||
-rw-r--r-- | drivers/acpi/tables/tbfind.c | 126 | ||||
-rw-r--r-- | drivers/acpi/tables/tbget.c | 471 | ||||
-rw-r--r-- | drivers/acpi/tables/tbgetall.c | 311 | ||||
-rw-r--r-- | drivers/acpi/tables/tbinstal.c | 664 | ||||
-rw-r--r-- | drivers/acpi/tables/tbrsdt.c | 307 | ||||
-rw-r--r-- | drivers/acpi/tables/tbutils.c | 513 | ||||
-rw-r--r-- | drivers/acpi/tables/tbxface.c | 671 | ||||
-rw-r--r-- | drivers/acpi/tables/tbxfroot.c | 552 |
11 files changed, 1711 insertions, 2963 deletions
diff --git a/drivers/acpi/tables/Makefile b/drivers/acpi/tables/Makefile index aa4c69594d97..0a7d7afac255 100644 --- a/drivers/acpi/tables/Makefile +++ b/drivers/acpi/tables/Makefile | |||
@@ -2,7 +2,6 @@ | |||
2 | # Makefile for all Linux ACPI interpreter subdirectories | 2 | # Makefile for all Linux ACPI interpreter subdirectories |
3 | # | 3 | # |
4 | 4 | ||
5 | obj-y := tbconvrt.o tbget.o tbrsdt.o tbxface.o \ | 5 | obj-y := tbxface.o tbinstal.o tbutils.o tbfind.o tbfadt.o |
6 | tbgetall.o tbinstal.o tbutils.o tbxfroot.o | ||
7 | 6 | ||
8 | EXTRA_CFLAGS += $(ACPI_CFLAGS) | 7 | EXTRA_CFLAGS += $(ACPI_CFLAGS) |
diff --git a/drivers/acpi/tables/tbconvrt.c b/drivers/acpi/tables/tbconvrt.c deleted file mode 100644 index d697fcb35d52..000000000000 --- a/drivers/acpi/tables/tbconvrt.c +++ /dev/null | |||
@@ -1,622 +0,0 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Module Name: tbconvrt - ACPI Table conversion utilities | ||
4 | * | ||
5 | *****************************************************************************/ | ||
6 | |||
7 | /* | ||
8 | * Copyright (C) 2000 - 2006, R. Byron Moore | ||
9 | * All rights reserved. | ||
10 | * | ||
11 | * Redistribution and use in source and binary forms, with or without | ||
12 | * modification, are permitted provided that the following conditions | ||
13 | * are met: | ||
14 | * 1. Redistributions of source code must retain the above copyright | ||
15 | * notice, this list of conditions, and the following disclaimer, | ||
16 | * without modification. | ||
17 | * 2. Redistributions in binary form must reproduce at minimum a disclaimer | ||
18 | * substantially similar to the "NO WARRANTY" disclaimer below | ||
19 | * ("Disclaimer") and any redistribution must be conditioned upon | ||
20 | * including a substantially similar Disclaimer requirement for further | ||
21 | * binary redistribution. | ||
22 | * 3. Neither the names of the above-listed copyright holders nor the names | ||
23 | * of any contributors may be used to endorse or promote products derived | ||
24 | * from this software without specific prior written permission. | ||
25 | * | ||
26 | * Alternatively, this software may be distributed under the terms of the | ||
27 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
28 | * Software Foundation. | ||
29 | * | ||
30 | * NO WARRANTY | ||
31 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
32 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
33 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR | ||
34 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
35 | * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
36 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
37 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
38 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | ||
39 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING | ||
40 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
41 | * POSSIBILITY OF SUCH DAMAGES. | ||
42 | */ | ||
43 | |||
44 | #include <acpi/acpi.h> | ||
45 | #include <acpi/actables.h> | ||
46 | |||
47 | #define _COMPONENT ACPI_TABLES | ||
48 | ACPI_MODULE_NAME("tbconvrt") | ||
49 | |||
50 | /* Local prototypes */ | ||
51 | static void | ||
52 | acpi_tb_init_generic_address(struct acpi_generic_address *new_gas_struct, | ||
53 | u8 register_bit_width, | ||
54 | acpi_physical_address address); | ||
55 | |||
56 | static void | ||
57 | acpi_tb_convert_fadt1(struct fadt_descriptor *local_fadt, | ||
58 | struct fadt_descriptor_rev1 *original_fadt); | ||
59 | |||
60 | static void | ||
61 | acpi_tb_convert_fadt2(struct fadt_descriptor *local_fadt, | ||
62 | struct fadt_descriptor *original_fadt); | ||
63 | |||
64 | u8 acpi_fadt_is_v1; | ||
65 | ACPI_EXPORT_SYMBOL(acpi_fadt_is_v1) | ||
66 | |||
67 | /******************************************************************************* | ||
68 | * | ||
69 | * FUNCTION: acpi_tb_get_table_count | ||
70 | * | ||
71 | * PARAMETERS: RSDP - Pointer to the RSDP | ||
72 | * RSDT - Pointer to the RSDT/XSDT | ||
73 | * | ||
74 | * RETURN: The number of tables pointed to by the RSDT or XSDT. | ||
75 | * | ||
76 | * DESCRIPTION: Calculate the number of tables. Automatically handles either | ||
77 | * an RSDT or XSDT. | ||
78 | * | ||
79 | ******************************************************************************/ | ||
80 | |||
81 | u32 | ||
82 | acpi_tb_get_table_count(struct rsdp_descriptor *RSDP, | ||
83 | struct acpi_table_header *RSDT) | ||
84 | { | ||
85 | u32 pointer_size; | ||
86 | |||
87 | ACPI_FUNCTION_ENTRY(); | ||
88 | |||
89 | /* RSDT pointers are 32 bits, XSDT pointers are 64 bits */ | ||
90 | |||
91 | if (acpi_gbl_root_table_type == ACPI_TABLE_TYPE_RSDT) { | ||
92 | pointer_size = sizeof(u32); | ||
93 | } else { | ||
94 | pointer_size = sizeof(u64); | ||
95 | } | ||
96 | |||
97 | /* | ||
98 | * Determine the number of tables pointed to by the RSDT/XSDT. | ||
99 | * This is defined by the ACPI Specification to be the number of | ||
100 | * pointers contained within the RSDT/XSDT. The size of the pointers | ||
101 | * is architecture-dependent. | ||
102 | */ | ||
103 | return ((RSDT->length - | ||
104 | sizeof(struct acpi_table_header)) / pointer_size); | ||
105 | } | ||
106 | |||
107 | /******************************************************************************* | ||
108 | * | ||
109 | * FUNCTION: acpi_tb_convert_to_xsdt | ||
110 | * | ||
111 | * PARAMETERS: table_info - Info about the RSDT | ||
112 | * | ||
113 | * RETURN: Status | ||
114 | * | ||
115 | * DESCRIPTION: Convert an RSDT to an XSDT (internal common format) | ||
116 | * | ||
117 | ******************************************************************************/ | ||
118 | |||
119 | acpi_status acpi_tb_convert_to_xsdt(struct acpi_table_desc *table_info) | ||
120 | { | ||
121 | acpi_size table_size; | ||
122 | u32 i; | ||
123 | struct xsdt_descriptor *new_table; | ||
124 | |||
125 | ACPI_FUNCTION_ENTRY(); | ||
126 | |||
127 | /* Compute size of the converted XSDT */ | ||
128 | |||
129 | table_size = ((acpi_size) acpi_gbl_rsdt_table_count * sizeof(u64)) + | ||
130 | sizeof(struct acpi_table_header); | ||
131 | |||
132 | /* Allocate an XSDT */ | ||
133 | |||
134 | new_table = ACPI_ALLOCATE_ZEROED(table_size); | ||
135 | if (!new_table) { | ||
136 | return (AE_NO_MEMORY); | ||
137 | } | ||
138 | |||
139 | /* Copy the header and set the length */ | ||
140 | |||
141 | ACPI_MEMCPY(new_table, table_info->pointer, | ||
142 | sizeof(struct acpi_table_header)); | ||
143 | new_table->length = (u32) table_size; | ||
144 | |||
145 | /* Copy the table pointers */ | ||
146 | |||
147 | for (i = 0; i < acpi_gbl_rsdt_table_count; i++) { | ||
148 | |||
149 | /* RSDT pointers are 32 bits, XSDT pointers are 64 bits */ | ||
150 | |||
151 | if (acpi_gbl_root_table_type == ACPI_TABLE_TYPE_RSDT) { | ||
152 | ACPI_STORE_ADDRESS(new_table->table_offset_entry[i], | ||
153 | (ACPI_CAST_PTR | ||
154 | (struct rsdt_descriptor, | ||
155 | table_info->pointer))-> | ||
156 | table_offset_entry[i]); | ||
157 | } else { | ||
158 | new_table->table_offset_entry[i] = | ||
159 | (ACPI_CAST_PTR(struct xsdt_descriptor, | ||
160 | table_info->pointer))-> | ||
161 | table_offset_entry[i]; | ||
162 | } | ||
163 | } | ||
164 | |||
165 | /* Delete the original table (either mapped or in a buffer) */ | ||
166 | |||
167 | acpi_tb_delete_single_table(table_info); | ||
168 | |||
169 | /* Point the table descriptor to the new table */ | ||
170 | |||
171 | table_info->pointer = | ||
172 | ACPI_CAST_PTR(struct acpi_table_header, new_table); | ||
173 | table_info->length = table_size; | ||
174 | table_info->allocation = ACPI_MEM_ALLOCATED; | ||
175 | |||
176 | return (AE_OK); | ||
177 | } | ||
178 | |||
179 | /******************************************************************************* | ||
180 | * | ||
181 | * FUNCTION: acpi_tb_init_generic_address | ||
182 | * | ||
183 | * PARAMETERS: new_gas_struct - GAS struct to be initialized | ||
184 | * register_bit_width - Width of this register | ||
185 | * Address - Address of the register | ||
186 | * | ||
187 | * RETURN: None | ||
188 | * | ||
189 | * DESCRIPTION: Initialize a GAS structure. | ||
190 | * | ||
191 | ******************************************************************************/ | ||
192 | |||
193 | static void | ||
194 | acpi_tb_init_generic_address(struct acpi_generic_address *new_gas_struct, | ||
195 | u8 register_bit_width, | ||
196 | acpi_physical_address address) | ||
197 | { | ||
198 | |||
199 | ACPI_STORE_ADDRESS(new_gas_struct->address, address); | ||
200 | |||
201 | new_gas_struct->address_space_id = ACPI_ADR_SPACE_SYSTEM_IO; | ||
202 | new_gas_struct->register_bit_width = register_bit_width; | ||
203 | new_gas_struct->register_bit_offset = 0; | ||
204 | new_gas_struct->access_width = 0; | ||
205 | } | ||
206 | |||
207 | /******************************************************************************* | ||
208 | * | ||
209 | * FUNCTION: acpi_tb_convert_fadt1 | ||
210 | * | ||
211 | * PARAMETERS: local_fadt - Pointer to new FADT | ||
212 | * original_fadt - Pointer to old FADT | ||
213 | * | ||
214 | * RETURN: None, populates local_fadt | ||
215 | * | ||
216 | * DESCRIPTION: Convert an ACPI 1.0 FADT to common internal format | ||
217 | * | ||
218 | ******************************************************************************/ | ||
219 | |||
220 | static void | ||
221 | acpi_tb_convert_fadt1(struct fadt_descriptor *local_fadt, | ||
222 | struct fadt_descriptor_rev1 *original_fadt) | ||
223 | { | ||
224 | |||
225 | /* ACPI 1.0 FACS */ | ||
226 | /* The BIOS stored FADT should agree with Revision 1.0 */ | ||
227 | acpi_fadt_is_v1 = 1; | ||
228 | |||
229 | /* | ||
230 | * Copy the table header and the common part of the tables. | ||
231 | * | ||
232 | * The 2.0 table is an extension of the 1.0 table, so the entire 1.0 | ||
233 | * table can be copied first, then expand some fields to 64 bits. | ||
234 | */ | ||
235 | ACPI_MEMCPY(local_fadt, original_fadt, | ||
236 | sizeof(struct fadt_descriptor_rev1)); | ||
237 | |||
238 | /* Convert table pointers to 64-bit fields */ | ||
239 | |||
240 | ACPI_STORE_ADDRESS(local_fadt->xfirmware_ctrl, | ||
241 | local_fadt->V1_firmware_ctrl); | ||
242 | ACPI_STORE_ADDRESS(local_fadt->Xdsdt, local_fadt->V1_dsdt); | ||
243 | |||
244 | /* | ||
245 | * System Interrupt Model isn't used in ACPI 2.0 | ||
246 | * (local_fadt->Reserved1 = 0;) | ||
247 | */ | ||
248 | |||
249 | /* | ||
250 | * This field is set by the OEM to convey the preferred power management | ||
251 | * profile to OSPM. It doesn't have any 1.0 equivalence. Since we don't | ||
252 | * know what kind of 32-bit system this is, we will use "unspecified". | ||
253 | */ | ||
254 | local_fadt->prefer_PM_profile = PM_UNSPECIFIED; | ||
255 | |||
256 | /* | ||
257 | * Processor Performance State Control. This is the value OSPM writes to | ||
258 | * the SMI_CMD register to assume processor performance state control | ||
259 | * responsibility. There isn't any equivalence in 1.0, but as many 1.x | ||
260 | * ACPI tables contain _PCT and _PSS we also keep this value, unless | ||
261 | * acpi_strict is set. | ||
262 | */ | ||
263 | if (acpi_strict) | ||
264 | local_fadt->pstate_cnt = 0; | ||
265 | |||
266 | /* | ||
267 | * Support for the _CST object and C States change notification. | ||
268 | * This data item hasn't any 1.0 equivalence so leave it zero. | ||
269 | */ | ||
270 | local_fadt->cst_cnt = 0; | ||
271 | |||
272 | /* | ||
273 | * FADT Rev 2 was an interim FADT released between ACPI 1.0 and ACPI 2.0. | ||
274 | * It primarily adds the FADT reset mechanism. | ||
275 | */ | ||
276 | if ((original_fadt->revision == 2) && | ||
277 | (original_fadt->length == | ||
278 | sizeof(struct fadt_descriptor_rev2_minus))) { | ||
279 | /* | ||
280 | * Grab the entire generic address struct, plus the 1-byte reset value | ||
281 | * that immediately follows. | ||
282 | */ | ||
283 | ACPI_MEMCPY(&local_fadt->reset_register, | ||
284 | &(ACPI_CAST_PTR(struct fadt_descriptor_rev2_minus, | ||
285 | original_fadt))->reset_register, | ||
286 | sizeof(struct acpi_generic_address) + 1); | ||
287 | } else { | ||
288 | /* | ||
289 | * Since there isn't any equivalence in 1.0 and since it is highly | ||
290 | * likely that a 1.0 system has legacy support. | ||
291 | */ | ||
292 | local_fadt->iapc_boot_arch = BAF_LEGACY_DEVICES; | ||
293 | } | ||
294 | |||
295 | /* | ||
296 | * Convert the V1.0 block addresses to V2.0 GAS structures | ||
297 | */ | ||
298 | acpi_tb_init_generic_address(&local_fadt->xpm1a_evt_blk, | ||
299 | local_fadt->pm1_evt_len, | ||
300 | (acpi_physical_address) local_fadt-> | ||
301 | V1_pm1a_evt_blk); | ||
302 | acpi_tb_init_generic_address(&local_fadt->xpm1b_evt_blk, | ||
303 | local_fadt->pm1_evt_len, | ||
304 | (acpi_physical_address) local_fadt-> | ||
305 | V1_pm1b_evt_blk); | ||
306 | acpi_tb_init_generic_address(&local_fadt->xpm1a_cnt_blk, | ||
307 | local_fadt->pm1_cnt_len, | ||
308 | (acpi_physical_address) local_fadt-> | ||
309 | V1_pm1a_cnt_blk); | ||
310 | acpi_tb_init_generic_address(&local_fadt->xpm1b_cnt_blk, | ||
311 | local_fadt->pm1_cnt_len, | ||
312 | (acpi_physical_address) local_fadt-> | ||
313 | V1_pm1b_cnt_blk); | ||
314 | acpi_tb_init_generic_address(&local_fadt->xpm2_cnt_blk, | ||
315 | local_fadt->pm2_cnt_len, | ||
316 | (acpi_physical_address) local_fadt-> | ||
317 | V1_pm2_cnt_blk); | ||
318 | acpi_tb_init_generic_address(&local_fadt->xpm_tmr_blk, | ||
319 | local_fadt->pm_tm_len, | ||
320 | (acpi_physical_address) local_fadt-> | ||
321 | V1_pm_tmr_blk); | ||
322 | acpi_tb_init_generic_address(&local_fadt->xgpe0_blk, 0, | ||
323 | (acpi_physical_address) local_fadt-> | ||
324 | V1_gpe0_blk); | ||
325 | acpi_tb_init_generic_address(&local_fadt->xgpe1_blk, 0, | ||
326 | (acpi_physical_address) local_fadt-> | ||
327 | V1_gpe1_blk); | ||
328 | |||
329 | /* Create separate GAS structs for the PM1 Enable registers */ | ||
330 | |||
331 | acpi_tb_init_generic_address(&acpi_gbl_xpm1a_enable, | ||
332 | (u8) ACPI_DIV_2(acpi_gbl_FADT-> | ||
333 | pm1_evt_len), | ||
334 | (acpi_physical_address) | ||
335 | (local_fadt->xpm1a_evt_blk.address + | ||
336 | ACPI_DIV_2(acpi_gbl_FADT->pm1_evt_len))); | ||
337 | |||
338 | /* PM1B is optional; leave null if not present */ | ||
339 | |||
340 | if (local_fadt->xpm1b_evt_blk.address) { | ||
341 | acpi_tb_init_generic_address(&acpi_gbl_xpm1b_enable, | ||
342 | (u8) ACPI_DIV_2(acpi_gbl_FADT-> | ||
343 | pm1_evt_len), | ||
344 | (acpi_physical_address) | ||
345 | (local_fadt->xpm1b_evt_blk. | ||
346 | address + | ||
347 | ACPI_DIV_2(acpi_gbl_FADT-> | ||
348 | pm1_evt_len))); | ||
349 | } | ||
350 | } | ||
351 | |||
352 | /******************************************************************************* | ||
353 | * | ||
354 | * FUNCTION: acpi_tb_convert_fadt2 | ||
355 | * | ||
356 | * PARAMETERS: local_fadt - Pointer to new FADT | ||
357 | * original_fadt - Pointer to old FADT | ||
358 | * | ||
359 | * RETURN: None, populates local_fadt | ||
360 | * | ||
361 | * DESCRIPTION: Convert an ACPI 2.0 FADT to common internal format. | ||
362 | * Handles optional "X" fields. | ||
363 | * | ||
364 | ******************************************************************************/ | ||
365 | |||
366 | static void | ||
367 | acpi_tb_convert_fadt2(struct fadt_descriptor *local_fadt, | ||
368 | struct fadt_descriptor *original_fadt) | ||
369 | { | ||
370 | |||
371 | /* We have an ACPI 2.0 FADT but we must copy it to our local buffer */ | ||
372 | |||
373 | ACPI_MEMCPY(local_fadt, original_fadt, sizeof(struct fadt_descriptor)); | ||
374 | |||
375 | /* | ||
376 | * "X" fields are optional extensions to the original V1.0 fields, so | ||
377 | * we must selectively expand V1.0 fields if the corresponding X field | ||
378 | * is zero. | ||
379 | */ | ||
380 | if (!(local_fadt->xfirmware_ctrl)) { | ||
381 | ACPI_STORE_ADDRESS(local_fadt->xfirmware_ctrl, | ||
382 | local_fadt->V1_firmware_ctrl); | ||
383 | } | ||
384 | |||
385 | if (!(local_fadt->Xdsdt)) { | ||
386 | ACPI_STORE_ADDRESS(local_fadt->Xdsdt, local_fadt->V1_dsdt); | ||
387 | } | ||
388 | |||
389 | if (!(local_fadt->xpm1a_evt_blk.address)) { | ||
390 | acpi_tb_init_generic_address(&local_fadt->xpm1a_evt_blk, | ||
391 | local_fadt->pm1_evt_len, | ||
392 | (acpi_physical_address) | ||
393 | local_fadt->V1_pm1a_evt_blk); | ||
394 | } | ||
395 | |||
396 | if (!(local_fadt->xpm1b_evt_blk.address)) { | ||
397 | acpi_tb_init_generic_address(&local_fadt->xpm1b_evt_blk, | ||
398 | local_fadt->pm1_evt_len, | ||
399 | (acpi_physical_address) | ||
400 | local_fadt->V1_pm1b_evt_blk); | ||
401 | } | ||
402 | |||
403 | if (!(local_fadt->xpm1a_cnt_blk.address)) { | ||
404 | acpi_tb_init_generic_address(&local_fadt->xpm1a_cnt_blk, | ||
405 | local_fadt->pm1_cnt_len, | ||
406 | (acpi_physical_address) | ||
407 | local_fadt->V1_pm1a_cnt_blk); | ||
408 | } | ||
409 | |||
410 | if (!(local_fadt->xpm1b_cnt_blk.address)) { | ||
411 | acpi_tb_init_generic_address(&local_fadt->xpm1b_cnt_blk, | ||
412 | local_fadt->pm1_cnt_len, | ||
413 | (acpi_physical_address) | ||
414 | local_fadt->V1_pm1b_cnt_blk); | ||
415 | } | ||
416 | |||
417 | if (!(local_fadt->xpm2_cnt_blk.address)) { | ||
418 | acpi_tb_init_generic_address(&local_fadt->xpm2_cnt_blk, | ||
419 | local_fadt->pm2_cnt_len, | ||
420 | (acpi_physical_address) | ||
421 | local_fadt->V1_pm2_cnt_blk); | ||
422 | } | ||
423 | |||
424 | if (!(local_fadt->xpm_tmr_blk.address)) { | ||
425 | acpi_tb_init_generic_address(&local_fadt->xpm_tmr_blk, | ||
426 | local_fadt->pm_tm_len, | ||
427 | (acpi_physical_address) | ||
428 | local_fadt->V1_pm_tmr_blk); | ||
429 | } | ||
430 | |||
431 | if (!(local_fadt->xgpe0_blk.address)) { | ||
432 | acpi_tb_init_generic_address(&local_fadt->xgpe0_blk, | ||
433 | 0, | ||
434 | (acpi_physical_address) | ||
435 | local_fadt->V1_gpe0_blk); | ||
436 | } | ||
437 | |||
438 | if (!(local_fadt->xgpe1_blk.address)) { | ||
439 | acpi_tb_init_generic_address(&local_fadt->xgpe1_blk, | ||
440 | 0, | ||
441 | (acpi_physical_address) | ||
442 | local_fadt->V1_gpe1_blk); | ||
443 | } | ||
444 | |||
445 | /* Create separate GAS structs for the PM1 Enable registers */ | ||
446 | |||
447 | acpi_tb_init_generic_address(&acpi_gbl_xpm1a_enable, | ||
448 | (u8) ACPI_DIV_2(acpi_gbl_FADT-> | ||
449 | pm1_evt_len), | ||
450 | (acpi_physical_address) | ||
451 | (local_fadt->xpm1a_evt_blk.address + | ||
452 | ACPI_DIV_2(acpi_gbl_FADT->pm1_evt_len))); | ||
453 | |||
454 | acpi_gbl_xpm1a_enable.address_space_id = | ||
455 | local_fadt->xpm1a_evt_blk.address_space_id; | ||
456 | |||
457 | /* PM1B is optional; leave null if not present */ | ||
458 | |||
459 | if (local_fadt->xpm1b_evt_blk.address) { | ||
460 | acpi_tb_init_generic_address(&acpi_gbl_xpm1b_enable, | ||
461 | (u8) ACPI_DIV_2(acpi_gbl_FADT-> | ||
462 | pm1_evt_len), | ||
463 | (acpi_physical_address) | ||
464 | (local_fadt->xpm1b_evt_blk. | ||
465 | address + | ||
466 | ACPI_DIV_2(acpi_gbl_FADT-> | ||
467 | pm1_evt_len))); | ||
468 | |||
469 | acpi_gbl_xpm1b_enable.address_space_id = | ||
470 | local_fadt->xpm1b_evt_blk.address_space_id; | ||
471 | } | ||
472 | } | ||
473 | |||
474 | /******************************************************************************* | ||
475 | * | ||
476 | * FUNCTION: acpi_tb_convert_table_fadt | ||
477 | * | ||
478 | * PARAMETERS: None | ||
479 | * | ||
480 | * RETURN: Status | ||
481 | * | ||
482 | * DESCRIPTION: Converts a BIOS supplied ACPI 1.0 FADT to a local | ||
483 | * ACPI 2.0 FADT. If the BIOS supplied a 2.0 FADT then it is simply | ||
484 | * copied to the local FADT. The ACPI CA software uses this | ||
485 | * local FADT. Thus a significant amount of special #ifdef | ||
486 | * type codeing is saved. | ||
487 | * | ||
488 | ******************************************************************************/ | ||
489 | |||
490 | acpi_status acpi_tb_convert_table_fadt(void) | ||
491 | { | ||
492 | struct fadt_descriptor *local_fadt; | ||
493 | struct acpi_table_desc *table_desc; | ||
494 | |||
495 | ACPI_FUNCTION_TRACE(tb_convert_table_fadt); | ||
496 | |||
497 | /* | ||
498 | * acpi_gbl_FADT is valid. Validate the FADT length. The table must be | ||
499 | * at least as long as the version 1.0 FADT | ||
500 | */ | ||
501 | if (acpi_gbl_FADT->length < sizeof(struct fadt_descriptor_rev1)) { | ||
502 | ACPI_ERROR((AE_INFO, "FADT is invalid, too short: 0x%X", | ||
503 | acpi_gbl_FADT->length)); | ||
504 | return_ACPI_STATUS(AE_INVALID_TABLE_LENGTH); | ||
505 | } | ||
506 | |||
507 | /* Allocate buffer for the ACPI 2.0(+) FADT */ | ||
508 | |||
509 | local_fadt = ACPI_ALLOCATE_ZEROED(sizeof(struct fadt_descriptor)); | ||
510 | if (!local_fadt) { | ||
511 | return_ACPI_STATUS(AE_NO_MEMORY); | ||
512 | } | ||
513 | |||
514 | if (acpi_gbl_FADT->revision >= FADT2_REVISION_ID) { | ||
515 | if (acpi_gbl_FADT->length < sizeof(struct fadt_descriptor)) { | ||
516 | |||
517 | /* Length is too short to be a V2.0 table */ | ||
518 | |||
519 | ACPI_WARNING((AE_INFO, | ||
520 | "Inconsistent FADT length (0x%X) and revision (0x%X), using FADT V1.0 portion of table", | ||
521 | acpi_gbl_FADT->length, | ||
522 | acpi_gbl_FADT->revision)); | ||
523 | |||
524 | acpi_tb_convert_fadt1(local_fadt, | ||
525 | (void *)acpi_gbl_FADT); | ||
526 | } else { | ||
527 | /* Valid V2.0 table */ | ||
528 | |||
529 | acpi_tb_convert_fadt2(local_fadt, acpi_gbl_FADT); | ||
530 | } | ||
531 | } else { | ||
532 | /* Valid V1.0 table */ | ||
533 | |||
534 | acpi_tb_convert_fadt1(local_fadt, (void *)acpi_gbl_FADT); | ||
535 | } | ||
536 | |||
537 | /* Global FADT pointer will point to the new common V2.0 FADT */ | ||
538 | |||
539 | acpi_gbl_FADT = local_fadt; | ||
540 | acpi_gbl_FADT->length = sizeof(struct fadt_descriptor); | ||
541 | |||
542 | /* Free the original table */ | ||
543 | |||
544 | table_desc = acpi_gbl_table_lists[ACPI_TABLE_ID_FADT].next; | ||
545 | acpi_tb_delete_single_table(table_desc); | ||
546 | |||
547 | /* Install the new table */ | ||
548 | |||
549 | table_desc->pointer = | ||
550 | ACPI_CAST_PTR(struct acpi_table_header, acpi_gbl_FADT); | ||
551 | table_desc->allocation = ACPI_MEM_ALLOCATED; | ||
552 | table_desc->length = sizeof(struct fadt_descriptor); | ||
553 | |||
554 | /* Dump the entire FADT */ | ||
555 | |||
556 | ACPI_DEBUG_PRINT((ACPI_DB_TABLES, | ||
557 | "Hex dump of common internal FADT, size %d (%X)\n", | ||
558 | acpi_gbl_FADT->length, acpi_gbl_FADT->length)); | ||
559 | |||
560 | ACPI_DUMP_BUFFER(ACPI_CAST_PTR(u8, acpi_gbl_FADT), | ||
561 | acpi_gbl_FADT->length); | ||
562 | |||
563 | return_ACPI_STATUS(AE_OK); | ||
564 | } | ||
565 | |||
566 | /******************************************************************************* | ||
567 | * | ||
568 | * FUNCTION: acpi_tb_build_common_facs | ||
569 | * | ||
570 | * PARAMETERS: table_info - Info for currently installed FACS | ||
571 | * | ||
572 | * RETURN: Status | ||
573 | * | ||
574 | * DESCRIPTION: Convert ACPI 1.0 and ACPI 2.0 FACS to a common internal | ||
575 | * table format. | ||
576 | * | ||
577 | ******************************************************************************/ | ||
578 | |||
579 | acpi_status acpi_tb_build_common_facs(struct acpi_table_desc *table_info) | ||
580 | { | ||
581 | |||
582 | ACPI_FUNCTION_TRACE(tb_build_common_facs); | ||
583 | |||
584 | /* Absolute minimum length is 24, but the ACPI spec says 64 */ | ||
585 | |||
586 | if (acpi_gbl_FACS->length < 24) { | ||
587 | ACPI_ERROR((AE_INFO, "Invalid FACS table length: 0x%X", | ||
588 | acpi_gbl_FACS->length)); | ||
589 | return_ACPI_STATUS(AE_INVALID_TABLE_LENGTH); | ||
590 | } | ||
591 | |||
592 | if (acpi_gbl_FACS->length < 64) { | ||
593 | ACPI_WARNING((AE_INFO, | ||
594 | "FACS is shorter than the ACPI specification allows: 0x%X, using anyway", | ||
595 | acpi_gbl_FACS->length)); | ||
596 | } | ||
597 | |||
598 | /* Copy fields to the new FACS */ | ||
599 | |||
600 | acpi_gbl_common_fACS.global_lock = &(acpi_gbl_FACS->global_lock); | ||
601 | |||
602 | if ((acpi_gbl_RSDP->revision < 2) || | ||
603 | (acpi_gbl_FACS->length < 32) || | ||
604 | (!(acpi_gbl_FACS->xfirmware_waking_vector))) { | ||
605 | |||
606 | /* ACPI 1.0 FACS or short table or optional X_ field is zero */ | ||
607 | |||
608 | acpi_gbl_common_fACS.firmware_waking_vector = ACPI_CAST_PTR(u64, | ||
609 | & | ||
610 | (acpi_gbl_FACS-> | ||
611 | firmware_waking_vector)); | ||
612 | acpi_gbl_common_fACS.vector_width = 32; | ||
613 | } else { | ||
614 | /* ACPI 2.0 FACS with valid X_ field */ | ||
615 | |||
616 | acpi_gbl_common_fACS.firmware_waking_vector = | ||
617 | &acpi_gbl_FACS->xfirmware_waking_vector; | ||
618 | acpi_gbl_common_fACS.vector_width = 64; | ||
619 | } | ||
620 | |||
621 | return_ACPI_STATUS(AE_OK); | ||
622 | } | ||
diff --git a/drivers/acpi/tables/tbfadt.c b/drivers/acpi/tables/tbfadt.c new file mode 100644 index 000000000000..807c7116e94b --- /dev/null +++ b/drivers/acpi/tables/tbfadt.c | |||
@@ -0,0 +1,434 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Module Name: tbfadt - FADT table utilities | ||
4 | * | ||
5 | *****************************************************************************/ | ||
6 | |||
7 | /* | ||
8 | * Copyright (C) 2000 - 2007, R. Byron Moore | ||
9 | * All rights reserved. | ||
10 | * | ||
11 | * Redistribution and use in source and binary forms, with or without | ||
12 | * modification, are permitted provided that the following conditions | ||
13 | * are met: | ||
14 | * 1. Redistributions of source code must retain the above copyright | ||
15 | * notice, this list of conditions, and the following disclaimer, | ||
16 | * without modification. | ||
17 | * 2. Redistributions in binary form must reproduce at minimum a disclaimer | ||
18 | * substantially similar to the "NO WARRANTY" disclaimer below | ||
19 | * ("Disclaimer") and any redistribution must be conditioned upon | ||
20 | * including a substantially similar Disclaimer requirement for further | ||
21 | * binary redistribution. | ||
22 | * 3. Neither the names of the above-listed copyright holders nor the names | ||
23 | * of any contributors may be used to endorse or promote products derived | ||
24 | * from this software without specific prior written permission. | ||
25 | * | ||
26 | * Alternatively, this software may be distributed under the terms of the | ||
27 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
28 | * Software Foundation. | ||
29 | * | ||
30 | * NO WARRANTY | ||
31 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
32 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
33 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR | ||
34 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
35 | * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
36 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
37 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
38 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | ||
39 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING | ||
40 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
41 | * POSSIBILITY OF SUCH DAMAGES. | ||
42 | */ | ||
43 | |||
44 | #include <acpi/acpi.h> | ||
45 | #include <acpi/actables.h> | ||
46 | |||
47 | #define _COMPONENT ACPI_TABLES | ||
48 | ACPI_MODULE_NAME("tbfadt") | ||
49 | |||
50 | /* Local prototypes */ | ||
51 | static void inline | ||
52 | acpi_tb_init_generic_address(struct acpi_generic_address *generic_address, | ||
53 | u8 bit_width, u64 address); | ||
54 | |||
55 | static void acpi_tb_convert_fadt(void); | ||
56 | |||
57 | static void acpi_tb_validate_fadt(void); | ||
58 | |||
59 | /* Table for conversion of FADT to common internal format and FADT validation */ | ||
60 | |||
61 | typedef struct acpi_fadt_info { | ||
62 | char *name; | ||
63 | u8 target; | ||
64 | u8 source; | ||
65 | u8 length; | ||
66 | u8 type; | ||
67 | |||
68 | } acpi_fadt_info; | ||
69 | |||
70 | #define ACPI_FADT_REQUIRED 1 | ||
71 | #define ACPI_FADT_SEPARATE_LENGTH 2 | ||
72 | |||
73 | static struct acpi_fadt_info fadt_info_table[] = { | ||
74 | {"Pm1aEventBlock", ACPI_FADT_OFFSET(xpm1a_event_block), | ||
75 | ACPI_FADT_OFFSET(pm1a_event_block), | ||
76 | ACPI_FADT_OFFSET(pm1_event_length), ACPI_FADT_REQUIRED}, | ||
77 | |||
78 | {"Pm1bEventBlock", ACPI_FADT_OFFSET(xpm1b_event_block), | ||
79 | ACPI_FADT_OFFSET(pm1b_event_block), | ||
80 | ACPI_FADT_OFFSET(pm1_event_length), 0}, | ||
81 | |||
82 | {"Pm1aControlBlock", ACPI_FADT_OFFSET(xpm1a_control_block), | ||
83 | ACPI_FADT_OFFSET(pm1a_control_block), | ||
84 | ACPI_FADT_OFFSET(pm1_control_length), ACPI_FADT_REQUIRED}, | ||
85 | |||
86 | {"Pm1bControlBlock", ACPI_FADT_OFFSET(xpm1b_control_block), | ||
87 | ACPI_FADT_OFFSET(pm1b_control_block), | ||
88 | ACPI_FADT_OFFSET(pm1_control_length), 0}, | ||
89 | |||
90 | {"Pm2ControlBlock", ACPI_FADT_OFFSET(xpm2_control_block), | ||
91 | ACPI_FADT_OFFSET(pm2_control_block), | ||
92 | ACPI_FADT_OFFSET(pm2_control_length), ACPI_FADT_SEPARATE_LENGTH}, | ||
93 | |||
94 | {"PmTimerBlock", ACPI_FADT_OFFSET(xpm_timer_block), | ||
95 | ACPI_FADT_OFFSET(pm_timer_block), | ||
96 | ACPI_FADT_OFFSET(pm_timer_length), ACPI_FADT_REQUIRED}, | ||
97 | |||
98 | {"Gpe0Block", ACPI_FADT_OFFSET(xgpe0_block), | ||
99 | ACPI_FADT_OFFSET(gpe0_block), | ||
100 | ACPI_FADT_OFFSET(gpe0_block_length), ACPI_FADT_SEPARATE_LENGTH}, | ||
101 | |||
102 | {"Gpe1Block", ACPI_FADT_OFFSET(xgpe1_block), | ||
103 | ACPI_FADT_OFFSET(gpe1_block), | ||
104 | ACPI_FADT_OFFSET(gpe1_block_length), ACPI_FADT_SEPARATE_LENGTH} | ||
105 | }; | ||
106 | |||
107 | #define ACPI_FADT_INFO_ENTRIES (sizeof (fadt_info_table) / sizeof (struct acpi_fadt_info)) | ||
108 | |||
109 | /******************************************************************************* | ||
110 | * | ||
111 | * FUNCTION: acpi_tb_init_generic_address | ||
112 | * | ||
113 | * PARAMETERS: generic_address - GAS struct to be initialized | ||
114 | * bit_width - Width of this register | ||
115 | * Address - Address of the register | ||
116 | * | ||
117 | * RETURN: None | ||
118 | * | ||
119 | * DESCRIPTION: Initialize a Generic Address Structure (GAS) | ||
120 | * See the ACPI specification for a full description and | ||
121 | * definition of this structure. | ||
122 | * | ||
123 | ******************************************************************************/ | ||
124 | |||
125 | static void inline | ||
126 | acpi_tb_init_generic_address(struct acpi_generic_address *generic_address, | ||
127 | u8 bit_width, u64 address) | ||
128 | { | ||
129 | |||
130 | /* | ||
131 | * The 64-bit Address field is non-aligned in the byte packed | ||
132 | * GAS struct. | ||
133 | */ | ||
134 | ACPI_MOVE_64_TO_64(&generic_address->address, &address); | ||
135 | |||
136 | /* All other fields are byte-wide */ | ||
137 | |||
138 | generic_address->space_id = ACPI_ADR_SPACE_SYSTEM_IO; | ||
139 | generic_address->bit_width = bit_width; | ||
140 | generic_address->bit_offset = 0; | ||
141 | generic_address->access_width = 0; | ||
142 | } | ||
143 | |||
144 | /******************************************************************************* | ||
145 | * | ||
146 | * FUNCTION: acpi_tb_parse_fadt | ||
147 | * | ||
148 | * PARAMETERS: table_index - Index for the FADT | ||
149 | * Flags - Flags | ||
150 | * | ||
151 | * RETURN: None | ||
152 | * | ||
153 | * DESCRIPTION: Initialize the FADT, DSDT and FACS tables | ||
154 | * (FADT contains the addresses of the DSDT and FACS) | ||
155 | * | ||
156 | ******************************************************************************/ | ||
157 | |||
158 | void acpi_tb_parse_fadt(acpi_native_uint table_index, u8 flags) | ||
159 | { | ||
160 | u32 length; | ||
161 | struct acpi_table_header *table; | ||
162 | |||
163 | /* | ||
164 | * The FADT has multiple versions with different lengths, | ||
165 | * and it contains pointers to both the DSDT and FACS tables. | ||
166 | * | ||
167 | * Get a local copy of the FADT and convert it to a common format | ||
168 | * Map entire FADT, assumed to be smaller than one page. | ||
169 | */ | ||
170 | length = acpi_gbl_root_table_list.tables[table_index].length; | ||
171 | |||
172 | table = | ||
173 | acpi_os_map_memory(acpi_gbl_root_table_list.tables[table_index]. | ||
174 | address, length); | ||
175 | if (!table) { | ||
176 | return; | ||
177 | } | ||
178 | |||
179 | /* | ||
180 | * Validate the FADT checksum before we copy the table. Ignore | ||
181 | * checksum error as we want to try to get the DSDT and FACS. | ||
182 | */ | ||
183 | (void)acpi_tb_verify_checksum(table, length); | ||
184 | |||
185 | /* Obtain a local copy of the FADT in common ACPI 2.0+ format */ | ||
186 | |||
187 | acpi_tb_create_local_fadt(table, length); | ||
188 | |||
189 | /* All done with the real FADT, unmap it */ | ||
190 | |||
191 | acpi_os_unmap_memory(table, length); | ||
192 | |||
193 | /* Obtain the DSDT and FACS tables via their addresses within the FADT */ | ||
194 | |||
195 | acpi_tb_install_table((acpi_physical_address) acpi_gbl_FADT.Xdsdt, | ||
196 | flags, ACPI_SIG_DSDT, ACPI_TABLE_INDEX_DSDT); | ||
197 | |||
198 | acpi_tb_install_table((acpi_physical_address) acpi_gbl_FADT.Xfacs, | ||
199 | flags, ACPI_SIG_FACS, ACPI_TABLE_INDEX_FACS); | ||
200 | } | ||
201 | |||
202 | /******************************************************************************* | ||
203 | * | ||
204 | * FUNCTION: acpi_tb_create_local_fadt | ||
205 | * | ||
206 | * PARAMETERS: Table - Pointer to BIOS FADT | ||
207 | * Length - Length of the table | ||
208 | * | ||
209 | * RETURN: None | ||
210 | * | ||
211 | * DESCRIPTION: Get a local copy of the FADT and convert it to a common format. | ||
212 | * Performs validation on some important FADT fields. | ||
213 | * | ||
214 | ******************************************************************************/ | ||
215 | |||
216 | void acpi_tb_create_local_fadt(struct acpi_table_header *table, u32 length) | ||
217 | { | ||
218 | |||
219 | /* | ||
220 | * Check if the FADT is larger than what we know about (ACPI 2.0 version). | ||
221 | * Truncate the table, but make some noise. | ||
222 | */ | ||
223 | if (length > sizeof(struct acpi_table_fadt)) { | ||
224 | ACPI_WARNING((AE_INFO, | ||
225 | "FADT (revision %u) is longer than ACPI 2.0 version, truncating length 0x%X to 0x%zX", | ||
226 | table->revision, (unsigned)length, | ||
227 | sizeof(struct acpi_table_fadt))); | ||
228 | } | ||
229 | |||
230 | /* Copy the entire FADT locally. Zero first for tb_convert_fadt */ | ||
231 | |||
232 | ACPI_MEMSET(&acpi_gbl_FADT, 0, sizeof(struct acpi_table_fadt)); | ||
233 | |||
234 | ACPI_MEMCPY(&acpi_gbl_FADT, table, | ||
235 | ACPI_MIN(length, sizeof(struct acpi_table_fadt))); | ||
236 | |||
237 | /* | ||
238 | * 1) Convert the local copy of the FADT to the common internal format | ||
239 | * 2) Validate some of the important values within the FADT | ||
240 | */ | ||
241 | acpi_tb_convert_fadt(); | ||
242 | acpi_tb_validate_fadt(); | ||
243 | } | ||
244 | |||
245 | /******************************************************************************* | ||
246 | * | ||
247 | * FUNCTION: acpi_tb_convert_fadt | ||
248 | * | ||
249 | * PARAMETERS: None, uses acpi_gbl_FADT | ||
250 | * | ||
251 | * RETURN: None | ||
252 | * | ||
253 | * DESCRIPTION: Converts all versions of the FADT to a common internal format. | ||
254 | * -> Expand all 32-bit addresses to 64-bit. | ||
255 | * | ||
256 | * NOTE: acpi_gbl_FADT must be of size (struct acpi_table_fadt), | ||
257 | * and must contain a copy of the actual FADT. | ||
258 | * | ||
259 | * ACPICA will use the "X" fields of the FADT for all addresses. | ||
260 | * | ||
261 | * "X" fields are optional extensions to the original V1.0 fields. Even if | ||
262 | * they are present in the structure, they can be optionally not used by | ||
263 | * setting them to zero. Therefore, we must selectively expand V1.0 fields | ||
264 | * if the corresponding X field is zero. | ||
265 | * | ||
266 | * For ACPI 1.0 FADTs, all address fields are expanded to the corresponding | ||
267 | * "X" fields. | ||
268 | * | ||
269 | * For ACPI 2.0 FADTs, any "X" fields that are NULL are filled in by | ||
270 | * expanding the corresponding ACPI 1.0 field. | ||
271 | * | ||
272 | ******************************************************************************/ | ||
273 | |||
274 | static void acpi_tb_convert_fadt(void) | ||
275 | { | ||
276 | u8 pm1_register_length; | ||
277 | struct acpi_generic_address *target; | ||
278 | acpi_native_uint i; | ||
279 | |||
280 | /* Update the local FADT table header length */ | ||
281 | |||
282 | acpi_gbl_FADT.header.length = sizeof(struct acpi_table_fadt); | ||
283 | |||
284 | /* Expand the 32-bit FACS and DSDT addresses to 64-bit as necessary */ | ||
285 | |||
286 | if (!acpi_gbl_FADT.Xfacs) { | ||
287 | acpi_gbl_FADT.Xfacs = (u64) acpi_gbl_FADT.facs; | ||
288 | } | ||
289 | |||
290 | if (!acpi_gbl_FADT.Xdsdt) { | ||
291 | acpi_gbl_FADT.Xdsdt = (u64) acpi_gbl_FADT.dsdt; | ||
292 | } | ||
293 | |||
294 | /* | ||
295 | * Expand the 32-bit V1.0 addresses to the 64-bit "X" generic address | ||
296 | * structures as necessary. | ||
297 | */ | ||
298 | for (i = 0; i < ACPI_FADT_INFO_ENTRIES; i++) { | ||
299 | target = | ||
300 | ACPI_ADD_PTR(struct acpi_generic_address, &acpi_gbl_FADT, | ||
301 | fadt_info_table[i].target); | ||
302 | |||
303 | /* Expand only if the X target is null */ | ||
304 | |||
305 | if (!target->address) { | ||
306 | acpi_tb_init_generic_address(target, | ||
307 | *ACPI_ADD_PTR(u8, | ||
308 | &acpi_gbl_FADT, | ||
309 | fadt_info_table | ||
310 | [i].length), | ||
311 | (u64) * ACPI_ADD_PTR(u32, | ||
312 | &acpi_gbl_FADT, | ||
313 | fadt_info_table | ||
314 | [i]. | ||
315 | source)); | ||
316 | } | ||
317 | } | ||
318 | |||
319 | /* | ||
320 | * Calculate separate GAS structs for the PM1 Enable registers. | ||
321 | * These addresses do not appear (directly) in the FADT, so it is | ||
322 | * useful to calculate them once, here. | ||
323 | * | ||
324 | * The PM event blocks are split into two register blocks, first is the | ||
325 | * PM Status Register block, followed immediately by the PM Enable Register | ||
326 | * block. Each is of length (pm1_event_length/2) | ||
327 | */ | ||
328 | pm1_register_length = (u8) ACPI_DIV_2(acpi_gbl_FADT.pm1_event_length); | ||
329 | |||
330 | /* The PM1A register block is required */ | ||
331 | |||
332 | acpi_tb_init_generic_address(&acpi_gbl_xpm1a_enable, | ||
333 | pm1_register_length, | ||
334 | (acpi_gbl_FADT.xpm1a_event_block.address + | ||
335 | pm1_register_length)); | ||
336 | /* Don't forget to copy space_id of the GAS */ | ||
337 | acpi_gbl_xpm1a_enable.space_id = acpi_gbl_FADT.xpm1a_event_block.space_id; | ||
338 | |||
339 | /* The PM1B register block is optional, ignore if not present */ | ||
340 | |||
341 | if (acpi_gbl_FADT.xpm1b_event_block.address) { | ||
342 | acpi_tb_init_generic_address(&acpi_gbl_xpm1b_enable, | ||
343 | pm1_register_length, | ||
344 | (acpi_gbl_FADT.xpm1b_event_block. | ||
345 | address + pm1_register_length)); | ||
346 | /* Don't forget to copy space_id of the GAS */ | ||
347 | acpi_gbl_xpm1b_enable.space_id = acpi_gbl_FADT.xpm1a_event_block.space_id; | ||
348 | |||
349 | } | ||
350 | } | ||
351 | |||
352 | /****************************************************************************** | ||
353 | * | ||
354 | * FUNCTION: acpi_tb_validate_fadt | ||
355 | * | ||
356 | * PARAMETERS: Table - Pointer to the FADT to be validated | ||
357 | * | ||
358 | * RETURN: None | ||
359 | * | ||
360 | * DESCRIPTION: Validate various important fields within the FADT. If a problem | ||
361 | * is found, issue a message, but no status is returned. | ||
362 | * Used by both the table manager and the disassembler. | ||
363 | * | ||
364 | * Possible additional checks: | ||
365 | * (acpi_gbl_FADT.pm1_event_length >= 4) | ||
366 | * (acpi_gbl_FADT.pm1_control_length >= 2) | ||
367 | * (acpi_gbl_FADT.pm_timer_length >= 4) | ||
368 | * Gpe block lengths must be multiple of 2 | ||
369 | * | ||
370 | ******************************************************************************/ | ||
371 | |||
372 | static void acpi_tb_validate_fadt(void) | ||
373 | { | ||
374 | u32 *address32; | ||
375 | struct acpi_generic_address *address64; | ||
376 | u8 length; | ||
377 | acpi_native_uint i; | ||
378 | |||
379 | /* Examine all of the 64-bit extended address fields (X fields) */ | ||
380 | |||
381 | for (i = 0; i < ACPI_FADT_INFO_ENTRIES; i++) { | ||
382 | |||
383 | /* Generate pointers to the 32-bit and 64-bit addresses and get the length */ | ||
384 | |||
385 | address64 = | ||
386 | ACPI_ADD_PTR(struct acpi_generic_address, &acpi_gbl_FADT, | ||
387 | fadt_info_table[i].target); | ||
388 | address32 = | ||
389 | ACPI_ADD_PTR(u32, &acpi_gbl_FADT, | ||
390 | fadt_info_table[i].source); | ||
391 | length = | ||
392 | *ACPI_ADD_PTR(u8, &acpi_gbl_FADT, | ||
393 | fadt_info_table[i].length); | ||
394 | |||
395 | if (fadt_info_table[i].type & ACPI_FADT_REQUIRED) { | ||
396 | /* | ||
397 | * Field is required (Pm1a_event, Pm1a_control, pm_timer). | ||
398 | * Both the address and length must be non-zero. | ||
399 | */ | ||
400 | if (!address64->address || !length) { | ||
401 | ACPI_ERROR((AE_INFO, | ||
402 | "Required field \"%s\" has zero address and/or length: %8.8X%8.8X/%X", | ||
403 | fadt_info_table[i].name, | ||
404 | ACPI_FORMAT_UINT64(address64-> | ||
405 | address), | ||
406 | length)); | ||
407 | } | ||
408 | } else if (fadt_info_table[i].type & ACPI_FADT_SEPARATE_LENGTH) { | ||
409 | /* | ||
410 | * Field is optional (PM2Control, GPE0, GPE1) AND has its own | ||
411 | * length field. If present, both the address and length must be valid. | ||
412 | */ | ||
413 | if ((address64->address && !length) | ||
414 | || (!address64->address && length)) { | ||
415 | ACPI_WARNING((AE_INFO, | ||
416 | "Optional field \"%s\" has zero address or length: %8.8X%8.8X/%X", | ||
417 | fadt_info_table[i].name, | ||
418 | ACPI_FORMAT_UINT64(address64-> | ||
419 | address), | ||
420 | length)); | ||
421 | } | ||
422 | } | ||
423 | |||
424 | /* If both 32- and 64-bit addresses are valid (non-zero), they must match */ | ||
425 | |||
426 | if (address64->address && *address32 && | ||
427 | (address64->address != (u64) * address32)) { | ||
428 | ACPI_ERROR((AE_INFO, | ||
429 | "32/64X address mismatch in \"%s\": [%8.8X] [%8.8X%8.8X], using 64X", | ||
430 | fadt_info_table[i].name, *address32, | ||
431 | ACPI_FORMAT_UINT64(address64->address))); | ||
432 | } | ||
433 | } | ||
434 | } | ||
diff --git a/drivers/acpi/tables/tbfind.c b/drivers/acpi/tables/tbfind.c new file mode 100644 index 000000000000..058c064948e1 --- /dev/null +++ b/drivers/acpi/tables/tbfind.c | |||
@@ -0,0 +1,126 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Module Name: tbfind - find table | ||
4 | * | ||
5 | *****************************************************************************/ | ||
6 | |||
7 | /* | ||
8 | * Copyright (C) 2000 - 2007, R. Byron Moore | ||
9 | * All rights reserved. | ||
10 | * | ||
11 | * Redistribution and use in source and binary forms, with or without | ||
12 | * modification, are permitted provided that the following conditions | ||
13 | * are met: | ||
14 | * 1. Redistributions of source code must retain the above copyright | ||
15 | * notice, this list of conditions, and the following disclaimer, | ||
16 | * without modification. | ||
17 | * 2. Redistributions in binary form must reproduce at minimum a disclaimer | ||
18 | * substantially similar to the "NO WARRANTY" disclaimer below | ||
19 | * ("Disclaimer") and any redistribution must be conditioned upon | ||
20 | * including a substantially similar Disclaimer requirement for further | ||
21 | * binary redistribution. | ||
22 | * 3. Neither the names of the above-listed copyright holders nor the names | ||
23 | * of any contributors may be used to endorse or promote products derived | ||
24 | * from this software without specific prior written permission. | ||
25 | * | ||
26 | * Alternatively, this software may be distributed under the terms of the | ||
27 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
28 | * Software Foundation. | ||
29 | * | ||
30 | * NO WARRANTY | ||
31 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
32 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
33 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR | ||
34 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
35 | * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
36 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
37 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
38 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | ||
39 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING | ||
40 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
41 | * POSSIBILITY OF SUCH DAMAGES. | ||
42 | */ | ||
43 | |||
44 | #include <acpi/acpi.h> | ||
45 | #include <acpi/actables.h> | ||
46 | |||
47 | #define _COMPONENT ACPI_TABLES | ||
48 | ACPI_MODULE_NAME("tbfind") | ||
49 | |||
50 | /******************************************************************************* | ||
51 | * | ||
52 | * FUNCTION: acpi_tb_find_table | ||
53 | * | ||
54 | * PARAMETERS: Signature - String with ACPI table signature | ||
55 | * oem_id - String with the table OEM ID | ||
56 | * oem_table_id - String with the OEM Table ID | ||
57 | * table_index - Where the table index is returned | ||
58 | * | ||
59 | * RETURN: Status and table index | ||
60 | * | ||
61 | * DESCRIPTION: Find an ACPI table (in the RSDT/XSDT) that matches the | ||
62 | * Signature, OEM ID and OEM Table ID. Returns an index that can | ||
63 | * be used to get the table header or entire table. | ||
64 | * | ||
65 | ******************************************************************************/ | ||
66 | acpi_status | ||
67 | acpi_tb_find_table(char *signature, | ||
68 | char *oem_id, | ||
69 | char *oem_table_id, acpi_native_uint * table_index) | ||
70 | { | ||
71 | acpi_native_uint i; | ||
72 | acpi_status status; | ||
73 | |||
74 | ACPI_FUNCTION_TRACE(tb_find_table); | ||
75 | |||
76 | for (i = 0; i < acpi_gbl_root_table_list.count; ++i) { | ||
77 | if (ACPI_MEMCMP(&(acpi_gbl_root_table_list.tables[i].signature), | ||
78 | signature, ACPI_NAME_SIZE)) { | ||
79 | |||
80 | /* Not the requested table */ | ||
81 | |||
82 | continue; | ||
83 | } | ||
84 | |||
85 | /* Table with matching signature has been found */ | ||
86 | |||
87 | if (!acpi_gbl_root_table_list.tables[i].pointer) { | ||
88 | |||
89 | /* Table is not currently mapped, map it */ | ||
90 | |||
91 | status = | ||
92 | acpi_tb_verify_table(&acpi_gbl_root_table_list. | ||
93 | tables[i]); | ||
94 | if (ACPI_FAILURE(status)) { | ||
95 | return_ACPI_STATUS(status); | ||
96 | } | ||
97 | |||
98 | if (!acpi_gbl_root_table_list.tables[i].pointer) { | ||
99 | continue; | ||
100 | } | ||
101 | } | ||
102 | |||
103 | /* Check for table match on all IDs */ | ||
104 | |||
105 | if (!ACPI_MEMCMP | ||
106 | (acpi_gbl_root_table_list.tables[i].pointer->signature, | ||
107 | signature, ACPI_NAME_SIZE) && (!oem_id[0] | ||
108 | || | ||
109 | !ACPI_MEMCMP | ||
110 | (acpi_gbl_root_table_list. | ||
111 | tables[i].pointer->oem_id, | ||
112 | oem_id, ACPI_OEM_ID_SIZE)) | ||
113 | && (!oem_table_id[0] | ||
114 | || !ACPI_MEMCMP(acpi_gbl_root_table_list.tables[i]. | ||
115 | pointer->oem_table_id, oem_table_id, | ||
116 | ACPI_OEM_TABLE_ID_SIZE))) { | ||
117 | *table_index = i; | ||
118 | |||
119 | ACPI_DEBUG_PRINT((ACPI_DB_TABLES, | ||
120 | "Found table [%4.4s]\n", signature)); | ||
121 | return_ACPI_STATUS(AE_OK); | ||
122 | } | ||
123 | } | ||
124 | |||
125 | return_ACPI_STATUS(AE_NOT_FOUND); | ||
126 | } | ||
diff --git a/drivers/acpi/tables/tbget.c b/drivers/acpi/tables/tbget.c deleted file mode 100644 index 11e2d4454e05..000000000000 --- a/drivers/acpi/tables/tbget.c +++ /dev/null | |||
@@ -1,471 +0,0 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Module Name: tbget - ACPI Table get* routines | ||
4 | * | ||
5 | *****************************************************************************/ | ||
6 | |||
7 | /* | ||
8 | * Copyright (C) 2000 - 2006, R. Byron Moore | ||
9 | * All rights reserved. | ||
10 | * | ||
11 | * Redistribution and use in source and binary forms, with or without | ||
12 | * modification, are permitted provided that the following conditions | ||
13 | * are met: | ||
14 | * 1. Redistributions of source code must retain the above copyright | ||
15 | * notice, this list of conditions, and the following disclaimer, | ||
16 | * without modification. | ||
17 | * 2. Redistributions in binary form must reproduce at minimum a disclaimer | ||
18 | * substantially similar to the "NO WARRANTY" disclaimer below | ||
19 | * ("Disclaimer") and any redistribution must be conditioned upon | ||
20 | * including a substantially similar Disclaimer requirement for further | ||
21 | * binary redistribution. | ||
22 | * 3. Neither the names of the above-listed copyright holders nor the names | ||
23 | * of any contributors may be used to endorse or promote products derived | ||
24 | * from this software without specific prior written permission. | ||
25 | * | ||
26 | * Alternatively, this software may be distributed under the terms of the | ||
27 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
28 | * Software Foundation. | ||
29 | * | ||
30 | * NO WARRANTY | ||
31 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
32 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
33 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR | ||
34 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
35 | * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
36 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
37 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
38 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | ||
39 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING | ||
40 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
41 | * POSSIBILITY OF SUCH DAMAGES. | ||
42 | */ | ||
43 | |||
44 | #include <acpi/acpi.h> | ||
45 | #include <acpi/actables.h> | ||
46 | |||
47 | #define _COMPONENT ACPI_TABLES | ||
48 | ACPI_MODULE_NAME("tbget") | ||
49 | |||
50 | /* Local prototypes */ | ||
51 | static acpi_status | ||
52 | acpi_tb_get_this_table(struct acpi_pointer *address, | ||
53 | struct acpi_table_header *header, | ||
54 | struct acpi_table_desc *table_info); | ||
55 | |||
56 | static acpi_status | ||
57 | acpi_tb_table_override(struct acpi_table_header *header, | ||
58 | struct acpi_table_desc *table_info); | ||
59 | |||
60 | /******************************************************************************* | ||
61 | * | ||
62 | * FUNCTION: acpi_tb_get_table | ||
63 | * | ||
64 | * PARAMETERS: Address - Address of table to retrieve. Can be | ||
65 | * Logical or Physical | ||
66 | * table_info - Where table info is returned | ||
67 | * | ||
68 | * RETURN: None | ||
69 | * | ||
70 | * DESCRIPTION: Get entire table of unknown size. | ||
71 | * | ||
72 | ******************************************************************************/ | ||
73 | |||
74 | acpi_status | ||
75 | acpi_tb_get_table(struct acpi_pointer *address, | ||
76 | struct acpi_table_desc *table_info) | ||
77 | { | ||
78 | acpi_status status; | ||
79 | struct acpi_table_header header; | ||
80 | |||
81 | ACPI_FUNCTION_TRACE(tb_get_table); | ||
82 | |||
83 | /* Get the header in order to get signature and table size */ | ||
84 | |||
85 | status = acpi_tb_get_table_header(address, &header); | ||
86 | if (ACPI_FAILURE(status)) { | ||
87 | return_ACPI_STATUS(status); | ||
88 | } | ||
89 | |||
90 | /* Get the entire table */ | ||
91 | |||
92 | status = acpi_tb_get_table_body(address, &header, table_info); | ||
93 | if (ACPI_FAILURE(status)) { | ||
94 | ACPI_EXCEPTION((AE_INFO, status, | ||
95 | "Could not get ACPI table (size %X)", | ||
96 | header.length)); | ||
97 | return_ACPI_STATUS(status); | ||
98 | } | ||
99 | |||
100 | return_ACPI_STATUS(AE_OK); | ||
101 | } | ||
102 | |||
103 | /******************************************************************************* | ||
104 | * | ||
105 | * FUNCTION: acpi_tb_get_table_header | ||
106 | * | ||
107 | * PARAMETERS: Address - Address of table to retrieve. Can be | ||
108 | * Logical or Physical | ||
109 | * return_header - Where the table header is returned | ||
110 | * | ||
111 | * RETURN: Status | ||
112 | * | ||
113 | * DESCRIPTION: Get an ACPI table header. Works in both physical or virtual | ||
114 | * addressing mode. Works with both physical or logical pointers. | ||
115 | * Table is either copied or mapped, depending on the pointer | ||
116 | * type and mode of the processor. | ||
117 | * | ||
118 | ******************************************************************************/ | ||
119 | |||
120 | acpi_status | ||
121 | acpi_tb_get_table_header(struct acpi_pointer *address, | ||
122 | struct acpi_table_header *return_header) | ||
123 | { | ||
124 | acpi_status status = AE_OK; | ||
125 | struct acpi_table_header *header = NULL; | ||
126 | |||
127 | ACPI_FUNCTION_TRACE(tb_get_table_header); | ||
128 | |||
129 | /* | ||
130 | * Flags contains the current processor mode (Virtual or Physical | ||
131 | * addressing) The pointer_type is either Logical or Physical | ||
132 | */ | ||
133 | switch (address->pointer_type) { | ||
134 | case ACPI_PHYSMODE_PHYSPTR: | ||
135 | case ACPI_LOGMODE_LOGPTR: | ||
136 | |||
137 | /* Pointer matches processor mode, copy the header */ | ||
138 | |||
139 | ACPI_MEMCPY(return_header, address->pointer.logical, | ||
140 | sizeof(struct acpi_table_header)); | ||
141 | break; | ||
142 | |||
143 | case ACPI_LOGMODE_PHYSPTR: | ||
144 | |||
145 | /* Create a logical address for the physical pointer */ | ||
146 | |||
147 | status = acpi_os_map_memory(address->pointer.physical, | ||
148 | sizeof(struct acpi_table_header), | ||
149 | (void *)&header); | ||
150 | if (ACPI_FAILURE(status)) { | ||
151 | ACPI_ERROR((AE_INFO, | ||
152 | "Could not map memory at %8.8X%8.8X for table header", | ||
153 | ACPI_FORMAT_UINT64(address->pointer. | ||
154 | physical))); | ||
155 | return_ACPI_STATUS(status); | ||
156 | } | ||
157 | |||
158 | /* Copy header and delete mapping */ | ||
159 | |||
160 | ACPI_MEMCPY(return_header, header, | ||
161 | sizeof(struct acpi_table_header)); | ||
162 | acpi_os_unmap_memory(header, sizeof(struct acpi_table_header)); | ||
163 | break; | ||
164 | |||
165 | default: | ||
166 | |||
167 | ACPI_ERROR((AE_INFO, "Invalid address flags %X", | ||
168 | address->pointer_type)); | ||
169 | return_ACPI_STATUS(AE_BAD_PARAMETER); | ||
170 | } | ||
171 | |||
172 | ACPI_DEBUG_PRINT((ACPI_DB_TABLES, "Table Signature: [%4.4s]\n", | ||
173 | return_header->signature)); | ||
174 | |||
175 | return_ACPI_STATUS(AE_OK); | ||
176 | } | ||
177 | |||
178 | /******************************************************************************* | ||
179 | * | ||
180 | * FUNCTION: acpi_tb_get_table_body | ||
181 | * | ||
182 | * PARAMETERS: Address - Address of table to retrieve. Can be | ||
183 | * Logical or Physical | ||
184 | * Header - Header of the table to retrieve | ||
185 | * table_info - Where the table info is returned | ||
186 | * | ||
187 | * RETURN: Status | ||
188 | * | ||
189 | * DESCRIPTION: Get an entire ACPI table with support to allow the host OS to | ||
190 | * replace the table with a newer version (table override.) | ||
191 | * Works in both physical or virtual | ||
192 | * addressing mode. Works with both physical or logical pointers. | ||
193 | * Table is either copied or mapped, depending on the pointer | ||
194 | * type and mode of the processor. | ||
195 | * | ||
196 | ******************************************************************************/ | ||
197 | |||
198 | acpi_status | ||
199 | acpi_tb_get_table_body(struct acpi_pointer *address, | ||
200 | struct acpi_table_header *header, | ||
201 | struct acpi_table_desc *table_info) | ||
202 | { | ||
203 | acpi_status status; | ||
204 | |||
205 | ACPI_FUNCTION_TRACE(tb_get_table_body); | ||
206 | |||
207 | if (!table_info || !address) { | ||
208 | return_ACPI_STATUS(AE_BAD_PARAMETER); | ||
209 | } | ||
210 | |||
211 | /* Attempt table override. */ | ||
212 | |||
213 | status = acpi_tb_table_override(header, table_info); | ||
214 | if (ACPI_SUCCESS(status)) { | ||
215 | |||
216 | /* Table was overridden by the host OS */ | ||
217 | |||
218 | return_ACPI_STATUS(status); | ||
219 | } | ||
220 | |||
221 | /* No override, get the original table */ | ||
222 | |||
223 | status = acpi_tb_get_this_table(address, header, table_info); | ||
224 | return_ACPI_STATUS(status); | ||
225 | } | ||
226 | |||
227 | /******************************************************************************* | ||
228 | * | ||
229 | * FUNCTION: acpi_tb_table_override | ||
230 | * | ||
231 | * PARAMETERS: Header - Pointer to table header | ||
232 | * table_info - Return info if table is overridden | ||
233 | * | ||
234 | * RETURN: None | ||
235 | * | ||
236 | * DESCRIPTION: Attempts override of current table with a new one if provided | ||
237 | * by the host OS. | ||
238 | * | ||
239 | ******************************************************************************/ | ||
240 | |||
241 | static acpi_status | ||
242 | acpi_tb_table_override(struct acpi_table_header *header, | ||
243 | struct acpi_table_desc *table_info) | ||
244 | { | ||
245 | struct acpi_table_header *new_table; | ||
246 | acpi_status status; | ||
247 | struct acpi_pointer address; | ||
248 | |||
249 | ACPI_FUNCTION_TRACE(tb_table_override); | ||
250 | |||
251 | /* | ||
252 | * The OSL will examine the header and decide whether to override this | ||
253 | * table. If it decides to override, a table will be returned in new_table, | ||
254 | * which we will then copy. | ||
255 | */ | ||
256 | status = acpi_os_table_override(header, &new_table); | ||
257 | if (ACPI_FAILURE(status)) { | ||
258 | |||
259 | /* Some severe error from the OSL, but we basically ignore it */ | ||
260 | |||
261 | ACPI_EXCEPTION((AE_INFO, status, | ||
262 | "Could not override ACPI table")); | ||
263 | return_ACPI_STATUS(status); | ||
264 | } | ||
265 | |||
266 | if (!new_table) { | ||
267 | |||
268 | /* No table override */ | ||
269 | |||
270 | return_ACPI_STATUS(AE_NO_ACPI_TABLES); | ||
271 | } | ||
272 | |||
273 | /* | ||
274 | * We have a new table to override the old one. Get a copy of | ||
275 | * the new one. We know that the new table has a logical pointer. | ||
276 | */ | ||
277 | address.pointer_type = ACPI_LOGICAL_POINTER | ACPI_LOGICAL_ADDRESSING; | ||
278 | address.pointer.logical = new_table; | ||
279 | |||
280 | status = acpi_tb_get_this_table(&address, new_table, table_info); | ||
281 | if (ACPI_FAILURE(status)) { | ||
282 | ACPI_EXCEPTION((AE_INFO, status, "Could not copy ACPI table")); | ||
283 | return_ACPI_STATUS(status); | ||
284 | } | ||
285 | |||
286 | /* Copy the table info */ | ||
287 | |||
288 | ACPI_INFO((AE_INFO, "Table [%4.4s] replaced by host OS", | ||
289 | table_info->pointer->signature)); | ||
290 | |||
291 | return_ACPI_STATUS(AE_OK); | ||
292 | } | ||
293 | |||
294 | /******************************************************************************* | ||
295 | * | ||
296 | * FUNCTION: acpi_tb_get_this_table | ||
297 | * | ||
298 | * PARAMETERS: Address - Address of table to retrieve. Can be | ||
299 | * Logical or Physical | ||
300 | * Header - Header of the table to retrieve | ||
301 | * table_info - Where the table info is returned | ||
302 | * | ||
303 | * RETURN: Status | ||
304 | * | ||
305 | * DESCRIPTION: Get an entire ACPI table. Works in both physical or virtual | ||
306 | * addressing mode. Works with both physical or logical pointers. | ||
307 | * Table is either copied or mapped, depending on the pointer | ||
308 | * type and mode of the processor. | ||
309 | * | ||
310 | ******************************************************************************/ | ||
311 | |||
312 | static acpi_status | ||
313 | acpi_tb_get_this_table(struct acpi_pointer *address, | ||
314 | struct acpi_table_header *header, | ||
315 | struct acpi_table_desc *table_info) | ||
316 | { | ||
317 | struct acpi_table_header *full_table = NULL; | ||
318 | u8 allocation; | ||
319 | acpi_status status = AE_OK; | ||
320 | |||
321 | ACPI_FUNCTION_TRACE(tb_get_this_table); | ||
322 | |||
323 | /* Validate minimum length */ | ||
324 | |||
325 | if (header->length < sizeof(struct acpi_table_header)) { | ||
326 | ACPI_ERROR((AE_INFO, | ||
327 | "Table length (%X) is smaller than minimum (%zX)", | ||
328 | header->length, sizeof(struct acpi_table_header))); | ||
329 | |||
330 | return_ACPI_STATUS(AE_INVALID_TABLE_LENGTH); | ||
331 | } | ||
332 | |||
333 | /* | ||
334 | * Flags contains the current processor mode (Virtual or Physical | ||
335 | * addressing) The pointer_type is either Logical or Physical | ||
336 | */ | ||
337 | switch (address->pointer_type) { | ||
338 | case ACPI_PHYSMODE_PHYSPTR: | ||
339 | case ACPI_LOGMODE_LOGPTR: | ||
340 | |||
341 | /* Pointer matches processor mode, copy the table to a new buffer */ | ||
342 | |||
343 | full_table = ACPI_ALLOCATE(header->length); | ||
344 | if (!full_table) { | ||
345 | ACPI_ERROR((AE_INFO, | ||
346 | "Could not allocate table memory for [%4.4s] length %X", | ||
347 | header->signature, header->length)); | ||
348 | return_ACPI_STATUS(AE_NO_MEMORY); | ||
349 | } | ||
350 | |||
351 | /* Copy the entire table (including header) to the local buffer */ | ||
352 | |||
353 | ACPI_MEMCPY(full_table, address->pointer.logical, | ||
354 | header->length); | ||
355 | |||
356 | /* Save allocation type */ | ||
357 | |||
358 | allocation = ACPI_MEM_ALLOCATED; | ||
359 | break; | ||
360 | |||
361 | case ACPI_LOGMODE_PHYSPTR: | ||
362 | |||
363 | /* | ||
364 | * Just map the table's physical memory | ||
365 | * into our address space. | ||
366 | */ | ||
367 | status = acpi_os_map_memory(address->pointer.physical, | ||
368 | (acpi_size) header->length, | ||
369 | ACPI_CAST_PTR(void, &full_table)); | ||
370 | if (ACPI_FAILURE(status)) { | ||
371 | ACPI_ERROR((AE_INFO, | ||
372 | "Could not map memory for table [%4.4s] at %8.8X%8.8X for length %X", | ||
373 | header->signature, | ||
374 | ACPI_FORMAT_UINT64(address->pointer. | ||
375 | physical), | ||
376 | header->length)); | ||
377 | return (status); | ||
378 | } | ||
379 | |||
380 | /* Save allocation type */ | ||
381 | |||
382 | allocation = ACPI_MEM_MAPPED; | ||
383 | break; | ||
384 | |||
385 | default: | ||
386 | |||
387 | ACPI_ERROR((AE_INFO, "Invalid address flags %X", | ||
388 | address->pointer_type)); | ||
389 | return_ACPI_STATUS(AE_BAD_PARAMETER); | ||
390 | } | ||
391 | |||
392 | /* | ||
393 | * Validate checksum for _most_ tables, | ||
394 | * even the ones whose signature we don't recognize | ||
395 | */ | ||
396 | if (table_info->type != ACPI_TABLE_ID_FACS) { | ||
397 | status = acpi_tb_verify_table_checksum(full_table); | ||
398 | |||
399 | #if (!ACPI_CHECKSUM_ABORT) | ||
400 | if (ACPI_FAILURE(status)) { | ||
401 | |||
402 | /* Ignore the error if configuration says so */ | ||
403 | |||
404 | status = AE_OK; | ||
405 | } | ||
406 | #endif | ||
407 | } | ||
408 | |||
409 | /* Return values */ | ||
410 | |||
411 | table_info->pointer = full_table; | ||
412 | table_info->length = (acpi_size) header->length; | ||
413 | table_info->allocation = allocation; | ||
414 | |||
415 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | ||
416 | "Found table [%4.4s] at %8.8X%8.8X, mapped/copied to %p\n", | ||
417 | full_table->signature, | ||
418 | ACPI_FORMAT_UINT64(address->pointer.physical), | ||
419 | full_table)); | ||
420 | |||
421 | return_ACPI_STATUS(status); | ||
422 | } | ||
423 | |||
424 | /******************************************************************************* | ||
425 | * | ||
426 | * FUNCTION: acpi_tb_get_table_ptr | ||
427 | * | ||
428 | * PARAMETERS: table_type - one of the defined table types | ||
429 | * Instance - Which table of this type | ||
430 | * return_table - pointer to location to place the pointer for | ||
431 | * return | ||
432 | * | ||
433 | * RETURN: Status | ||
434 | * | ||
435 | * DESCRIPTION: This function is called to get the pointer to an ACPI table. | ||
436 | * | ||
437 | ******************************************************************************/ | ||
438 | |||
439 | acpi_status | ||
440 | acpi_tb_get_table_ptr(acpi_table_type table_type, | ||
441 | u32 instance, struct acpi_table_header **return_table) | ||
442 | { | ||
443 | struct acpi_table_desc *table_desc; | ||
444 | u32 i; | ||
445 | |||
446 | ACPI_FUNCTION_TRACE(tb_get_table_ptr); | ||
447 | |||
448 | if (table_type > ACPI_TABLE_ID_MAX) { | ||
449 | return_ACPI_STATUS(AE_BAD_PARAMETER); | ||
450 | } | ||
451 | |||
452 | /* Check for instance out of range of the current table count */ | ||
453 | |||
454 | if (instance > acpi_gbl_table_lists[table_type].count) { | ||
455 | return_ACPI_STATUS(AE_NOT_EXIST); | ||
456 | } | ||
457 | |||
458 | /* | ||
459 | * Walk the list to get the desired table | ||
460 | * Note: Instance is one-based | ||
461 | */ | ||
462 | table_desc = acpi_gbl_table_lists[table_type].next; | ||
463 | for (i = 1; i < instance; i++) { | ||
464 | table_desc = table_desc->next; | ||
465 | } | ||
466 | |||
467 | /* We are now pointing to the requested table's descriptor */ | ||
468 | |||
469 | *return_table = table_desc->pointer; | ||
470 | return_ACPI_STATUS(AE_OK); | ||
471 | } | ||
diff --git a/drivers/acpi/tables/tbgetall.c b/drivers/acpi/tables/tbgetall.c deleted file mode 100644 index ad982112e4c6..000000000000 --- a/drivers/acpi/tables/tbgetall.c +++ /dev/null | |||
@@ -1,311 +0,0 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Module Name: tbgetall - Get all required ACPI tables | ||
4 | * | ||
5 | *****************************************************************************/ | ||
6 | |||
7 | /* | ||
8 | * Copyright (C) 2000 - 2006, R. Byron Moore | ||
9 | * All rights reserved. | ||
10 | * | ||
11 | * Redistribution and use in source and binary forms, with or without | ||
12 | * modification, are permitted provided that the following conditions | ||
13 | * are met: | ||
14 | * 1. Redistributions of source code must retain the above copyright | ||
15 | * notice, this list of conditions, and the following disclaimer, | ||
16 | * without modification. | ||
17 | * 2. Redistributions in binary form must reproduce at minimum a disclaimer | ||
18 | * substantially similar to the "NO WARRANTY" disclaimer below | ||
19 | * ("Disclaimer") and any redistribution must be conditioned upon | ||
20 | * including a substantially similar Disclaimer requirement for further | ||
21 | * binary redistribution. | ||
22 | * 3. Neither the names of the above-listed copyright holders nor the names | ||
23 | * of any contributors may be used to endorse or promote products derived | ||
24 | * from this software without specific prior written permission. | ||
25 | * | ||
26 | * Alternatively, this software may be distributed under the terms of the | ||
27 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
28 | * Software Foundation. | ||
29 | * | ||
30 | * NO WARRANTY | ||
31 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
32 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
33 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR | ||
34 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
35 | * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
36 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
37 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
38 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | ||
39 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING | ||
40 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
41 | * POSSIBILITY OF SUCH DAMAGES. | ||
42 | */ | ||
43 | |||
44 | #include <acpi/acpi.h> | ||
45 | #include <acpi/actables.h> | ||
46 | |||
47 | #define _COMPONENT ACPI_TABLES | ||
48 | ACPI_MODULE_NAME("tbgetall") | ||
49 | |||
50 | /* Local prototypes */ | ||
51 | static acpi_status | ||
52 | acpi_tb_get_primary_table(struct acpi_pointer *address, | ||
53 | struct acpi_table_desc *table_info); | ||
54 | |||
55 | static acpi_status | ||
56 | acpi_tb_get_secondary_table(struct acpi_pointer *address, | ||
57 | acpi_string signature, | ||
58 | struct acpi_table_desc *table_info); | ||
59 | |||
60 | /******************************************************************************* | ||
61 | * | ||
62 | * FUNCTION: acpi_tb_get_primary_table | ||
63 | * | ||
64 | * PARAMETERS: Address - Physical address of table to retrieve | ||
65 | * *table_info - Where the table info is returned | ||
66 | * | ||
67 | * RETURN: Status | ||
68 | * | ||
69 | * DESCRIPTION: Maps the physical address of table into a logical address | ||
70 | * | ||
71 | ******************************************************************************/ | ||
72 | |||
73 | static acpi_status | ||
74 | acpi_tb_get_primary_table(struct acpi_pointer *address, | ||
75 | struct acpi_table_desc *table_info) | ||
76 | { | ||
77 | acpi_status status; | ||
78 | struct acpi_table_header header; | ||
79 | |||
80 | ACPI_FUNCTION_TRACE(tb_get_primary_table); | ||
81 | |||
82 | /* Ignore a NULL address in the RSDT */ | ||
83 | |||
84 | if (!address->pointer.value) { | ||
85 | return_ACPI_STATUS(AE_OK); | ||
86 | } | ||
87 | |||
88 | /* Get the header in order to get signature and table size */ | ||
89 | |||
90 | status = acpi_tb_get_table_header(address, &header); | ||
91 | if (ACPI_FAILURE(status)) { | ||
92 | return_ACPI_STATUS(status); | ||
93 | } | ||
94 | |||
95 | /* Clear the table_info */ | ||
96 | |||
97 | ACPI_MEMSET(table_info, 0, sizeof(struct acpi_table_desc)); | ||
98 | |||
99 | /* | ||
100 | * Check the table signature and make sure it is recognized. | ||
101 | * Also checks the header checksum | ||
102 | */ | ||
103 | table_info->pointer = &header; | ||
104 | status = acpi_tb_recognize_table(table_info, ACPI_TABLE_PRIMARY); | ||
105 | if (ACPI_FAILURE(status)) { | ||
106 | return_ACPI_STATUS(status); | ||
107 | } | ||
108 | |||
109 | /* Get the entire table */ | ||
110 | |||
111 | status = acpi_tb_get_table_body(address, &header, table_info); | ||
112 | if (ACPI_FAILURE(status)) { | ||
113 | return_ACPI_STATUS(status); | ||
114 | } | ||
115 | |||
116 | /* Install the table */ | ||
117 | |||
118 | status = acpi_tb_install_table(table_info); | ||
119 | return_ACPI_STATUS(status); | ||
120 | } | ||
121 | |||
122 | /******************************************************************************* | ||
123 | * | ||
124 | * FUNCTION: acpi_tb_get_secondary_table | ||
125 | * | ||
126 | * PARAMETERS: Address - Physical address of table to retrieve | ||
127 | * *table_info - Where the table info is returned | ||
128 | * | ||
129 | * RETURN: Status | ||
130 | * | ||
131 | * DESCRIPTION: Maps the physical address of table into a logical address | ||
132 | * | ||
133 | ******************************************************************************/ | ||
134 | |||
135 | static acpi_status | ||
136 | acpi_tb_get_secondary_table(struct acpi_pointer *address, | ||
137 | acpi_string signature, | ||
138 | struct acpi_table_desc *table_info) | ||
139 | { | ||
140 | acpi_status status; | ||
141 | struct acpi_table_header header; | ||
142 | |||
143 | ACPI_FUNCTION_TRACE_STR(tb_get_secondary_table, signature); | ||
144 | |||
145 | /* Get the header in order to match the signature */ | ||
146 | |||
147 | status = acpi_tb_get_table_header(address, &header); | ||
148 | if (ACPI_FAILURE(status)) { | ||
149 | return_ACPI_STATUS(status); | ||
150 | } | ||
151 | |||
152 | /* Signature must match request */ | ||
153 | |||
154 | if (!ACPI_COMPARE_NAME(header.signature, signature)) { | ||
155 | ACPI_ERROR((AE_INFO, | ||
156 | "Incorrect table signature - wanted [%s] found [%4.4s]", | ||
157 | signature, header.signature)); | ||
158 | return_ACPI_STATUS(AE_BAD_SIGNATURE); | ||
159 | } | ||
160 | |||
161 | /* | ||
162 | * Check the table signature and make sure it is recognized. | ||
163 | * Also checks the header checksum | ||
164 | */ | ||
165 | table_info->pointer = &header; | ||
166 | status = acpi_tb_recognize_table(table_info, ACPI_TABLE_SECONDARY); | ||
167 | if (ACPI_FAILURE(status)) { | ||
168 | return_ACPI_STATUS(status); | ||
169 | } | ||
170 | |||
171 | /* Get the entire table */ | ||
172 | |||
173 | status = acpi_tb_get_table_body(address, &header, table_info); | ||
174 | if (ACPI_FAILURE(status)) { | ||
175 | return_ACPI_STATUS(status); | ||
176 | } | ||
177 | |||
178 | /* Install the table */ | ||
179 | |||
180 | status = acpi_tb_install_table(table_info); | ||
181 | return_ACPI_STATUS(status); | ||
182 | } | ||
183 | |||
184 | /******************************************************************************* | ||
185 | * | ||
186 | * FUNCTION: acpi_tb_get_required_tables | ||
187 | * | ||
188 | * PARAMETERS: None | ||
189 | * | ||
190 | * RETURN: Status | ||
191 | * | ||
192 | * DESCRIPTION: Load and validate tables other than the RSDT. The RSDT must | ||
193 | * already be loaded and validated. | ||
194 | * | ||
195 | * Get the minimum set of ACPI tables, namely: | ||
196 | * | ||
197 | * 1) FADT (via RSDT in loop below) | ||
198 | * 2) FACS (via FADT) | ||
199 | * 3) DSDT (via FADT) | ||
200 | * | ||
201 | ******************************************************************************/ | ||
202 | |||
203 | acpi_status acpi_tb_get_required_tables(void) | ||
204 | { | ||
205 | acpi_status status = AE_OK; | ||
206 | u32 i; | ||
207 | struct acpi_table_desc table_info; | ||
208 | struct acpi_pointer address; | ||
209 | |||
210 | ACPI_FUNCTION_TRACE(tb_get_required_tables); | ||
211 | |||
212 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "%d ACPI tables in RSDT\n", | ||
213 | acpi_gbl_rsdt_table_count)); | ||
214 | |||
215 | address.pointer_type = acpi_gbl_table_flags | ACPI_LOGICAL_ADDRESSING; | ||
216 | |||
217 | /* | ||
218 | * Loop through all table pointers found in RSDT. | ||
219 | * This will NOT include the FACS and DSDT - we must get | ||
220 | * them after the loop. | ||
221 | * | ||
222 | * The only tables we are interested in getting here is the FADT and | ||
223 | * any SSDTs. | ||
224 | */ | ||
225 | for (i = 0; i < acpi_gbl_rsdt_table_count; i++) { | ||
226 | |||
227 | /* Get the table address from the common internal XSDT */ | ||
228 | |||
229 | address.pointer.value = acpi_gbl_XSDT->table_offset_entry[i]; | ||
230 | |||
231 | /* | ||
232 | * Get the tables needed by this subsystem (FADT and any SSDTs). | ||
233 | * NOTE: All other tables are completely ignored at this time. | ||
234 | */ | ||
235 | status = acpi_tb_get_primary_table(&address, &table_info); | ||
236 | if ((status != AE_OK) && (status != AE_TABLE_NOT_SUPPORTED)) { | ||
237 | ACPI_WARNING((AE_INFO, | ||
238 | "%s, while getting table at %8.8X%8.8X", | ||
239 | acpi_format_exception(status), | ||
240 | ACPI_FORMAT_UINT64(address.pointer. | ||
241 | value))); | ||
242 | } | ||
243 | } | ||
244 | |||
245 | /* We must have a FADT to continue */ | ||
246 | |||
247 | if (!acpi_gbl_FADT) { | ||
248 | ACPI_ERROR((AE_INFO, "No FADT present in RSDT/XSDT")); | ||
249 | return_ACPI_STATUS(AE_NO_ACPI_TABLES); | ||
250 | } | ||
251 | |||
252 | /* | ||
253 | * Convert the FADT to a common format. This allows earlier revisions of | ||
254 | * the table to coexist with newer versions, using common access code. | ||
255 | */ | ||
256 | status = acpi_tb_convert_table_fadt(); | ||
257 | if (ACPI_FAILURE(status)) { | ||
258 | ACPI_ERROR((AE_INFO, | ||
259 | "Could not convert FADT to internal common format")); | ||
260 | return_ACPI_STATUS(status); | ||
261 | } | ||
262 | |||
263 | /* Get the FACS (Pointed to by the FADT) */ | ||
264 | |||
265 | address.pointer.value = acpi_gbl_FADT->xfirmware_ctrl; | ||
266 | |||
267 | status = acpi_tb_get_secondary_table(&address, FACS_SIG, &table_info); | ||
268 | if (ACPI_FAILURE(status)) { | ||
269 | ACPI_EXCEPTION((AE_INFO, status, | ||
270 | "Could not get/install the FACS")); | ||
271 | return_ACPI_STATUS(status); | ||
272 | } | ||
273 | |||
274 | /* | ||
275 | * Create the common FACS pointer table | ||
276 | * (Contains pointers to the original table) | ||
277 | */ | ||
278 | status = acpi_tb_build_common_facs(&table_info); | ||
279 | if (ACPI_FAILURE(status)) { | ||
280 | return_ACPI_STATUS(status); | ||
281 | } | ||
282 | |||
283 | /* Get/install the DSDT (Pointed to by the FADT) */ | ||
284 | |||
285 | address.pointer.value = acpi_gbl_FADT->Xdsdt; | ||
286 | |||
287 | status = acpi_tb_get_secondary_table(&address, DSDT_SIG, &table_info); | ||
288 | if (ACPI_FAILURE(status)) { | ||
289 | ACPI_ERROR((AE_INFO, "Could not get/install the DSDT")); | ||
290 | return_ACPI_STATUS(status); | ||
291 | } | ||
292 | |||
293 | /* Set Integer Width (32/64) based upon DSDT revision */ | ||
294 | |||
295 | acpi_ut_set_integer_width(acpi_gbl_DSDT->revision); | ||
296 | |||
297 | /* Dump the entire DSDT */ | ||
298 | |||
299 | ACPI_DEBUG_PRINT((ACPI_DB_TABLES, | ||
300 | "Hex dump of entire DSDT, size %d (0x%X), Integer width = %d\n", | ||
301 | acpi_gbl_DSDT->length, acpi_gbl_DSDT->length, | ||
302 | acpi_gbl_integer_bit_width)); | ||
303 | |||
304 | ACPI_DUMP_BUFFER(ACPI_CAST_PTR(u8, acpi_gbl_DSDT), | ||
305 | acpi_gbl_DSDT->length); | ||
306 | |||
307 | /* Always delete the RSDP mapping, we are done with it */ | ||
308 | |||
309 | acpi_tb_delete_tables_by_type(ACPI_TABLE_ID_RSDP); | ||
310 | return_ACPI_STATUS(status); | ||
311 | } | ||
diff --git a/drivers/acpi/tables/tbinstal.c b/drivers/acpi/tables/tbinstal.c index 1668a232fb67..0e7b121a99ce 100644 --- a/drivers/acpi/tables/tbinstal.c +++ b/drivers/acpi/tables/tbinstal.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 |
@@ -42,510 +42,498 @@ | |||
42 | */ | 42 | */ |
43 | 43 | ||
44 | #include <acpi/acpi.h> | 44 | #include <acpi/acpi.h> |
45 | #include <acpi/acnamesp.h> | ||
45 | #include <acpi/actables.h> | 46 | #include <acpi/actables.h> |
46 | 47 | ||
47 | #define _COMPONENT ACPI_TABLES | 48 | #define _COMPONENT ACPI_TABLES |
48 | ACPI_MODULE_NAME("tbinstal") | 49 | ACPI_MODULE_NAME("tbinstal") |
49 | 50 | ||
50 | /* Local prototypes */ | 51 | /****************************************************************************** |
51 | static acpi_status | ||
52 | acpi_tb_match_signature(char *signature, | ||
53 | struct acpi_table_desc *table_info, u8 search_type); | ||
54 | |||
55 | /******************************************************************************* | ||
56 | * | 52 | * |
57 | * FUNCTION: acpi_tb_match_signature | 53 | * FUNCTION: acpi_tb_verify_table |
58 | * | 54 | * |
59 | * PARAMETERS: Signature - Table signature to match | 55 | * PARAMETERS: table_desc - table |
60 | * table_info - Return data | ||
61 | * search_type - Table type to match (primary/secondary) | ||
62 | * | 56 | * |
63 | * RETURN: Status | 57 | * RETURN: Status |
64 | * | 58 | * |
65 | * DESCRIPTION: Compare signature against the list of "ACPI-subsystem-owned" | 59 | * DESCRIPTION: this function is called to verify and map table |
66 | * tables (DSDT/FADT/SSDT, etc.) Returns the table_type_iD on match. | ||
67 | * | 60 | * |
68 | ******************************************************************************/ | 61 | *****************************************************************************/ |
69 | 62 | acpi_status acpi_tb_verify_table(struct acpi_table_desc *table_desc) | |
70 | static acpi_status | ||
71 | acpi_tb_match_signature(char *signature, | ||
72 | struct acpi_table_desc *table_info, u8 search_type) | ||
73 | { | 63 | { |
74 | acpi_native_uint i; | 64 | acpi_status status = AE_OK; |
75 | 65 | ||
76 | ACPI_FUNCTION_TRACE(tb_match_signature); | 66 | ACPI_FUNCTION_TRACE(tb_verify_table); |
77 | 67 | ||
78 | /* Search for a signature match among the known table types */ | 68 | /* Map the table if necessary */ |
79 | 69 | ||
80 | for (i = 0; i < (ACPI_TABLE_ID_MAX + 1); i++) { | 70 | if (!table_desc->pointer) { |
81 | if (!(acpi_gbl_table_data[i].flags & search_type)) { | 71 | if ((table_desc->flags & ACPI_TABLE_ORIGIN_MASK) == |
82 | continue; | 72 | ACPI_TABLE_ORIGIN_MAPPED) { |
73 | table_desc->pointer = | ||
74 | acpi_os_map_memory(table_desc->address, | ||
75 | table_desc->length); | ||
83 | } | 76 | } |
77 | if (!table_desc->pointer) { | ||
78 | return_ACPI_STATUS(AE_NO_MEMORY); | ||
79 | } | ||
80 | } | ||
84 | 81 | ||
85 | if (!ACPI_STRNCMP(signature, acpi_gbl_table_data[i].signature, | 82 | /* FACS is the odd table, has no standard ACPI header and no checksum */ |
86 | acpi_gbl_table_data[i].sig_length)) { | ||
87 | |||
88 | /* Found a signature match, return index if requested */ | ||
89 | 83 | ||
90 | if (table_info) { | 84 | if (!ACPI_COMPARE_NAME(&table_desc->signature, ACPI_SIG_FACS)) { |
91 | table_info->type = (u8) i; | ||
92 | } | ||
93 | 85 | ||
94 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 86 | /* Always calculate checksum, ignore bad checksum if requested */ |
95 | "Table [%4.4s] is an ACPI table consumed by the core subsystem\n", | ||
96 | (char *)acpi_gbl_table_data[i]. | ||
97 | signature)); | ||
98 | 87 | ||
99 | return_ACPI_STATUS(AE_OK); | 88 | status = |
100 | } | 89 | acpi_tb_verify_checksum(table_desc->pointer, |
90 | table_desc->length); | ||
101 | } | 91 | } |
102 | 92 | ||
103 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 93 | return_ACPI_STATUS(status); |
104 | "Table [%4.4s] is not an ACPI table consumed by the core subsystem - ignored\n", | ||
105 | (char *)signature)); | ||
106 | |||
107 | return_ACPI_STATUS(AE_TABLE_NOT_SUPPORTED); | ||
108 | } | 94 | } |
109 | 95 | ||
110 | /******************************************************************************* | 96 | /******************************************************************************* |
111 | * | 97 | * |
112 | * FUNCTION: acpi_tb_install_table | 98 | * FUNCTION: acpi_tb_add_table |
113 | * | 99 | * |
114 | * PARAMETERS: table_info - Return value from acpi_tb_get_table_body | 100 | * PARAMETERS: table_desc - Table descriptor |
101 | * table_index - Where the table index is returned | ||
115 | * | 102 | * |
116 | * RETURN: Status | 103 | * RETURN: Status |
117 | * | 104 | * |
118 | * DESCRIPTION: Install the table into the global data structures. | 105 | * DESCRIPTION: This function is called to add the ACPI table |
119 | * | 106 | * |
120 | ******************************************************************************/ | 107 | ******************************************************************************/ |
121 | 108 | ||
122 | acpi_status acpi_tb_install_table(struct acpi_table_desc *table_info) | 109 | acpi_status |
110 | acpi_tb_add_table(struct acpi_table_desc *table_desc, | ||
111 | acpi_native_uint * table_index) | ||
123 | { | 112 | { |
124 | acpi_status status; | 113 | acpi_native_uint i; |
125 | 114 | acpi_native_uint length; | |
126 | ACPI_FUNCTION_TRACE(tb_install_table); | 115 | acpi_status status = AE_OK; |
127 | 116 | ||
128 | /* Lock tables while installing */ | 117 | ACPI_FUNCTION_TRACE(tb_add_table); |
129 | 118 | ||
130 | status = acpi_ut_acquire_mutex(ACPI_MTX_TABLES); | 119 | if (!table_desc->pointer) { |
131 | if (ACPI_FAILURE(status)) { | 120 | status = acpi_tb_verify_table(table_desc); |
132 | ACPI_EXCEPTION((AE_INFO, status, | 121 | if (ACPI_FAILURE(status) || !table_desc->pointer) { |
133 | "Could not acquire table mutex")); | 122 | return_ACPI_STATUS(status); |
134 | return_ACPI_STATUS(status); | 123 | } |
135 | } | 124 | } |
136 | 125 | ||
137 | /* | 126 | /* The table must be either an SSDT or a PSDT */ |
138 | * Ignore a table that is already installed. For example, some BIOS | 127 | |
139 | * ASL code will repeatedly attempt to load the same SSDT. | 128 | if ((!ACPI_COMPARE_NAME(table_desc->pointer->signature, ACPI_SIG_PSDT)) |
140 | */ | 129 | && |
141 | status = acpi_tb_is_table_installed(table_info); | 130 | (!ACPI_COMPARE_NAME(table_desc->pointer->signature, ACPI_SIG_SSDT))) |
142 | if (ACPI_FAILURE(status)) { | 131 | { |
143 | goto unlock_and_exit; | 132 | ACPI_ERROR((AE_INFO, |
133 | "Table has invalid signature [%4.4s], must be SSDT or PSDT", | ||
134 | table_desc->pointer->signature)); | ||
135 | return_ACPI_STATUS(AE_BAD_SIGNATURE); | ||
144 | } | 136 | } |
145 | 137 | ||
146 | /* Install the table into the global data structure */ | 138 | (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); |
139 | |||
140 | /* Check if table is already registered */ | ||
141 | |||
142 | for (i = 0; i < acpi_gbl_root_table_list.count; ++i) { | ||
143 | if (!acpi_gbl_root_table_list.tables[i].pointer) { | ||
144 | status = | ||
145 | acpi_tb_verify_table(&acpi_gbl_root_table_list. | ||
146 | tables[i]); | ||
147 | if (ACPI_FAILURE(status) | ||
148 | || !acpi_gbl_root_table_list.tables[i].pointer) { | ||
149 | continue; | ||
150 | } | ||
151 | } | ||
152 | |||
153 | length = ACPI_MIN(table_desc->length, | ||
154 | acpi_gbl_root_table_list.tables[i].length); | ||
155 | if (ACPI_MEMCMP(table_desc->pointer, | ||
156 | acpi_gbl_root_table_list.tables[i].pointer, | ||
157 | length)) { | ||
158 | continue; | ||
159 | } | ||
160 | |||
161 | /* Table is already registered */ | ||
162 | |||
163 | acpi_tb_delete_table(table_desc); | ||
164 | *table_index = i; | ||
165 | goto release; | ||
166 | } | ||
147 | 167 | ||
148 | status = acpi_tb_init_table_descriptor(table_info->type, table_info); | 168 | /* |
169 | * Add the table to the global table list | ||
170 | */ | ||
171 | status = acpi_tb_store_table(table_desc->address, table_desc->pointer, | ||
172 | table_desc->length, table_desc->flags, | ||
173 | table_index); | ||
149 | if (ACPI_FAILURE(status)) { | 174 | if (ACPI_FAILURE(status)) { |
150 | ACPI_EXCEPTION((AE_INFO, status, | 175 | goto release; |
151 | "Could not install table [%4.4s]", | ||
152 | table_info->pointer->signature)); | ||
153 | } | 176 | } |
154 | 177 | ||
155 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "%s located at %p\n", | 178 | acpi_tb_print_table_header(table_desc->address, table_desc->pointer); |
156 | acpi_gbl_table_data[table_info->type].name, | ||
157 | table_info->pointer)); | ||
158 | 179 | ||
159 | unlock_and_exit: | 180 | release: |
160 | (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); | 181 | (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); |
161 | return_ACPI_STATUS(status); | 182 | return_ACPI_STATUS(status); |
162 | } | 183 | } |
163 | 184 | ||
164 | /******************************************************************************* | 185 | /******************************************************************************* |
165 | * | 186 | * |
166 | * FUNCTION: acpi_tb_recognize_table | 187 | * FUNCTION: acpi_tb_resize_root_table_list |
167 | * | 188 | * |
168 | * PARAMETERS: table_info - Return value from acpi_tb_get_table_body | 189 | * PARAMETERS: None |
169 | * search_type - Table type to match (primary/secondary) | ||
170 | * | 190 | * |
171 | * RETURN: Status | 191 | * RETURN: Status |
172 | * | 192 | * |
173 | * DESCRIPTION: Check a table signature for a match against known table types | 193 | * DESCRIPTION: Expand the size of global table array |
174 | * | ||
175 | * NOTE: All table pointers are validated as follows: | ||
176 | * 1) Table pointer must point to valid physical memory | ||
177 | * 2) Signature must be 4 ASCII chars, even if we don't recognize the | ||
178 | * name | ||
179 | * 3) Table must be readable for length specified in the header | ||
180 | * 4) Table checksum must be valid (with the exception of the FACS | ||
181 | * which has no checksum for some odd reason) | ||
182 | * | 194 | * |
183 | ******************************************************************************/ | 195 | ******************************************************************************/ |
184 | 196 | ||
185 | acpi_status | 197 | acpi_status acpi_tb_resize_root_table_list(void) |
186 | acpi_tb_recognize_table(struct acpi_table_desc *table_info, u8 search_type) | ||
187 | { | 198 | { |
188 | struct acpi_table_header *table_header; | 199 | struct acpi_table_desc *tables; |
189 | acpi_status status; | ||
190 | 200 | ||
191 | ACPI_FUNCTION_TRACE(tb_recognize_table); | 201 | ACPI_FUNCTION_TRACE(tb_resize_root_table_list); |
192 | 202 | ||
193 | /* Ensure that we have a valid table pointer */ | 203 | /* allow_resize flag is a parameter to acpi_initialize_tables */ |
194 | 204 | ||
195 | table_header = (struct acpi_table_header *)table_info->pointer; | 205 | if (!(acpi_gbl_root_table_list.flags & ACPI_ROOT_ALLOW_RESIZE)) { |
196 | if (!table_header) { | 206 | ACPI_ERROR((AE_INFO, |
197 | return_ACPI_STATUS(AE_BAD_PARAMETER); | 207 | "Resize of Root Table Array is not allowed")); |
208 | return_ACPI_STATUS(AE_SUPPORT); | ||
198 | } | 209 | } |
199 | 210 | ||
200 | /* | 211 | /* Increase the Table Array size */ |
201 | * We only "recognize" a limited number of ACPI tables -- namely, the | 212 | |
202 | * ones that are used by the subsystem (DSDT, FADT, etc.) | 213 | tables = ACPI_ALLOCATE_ZEROED((acpi_gbl_root_table_list.size + |
203 | * | 214 | ACPI_ROOT_TABLE_SIZE_INCREMENT) |
204 | * An AE_TABLE_NOT_SUPPORTED means that the table was not recognized. | 215 | * sizeof(struct acpi_table_desc)); |
205 | * This can be any one of many valid ACPI tables, it just isn't one of | 216 | if (!tables) { |
206 | * the tables that is consumed by the core subsystem | 217 | ACPI_ERROR((AE_INFO, |
207 | */ | 218 | "Could not allocate new root table array")); |
208 | status = acpi_tb_match_signature(table_header->signature, | 219 | return_ACPI_STATUS(AE_NO_MEMORY); |
209 | table_info, search_type); | ||
210 | if (ACPI_FAILURE(status)) { | ||
211 | return_ACPI_STATUS(status); | ||
212 | } | 220 | } |
213 | 221 | ||
214 | status = acpi_tb_validate_table_header(table_header); | 222 | /* Copy and free the previous table array */ |
215 | if (ACPI_FAILURE(status)) { | 223 | |
216 | return_ACPI_STATUS(status); | 224 | if (acpi_gbl_root_table_list.tables) { |
225 | ACPI_MEMCPY(tables, acpi_gbl_root_table_list.tables, | ||
226 | acpi_gbl_root_table_list.size * | ||
227 | sizeof(struct acpi_table_desc)); | ||
228 | |||
229 | if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) { | ||
230 | ACPI_FREE(acpi_gbl_root_table_list.tables); | ||
231 | } | ||
217 | } | 232 | } |
218 | 233 | ||
219 | /* Return the table type and length via the info struct */ | 234 | acpi_gbl_root_table_list.tables = tables; |
235 | acpi_gbl_root_table_list.size += ACPI_ROOT_TABLE_SIZE_INCREMENT; | ||
236 | acpi_gbl_root_table_list.flags |= (u8) ACPI_ROOT_ORIGIN_ALLOCATED; | ||
220 | 237 | ||
221 | table_info->length = (acpi_size) table_header->length; | 238 | return_ACPI_STATUS(AE_OK); |
222 | return_ACPI_STATUS(status); | ||
223 | } | 239 | } |
224 | 240 | ||
225 | /******************************************************************************* | 241 | /******************************************************************************* |
226 | * | 242 | * |
227 | * FUNCTION: acpi_tb_init_table_descriptor | 243 | * FUNCTION: acpi_tb_store_table |
228 | * | 244 | * |
229 | * PARAMETERS: table_type - The type of the table | 245 | * PARAMETERS: Address - Table address |
230 | * table_info - A table info struct | 246 | * Table - Table header |
247 | * Length - Table length | ||
248 | * Flags - flags | ||
231 | * | 249 | * |
232 | * RETURN: None. | 250 | * RETURN: Status and table index. |
233 | * | 251 | * |
234 | * DESCRIPTION: Install a table into the global data structs. | 252 | * DESCRIPTION: Add an ACPI table to the global table list |
235 | * | 253 | * |
236 | ******************************************************************************/ | 254 | ******************************************************************************/ |
237 | 255 | ||
238 | acpi_status | 256 | acpi_status |
239 | acpi_tb_init_table_descriptor(acpi_table_type table_type, | 257 | acpi_tb_store_table(acpi_physical_address address, |
240 | struct acpi_table_desc *table_info) | 258 | struct acpi_table_header *table, |
259 | u32 length, u8 flags, acpi_native_uint * table_index) | ||
241 | { | 260 | { |
242 | struct acpi_table_list *list_head; | 261 | acpi_status status = AE_OK; |
243 | struct acpi_table_desc *table_desc; | ||
244 | acpi_status status; | ||
245 | |||
246 | ACPI_FUNCTION_TRACE_U32(tb_init_table_descriptor, table_type); | ||
247 | 262 | ||
248 | /* Allocate a descriptor for this table */ | 263 | /* Ensure that there is room for the table in the Root Table List */ |
249 | 264 | ||
250 | table_desc = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_table_desc)); | 265 | if (acpi_gbl_root_table_list.count >= acpi_gbl_root_table_list.size) { |
251 | if (!table_desc) { | 266 | status = acpi_tb_resize_root_table_list(); |
252 | return_ACPI_STATUS(AE_NO_MEMORY); | 267 | if (ACPI_FAILURE(status)) { |
268 | return (status); | ||
269 | } | ||
253 | } | 270 | } |
254 | 271 | ||
255 | /* Get a new owner ID for the table */ | 272 | /* Initialize added table */ |
273 | |||
274 | acpi_gbl_root_table_list.tables[acpi_gbl_root_table_list.count]. | ||
275 | address = address; | ||
276 | acpi_gbl_root_table_list.tables[acpi_gbl_root_table_list.count]. | ||
277 | pointer = table; | ||
278 | acpi_gbl_root_table_list.tables[acpi_gbl_root_table_list.count].length = | ||
279 | length; | ||
280 | acpi_gbl_root_table_list.tables[acpi_gbl_root_table_list.count]. | ||
281 | owner_id = 0; | ||
282 | acpi_gbl_root_table_list.tables[acpi_gbl_root_table_list.count].flags = | ||
283 | flags; | ||
284 | |||
285 | ACPI_MOVE_32_TO_32(& | ||
286 | (acpi_gbl_root_table_list. | ||
287 | tables[acpi_gbl_root_table_list.count].signature), | ||
288 | table->signature); | ||
289 | |||
290 | *table_index = acpi_gbl_root_table_list.count; | ||
291 | acpi_gbl_root_table_list.count++; | ||
292 | return (status); | ||
293 | } | ||
256 | 294 | ||
257 | status = acpi_ut_allocate_owner_id(&table_desc->owner_id); | 295 | /******************************************************************************* |
258 | if (ACPI_FAILURE(status)) { | 296 | * |
259 | goto error_exit1; | 297 | * FUNCTION: acpi_tb_delete_table |
260 | } | 298 | * |
299 | * PARAMETERS: table_index - Table index | ||
300 | * | ||
301 | * RETURN: None | ||
302 | * | ||
303 | * DESCRIPTION: Delete one internal ACPI table | ||
304 | * | ||
305 | ******************************************************************************/ | ||
261 | 306 | ||
262 | /* Install the table into the global data structure */ | 307 | void acpi_tb_delete_table(struct acpi_table_desc *table_desc) |
308 | { | ||
309 | /* Table must be mapped or allocated */ | ||
310 | if (!table_desc->pointer) { | ||
311 | return; | ||
312 | } | ||
313 | switch (table_desc->flags & ACPI_TABLE_ORIGIN_MASK) { | ||
314 | case ACPI_TABLE_ORIGIN_MAPPED: | ||
315 | acpi_os_unmap_memory(table_desc->pointer, table_desc->length); | ||
316 | break; | ||
317 | case ACPI_TABLE_ORIGIN_ALLOCATED: | ||
318 | ACPI_FREE(table_desc->pointer); | ||
319 | break; | ||
320 | default:; | ||
321 | } | ||
263 | 322 | ||
264 | list_head = &acpi_gbl_table_lists[table_type]; | 323 | table_desc->pointer = NULL; |
324 | } | ||
265 | 325 | ||
266 | /* | 326 | /******************************************************************************* |
267 | * Two major types of tables: 1) Only one instance is allowed. This | 327 | * |
268 | * includes most ACPI tables such as the DSDT. 2) Multiple instances of | 328 | * FUNCTION: acpi_tb_terminate |
269 | * the table are allowed. This includes SSDT and PSDTs. | 329 | * |
270 | */ | 330 | * PARAMETERS: None |
271 | if (ACPI_IS_SINGLE_TABLE(acpi_gbl_table_data[table_type].flags)) { | 331 | * |
272 | /* | 332 | * RETURN: None |
273 | * Only one table allowed, and a table has alread been installed | 333 | * |
274 | * at this location, so return an error. | 334 | * DESCRIPTION: Delete all internal ACPI tables |
275 | */ | 335 | * |
276 | if (list_head->next) { | 336 | ******************************************************************************/ |
277 | status = AE_ALREADY_EXISTS; | ||
278 | goto error_exit2; | ||
279 | } | ||
280 | 337 | ||
281 | table_desc->next = list_head->next; | 338 | void acpi_tb_terminate(void) |
282 | list_head->next = table_desc; | 339 | { |
340 | acpi_native_uint i; | ||
283 | 341 | ||
284 | if (table_desc->next) { | 342 | ACPI_FUNCTION_TRACE(tb_terminate); |
285 | table_desc->next->prev = table_desc; | ||
286 | } | ||
287 | 343 | ||
288 | list_head->count++; | 344 | (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); |
289 | } else { | ||
290 | /* | ||
291 | * Link the new table in to the list of tables of this type. | ||
292 | * Insert at the end of the list, order IS IMPORTANT. | ||
293 | * | ||
294 | * table_desc->Prev & Next are already NULL from calloc() | ||
295 | */ | ||
296 | list_head->count++; | ||
297 | |||
298 | if (!list_head->next) { | ||
299 | list_head->next = table_desc; | ||
300 | } else { | ||
301 | table_desc->next = list_head->next; | ||
302 | 345 | ||
303 | while (table_desc->next->next) { | 346 | /* Delete the individual tables */ |
304 | table_desc->next = table_desc->next->next; | ||
305 | } | ||
306 | 347 | ||
307 | table_desc->next->next = table_desc; | 348 | for (i = 0; i < acpi_gbl_root_table_list.count; ++i) { |
308 | table_desc->prev = table_desc->next; | 349 | acpi_tb_delete_table(&acpi_gbl_root_table_list.tables[i]); |
309 | table_desc->next = NULL; | ||
310 | } | ||
311 | } | 350 | } |
312 | 351 | ||
313 | /* Finish initialization of the table descriptor */ | ||
314 | |||
315 | table_desc->loaded_into_namespace = FALSE; | ||
316 | table_desc->type = (u8) table_type; | ||
317 | table_desc->pointer = table_info->pointer; | ||
318 | table_desc->length = table_info->length; | ||
319 | table_desc->allocation = table_info->allocation; | ||
320 | table_desc->aml_start = (u8 *) (table_desc->pointer + 1), | ||
321 | table_desc->aml_length = (u32) | ||
322 | (table_desc->length - (u32) sizeof(struct acpi_table_header)); | ||
323 | |||
324 | /* | 352 | /* |
325 | * Set the appropriate global pointer (if there is one) to point to the | 353 | * Delete the root table array if allocated locally. Array cannot be |
326 | * newly installed table | 354 | * mapped, so we don't need to check for that flag. |
327 | */ | 355 | */ |
328 | if (acpi_gbl_table_data[table_type].global_ptr) { | 356 | if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) { |
329 | *(acpi_gbl_table_data[table_type].global_ptr) = | 357 | ACPI_FREE(acpi_gbl_root_table_list.tables); |
330 | table_info->pointer; | ||
331 | } | 358 | } |
332 | 359 | ||
333 | /* Return Data */ | 360 | acpi_gbl_root_table_list.tables = NULL; |
334 | 361 | acpi_gbl_root_table_list.flags = 0; | |
335 | table_info->owner_id = table_desc->owner_id; | 362 | acpi_gbl_root_table_list.count = 0; |
336 | table_info->installed_desc = table_desc; | ||
337 | return_ACPI_STATUS(AE_OK); | ||
338 | |||
339 | /* Error exit with cleanup */ | ||
340 | |||
341 | error_exit2: | ||
342 | |||
343 | acpi_ut_release_owner_id(&table_desc->owner_id); | ||
344 | 363 | ||
345 | error_exit1: | 364 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "ACPI Tables freed\n")); |
346 | 365 | (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); | |
347 | ACPI_FREE(table_desc); | ||
348 | return_ACPI_STATUS(status); | ||
349 | } | 366 | } |
350 | 367 | ||
351 | /******************************************************************************* | 368 | /******************************************************************************* |
352 | * | 369 | * |
353 | * FUNCTION: acpi_tb_delete_all_tables | 370 | * FUNCTION: acpi_tb_delete_namespace_by_owner |
354 | * | 371 | * |
355 | * PARAMETERS: None. | 372 | * PARAMETERS: table_index - Table index |
356 | * | 373 | * |
357 | * RETURN: None. | 374 | * RETURN: None |
358 | * | 375 | * |
359 | * DESCRIPTION: Delete all internal ACPI tables | 376 | * DESCRIPTION: Delete all namespace objects created when this table was loaded. |
360 | * | 377 | * |
361 | ******************************************************************************/ | 378 | ******************************************************************************/ |
362 | 379 | ||
363 | void acpi_tb_delete_all_tables(void) | 380 | void acpi_tb_delete_namespace_by_owner(acpi_native_uint table_index) |
364 | { | 381 | { |
365 | acpi_table_type type; | 382 | acpi_owner_id owner_id; |
366 | 383 | ||
367 | /* | 384 | (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); |
368 | * Free memory allocated for ACPI tables | 385 | if (table_index < acpi_gbl_root_table_list.count) { |
369 | * Memory can either be mapped or allocated | 386 | owner_id = |
370 | */ | 387 | acpi_gbl_root_table_list.tables[table_index].owner_id; |
371 | for (type = 0; type < (ACPI_TABLE_ID_MAX + 1); type++) { | 388 | } else { |
372 | acpi_tb_delete_tables_by_type(type); | 389 | (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); |
390 | return; | ||
373 | } | 391 | } |
392 | |||
393 | (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); | ||
394 | acpi_ns_delete_namespace_by_owner(owner_id); | ||
374 | } | 395 | } |
375 | 396 | ||
376 | /******************************************************************************* | 397 | /******************************************************************************* |
377 | * | 398 | * |
378 | * FUNCTION: acpi_tb_delete_tables_by_type | 399 | * FUNCTION: acpi_tb_allocate_owner_id |
379 | * | 400 | * |
380 | * PARAMETERS: Type - The table type to be deleted | 401 | * PARAMETERS: table_index - Table index |
381 | * | 402 | * |
382 | * RETURN: None. | 403 | * RETURN: Status |
383 | * | 404 | * |
384 | * DESCRIPTION: Delete an internal ACPI table | 405 | * DESCRIPTION: Allocates owner_id in table_desc |
385 | * Locks the ACPI table mutex | ||
386 | * | 406 | * |
387 | ******************************************************************************/ | 407 | ******************************************************************************/ |
388 | 408 | ||
389 | void acpi_tb_delete_tables_by_type(acpi_table_type type) | 409 | acpi_status acpi_tb_allocate_owner_id(acpi_native_uint table_index) |
390 | { | 410 | { |
391 | struct acpi_table_desc *table_desc; | 411 | acpi_status status = AE_BAD_PARAMETER; |
392 | u32 count; | ||
393 | u32 i; | ||
394 | 412 | ||
395 | ACPI_FUNCTION_TRACE_U32(tb_delete_tables_by_type, type); | 413 | ACPI_FUNCTION_TRACE(tb_allocate_owner_id); |
396 | 414 | ||
397 | if (type > ACPI_TABLE_ID_MAX) { | 415 | (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); |
398 | return_VOID; | 416 | if (table_index < acpi_gbl_root_table_list.count) { |
399 | } | 417 | status = acpi_ut_allocate_owner_id |
400 | 418 | (&(acpi_gbl_root_table_list.tables[table_index].owner_id)); | |
401 | if (ACPI_FAILURE(acpi_ut_acquire_mutex(ACPI_MTX_TABLES))) { | ||
402 | return; | ||
403 | } | ||
404 | |||
405 | /* Clear the appropriate "typed" global table pointer */ | ||
406 | |||
407 | switch (type) { | ||
408 | case ACPI_TABLE_ID_RSDP: | ||
409 | acpi_gbl_RSDP = NULL; | ||
410 | break; | ||
411 | |||
412 | case ACPI_TABLE_ID_DSDT: | ||
413 | acpi_gbl_DSDT = NULL; | ||
414 | break; | ||
415 | |||
416 | case ACPI_TABLE_ID_FADT: | ||
417 | acpi_gbl_FADT = NULL; | ||
418 | break; | ||
419 | |||
420 | case ACPI_TABLE_ID_FACS: | ||
421 | acpi_gbl_FACS = NULL; | ||
422 | break; | ||
423 | |||
424 | case ACPI_TABLE_ID_XSDT: | ||
425 | acpi_gbl_XSDT = NULL; | ||
426 | break; | ||
427 | |||
428 | case ACPI_TABLE_ID_SSDT: | ||
429 | case ACPI_TABLE_ID_PSDT: | ||
430 | default: | ||
431 | break; | ||
432 | } | ||
433 | |||
434 | /* | ||
435 | * Free the table | ||
436 | * 1) Get the head of the list | ||
437 | */ | ||
438 | table_desc = acpi_gbl_table_lists[type].next; | ||
439 | count = acpi_gbl_table_lists[type].count; | ||
440 | |||
441 | /* | ||
442 | * 2) Walk the entire list, deleting both the allocated tables | ||
443 | * and the table descriptors | ||
444 | */ | ||
445 | for (i = 0; i < count; i++) { | ||
446 | table_desc = acpi_tb_uninstall_table(table_desc); | ||
447 | } | 419 | } |
448 | 420 | ||
449 | (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); | 421 | (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); |
450 | return_VOID; | 422 | return_ACPI_STATUS(status); |
451 | } | 423 | } |
452 | 424 | ||
453 | /******************************************************************************* | 425 | /******************************************************************************* |
454 | * | 426 | * |
455 | * FUNCTION: acpi_tb_delete_single_table | 427 | * FUNCTION: acpi_tb_release_owner_id |
456 | * | 428 | * |
457 | * PARAMETERS: table_info - A table info struct | 429 | * PARAMETERS: table_index - Table index |
458 | * | 430 | * |
459 | * RETURN: None. | 431 | * RETURN: Status |
460 | * | 432 | * |
461 | * DESCRIPTION: Low-level free for a single ACPI table. Handles cases where | 433 | * DESCRIPTION: Releases owner_id in table_desc |
462 | * the table was allocated a buffer or was mapped. | ||
463 | * | 434 | * |
464 | ******************************************************************************/ | 435 | ******************************************************************************/ |
465 | 436 | ||
466 | void acpi_tb_delete_single_table(struct acpi_table_desc *table_desc) | 437 | acpi_status acpi_tb_release_owner_id(acpi_native_uint table_index) |
467 | { | 438 | { |
439 | acpi_status status = AE_BAD_PARAMETER; | ||
468 | 440 | ||
469 | /* Must have a valid table descriptor and pointer */ | 441 | ACPI_FUNCTION_TRACE(tb_release_owner_id); |
470 | 442 | ||
471 | if ((!table_desc) || (!table_desc->pointer)) { | 443 | (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); |
472 | return; | 444 | if (table_index < acpi_gbl_root_table_list.count) { |
445 | acpi_ut_release_owner_id(& | ||
446 | (acpi_gbl_root_table_list. | ||
447 | tables[table_index].owner_id)); | ||
448 | status = AE_OK; | ||
473 | } | 449 | } |
474 | 450 | ||
475 | /* Valid table, determine type of memory allocation */ | 451 | (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); |
476 | 452 | return_ACPI_STATUS(status); | |
477 | switch (table_desc->allocation) { | ||
478 | case ACPI_MEM_NOT_ALLOCATED: | ||
479 | break; | ||
480 | |||
481 | case ACPI_MEM_ALLOCATED: | ||
482 | |||
483 | ACPI_FREE(table_desc->pointer); | ||
484 | break; | ||
485 | |||
486 | case ACPI_MEM_MAPPED: | ||
487 | |||
488 | acpi_os_unmap_memory(table_desc->pointer, table_desc->length); | ||
489 | break; | ||
490 | |||
491 | default: | ||
492 | break; | ||
493 | } | ||
494 | } | 453 | } |
495 | 454 | ||
496 | /******************************************************************************* | 455 | /******************************************************************************* |
497 | * | 456 | * |
498 | * FUNCTION: acpi_tb_uninstall_table | 457 | * FUNCTION: acpi_tb_get_owner_id |
499 | * | 458 | * |
500 | * PARAMETERS: table_info - A table info struct | 459 | * PARAMETERS: table_index - Table index |
460 | * owner_id - Where the table owner_id is returned | ||
501 | * | 461 | * |
502 | * RETURN: Pointer to the next table in the list (of same type) | 462 | * RETURN: Status |
503 | * | 463 | * |
504 | * DESCRIPTION: Free the memory associated with an internal ACPI table that | 464 | * DESCRIPTION: returns owner_id for the ACPI table |
505 | * is either installed or has never been installed. | ||
506 | * Table mutex should be locked. | ||
507 | * | 465 | * |
508 | ******************************************************************************/ | 466 | ******************************************************************************/ |
509 | 467 | ||
510 | struct acpi_table_desc *acpi_tb_uninstall_table(struct acpi_table_desc | 468 | acpi_status |
511 | *table_desc) | 469 | acpi_tb_get_owner_id(acpi_native_uint table_index, acpi_owner_id * owner_id) |
512 | { | 470 | { |
513 | struct acpi_table_desc *next_desc; | 471 | acpi_status status = AE_BAD_PARAMETER; |
514 | 472 | ||
515 | ACPI_FUNCTION_TRACE_PTR(tb_uninstall_table, table_desc); | 473 | ACPI_FUNCTION_TRACE(tb_get_owner_id); |
516 | 474 | ||
517 | if (!table_desc) { | 475 | (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); |
518 | return_PTR(NULL); | 476 | if (table_index < acpi_gbl_root_table_list.count) { |
477 | *owner_id = | ||
478 | acpi_gbl_root_table_list.tables[table_index].owner_id; | ||
479 | status = AE_OK; | ||
519 | } | 480 | } |
520 | 481 | ||
521 | /* Unlink the descriptor from the doubly linked list */ | 482 | (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); |
483 | return_ACPI_STATUS(status); | ||
484 | } | ||
522 | 485 | ||
523 | if (table_desc->prev) { | 486 | /******************************************************************************* |
524 | table_desc->prev->next = table_desc->next; | 487 | * |
525 | } else { | 488 | * FUNCTION: acpi_tb_is_table_loaded |
526 | /* Is first on list, update list head */ | 489 | * |
490 | * PARAMETERS: table_index - Table index | ||
491 | * | ||
492 | * RETURN: Table Loaded Flag | ||
493 | * | ||
494 | ******************************************************************************/ | ||
527 | 495 | ||
528 | acpi_gbl_table_lists[table_desc->type].next = table_desc->next; | 496 | u8 acpi_tb_is_table_loaded(acpi_native_uint table_index) |
529 | } | 497 | { |
498 | u8 is_loaded = FALSE; | ||
530 | 499 | ||
531 | if (table_desc->next) { | 500 | (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); |
532 | table_desc->next->prev = table_desc->prev; | 501 | if (table_index < acpi_gbl_root_table_list.count) { |
502 | is_loaded = (u8) | ||
503 | (acpi_gbl_root_table_list.tables[table_index]. | ||
504 | flags & ACPI_TABLE_IS_LOADED); | ||
533 | } | 505 | } |
534 | 506 | ||
535 | /* Free the memory allocated for the table itself */ | 507 | (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); |
536 | 508 | return (is_loaded); | |
537 | acpi_tb_delete_single_table(table_desc); | 509 | } |
538 | |||
539 | /* Free the owner ID associated with this table */ | ||
540 | |||
541 | acpi_ut_release_owner_id(&table_desc->owner_id); | ||
542 | 510 | ||
543 | /* Free the table descriptor */ | 511 | /******************************************************************************* |
512 | * | ||
513 | * FUNCTION: acpi_tb_set_table_loaded_flag | ||
514 | * | ||
515 | * PARAMETERS: table_index - Table index | ||
516 | * is_loaded - TRUE if table is loaded, FALSE otherwise | ||
517 | * | ||
518 | * RETURN: None | ||
519 | * | ||
520 | * DESCRIPTION: Sets the table loaded flag to either TRUE or FALSE. | ||
521 | * | ||
522 | ******************************************************************************/ | ||
544 | 523 | ||
545 | next_desc = table_desc->next; | 524 | void acpi_tb_set_table_loaded_flag(acpi_native_uint table_index, u8 is_loaded) |
546 | ACPI_FREE(table_desc); | 525 | { |
547 | 526 | ||
548 | /* Return pointer to the next descriptor */ | 527 | (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); |
528 | if (table_index < acpi_gbl_root_table_list.count) { | ||
529 | if (is_loaded) { | ||
530 | acpi_gbl_root_table_list.tables[table_index].flags |= | ||
531 | ACPI_TABLE_IS_LOADED; | ||
532 | } else { | ||
533 | acpi_gbl_root_table_list.tables[table_index].flags &= | ||
534 | ~ACPI_TABLE_IS_LOADED; | ||
535 | } | ||
536 | } | ||
549 | 537 | ||
550 | return_PTR(next_desc); | 538 | (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); |
551 | } | 539 | } |
diff --git a/drivers/acpi/tables/tbrsdt.c b/drivers/acpi/tables/tbrsdt.c deleted file mode 100644 index 86a5fca9b739..000000000000 --- a/drivers/acpi/tables/tbrsdt.c +++ /dev/null | |||
@@ -1,307 +0,0 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Module Name: tbrsdt - ACPI RSDT table utilities | ||
4 | * | ||
5 | *****************************************************************************/ | ||
6 | |||
7 | /* | ||
8 | * Copyright (C) 2000 - 2006, R. Byron Moore | ||
9 | * All rights reserved. | ||
10 | * | ||
11 | * Redistribution and use in source and binary forms, with or without | ||
12 | * modification, are permitted provided that the following conditions | ||
13 | * are met: | ||
14 | * 1. Redistributions of source code must retain the above copyright | ||
15 | * notice, this list of conditions, and the following disclaimer, | ||
16 | * without modification. | ||
17 | * 2. Redistributions in binary form must reproduce at minimum a disclaimer | ||
18 | * substantially similar to the "NO WARRANTY" disclaimer below | ||
19 | * ("Disclaimer") and any redistribution must be conditioned upon | ||
20 | * including a substantially similar Disclaimer requirement for further | ||
21 | * binary redistribution. | ||
22 | * 3. Neither the names of the above-listed copyright holders nor the names | ||
23 | * of any contributors may be used to endorse or promote products derived | ||
24 | * from this software without specific prior written permission. | ||
25 | * | ||
26 | * Alternatively, this software may be distributed under the terms of the | ||
27 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
28 | * Software Foundation. | ||
29 | * | ||
30 | * NO WARRANTY | ||
31 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
32 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
33 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR | ||
34 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
35 | * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
36 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
37 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
38 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | ||
39 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING | ||
40 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
41 | * POSSIBILITY OF SUCH DAMAGES. | ||
42 | */ | ||
43 | |||
44 | #include <acpi/acpi.h> | ||
45 | #include <acpi/actables.h> | ||
46 | |||
47 | #define _COMPONENT ACPI_TABLES | ||
48 | ACPI_MODULE_NAME("tbrsdt") | ||
49 | |||
50 | /******************************************************************************* | ||
51 | * | ||
52 | * FUNCTION: acpi_tb_verify_rsdp | ||
53 | * | ||
54 | * PARAMETERS: Address - RSDP (Pointer to RSDT) | ||
55 | * | ||
56 | * RETURN: Status | ||
57 | * | ||
58 | * DESCRIPTION: Load and validate the RSDP (ptr) and RSDT (table) | ||
59 | * | ||
60 | ******************************************************************************/ | ||
61 | acpi_status acpi_tb_verify_rsdp(struct acpi_pointer *address) | ||
62 | { | ||
63 | struct acpi_table_desc table_info; | ||
64 | acpi_status status; | ||
65 | struct rsdp_descriptor *rsdp; | ||
66 | |||
67 | ACPI_FUNCTION_TRACE(tb_verify_rsdp); | ||
68 | |||
69 | switch (address->pointer_type) { | ||
70 | case ACPI_LOGICAL_POINTER: | ||
71 | |||
72 | rsdp = address->pointer.logical; | ||
73 | break; | ||
74 | |||
75 | case ACPI_PHYSICAL_POINTER: | ||
76 | /* | ||
77 | * Obtain access to the RSDP structure | ||
78 | */ | ||
79 | status = acpi_os_map_memory(address->pointer.physical, | ||
80 | sizeof(struct rsdp_descriptor), | ||
81 | ACPI_CAST_PTR(void, &rsdp)); | ||
82 | if (ACPI_FAILURE(status)) { | ||
83 | return_ACPI_STATUS(status); | ||
84 | } | ||
85 | break; | ||
86 | |||
87 | default: | ||
88 | return_ACPI_STATUS(AE_BAD_PARAMETER); | ||
89 | } | ||
90 | |||
91 | /* Verify RSDP signature and checksum */ | ||
92 | |||
93 | status = acpi_tb_validate_rsdp(rsdp); | ||
94 | if (ACPI_FAILURE(status)) { | ||
95 | goto cleanup; | ||
96 | } | ||
97 | |||
98 | /* RSDP is ok. Init the table info */ | ||
99 | |||
100 | table_info.pointer = ACPI_CAST_PTR(struct acpi_table_header, rsdp); | ||
101 | table_info.length = sizeof(struct rsdp_descriptor); | ||
102 | |||
103 | if (address->pointer_type == ACPI_PHYSICAL_POINTER) { | ||
104 | table_info.allocation = ACPI_MEM_MAPPED; | ||
105 | } else { | ||
106 | table_info.allocation = ACPI_MEM_NOT_ALLOCATED; | ||
107 | } | ||
108 | |||
109 | /* Save the table pointers and allocation info */ | ||
110 | |||
111 | status = acpi_tb_init_table_descriptor(ACPI_TABLE_ID_RSDP, &table_info); | ||
112 | if (ACPI_FAILURE(status)) { | ||
113 | goto cleanup; | ||
114 | } | ||
115 | |||
116 | /* Save the RSDP in a global for easy access */ | ||
117 | |||
118 | acpi_gbl_RSDP = | ||
119 | ACPI_CAST_PTR(struct rsdp_descriptor, table_info.pointer); | ||
120 | return_ACPI_STATUS(status); | ||
121 | |||
122 | /* Error exit */ | ||
123 | cleanup: | ||
124 | |||
125 | if (acpi_gbl_table_flags & ACPI_PHYSICAL_POINTER) { | ||
126 | acpi_os_unmap_memory(rsdp, sizeof(struct rsdp_descriptor)); | ||
127 | } | ||
128 | return_ACPI_STATUS(status); | ||
129 | } | ||
130 | |||
131 | /******************************************************************************* | ||
132 | * | ||
133 | * FUNCTION: acpi_tb_get_rsdt_address | ||
134 | * | ||
135 | * PARAMETERS: out_address - Where the address is returned | ||
136 | * | ||
137 | * RETURN: None, Address | ||
138 | * | ||
139 | * DESCRIPTION: Extract the address of either the RSDT or XSDT, depending on the | ||
140 | * version of the RSDP and whether the XSDT pointer is valid | ||
141 | * | ||
142 | ******************************************************************************/ | ||
143 | |||
144 | void acpi_tb_get_rsdt_address(struct acpi_pointer *out_address) | ||
145 | { | ||
146 | |||
147 | ACPI_FUNCTION_ENTRY(); | ||
148 | |||
149 | out_address->pointer_type = | ||
150 | acpi_gbl_table_flags | ACPI_LOGICAL_ADDRESSING; | ||
151 | |||
152 | /* Use XSDT if it is present */ | ||
153 | |||
154 | if ((acpi_gbl_RSDP->revision >= 2) && | ||
155 | acpi_gbl_RSDP->xsdt_physical_address) { | ||
156 | out_address->pointer.value = | ||
157 | acpi_gbl_RSDP->xsdt_physical_address; | ||
158 | acpi_gbl_root_table_type = ACPI_TABLE_TYPE_XSDT; | ||
159 | } else { | ||
160 | /* No XSDT, use the RSDT */ | ||
161 | |||
162 | out_address->pointer.value = | ||
163 | acpi_gbl_RSDP->rsdt_physical_address; | ||
164 | acpi_gbl_root_table_type = ACPI_TABLE_TYPE_RSDT; | ||
165 | } | ||
166 | } | ||
167 | |||
168 | /******************************************************************************* | ||
169 | * | ||
170 | * FUNCTION: acpi_tb_validate_rsdt | ||
171 | * | ||
172 | * PARAMETERS: table_ptr - Addressable pointer to the RSDT. | ||
173 | * | ||
174 | * RETURN: Status | ||
175 | * | ||
176 | * DESCRIPTION: Validate signature for the RSDT or XSDT | ||
177 | * | ||
178 | ******************************************************************************/ | ||
179 | |||
180 | acpi_status acpi_tb_validate_rsdt(struct acpi_table_header *table_ptr) | ||
181 | { | ||
182 | char *signature; | ||
183 | |||
184 | ACPI_FUNCTION_ENTRY(); | ||
185 | |||
186 | /* Validate minimum length */ | ||
187 | |||
188 | if (table_ptr->length < sizeof(struct acpi_table_header)) { | ||
189 | ACPI_ERROR((AE_INFO, | ||
190 | "RSDT/XSDT length (%X) is smaller than minimum (%zX)", | ||
191 | table_ptr->length, | ||
192 | sizeof(struct acpi_table_header))); | ||
193 | |||
194 | return (AE_INVALID_TABLE_LENGTH); | ||
195 | } | ||
196 | |||
197 | /* Search for appropriate signature, RSDT or XSDT */ | ||
198 | |||
199 | if (acpi_gbl_root_table_type == ACPI_TABLE_TYPE_RSDT) { | ||
200 | signature = RSDT_SIG; | ||
201 | } else { | ||
202 | signature = XSDT_SIG; | ||
203 | } | ||
204 | |||
205 | if (!ACPI_COMPARE_NAME(table_ptr->signature, signature)) { | ||
206 | |||
207 | /* Invalid RSDT or XSDT signature */ | ||
208 | |||
209 | ACPI_ERROR((AE_INFO, | ||
210 | "Invalid signature where RSDP indicates RSDT/XSDT should be located. RSDP:")); | ||
211 | |||
212 | ACPI_DUMP_BUFFER(acpi_gbl_RSDP, 20); | ||
213 | |||
214 | ACPI_ERROR((AE_INFO, | ||
215 | "RSDT/XSDT signature at %X is invalid", | ||
216 | acpi_gbl_RSDP->rsdt_physical_address)); | ||
217 | |||
218 | if (acpi_gbl_root_table_type == ACPI_TABLE_TYPE_RSDT) { | ||
219 | ACPI_ERROR((AE_INFO, "Looking for RSDT")); | ||
220 | } else { | ||
221 | ACPI_ERROR((AE_INFO, "Looking for XSDT")); | ||
222 | } | ||
223 | |||
224 | ACPI_DUMP_BUFFER(ACPI_CAST_PTR(char, table_ptr), 48); | ||
225 | return (AE_BAD_SIGNATURE); | ||
226 | } | ||
227 | |||
228 | return (AE_OK); | ||
229 | } | ||
230 | |||
231 | /******************************************************************************* | ||
232 | * | ||
233 | * FUNCTION: acpi_tb_get_table_rsdt | ||
234 | * | ||
235 | * PARAMETERS: None | ||
236 | * | ||
237 | * RETURN: Status | ||
238 | * | ||
239 | * DESCRIPTION: Load and validate the RSDP (ptr) and RSDT (table) | ||
240 | * | ||
241 | ******************************************************************************/ | ||
242 | |||
243 | acpi_status acpi_tb_get_table_rsdt(void) | ||
244 | { | ||
245 | struct acpi_table_desc table_info; | ||
246 | acpi_status status; | ||
247 | struct acpi_pointer address; | ||
248 | |||
249 | ACPI_FUNCTION_TRACE(tb_get_table_rsdt); | ||
250 | |||
251 | /* Get the RSDT/XSDT via the RSDP */ | ||
252 | |||
253 | acpi_tb_get_rsdt_address(&address); | ||
254 | |||
255 | table_info.type = ACPI_TABLE_ID_XSDT; | ||
256 | status = acpi_tb_get_table(&address, &table_info); | ||
257 | if (ACPI_FAILURE(status)) { | ||
258 | ACPI_EXCEPTION((AE_INFO, status, | ||
259 | "Could not get the RSDT/XSDT")); | ||
260 | return_ACPI_STATUS(status); | ||
261 | } | ||
262 | |||
263 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | ||
264 | "RSDP located at %p, points to RSDT physical=%8.8X%8.8X\n", | ||
265 | acpi_gbl_RSDP, | ||
266 | ACPI_FORMAT_UINT64(address.pointer.value))); | ||
267 | |||
268 | /* Check the RSDT or XSDT signature */ | ||
269 | |||
270 | status = acpi_tb_validate_rsdt(table_info.pointer); | ||
271 | if (ACPI_FAILURE(status)) { | ||
272 | goto error_cleanup; | ||
273 | } | ||
274 | |||
275 | /* Get the number of tables defined in the RSDT or XSDT */ | ||
276 | |||
277 | acpi_gbl_rsdt_table_count = acpi_tb_get_table_count(acpi_gbl_RSDP, | ||
278 | table_info.pointer); | ||
279 | |||
280 | /* Convert and/or copy to an XSDT structure */ | ||
281 | |||
282 | status = acpi_tb_convert_to_xsdt(&table_info); | ||
283 | if (ACPI_FAILURE(status)) { | ||
284 | goto error_cleanup; | ||
285 | } | ||
286 | |||
287 | /* Save the table pointers and allocation info */ | ||
288 | |||
289 | status = acpi_tb_init_table_descriptor(ACPI_TABLE_ID_XSDT, &table_info); | ||
290 | if (ACPI_FAILURE(status)) { | ||
291 | goto error_cleanup; | ||
292 | } | ||
293 | |||
294 | acpi_gbl_XSDT = | ||
295 | ACPI_CAST_PTR(struct xsdt_descriptor, table_info.pointer); | ||
296 | |||
297 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "XSDT located at %p\n", acpi_gbl_XSDT)); | ||
298 | return_ACPI_STATUS(status); | ||
299 | |||
300 | error_cleanup: | ||
301 | |||
302 | /* Free table allocated by acpi_tb_get_table */ | ||
303 | |||
304 | acpi_tb_delete_single_table(&table_info); | ||
305 | |||
306 | return_ACPI_STATUS(status); | ||
307 | } | ||
diff --git a/drivers/acpi/tables/tbutils.c b/drivers/acpi/tables/tbutils.c index 209a401801e3..1da64b4518c0 100644 --- a/drivers/acpi/tables/tbutils.c +++ b/drivers/acpi/tables/tbutils.c | |||
@@ -1,11 +1,11 @@ | |||
1 | /****************************************************************************** | 1 | /****************************************************************************** |
2 | * | 2 | * |
3 | * Module Name: tbutils - Table manipulation utilities | 3 | * Module Name: tbutils - table utilities |
4 | * | 4 | * |
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,137 +48,119 @@ | |||
48 | ACPI_MODULE_NAME("tbutils") | 48 | ACPI_MODULE_NAME("tbutils") |
49 | 49 | ||
50 | /* Local prototypes */ | 50 | /* Local prototypes */ |
51 | #ifdef ACPI_OBSOLETE_FUNCTIONS | 51 | static acpi_physical_address |
52 | acpi_status | 52 | acpi_tb_get_root_table_entry(u8 * table_entry, |
53 | acpi_tb_handle_to_object(u16 table_id, struct acpi_table_desc **table_desc); | 53 | acpi_native_uint table_entry_size); |
54 | #endif | ||
55 | 54 | ||
56 | /******************************************************************************* | 55 | /******************************************************************************* |
57 | * | 56 | * |
58 | * FUNCTION: acpi_tb_is_table_installed | 57 | * FUNCTION: acpi_tb_tables_loaded |
59 | * | ||
60 | * PARAMETERS: new_table_desc - Descriptor for new table being installed | ||
61 | * | 58 | * |
62 | * RETURN: Status - AE_ALREADY_EXISTS if the table is already installed | 59 | * PARAMETERS: None |
63 | * | 60 | * |
64 | * DESCRIPTION: Determine if an ACPI table is already installed | 61 | * RETURN: TRUE if required ACPI tables are loaded |
65 | * | 62 | * |
66 | * MUTEX: Table data structures should be locked | 63 | * DESCRIPTION: Determine if the minimum required ACPI tables are present |
64 | * (FADT, FACS, DSDT) | ||
67 | * | 65 | * |
68 | ******************************************************************************/ | 66 | ******************************************************************************/ |
69 | 67 | ||
70 | acpi_status acpi_tb_is_table_installed(struct acpi_table_desc *new_table_desc) | 68 | u8 acpi_tb_tables_loaded(void) |
71 | { | 69 | { |
72 | struct acpi_table_desc *table_desc; | ||
73 | |||
74 | ACPI_FUNCTION_TRACE(tb_is_table_installed); | ||
75 | 70 | ||
76 | /* Get the list descriptor and first table descriptor */ | 71 | if (acpi_gbl_root_table_list.count >= 3) { |
77 | 72 | return (TRUE); | |
78 | table_desc = acpi_gbl_table_lists[new_table_desc->type].next; | 73 | } |
79 | 74 | ||
80 | /* Examine all installed tables of this type */ | 75 | return (FALSE); |
76 | } | ||
81 | 77 | ||
82 | while (table_desc) { | 78 | /******************************************************************************* |
83 | /* | 79 | * |
84 | * If the table lengths match, perform a full bytewise compare. This | 80 | * FUNCTION: acpi_tb_print_table_header |
85 | * means that we will allow tables with duplicate oem_table_id(s), as | 81 | * |
86 | * long as the tables are different in some way. | 82 | * PARAMETERS: Address - Table physical address |
87 | * | 83 | * Header - Table header |
88 | * Checking if the table has been loaded into the namespace means that | 84 | * |
89 | * we don't check for duplicate tables during the initial installation | 85 | * RETURN: None |
90 | * of tables within the RSDT/XSDT. | 86 | * |
91 | */ | 87 | * DESCRIPTION: Print an ACPI table header. Special cases for FACS and RSDP. |
92 | if ((table_desc->loaded_into_namespace) && | 88 | * |
93 | (table_desc->pointer->length == | 89 | ******************************************************************************/ |
94 | new_table_desc->pointer->length) | ||
95 | && | ||
96 | (!ACPI_MEMCMP | ||
97 | (table_desc->pointer, new_table_desc->pointer, | ||
98 | new_table_desc->pointer->length))) { | ||
99 | |||
100 | /* Match: this table is already installed */ | ||
101 | |||
102 | ACPI_DEBUG_PRINT((ACPI_DB_TABLES, | ||
103 | "Table [%4.4s] already installed: Rev %X OemTableId [%8.8s]\n", | ||
104 | new_table_desc->pointer->signature, | ||
105 | new_table_desc->pointer->revision, | ||
106 | new_table_desc->pointer-> | ||
107 | oem_table_id)); | ||
108 | |||
109 | new_table_desc->owner_id = table_desc->owner_id; | ||
110 | new_table_desc->installed_desc = table_desc; | ||
111 | |||
112 | return_ACPI_STATUS(AE_ALREADY_EXISTS); | ||
113 | } | ||
114 | 90 | ||
115 | /* Get next table on the list */ | 91 | void |
92 | acpi_tb_print_table_header(acpi_physical_address address, | ||
93 | struct acpi_table_header *header) | ||
94 | { | ||
116 | 95 | ||
117 | table_desc = table_desc->next; | 96 | if (ACPI_COMPARE_NAME(header->signature, ACPI_SIG_FACS)) { |
97 | |||
98 | /* FACS only has signature and length fields of common table header */ | ||
99 | |||
100 | ACPI_INFO((AE_INFO, "%4.4s %08lX, %04X", | ||
101 | header->signature, (unsigned long)address, | ||
102 | header->length)); | ||
103 | } else if (ACPI_COMPARE_NAME(header->signature, ACPI_SIG_RSDP)) { | ||
104 | |||
105 | /* RSDP has no common fields */ | ||
106 | |||
107 | ACPI_INFO((AE_INFO, "RSDP %08lX, %04X (r%d %6.6s)", | ||
108 | (unsigned long)address, | ||
109 | (ACPI_CAST_PTR(struct acpi_table_rsdp, header)-> | ||
110 | revision > | ||
111 | 0) ? ACPI_CAST_PTR(struct acpi_table_rsdp, | ||
112 | header)->length : 20, | ||
113 | ACPI_CAST_PTR(struct acpi_table_rsdp, | ||
114 | header)->revision, | ||
115 | ACPI_CAST_PTR(struct acpi_table_rsdp, | ||
116 | header)->oem_id)); | ||
117 | } else { | ||
118 | /* Standard ACPI table with full common header */ | ||
119 | |||
120 | ACPI_INFO((AE_INFO, | ||
121 | "%4.4s %08lX, %04X (r%d %6.6s %8.8s %8X %4.4s %8X)", | ||
122 | header->signature, (unsigned long)address, | ||
123 | header->length, header->revision, header->oem_id, | ||
124 | header->oem_table_id, header->oem_revision, | ||
125 | header->asl_compiler_id, | ||
126 | header->asl_compiler_revision)); | ||
118 | } | 127 | } |
119 | |||
120 | return_ACPI_STATUS(AE_OK); | ||
121 | } | 128 | } |
122 | 129 | ||
123 | /******************************************************************************* | 130 | /******************************************************************************* |
124 | * | 131 | * |
125 | * FUNCTION: acpi_tb_validate_table_header | 132 | * FUNCTION: acpi_tb_validate_checksum |
126 | * | 133 | * |
127 | * PARAMETERS: table_header - Logical pointer to the table | 134 | * PARAMETERS: Table - ACPI table to verify |
135 | * Length - Length of entire table | ||
128 | * | 136 | * |
129 | * RETURN: Status | 137 | * RETURN: Status |
130 | * | 138 | * |
131 | * DESCRIPTION: Check an ACPI table header for validity | 139 | * DESCRIPTION: Verifies that the table checksums to zero. Optionally returns |
132 | * | 140 | * exception on bad checksum. |
133 | * NOTE: Table pointers are validated as follows: | ||
134 | * 1) Table pointer must point to valid physical memory | ||
135 | * 2) Signature must be 4 ASCII chars, even if we don't recognize the | ||
136 | * name | ||
137 | * 3) Table must be readable for length specified in the header | ||
138 | * 4) Table checksum must be valid (with the exception of the FACS | ||
139 | * which has no checksum because it contains variable fields) | ||
140 | * | 141 | * |
141 | ******************************************************************************/ | 142 | ******************************************************************************/ |
142 | 143 | ||
143 | acpi_status | 144 | acpi_status acpi_tb_verify_checksum(struct acpi_table_header *table, u32 length) |
144 | acpi_tb_validate_table_header(struct acpi_table_header *table_header) | ||
145 | { | 145 | { |
146 | acpi_name signature; | 146 | u8 checksum; |
147 | |||
148 | ACPI_FUNCTION_ENTRY(); | ||
149 | |||
150 | /* Verify that this is a valid address */ | ||
151 | |||
152 | if (!acpi_os_readable(table_header, sizeof(struct acpi_table_header))) { | ||
153 | ACPI_ERROR((AE_INFO, | ||
154 | "Cannot read table header at %p", table_header)); | ||
155 | |||
156 | return (AE_BAD_ADDRESS); | ||
157 | } | ||
158 | 147 | ||
159 | /* Ensure that the signature is 4 ASCII characters */ | 148 | /* Compute the checksum on the table */ |
160 | 149 | ||
161 | ACPI_MOVE_32_TO_32(&signature, table_header->signature); | 150 | checksum = acpi_tb_checksum(ACPI_CAST_PTR(u8, table), length); |
162 | if (!acpi_ut_valid_acpi_name(signature)) { | ||
163 | ACPI_ERROR((AE_INFO, "Invalid table signature 0x%8.8X", | ||
164 | signature)); | ||
165 | 151 | ||
166 | ACPI_DUMP_BUFFER(table_header, | 152 | /* Checksum ok? (should be zero) */ |
167 | sizeof(struct acpi_table_header)); | ||
168 | return (AE_BAD_SIGNATURE); | ||
169 | } | ||
170 | 153 | ||
171 | /* Validate the table length */ | 154 | if (checksum) { |
155 | ACPI_WARNING((AE_INFO, | ||
156 | "Incorrect checksum in table [%4.4s] - %2.2X, should be %2.2X", | ||
157 | table->signature, table->checksum, | ||
158 | (u8) (table->checksum - checksum))); | ||
172 | 159 | ||
173 | if (table_header->length < sizeof(struct acpi_table_header)) { | 160 | #if (ACPI_CHECKSUM_ABORT) |
174 | ACPI_ERROR((AE_INFO, | ||
175 | "Invalid length 0x%X in table with signature %4.4s", | ||
176 | (u32) table_header->length, | ||
177 | ACPI_CAST_PTR(char, &signature))); | ||
178 | 161 | ||
179 | ACPI_DUMP_BUFFER(table_header, | 162 | return (AE_BAD_CHECKSUM); |
180 | sizeof(struct acpi_table_header)); | 163 | #endif |
181 | return (AE_BAD_HEADER); | ||
182 | } | 164 | } |
183 | 165 | ||
184 | return (AE_OK); | 166 | return (AE_OK); |
@@ -186,157 +168,320 @@ acpi_tb_validate_table_header(struct acpi_table_header *table_header) | |||
186 | 168 | ||
187 | /******************************************************************************* | 169 | /******************************************************************************* |
188 | * | 170 | * |
189 | * FUNCTION: acpi_tb_sum_table | 171 | * FUNCTION: acpi_tb_checksum |
190 | * | 172 | * |
191 | * PARAMETERS: Buffer - Buffer to sum | 173 | * PARAMETERS: Buffer - Pointer to memory region to be checked |
192 | * Length - Size of the buffer | 174 | * Length - Length of this memory region |
193 | * | 175 | * |
194 | * RETURN: 8 bit sum of buffer | 176 | * RETURN: Checksum (u8) |
195 | * | 177 | * |
196 | * DESCRIPTION: Computes an 8 bit sum of the buffer(length) and returns it. | 178 | * DESCRIPTION: Calculates circular checksum of memory region. |
197 | * | 179 | * |
198 | ******************************************************************************/ | 180 | ******************************************************************************/ |
199 | 181 | ||
200 | u8 acpi_tb_sum_table(void *buffer, u32 length) | 182 | u8 acpi_tb_checksum(u8 * buffer, acpi_native_uint length) |
201 | { | 183 | { |
202 | acpi_native_uint i; | ||
203 | u8 sum = 0; | 184 | u8 sum = 0; |
185 | u8 *end = buffer + length; | ||
204 | 186 | ||
205 | if (!buffer || !length) { | 187 | while (buffer < end) { |
206 | return (0); | 188 | sum = (u8) (sum + *(buffer++)); |
207 | } | 189 | } |
208 | 190 | ||
209 | for (i = 0; i < length; i++) { | 191 | return sum; |
210 | sum = (u8) (sum + ((u8 *) buffer)[i]); | ||
211 | } | ||
212 | return (sum); | ||
213 | } | 192 | } |
214 | 193 | ||
215 | /******************************************************************************* | 194 | /******************************************************************************* |
216 | * | 195 | * |
217 | * FUNCTION: acpi_tb_generate_checksum | 196 | * FUNCTION: acpi_tb_install_table |
218 | * | 197 | * |
219 | * PARAMETERS: Table - Pointer to a valid ACPI table (with a | 198 | * PARAMETERS: Address - Physical address of DSDT or FACS |
220 | * standard ACPI header) | 199 | * Flags - Flags |
200 | * Signature - Table signature, NULL if no need to | ||
201 | * match | ||
202 | * table_index - Index into root table array | ||
221 | * | 203 | * |
222 | * RETURN: 8 bit checksum of buffer | 204 | * RETURN: None |
223 | * | 205 | * |
224 | * DESCRIPTION: Computes an 8 bit checksum of the table. | 206 | * DESCRIPTION: Install an ACPI table into the global data structure. |
225 | * | 207 | * |
226 | ******************************************************************************/ | 208 | ******************************************************************************/ |
227 | 209 | ||
228 | u8 acpi_tb_generate_checksum(struct acpi_table_header * table) | 210 | void |
211 | acpi_tb_install_table(acpi_physical_address address, | ||
212 | u8 flags, char *signature, acpi_native_uint table_index) | ||
229 | { | 213 | { |
230 | u8 checksum; | 214 | struct acpi_table_header *table; |
215 | |||
216 | if (!address) { | ||
217 | ACPI_ERROR((AE_INFO, | ||
218 | "Null physical address for ACPI table [%s]", | ||
219 | signature)); | ||
220 | return; | ||
221 | } | ||
222 | |||
223 | /* Map just the table header */ | ||
224 | |||
225 | table = acpi_os_map_memory(address, sizeof(struct acpi_table_header)); | ||
226 | if (!table) { | ||
227 | return; | ||
228 | } | ||
229 | |||
230 | /* If a particular signature is expected, signature must match */ | ||
231 | |||
232 | if (signature && !ACPI_COMPARE_NAME(table->signature, signature)) { | ||
233 | ACPI_ERROR((AE_INFO, | ||
234 | "Invalid signature 0x%X for ACPI table [%s]", | ||
235 | *ACPI_CAST_PTR(u32, table->signature), signature)); | ||
236 | goto unmap_and_exit; | ||
237 | } | ||
231 | 238 | ||
232 | /* Sum the entire table as-is */ | 239 | /* Initialize the table entry */ |
233 | 240 | ||
234 | checksum = acpi_tb_sum_table(table, table->length); | 241 | acpi_gbl_root_table_list.tables[table_index].address = address; |
242 | acpi_gbl_root_table_list.tables[table_index].length = table->length; | ||
243 | acpi_gbl_root_table_list.tables[table_index].flags = flags; | ||
235 | 244 | ||
236 | /* Subtract off the existing checksum value in the table */ | 245 | ACPI_MOVE_32_TO_32(& |
246 | (acpi_gbl_root_table_list.tables[table_index]. | ||
247 | signature), table->signature); | ||
237 | 248 | ||
238 | checksum = (u8) (checksum - table->checksum); | 249 | acpi_tb_print_table_header(address, table); |
239 | 250 | ||
240 | /* Compute the final checksum */ | 251 | if (table_index == ACPI_TABLE_INDEX_DSDT) { |
241 | 252 | ||
242 | checksum = (u8) (0 - checksum); | 253 | /* Global integer width is based upon revision of the DSDT */ |
243 | return (checksum); | 254 | |
255 | acpi_ut_set_integer_width(table->revision); | ||
256 | } | ||
257 | |||
258 | unmap_and_exit: | ||
259 | acpi_os_unmap_memory(table, sizeof(struct acpi_table_header)); | ||
244 | } | 260 | } |
245 | 261 | ||
246 | /******************************************************************************* | 262 | /******************************************************************************* |
247 | * | 263 | * |
248 | * FUNCTION: acpi_tb_set_checksum | 264 | * FUNCTION: acpi_tb_get_root_table_entry |
249 | * | 265 | * |
250 | * PARAMETERS: Table - Pointer to a valid ACPI table (with a | 266 | * PARAMETERS: table_entry - Pointer to the RSDT/XSDT table entry |
251 | * standard ACPI header) | 267 | * table_entry_size - sizeof 32 or 64 (RSDT or XSDT) |
252 | * | 268 | * |
253 | * RETURN: None. Sets the table checksum field | 269 | * RETURN: Physical address extracted from the root table |
254 | * | 270 | * |
255 | * DESCRIPTION: Computes an 8 bit checksum of the table and inserts the | 271 | * DESCRIPTION: Get one root table entry. Handles 32-bit and 64-bit cases on |
256 | * checksum into the table header. | 272 | * both 32-bit and 64-bit platforms |
273 | * | ||
274 | * NOTE: acpi_physical_address is 32-bit on 32-bit platforms, 64-bit on | ||
275 | * 64-bit platforms. | ||
257 | * | 276 | * |
258 | ******************************************************************************/ | 277 | ******************************************************************************/ |
259 | 278 | ||
260 | void acpi_tb_set_checksum(struct acpi_table_header *table) | 279 | static acpi_physical_address |
280 | acpi_tb_get_root_table_entry(u8 * table_entry, | ||
281 | acpi_native_uint table_entry_size) | ||
261 | { | 282 | { |
283 | u64 address64; | ||
284 | |||
285 | /* | ||
286 | * Get the table physical address (32-bit for RSDT, 64-bit for XSDT): | ||
287 | * Note: Addresses are 32-bit aligned (not 64) in both RSDT and XSDT | ||
288 | */ | ||
289 | if (table_entry_size == sizeof(u32)) { | ||
290 | /* | ||
291 | * 32-bit platform, RSDT: Return 32-bit table entry | ||
292 | * 64-bit platform, RSDT: Expand 32-bit to 64-bit and return | ||
293 | */ | ||
294 | return ((acpi_physical_address) | ||
295 | (*ACPI_CAST_PTR(u32, table_entry))); | ||
296 | } else { | ||
297 | /* | ||
298 | * 32-bit platform, XSDT: Truncate 64-bit to 32-bit and return | ||
299 | * 64-bit platform, XSDT: Move (unaligned) 64-bit to local, return 64-bit | ||
300 | */ | ||
301 | ACPI_MOVE_64_TO_64(&address64, table_entry); | ||
262 | 302 | ||
263 | table->checksum = acpi_tb_generate_checksum(table); | 303 | #if ACPI_MACHINE_WIDTH == 32 |
304 | if (address64 > ACPI_UINT32_MAX) { | ||
305 | |||
306 | /* Will truncate 64-bit address to 32 bits, issue warning */ | ||
307 | |||
308 | ACPI_WARNING((AE_INFO, | ||
309 | "64-bit Physical Address in XSDT is too large (%8.8X%8.8X), truncating", | ||
310 | ACPI_FORMAT_UINT64(address64))); | ||
311 | } | ||
312 | #endif | ||
313 | return ((acpi_physical_address) (address64)); | ||
314 | } | ||
264 | } | 315 | } |
265 | 316 | ||
266 | /******************************************************************************* | 317 | /******************************************************************************* |
267 | * | 318 | * |
268 | * FUNCTION: acpi_tb_verify_table_checksum | 319 | * FUNCTION: acpi_tb_parse_root_table |
320 | * | ||
321 | * PARAMETERS: Rsdp - Pointer to the RSDP | ||
322 | * Flags - Flags | ||
269 | * | 323 | * |
270 | * PARAMETERS: *table_header - ACPI table to verify | 324 | * RETURN: Status |
271 | * | 325 | * |
272 | * RETURN: 8 bit checksum of table | 326 | * DESCRIPTION: This function is called to parse the Root System Description |
327 | * Table (RSDT or XSDT) | ||
273 | * | 328 | * |
274 | * DESCRIPTION: Generates an 8 bit checksum of table and returns and compares | 329 | * NOTE: Tables are mapped (not copied) for efficiency. The FACS must |
275 | * it to the existing checksum value. | 330 | * be mapped and cannot be copied because it contains the actual |
331 | * memory location of the ACPI Global Lock. | ||
276 | * | 332 | * |
277 | ******************************************************************************/ | 333 | ******************************************************************************/ |
278 | 334 | ||
279 | acpi_status | 335 | acpi_status __init |
280 | acpi_tb_verify_table_checksum(struct acpi_table_header *table_header) | 336 | acpi_tb_parse_root_table(acpi_physical_address rsdp_address, u8 flags) |
281 | { | 337 | { |
282 | u8 checksum; | 338 | struct acpi_table_rsdp *rsdp; |
339 | acpi_native_uint table_entry_size; | ||
340 | acpi_native_uint i; | ||
341 | u32 table_count; | ||
342 | struct acpi_table_header *table; | ||
343 | acpi_physical_address address; | ||
344 | u32 length; | ||
345 | u8 *table_entry; | ||
346 | acpi_status status; | ||
347 | |||
348 | ACPI_FUNCTION_TRACE(tb_parse_root_table); | ||
349 | |||
350 | /* | ||
351 | * Map the entire RSDP and extract the address of the RSDT or XSDT | ||
352 | */ | ||
353 | rsdp = acpi_os_map_memory(rsdp_address, sizeof(struct acpi_table_rsdp)); | ||
354 | if (!rsdp) { | ||
355 | return_ACPI_STATUS(AE_NO_MEMORY); | ||
356 | } | ||
283 | 357 | ||
284 | ACPI_FUNCTION_TRACE(tb_verify_table_checksum); | 358 | acpi_tb_print_table_header(rsdp_address, |
359 | ACPI_CAST_PTR(struct acpi_table_header, | ||
360 | rsdp)); | ||
285 | 361 | ||
286 | /* Compute the checksum on the table */ | 362 | /* Differentiate between RSDT and XSDT root tables */ |
287 | 363 | ||
288 | checksum = acpi_tb_generate_checksum(table_header); | 364 | if (rsdp->revision > 1 && rsdp->xsdt_physical_address) { |
365 | /* | ||
366 | * Root table is an XSDT (64-bit physical addresses). We must use the | ||
367 | * XSDT if the revision is > 1 and the XSDT pointer is present, as per | ||
368 | * the ACPI specification. | ||
369 | */ | ||
370 | address = (acpi_physical_address) rsdp->xsdt_physical_address; | ||
371 | table_entry_size = sizeof(u64); | ||
372 | } else { | ||
373 | /* Root table is an RSDT (32-bit physical addresses) */ | ||
289 | 374 | ||
290 | /* Checksum ok? */ | 375 | address = (acpi_physical_address) rsdp->rsdt_physical_address; |
376 | table_entry_size = sizeof(u32); | ||
377 | } | ||
291 | 378 | ||
292 | if (checksum == table_header->checksum) { | 379 | /* |
293 | return_ACPI_STATUS(AE_OK); | 380 | * It is not possible to map more than one entry in some environments, |
381 | * so unmap the RSDP here before mapping other tables | ||
382 | */ | ||
383 | acpi_os_unmap_memory(rsdp, sizeof(struct acpi_table_rsdp)); | ||
384 | |||
385 | /* Map the RSDT/XSDT table header to get the full table length */ | ||
386 | |||
387 | table = acpi_os_map_memory(address, sizeof(struct acpi_table_header)); | ||
388 | if (!table) { | ||
389 | return_ACPI_STATUS(AE_NO_MEMORY); | ||
294 | } | 390 | } |
295 | 391 | ||
296 | ACPI_WARNING((AE_INFO, | 392 | acpi_tb_print_table_header(address, table); |
297 | "Incorrect checksum in table [%4.4s] - is %2.2X, should be %2.2X", | ||
298 | table_header->signature, table_header->checksum, | ||
299 | checksum)); | ||
300 | 393 | ||
301 | return_ACPI_STATUS(AE_BAD_CHECKSUM); | 394 | /* Get the length of the full table, verify length and map entire table */ |
302 | } | ||
303 | 395 | ||
304 | #ifdef ACPI_OBSOLETE_FUNCTIONS | 396 | length = table->length; |
305 | /******************************************************************************* | 397 | acpi_os_unmap_memory(table, sizeof(struct acpi_table_header)); |
306 | * | ||
307 | * FUNCTION: acpi_tb_handle_to_object | ||
308 | * | ||
309 | * PARAMETERS: table_id - Id for which the function is searching | ||
310 | * table_desc - Pointer to return the matching table | ||
311 | * descriptor. | ||
312 | * | ||
313 | * RETURN: Search the tables to find one with a matching table_id and | ||
314 | * return a pointer to that table descriptor. | ||
315 | * | ||
316 | ******************************************************************************/ | ||
317 | 398 | ||
318 | acpi_status | 399 | if (length < sizeof(struct acpi_table_header)) { |
319 | acpi_tb_handle_to_object(u16 table_id, | 400 | ACPI_ERROR((AE_INFO, "Invalid length 0x%X in RSDT/XSDT", |
320 | struct acpi_table_desc **return_table_desc) | 401 | length)); |
321 | { | 402 | return_ACPI_STATUS(AE_INVALID_TABLE_LENGTH); |
322 | u32 i; | 403 | } |
323 | struct acpi_table_desc *table_desc; | ||
324 | 404 | ||
325 | ACPI_FUNCTION_NAME(tb_handle_to_object); | 405 | table = acpi_os_map_memory(address, length); |
406 | if (!table) { | ||
407 | return_ACPI_STATUS(AE_NO_MEMORY); | ||
408 | } | ||
409 | |||
410 | /* Validate the root table checksum */ | ||
411 | |||
412 | status = acpi_tb_verify_checksum(table, length); | ||
413 | if (ACPI_FAILURE(status)) { | ||
414 | acpi_os_unmap_memory(table, length); | ||
415 | return_ACPI_STATUS(status); | ||
416 | } | ||
326 | 417 | ||
327 | for (i = 0; i < ACPI_TABLE_MAX; i++) { | 418 | /* Calculate the number of tables described in the root table */ |
328 | table_desc = acpi_gbl_table_lists[i].next; | 419 | |
329 | while (table_desc) { | 420 | table_count = |
330 | if (table_desc->table_id == table_id) { | 421 | (u32) ((table->length - |
331 | *return_table_desc = table_desc; | 422 | sizeof(struct acpi_table_header)) / table_entry_size); |
332 | return (AE_OK); | 423 | |
424 | /* | ||
425 | * First two entries in the table array are reserved for the DSDT and FACS, | ||
426 | * which are not actually present in the RSDT/XSDT - they come from the FADT | ||
427 | */ | ||
428 | table_entry = | ||
429 | ACPI_CAST_PTR(u8, table) + sizeof(struct acpi_table_header); | ||
430 | acpi_gbl_root_table_list.count = 2; | ||
431 | |||
432 | /* | ||
433 | * Initialize the root table array from the RSDT/XSDT | ||
434 | */ | ||
435 | for (i = 0; i < table_count; i++) { | ||
436 | if (acpi_gbl_root_table_list.count >= | ||
437 | acpi_gbl_root_table_list.size) { | ||
438 | |||
439 | /* There is no more room in the root table array, attempt resize */ | ||
440 | |||
441 | status = acpi_tb_resize_root_table_list(); | ||
442 | if (ACPI_FAILURE(status)) { | ||
443 | ACPI_WARNING((AE_INFO, | ||
444 | "Truncating %u table entries!", | ||
445 | (unsigned) | ||
446 | (acpi_gbl_root_table_list.size - | ||
447 | acpi_gbl_root_table_list. | ||
448 | count))); | ||
449 | break; | ||
333 | } | 450 | } |
451 | } | ||
452 | |||
453 | /* Get the table physical address (32-bit for RSDT, 64-bit for XSDT) */ | ||
334 | 454 | ||
335 | table_desc = table_desc->next; | 455 | acpi_gbl_root_table_list.tables[acpi_gbl_root_table_list.count]. |
456 | address = | ||
457 | acpi_tb_get_root_table_entry(table_entry, table_entry_size); | ||
458 | |||
459 | table_entry += table_entry_size; | ||
460 | acpi_gbl_root_table_list.count++; | ||
461 | } | ||
462 | |||
463 | /* | ||
464 | * It is not possible to map more than one entry in some environments, | ||
465 | * so unmap the root table here before mapping other tables | ||
466 | */ | ||
467 | acpi_os_unmap_memory(table, length); | ||
468 | |||
469 | /* | ||
470 | * Complete the initialization of the root table array by examining | ||
471 | * the header of each table | ||
472 | */ | ||
473 | for (i = 2; i < acpi_gbl_root_table_list.count; i++) { | ||
474 | acpi_tb_install_table(acpi_gbl_root_table_list.tables[i]. | ||
475 | address, flags, NULL, i); | ||
476 | |||
477 | /* Special case for FADT - get the DSDT and FACS */ | ||
478 | |||
479 | if (ACPI_COMPARE_NAME | ||
480 | (&acpi_gbl_root_table_list.tables[i].signature, | ||
481 | ACPI_SIG_FADT)) { | ||
482 | acpi_tb_parse_fadt(i, flags); | ||
336 | } | 483 | } |
337 | } | 484 | } |
338 | 485 | ||
339 | ACPI_ERROR((AE_INFO, "TableId=%X does not exist", table_id)); | 486 | return_ACPI_STATUS(AE_OK); |
340 | return (AE_BAD_PARAMETER); | ||
341 | } | 487 | } |
342 | #endif | ||
diff --git a/drivers/acpi/tables/tbxface.c b/drivers/acpi/tables/tbxface.c index 5ba9303293ad..807978d5381a 100644 --- a/drivers/acpi/tables/tbxface.c +++ b/drivers/acpi/tables/tbxface.c | |||
@@ -6,7 +6,7 @@ | |||
6 | *****************************************************************************/ | 6 | *****************************************************************************/ |
7 | 7 | ||
8 | /* | 8 | /* |
9 | * Copyright (C) 2000 - 2006, R. Byron Moore | 9 | * Copyright (C) 2000 - 2007, R. Byron Moore |
10 | * All rights reserved. | 10 | * All rights reserved. |
11 | * | 11 | * |
12 | * Redistribution and use in source and binary forms, with or without | 12 | * Redistribution and use in source and binary forms, with or without |
@@ -49,80 +49,158 @@ | |||
49 | #define _COMPONENT ACPI_TABLES | 49 | #define _COMPONENT ACPI_TABLES |
50 | ACPI_MODULE_NAME("tbxface") | 50 | ACPI_MODULE_NAME("tbxface") |
51 | 51 | ||
52 | /* Local prototypes */ | ||
53 | static acpi_status acpi_tb_load_namespace(void); | ||
54 | |||
52 | /******************************************************************************* | 55 | /******************************************************************************* |
53 | * | 56 | * |
54 | * FUNCTION: acpi_load_tables | 57 | * FUNCTION: acpi_allocate_root_table |
55 | * | 58 | * |
56 | * PARAMETERS: None | 59 | * PARAMETERS: initial_table_count - Size of initial_table_array, in number of |
60 | * struct acpi_table_desc structures | ||
57 | * | 61 | * |
58 | * RETURN: Status | 62 | * RETURN: Status |
59 | * | 63 | * |
60 | * DESCRIPTION: This function is called to load the ACPI tables from the | 64 | * DESCRIPTION: Allocate a root table array. Used by i_aSL compiler and |
61 | * provided RSDT | 65 | * acpi_initialize_tables. |
62 | * | 66 | * |
63 | ******************************************************************************/ | 67 | ******************************************************************************/ |
64 | acpi_status acpi_load_tables(void) | 68 | |
69 | acpi_status acpi_allocate_root_table(u32 initial_table_count) | ||
65 | { | 70 | { |
66 | struct acpi_pointer rsdp_address; | ||
67 | acpi_status status; | ||
68 | 71 | ||
69 | ACPI_FUNCTION_TRACE(acpi_load_tables); | 72 | acpi_gbl_root_table_list.size = initial_table_count; |
73 | acpi_gbl_root_table_list.flags = ACPI_ROOT_ALLOW_RESIZE; | ||
70 | 74 | ||
71 | /* Get the RSDP */ | 75 | return (acpi_tb_resize_root_table_list()); |
76 | } | ||
72 | 77 | ||
73 | status = acpi_os_get_root_pointer(ACPI_LOGICAL_ADDRESSING, | 78 | /******************************************************************************* |
74 | &rsdp_address); | 79 | * |
75 | if (ACPI_FAILURE(status)) { | 80 | * FUNCTION: acpi_initialize_tables |
76 | ACPI_EXCEPTION((AE_INFO, status, "Could not get the RSDP")); | 81 | * |
77 | goto error_exit; | 82 | * PARAMETERS: initial_table_array - Pointer to an array of pre-allocated |
78 | } | 83 | * struct acpi_table_desc structures. If NULL, the |
84 | * array is dynamically allocated. | ||
85 | * initial_table_count - Size of initial_table_array, in number of | ||
86 | * struct acpi_table_desc structures | ||
87 | * allow_realloc - Flag to tell Table Manager if resize of | ||
88 | * pre-allocated array is allowed. Ignored | ||
89 | * if initial_table_array is NULL. | ||
90 | * | ||
91 | * RETURN: Status | ||
92 | * | ||
93 | * DESCRIPTION: Initialize the table manager, get the RSDP and RSDT/XSDT. | ||
94 | * | ||
95 | * NOTE: Allows static allocation of the initial table array in order | ||
96 | * to avoid the use of dynamic memory in confined environments | ||
97 | * such as the kernel boot sequence where it may not be available. | ||
98 | * | ||
99 | * If the host OS memory managers are initialized, use NULL for | ||
100 | * initial_table_array, and the table will be dynamically allocated. | ||
101 | * | ||
102 | ******************************************************************************/ | ||
79 | 103 | ||
80 | /* Map and validate the RSDP */ | 104 | acpi_status __init |
105 | acpi_initialize_tables(struct acpi_table_desc * initial_table_array, | ||
106 | u32 initial_table_count, u8 allow_resize) | ||
107 | { | ||
108 | acpi_physical_address rsdp_address; | ||
109 | acpi_status status; | ||
81 | 110 | ||
82 | acpi_gbl_table_flags = rsdp_address.pointer_type; | 111 | ACPI_FUNCTION_TRACE(acpi_initialize_tables); |
83 | 112 | ||
84 | status = acpi_tb_verify_rsdp(&rsdp_address); | 113 | /* |
85 | if (ACPI_FAILURE(status)) { | 114 | * Set up the Root Table Array |
86 | ACPI_EXCEPTION((AE_INFO, status, "During RSDP validation")); | 115 | * Allocate the table array if requested |
87 | goto error_exit; | 116 | */ |
117 | if (!initial_table_array) { | ||
118 | status = acpi_allocate_root_table(initial_table_count); | ||
119 | if (ACPI_FAILURE(status)) { | ||
120 | return_ACPI_STATUS(status); | ||
121 | } | ||
122 | } else { | ||
123 | /* Root Table Array has been statically allocated by the host */ | ||
124 | |||
125 | ACPI_MEMSET(initial_table_array, 0, | ||
126 | initial_table_count * | ||
127 | sizeof(struct acpi_table_desc)); | ||
128 | |||
129 | acpi_gbl_root_table_list.tables = initial_table_array; | ||
130 | acpi_gbl_root_table_list.size = initial_table_count; | ||
131 | acpi_gbl_root_table_list.flags = ACPI_ROOT_ORIGIN_UNKNOWN; | ||
132 | if (allow_resize) { | ||
133 | acpi_gbl_root_table_list.flags |= | ||
134 | ACPI_ROOT_ALLOW_RESIZE; | ||
135 | } | ||
88 | } | 136 | } |
89 | 137 | ||
90 | /* Get the RSDT via the RSDP */ | 138 | /* Get the address of the RSDP */ |
91 | 139 | ||
92 | status = acpi_tb_get_table_rsdt(); | 140 | rsdp_address = acpi_os_get_root_pointer(); |
93 | if (ACPI_FAILURE(status)) { | 141 | if (!rsdp_address) { |
94 | ACPI_EXCEPTION((AE_INFO, status, "Could not load RSDT")); | 142 | return_ACPI_STATUS(AE_NOT_FOUND); |
95 | goto error_exit; | ||
96 | } | 143 | } |
97 | 144 | ||
98 | /* Now get the tables needed by this subsystem (FADT, DSDT, etc.) */ | 145 | /* |
146 | * Get the root table (RSDT or XSDT) and extract all entries to the local | ||
147 | * Root Table Array. This array contains the information of the RSDT/XSDT | ||
148 | * in a common, more useable format. | ||
149 | */ | ||
150 | status = | ||
151 | acpi_tb_parse_root_table(rsdp_address, ACPI_TABLE_ORIGIN_MAPPED); | ||
152 | return_ACPI_STATUS(status); | ||
153 | } | ||
99 | 154 | ||
100 | status = acpi_tb_get_required_tables(); | 155 | /******************************************************************************* |
101 | if (ACPI_FAILURE(status)) { | 156 | * |
102 | ACPI_EXCEPTION((AE_INFO, status, | 157 | * FUNCTION: acpi_reallocate_root_table |
103 | "Could not get all required tables (DSDT/FADT/FACS)")); | 158 | * |
104 | goto error_exit; | 159 | * PARAMETERS: None |
160 | * | ||
161 | * RETURN: Status | ||
162 | * | ||
163 | * DESCRIPTION: Reallocate Root Table List into dynamic memory. Copies the | ||
164 | * root list from the previously provided scratch area. Should | ||
165 | * be called once dynamic memory allocation is available in the | ||
166 | * kernel | ||
167 | * | ||
168 | ******************************************************************************/ | ||
169 | acpi_status acpi_reallocate_root_table(void) | ||
170 | { | ||
171 | struct acpi_table_desc *tables; | ||
172 | acpi_size new_size; | ||
173 | |||
174 | ACPI_FUNCTION_TRACE(acpi_reallocate_root_table); | ||
175 | |||
176 | /* | ||
177 | * Only reallocate the root table if the host provided a static buffer | ||
178 | * for the table array in the call to acpi_initialize_tables. | ||
179 | */ | ||
180 | if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) { | ||
181 | return_ACPI_STATUS(AE_SUPPORT); | ||
105 | } | 182 | } |
106 | 183 | ||
107 | ACPI_DEBUG_PRINT((ACPI_DB_INIT, "ACPI Tables successfully acquired\n")); | 184 | new_size = |
185 | (acpi_gbl_root_table_list.count + | ||
186 | ACPI_ROOT_TABLE_SIZE_INCREMENT) * sizeof(struct acpi_table_desc); | ||
108 | 187 | ||
109 | /* Load the namespace from the tables */ | 188 | /* Create new array and copy the old array */ |
110 | 189 | ||
111 | status = acpi_ns_load_namespace(); | 190 | tables = ACPI_ALLOCATE_ZEROED(new_size); |
112 | if (ACPI_FAILURE(status)) { | 191 | if (!tables) { |
113 | ACPI_EXCEPTION((AE_INFO, status, "Could not load namespace")); | 192 | return_ACPI_STATUS(AE_NO_MEMORY); |
114 | goto error_exit; | ||
115 | } | 193 | } |
116 | 194 | ||
117 | return_ACPI_STATUS(AE_OK); | 195 | ACPI_MEMCPY(tables, acpi_gbl_root_table_list.tables, new_size); |
118 | 196 | ||
119 | error_exit: | 197 | acpi_gbl_root_table_list.size = acpi_gbl_root_table_list.count; |
120 | ACPI_EXCEPTION((AE_INFO, status, "Could not load tables")); | 198 | acpi_gbl_root_table_list.tables = tables; |
121 | return_ACPI_STATUS(status); | 199 | acpi_gbl_root_table_list.flags = |
122 | } | 200 | ACPI_ROOT_ORIGIN_ALLOCATED | ACPI_ROOT_ALLOW_RESIZE; |
123 | |||
124 | ACPI_EXPORT_SYMBOL(acpi_load_tables) | ||
125 | 201 | ||
202 | return_ACPI_STATUS(AE_OK); | ||
203 | } | ||
126 | /******************************************************************************* | 204 | /******************************************************************************* |
127 | * | 205 | * |
128 | * FUNCTION: acpi_load_table | 206 | * FUNCTION: acpi_load_table |
@@ -141,342 +219,405 @@ ACPI_EXPORT_SYMBOL(acpi_load_tables) | |||
141 | acpi_status acpi_load_table(struct acpi_table_header *table_ptr) | 219 | acpi_status acpi_load_table(struct acpi_table_header *table_ptr) |
142 | { | 220 | { |
143 | acpi_status status; | 221 | acpi_status status; |
144 | struct acpi_table_desc table_info; | 222 | acpi_native_uint table_index; |
145 | struct acpi_pointer address; | 223 | struct acpi_table_desc table_desc; |
146 | |||
147 | ACPI_FUNCTION_TRACE(acpi_load_table); | ||
148 | |||
149 | if (!table_ptr) { | ||
150 | return_ACPI_STATUS(AE_BAD_PARAMETER); | ||
151 | } | ||
152 | |||
153 | /* Copy the table to a local buffer */ | ||
154 | 224 | ||
155 | address.pointer_type = ACPI_LOGICAL_POINTER | ACPI_LOGICAL_ADDRESSING; | 225 | if (!table_ptr) |
156 | address.pointer.logical = table_ptr; | 226 | return AE_BAD_PARAMETER; |
157 | |||
158 | status = acpi_tb_get_table_body(&address, table_ptr, &table_info); | ||
159 | if (ACPI_FAILURE(status)) { | ||
160 | return_ACPI_STATUS(status); | ||
161 | } | ||
162 | |||
163 | /* Check signature for a valid table type */ | ||
164 | |||
165 | status = acpi_tb_recognize_table(&table_info, ACPI_TABLE_ALL); | ||
166 | if (ACPI_FAILURE(status)) { | ||
167 | return_ACPI_STATUS(status); | ||
168 | } | ||
169 | 227 | ||
170 | /* Install the new table into the local data structures */ | 228 | ACPI_MEMSET(&table_desc, 0, sizeof(struct acpi_table_desc)); |
229 | table_desc.pointer = table_ptr; | ||
230 | table_desc.length = table_ptr->length; | ||
231 | table_desc.flags = ACPI_TABLE_ORIGIN_UNKNOWN; | ||
171 | 232 | ||
172 | status = acpi_tb_install_table(&table_info); | 233 | /* |
234 | * Install the new table into the local data structures | ||
235 | */ | ||
236 | status = acpi_tb_add_table(&table_desc, &table_index); | ||
173 | if (ACPI_FAILURE(status)) { | 237 | if (ACPI_FAILURE(status)) { |
174 | if (status == AE_ALREADY_EXISTS) { | 238 | return status; |
175 | |||
176 | /* Table already exists, no error */ | ||
177 | |||
178 | status = AE_OK; | ||
179 | } | ||
180 | |||
181 | /* Free table allocated by acpi_tb_get_table_body */ | ||
182 | |||
183 | acpi_tb_delete_single_table(&table_info); | ||
184 | return_ACPI_STATUS(status); | ||
185 | } | 239 | } |
240 | status = acpi_ns_load_table(table_index, acpi_gbl_root_node); | ||
241 | return status; | ||
242 | } | ||
186 | 243 | ||
187 | /* Convert the table to common format if necessary */ | 244 | ACPI_EXPORT_SYMBOL(acpi_load_table) |
188 | |||
189 | switch (table_info.type) { | ||
190 | case ACPI_TABLE_ID_FADT: | ||
191 | |||
192 | status = acpi_tb_convert_table_fadt(); | ||
193 | break; | ||
194 | |||
195 | case ACPI_TABLE_ID_FACS: | ||
196 | 245 | ||
197 | status = acpi_tb_build_common_facs(&table_info); | 246 | /****************************************************************************** |
198 | break; | 247 | * |
248 | * FUNCTION: acpi_get_table_header | ||
249 | * | ||
250 | * PARAMETERS: Signature - ACPI signature of needed table | ||
251 | * Instance - Which instance (for SSDTs) | ||
252 | * out_table_header - The pointer to the table header to fill | ||
253 | * | ||
254 | * RETURN: Status and pointer to mapped table header | ||
255 | * | ||
256 | * DESCRIPTION: Finds an ACPI table header. | ||
257 | * | ||
258 | * NOTE: Caller is responsible in unmapping the header with | ||
259 | * acpi_os_unmap_memory | ||
260 | * | ||
261 | *****************************************************************************/ | ||
262 | acpi_status | ||
263 | acpi_get_table_header(char *signature, | ||
264 | acpi_native_uint instance, | ||
265 | struct acpi_table_header *out_table_header) | ||
266 | { | ||
267 | acpi_native_uint i; | ||
268 | acpi_native_uint j; | ||
269 | struct acpi_table_header *header; | ||
199 | 270 | ||
200 | default: | 271 | /* Parameter validation */ |
201 | /* Load table into namespace if it contains executable AML */ | ||
202 | 272 | ||
203 | status = | 273 | if (!signature || !out_table_header) { |
204 | acpi_ns_load_table(table_info.installed_desc, | 274 | return (AE_BAD_PARAMETER); |
205 | acpi_gbl_root_node); | ||
206 | break; | ||
207 | } | 275 | } |
208 | 276 | ||
209 | if (ACPI_FAILURE(status)) { | 277 | /* |
278 | * Walk the root table list | ||
279 | */ | ||
280 | for (i = 0, j = 0; i < acpi_gbl_root_table_list.count; i++) { | ||
281 | if (!ACPI_COMPARE_NAME | ||
282 | (&(acpi_gbl_root_table_list.tables[i].signature), | ||
283 | signature)) { | ||
284 | continue; | ||
285 | } | ||
210 | 286 | ||
211 | /* Uninstall table and free the buffer */ | 287 | if (++j < instance) { |
288 | continue; | ||
289 | } | ||
212 | 290 | ||
213 | (void)acpi_tb_uninstall_table(table_info.installed_desc); | 291 | if (!acpi_gbl_root_table_list.tables[i].pointer) { |
292 | if ((acpi_gbl_root_table_list.tables[i]. | ||
293 | flags & ACPI_TABLE_ORIGIN_MASK) == | ||
294 | ACPI_TABLE_ORIGIN_MAPPED) { | ||
295 | header = | ||
296 | acpi_os_map_memory(acpi_gbl_root_table_list. | ||
297 | tables[i].address, | ||
298 | sizeof(struct | ||
299 | acpi_table_header)); | ||
300 | if (!header) { | ||
301 | return AE_NO_MEMORY; | ||
302 | } | ||
303 | ACPI_MEMCPY(out_table_header, header, | ||
304 | sizeof(struct acpi_table_header)); | ||
305 | acpi_os_unmap_memory(header, | ||
306 | sizeof(struct | ||
307 | acpi_table_header)); | ||
308 | } else { | ||
309 | return AE_NOT_FOUND; | ||
310 | } | ||
311 | } else { | ||
312 | ACPI_MEMCPY(out_table_header, | ||
313 | acpi_gbl_root_table_list.tables[i].pointer, | ||
314 | sizeof(struct acpi_table_header)); | ||
315 | } | ||
316 | return (AE_OK); | ||
214 | } | 317 | } |
215 | 318 | ||
216 | return_ACPI_STATUS(status); | 319 | return (AE_NOT_FOUND); |
217 | } | 320 | } |
218 | 321 | ||
219 | ACPI_EXPORT_SYMBOL(acpi_load_table) | 322 | ACPI_EXPORT_SYMBOL(acpi_get_table_header) |
220 | 323 | ||
221 | /******************************************************************************* | 324 | |
325 | /****************************************************************************** | ||
222 | * | 326 | * |
223 | * FUNCTION: acpi_unload_table_id | 327 | * FUNCTION: acpi_unload_table_id |
224 | * | 328 | * |
225 | * PARAMETERS: table_type - Type of table to be unloaded | 329 | * PARAMETERS: id - Owner ID of the table to be removed. |
226 | * id - Owner ID of the table to be removed. | ||
227 | * | 330 | * |
228 | * RETURN: Status | 331 | * RETURN: Status |
229 | * | 332 | * |
230 | * DESCRIPTION: This routine is used to force the unload of a table (by id) | 333 | * DESCRIPTION: This routine is used to force the unload of a table (by id) |
231 | * | 334 | * |
232 | ******************************************************************************/ | 335 | ******************************************************************************/ |
233 | acpi_status acpi_unload_table_id(acpi_table_type table_type, acpi_owner_id id) | 336 | acpi_status acpi_unload_table_id(acpi_owner_id id) |
234 | { | 337 | { |
235 | struct acpi_table_desc *table_desc; | 338 | int i; |
236 | acpi_status status; | 339 | acpi_status status = AE_NOT_EXIST; |
237 | 340 | ||
238 | ACPI_FUNCTION_TRACE(acpi_unload_table); | 341 | ACPI_FUNCTION_TRACE(acpi_unload_table); |
239 | 342 | ||
240 | /* Parameter validation */ | ||
241 | if (table_type > ACPI_TABLE_ID_MAX) | ||
242 | return_ACPI_STATUS(AE_BAD_PARAMETER); | ||
243 | |||
244 | /* Find table from the requested type list */ | 343 | /* Find table from the requested type list */ |
245 | table_desc = acpi_gbl_table_lists[table_type].next; | 344 | for (i = 0; i < acpi_gbl_root_table_list.count; ++i) { |
246 | while (table_desc && table_desc->owner_id != id) | 345 | if (id != acpi_gbl_root_table_list.tables[i].owner_id) { |
247 | table_desc = table_desc->next; | 346 | continue; |
248 | 347 | } | |
249 | if (!table_desc) | 348 | /* |
250 | return_ACPI_STATUS(AE_NOT_EXIST); | 349 | * Delete all namespace objects owned by this table. Note that these |
251 | 350 | * objects can appear anywhere in the namespace by virtue of the AML | |
252 | /* | 351 | * "Scope" operator. Thus, we need to track ownership by an ID, not |
253 | * Delete all namespace objects owned by this table. Note that these | 352 | * simply a position within the hierarchy |
254 | * objects can appear anywhere in the namespace by virtue of the AML | 353 | */ |
255 | * "Scope" operator. Thus, we need to track ownership by an ID, not | 354 | acpi_tb_delete_namespace_by_owner(i); |
256 | * simply a position within the hierarchy | 355 | acpi_tb_release_owner_id(i); |
257 | */ | 356 | acpi_tb_set_table_loaded_flag(i, FALSE); |
258 | acpi_ns_delete_namespace_by_owner(table_desc->owner_id); | 357 | } |
259 | 358 | return_ACPI_STATUS(status); | |
260 | status = acpi_ut_acquire_mutex(ACPI_MTX_TABLES); | ||
261 | if (ACPI_FAILURE(status)) | ||
262 | return_ACPI_STATUS(status); | ||
263 | |||
264 | (void)acpi_tb_uninstall_table(table_desc); | ||
265 | |||
266 | (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); | ||
267 | |||
268 | return_ACPI_STATUS(AE_OK); | ||
269 | } | 359 | } |
270 | 360 | ||
271 | ACPI_EXPORT_SYMBOL(acpi_unload_table_id) | 361 | ACPI_EXPORT_SYMBOL(acpi_unload_table_id) |
272 | 362 | ||
273 | #ifdef ACPI_FUTURE_USAGE | ||
274 | /******************************************************************************* | 363 | /******************************************************************************* |
275 | * | 364 | * |
276 | * FUNCTION: acpi_unload_table | 365 | * FUNCTION: acpi_get_table |
277 | * | 366 | * |
278 | * PARAMETERS: table_type - Type of table to be unloaded | 367 | * PARAMETERS: Signature - ACPI signature of needed table |
368 | * Instance - Which instance (for SSDTs) | ||
369 | * out_table - Where the pointer to the table is returned | ||
279 | * | 370 | * |
280 | * RETURN: Status | 371 | * RETURN: Status and pointer to table |
281 | * | 372 | * |
282 | * DESCRIPTION: This routine is used to force the unload of a table | 373 | * DESCRIPTION: Finds and verifies an ACPI table. |
283 | * | 374 | * |
284 | ******************************************************************************/ | 375 | *****************************************************************************/ |
285 | acpi_status acpi_unload_table(acpi_table_type table_type) | 376 | acpi_status |
377 | acpi_get_table(char *signature, | ||
378 | acpi_native_uint instance, struct acpi_table_header ** out_table) | ||
286 | { | 379 | { |
287 | struct acpi_table_desc *table_desc; | 380 | acpi_native_uint i; |
288 | 381 | acpi_native_uint j; | |
289 | ACPI_FUNCTION_TRACE(acpi_unload_table); | 382 | acpi_status status; |
290 | 383 | ||
291 | /* Parameter validation */ | 384 | /* Parameter validation */ |
292 | 385 | ||
293 | if (table_type > ACPI_TABLE_ID_MAX) { | 386 | if (!signature || !out_table) { |
294 | return_ACPI_STATUS(AE_BAD_PARAMETER); | 387 | return (AE_BAD_PARAMETER); |
295 | } | 388 | } |
296 | 389 | ||
297 | /* Find all tables of the requested type */ | 390 | /* |
391 | * Walk the root table list | ||
392 | */ | ||
393 | for (i = 0, j = 0; i < acpi_gbl_root_table_list.count; i++) { | ||
394 | if (!ACPI_COMPARE_NAME | ||
395 | (&(acpi_gbl_root_table_list.tables[i].signature), | ||
396 | signature)) { | ||
397 | continue; | ||
398 | } | ||
298 | 399 | ||
299 | table_desc = acpi_gbl_table_lists[table_type].next; | 400 | if (++j < instance) { |
300 | if (!table_desc) { | 401 | continue; |
301 | return_ACPI_STATUS(AE_NOT_EXIST); | 402 | } |
302 | } | ||
303 | 403 | ||
304 | while (table_desc) { | 404 | status = |
305 | /* | 405 | acpi_tb_verify_table(&acpi_gbl_root_table_list.tables[i]); |
306 | * Delete all namespace objects owned by this table. Note that these | 406 | if (ACPI_SUCCESS(status)) { |
307 | * objects can appear anywhere in the namespace by virtue of the AML | 407 | *out_table = acpi_gbl_root_table_list.tables[i].pointer; |
308 | * "Scope" operator. Thus, we need to track ownership by an ID, not | 408 | } |
309 | * simply a position within the hierarchy | ||
310 | */ | ||
311 | acpi_ns_delete_namespace_by_owner(table_desc->owner_id); | ||
312 | table_desc = table_desc->next; | ||
313 | } | ||
314 | 409 | ||
315 | /* Delete (or unmap) all tables of this type */ | 410 | if (!acpi_gbl_permanent_mmap) { |
411 | acpi_gbl_root_table_list.tables[i].pointer = 0; | ||
412 | } | ||
316 | 413 | ||
317 | acpi_tb_delete_tables_by_type(table_type); | 414 | return (status); |
318 | return_ACPI_STATUS(AE_OK); | 415 | } |
416 | |||
417 | return (AE_NOT_FOUND); | ||
319 | } | 418 | } |
320 | 419 | ||
321 | ACPI_EXPORT_SYMBOL(acpi_unload_table) | 420 | ACPI_EXPORT_SYMBOL(acpi_get_table) |
322 | 421 | ||
323 | /******************************************************************************* | 422 | /******************************************************************************* |
324 | * | 423 | * |
325 | * FUNCTION: acpi_get_table_header | 424 | * FUNCTION: acpi_get_table_by_index |
326 | * | 425 | * |
327 | * PARAMETERS: table_type - one of the defined table types | 426 | * PARAMETERS: table_index - Table index |
328 | * Instance - the non zero instance of the table, allows | 427 | * Table - Where the pointer to the table is returned |
329 | * support for multiple tables of the same type | ||
330 | * see acpi_gbl_acpi_table_flag | ||
331 | * out_table_header - pointer to the struct acpi_table_header if successful | ||
332 | * | 428 | * |
333 | * DESCRIPTION: This function is called to get an ACPI table header. The caller | 429 | * RETURN: Status and pointer to the table |
334 | * supplies an pointer to a data area sufficient to contain an ACPI | ||
335 | * struct acpi_table_header structure. | ||
336 | * | 430 | * |
337 | * The header contains a length field that can be used to determine | 431 | * DESCRIPTION: Obtain a table by an index into the global table list. |
338 | * the size of the buffer needed to contain the entire table. This | ||
339 | * function is not valid for the RSD PTR table since it does not | ||
340 | * have a standard header and is fixed length. | ||
341 | * | 432 | * |
342 | ******************************************************************************/ | 433 | ******************************************************************************/ |
343 | acpi_status | 434 | acpi_status |
344 | acpi_get_table_header(acpi_table_type table_type, | 435 | acpi_get_table_by_index(acpi_native_uint table_index, |
345 | u32 instance, struct acpi_table_header *out_table_header) | 436 | struct acpi_table_header ** table) |
346 | { | 437 | { |
347 | struct acpi_table_header *tbl_ptr; | ||
348 | acpi_status status; | 438 | acpi_status status; |
349 | 439 | ||
350 | ACPI_FUNCTION_TRACE(acpi_get_table_header); | 440 | ACPI_FUNCTION_TRACE(acpi_get_table_by_index); |
441 | |||
442 | /* Parameter validation */ | ||
351 | 443 | ||
352 | if ((instance == 0) || | 444 | if (!table) { |
353 | (table_type == ACPI_TABLE_ID_RSDP) || (!out_table_header)) { | ||
354 | return_ACPI_STATUS(AE_BAD_PARAMETER); | 445 | return_ACPI_STATUS(AE_BAD_PARAMETER); |
355 | } | 446 | } |
356 | 447 | ||
357 | /* Check the table type and instance */ | 448 | (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); |
449 | |||
450 | /* Validate index */ | ||
358 | 451 | ||
359 | if ((table_type > ACPI_TABLE_ID_MAX) || | 452 | if (table_index >= acpi_gbl_root_table_list.count) { |
360 | (ACPI_IS_SINGLE_TABLE(acpi_gbl_table_data[table_type].flags) && | 453 | (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); |
361 | instance > 1)) { | ||
362 | return_ACPI_STATUS(AE_BAD_PARAMETER); | 454 | return_ACPI_STATUS(AE_BAD_PARAMETER); |
363 | } | 455 | } |
364 | 456 | ||
365 | /* Get a pointer to the entire table */ | 457 | if (!acpi_gbl_root_table_list.tables[table_index].pointer) { |
366 | 458 | ||
367 | status = acpi_tb_get_table_ptr(table_type, instance, &tbl_ptr); | 459 | /* Table is not mapped, map it */ |
368 | if (ACPI_FAILURE(status)) { | ||
369 | return_ACPI_STATUS(status); | ||
370 | } | ||
371 | 460 | ||
372 | /* The function will return a NULL pointer if the table is not loaded */ | 461 | status = |
373 | 462 | acpi_tb_verify_table(&acpi_gbl_root_table_list. | |
374 | if (tbl_ptr == NULL) { | 463 | tables[table_index]); |
375 | return_ACPI_STATUS(AE_NOT_EXIST); | 464 | if (ACPI_FAILURE(status)) { |
465 | (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); | ||
466 | return_ACPI_STATUS(status); | ||
467 | } | ||
376 | } | 468 | } |
377 | 469 | ||
378 | /* Copy the header to the caller's buffer */ | 470 | *table = acpi_gbl_root_table_list.tables[table_index].pointer; |
379 | 471 | (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); | |
380 | ACPI_MEMCPY(ACPI_CAST_PTR(void, out_table_header), | 472 | return_ACPI_STATUS(AE_OK); |
381 | ACPI_CAST_PTR(void, tbl_ptr), | ||
382 | sizeof(struct acpi_table_header)); | ||
383 | |||
384 | return_ACPI_STATUS(status); | ||
385 | } | 473 | } |
386 | 474 | ||
387 | ACPI_EXPORT_SYMBOL(acpi_get_table_header) | 475 | ACPI_EXPORT_SYMBOL(acpi_get_table_by_index) |
388 | #endif /* ACPI_FUTURE_USAGE */ | ||
389 | 476 | ||
390 | /******************************************************************************* | 477 | /******************************************************************************* |
391 | * | 478 | * |
392 | * FUNCTION: acpi_get_table | 479 | * FUNCTION: acpi_tb_load_namespace |
393 | * | 480 | * |
394 | * PARAMETERS: table_type - one of the defined table types | 481 | * PARAMETERS: None |
395 | * Instance - the non zero instance of the table, allows | ||
396 | * support for multiple tables of the same type | ||
397 | * see acpi_gbl_acpi_table_flag | ||
398 | * ret_buffer - pointer to a structure containing a buffer to | ||
399 | * receive the table | ||
400 | * | 482 | * |
401 | * RETURN: Status | 483 | * RETURN: Status |
402 | * | 484 | * |
403 | * DESCRIPTION: This function is called to get an ACPI table. The caller | 485 | * DESCRIPTION: Load the namespace from the DSDT and all SSDTs/PSDTs found in |
404 | * supplies an out_buffer large enough to contain the entire ACPI | 486 | * the RSDT/XSDT. |
405 | * table. The caller should call the acpi_get_table_header function | ||
406 | * first to determine the buffer size needed. Upon completion | ||
407 | * the out_buffer->Length field will indicate the number of bytes | ||
408 | * copied into the out_buffer->buf_ptr buffer. This table will be | ||
409 | * a complete table including the header. | ||
410 | * | 487 | * |
411 | ******************************************************************************/ | 488 | ******************************************************************************/ |
412 | acpi_status | 489 | static acpi_status acpi_tb_load_namespace(void) |
413 | acpi_get_table(acpi_table_type table_type, | ||
414 | u32 instance, struct acpi_buffer *ret_buffer) | ||
415 | { | 490 | { |
416 | struct acpi_table_header *tbl_ptr; | ||
417 | acpi_status status; | 491 | acpi_status status; |
418 | acpi_size table_length; | 492 | struct acpi_table_header *table; |
493 | acpi_native_uint i; | ||
419 | 494 | ||
420 | ACPI_FUNCTION_TRACE(acpi_get_table); | 495 | ACPI_FUNCTION_TRACE(tb_load_namespace); |
421 | 496 | ||
422 | /* Parameter validation */ | 497 | (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); |
423 | 498 | ||
424 | if (instance == 0) { | 499 | /* |
425 | return_ACPI_STATUS(AE_BAD_PARAMETER); | 500 | * Load the namespace. The DSDT is required, but any SSDT and PSDT tables |
501 | * are optional. | ||
502 | */ | ||
503 | if (!acpi_gbl_root_table_list.count || | ||
504 | !ACPI_COMPARE_NAME(& | ||
505 | (acpi_gbl_root_table_list. | ||
506 | tables[ACPI_TABLE_INDEX_DSDT].signature), | ||
507 | ACPI_SIG_DSDT) | ||
508 | || | ||
509 | ACPI_FAILURE(acpi_tb_verify_table | ||
510 | (&acpi_gbl_root_table_list. | ||
511 | tables[ACPI_TABLE_INDEX_DSDT]))) { | ||
512 | status = AE_NO_ACPI_TABLES; | ||
513 | goto unlock_and_exit; | ||
426 | } | 514 | } |
427 | 515 | ||
428 | status = acpi_ut_validate_buffer(ret_buffer); | 516 | /* |
429 | if (ACPI_FAILURE(status)) { | 517 | * Find DSDT table |
430 | return_ACPI_STATUS(status); | 518 | */ |
519 | status = | ||
520 | acpi_os_table_override(acpi_gbl_root_table_list. | ||
521 | tables[ACPI_TABLE_INDEX_DSDT].pointer, | ||
522 | &table); | ||
523 | if (ACPI_SUCCESS(status) && table) { | ||
524 | /* | ||
525 | * DSDT table has been found | ||
526 | */ | ||
527 | acpi_tb_delete_table(&acpi_gbl_root_table_list. | ||
528 | tables[ACPI_TABLE_INDEX_DSDT]); | ||
529 | acpi_gbl_root_table_list.tables[ACPI_TABLE_INDEX_DSDT].pointer = | ||
530 | table; | ||
531 | acpi_gbl_root_table_list.tables[ACPI_TABLE_INDEX_DSDT].length = | ||
532 | table->length; | ||
533 | acpi_gbl_root_table_list.tables[ACPI_TABLE_INDEX_DSDT].flags = | ||
534 | ACPI_TABLE_ORIGIN_UNKNOWN; | ||
535 | |||
536 | ACPI_INFO((AE_INFO, "Table DSDT replaced by host OS")); | ||
537 | acpi_tb_print_table_header(0, table); | ||
431 | } | 538 | } |
432 | 539 | ||
433 | /* Check the table type and instance */ | 540 | status = |
541 | acpi_tb_verify_table(&acpi_gbl_root_table_list. | ||
542 | tables[ACPI_TABLE_INDEX_DSDT]); | ||
543 | if (ACPI_FAILURE(status)) { | ||
434 | 544 | ||
435 | if ((table_type > ACPI_TABLE_ID_MAX) || | 545 | /* A valid DSDT is required */ |
436 | (ACPI_IS_SINGLE_TABLE(acpi_gbl_table_data[table_type].flags) && | 546 | |
437 | instance > 1)) { | 547 | status = AE_NO_ACPI_TABLES; |
438 | return_ACPI_STATUS(AE_BAD_PARAMETER); | 548 | goto unlock_and_exit; |
439 | } | 549 | } |
440 | 550 | ||
441 | /* Get a pointer to the entire table */ | 551 | (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); |
442 | 552 | ||
443 | status = acpi_tb_get_table_ptr(table_type, instance, &tbl_ptr); | 553 | /* |
554 | * Load and parse tables. | ||
555 | */ | ||
556 | status = acpi_ns_load_table(ACPI_TABLE_INDEX_DSDT, acpi_gbl_root_node); | ||
444 | if (ACPI_FAILURE(status)) { | 557 | if (ACPI_FAILURE(status)) { |
445 | return_ACPI_STATUS(status); | 558 | return_ACPI_STATUS(status); |
446 | } | 559 | } |
447 | 560 | ||
448 | /* | 561 | /* |
449 | * acpi_tb_get_table_ptr will return a NULL pointer if the | 562 | * Load any SSDT or PSDT tables. Note: Loop leaves tables locked |
450 | * table is not loaded. | ||
451 | */ | 563 | */ |
452 | if (tbl_ptr == NULL) { | 564 | (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); |
453 | return_ACPI_STATUS(AE_NOT_EXIST); | 565 | for (i = 0; i < acpi_gbl_root_table_list.count; ++i) { |
566 | if ((!ACPI_COMPARE_NAME | ||
567 | (&(acpi_gbl_root_table_list.tables[i].signature), | ||
568 | ACPI_SIG_SSDT) | ||
569 | && | ||
570 | !ACPI_COMPARE_NAME(& | ||
571 | (acpi_gbl_root_table_list.tables[i]. | ||
572 | signature), ACPI_SIG_PSDT)) | ||
573 | || | ||
574 | ACPI_FAILURE(acpi_tb_verify_table | ||
575 | (&acpi_gbl_root_table_list.tables[i]))) { | ||
576 | continue; | ||
577 | } | ||
578 | |||
579 | /* Ignore errors while loading tables, get as many as possible */ | ||
580 | |||
581 | (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); | ||
582 | (void)acpi_ns_load_table(i, acpi_gbl_root_node); | ||
583 | (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); | ||
454 | } | 584 | } |
455 | 585 | ||
456 | /* Get the table length */ | 586 | ACPI_DEBUG_PRINT((ACPI_DB_INIT, "ACPI Tables successfully acquired\n")); |
457 | 587 | ||
458 | if (table_type == ACPI_TABLE_ID_RSDP) { | 588 | unlock_and_exit: |
589 | (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); | ||
590 | return_ACPI_STATUS(status); | ||
591 | } | ||
459 | 592 | ||
460 | /* RSD PTR is the only "table" without a header */ | 593 | /******************************************************************************* |
594 | * | ||
595 | * FUNCTION: acpi_load_tables | ||
596 | * | ||
597 | * PARAMETERS: None | ||
598 | * | ||
599 | * RETURN: Status | ||
600 | * | ||
601 | * DESCRIPTION: Load the ACPI tables from the RSDT/XSDT | ||
602 | * | ||
603 | ******************************************************************************/ | ||
461 | 604 | ||
462 | table_length = sizeof(struct rsdp_descriptor); | 605 | acpi_status acpi_load_tables(void) |
463 | } else { | 606 | { |
464 | table_length = (acpi_size) tbl_ptr->length; | 607 | acpi_status status; |
465 | } | ||
466 | 608 | ||
467 | /* Validate/Allocate/Clear caller buffer */ | 609 | ACPI_FUNCTION_TRACE(acpi_load_tables); |
468 | 610 | ||
469 | status = acpi_ut_initialize_buffer(ret_buffer, table_length); | 611 | /* |
612 | * Load the namespace from the tables | ||
613 | */ | ||
614 | status = acpi_tb_load_namespace(); | ||
470 | if (ACPI_FAILURE(status)) { | 615 | if (ACPI_FAILURE(status)) { |
471 | return_ACPI_STATUS(status); | 616 | ACPI_EXCEPTION((AE_INFO, status, |
617 | "While loading namespace from ACPI tables")); | ||
472 | } | 618 | } |
473 | 619 | ||
474 | /* Copy the table to the buffer */ | 620 | return_ACPI_STATUS(status); |
475 | |||
476 | ACPI_MEMCPY(ACPI_CAST_PTR(void, ret_buffer->pointer), | ||
477 | ACPI_CAST_PTR(void, tbl_ptr), table_length); | ||
478 | |||
479 | return_ACPI_STATUS(AE_OK); | ||
480 | } | 621 | } |
481 | 622 | ||
482 | ACPI_EXPORT_SYMBOL(acpi_get_table) | 623 | ACPI_EXPORT_SYMBOL(acpi_load_tables) |
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 | ||