diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/acpi/tables |
Linux-2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'drivers/acpi/tables')
-rw-r--r-- | drivers/acpi/tables/Makefile | 8 | ||||
-rw-r--r-- | drivers/acpi/tables/tbconvrt.c | 564 | ||||
-rw-r--r-- | drivers/acpi/tables/tbget.c | 493 | ||||
-rw-r--r-- | drivers/acpi/tables/tbgetall.c | 313 | ||||
-rw-r--r-- | drivers/acpi/tables/tbinstal.c | 553 | ||||
-rw-r--r-- | drivers/acpi/tables/tbrsdt.c | 324 | ||||
-rw-r--r-- | drivers/acpi/tables/tbutils.c | 240 | ||||
-rw-r--r-- | drivers/acpi/tables/tbxface.c | 448 | ||||
-rw-r--r-- | drivers/acpi/tables/tbxfroot.c | 606 |
9 files changed, 3549 insertions, 0 deletions
diff --git a/drivers/acpi/tables/Makefile b/drivers/acpi/tables/Makefile new file mode 100644 index 00000000000..aa4c69594d9 --- /dev/null +++ b/drivers/acpi/tables/Makefile | |||
@@ -0,0 +1,8 @@ | |||
1 | # | ||
2 | # Makefile for all Linux ACPI interpreter subdirectories | ||
3 | # | ||
4 | |||
5 | obj-y := tbconvrt.o tbget.o tbrsdt.o tbxface.o \ | ||
6 | tbgetall.o tbinstal.o tbutils.o tbxfroot.o | ||
7 | |||
8 | EXTRA_CFLAGS += $(ACPI_CFLAGS) | ||
diff --git a/drivers/acpi/tables/tbconvrt.c b/drivers/acpi/tables/tbconvrt.c new file mode 100644 index 00000000000..334327c1f66 --- /dev/null +++ b/drivers/acpi/tables/tbconvrt.c | |||
@@ -0,0 +1,564 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Module Name: tbconvrt - ACPI Table conversion utilities | ||
4 | * | ||
5 | *****************************************************************************/ | ||
6 | |||
7 | /* | ||
8 | * Copyright (C) 2000 - 2005, 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 <linux/module.h> | ||
45 | |||
46 | #include <acpi/acpi.h> | ||
47 | #include <acpi/actables.h> | ||
48 | |||
49 | |||
50 | #define _COMPONENT ACPI_TABLES | ||
51 | ACPI_MODULE_NAME ("tbconvrt") | ||
52 | |||
53 | |||
54 | u8 acpi_fadt_is_v1; | ||
55 | EXPORT_SYMBOL(acpi_fadt_is_v1); | ||
56 | |||
57 | /******************************************************************************* | ||
58 | * | ||
59 | * FUNCTION: acpi_tb_get_table_count | ||
60 | * | ||
61 | * PARAMETERS: RSDP - Pointer to the RSDP | ||
62 | * RSDT - Pointer to the RSDT/XSDT | ||
63 | * | ||
64 | * RETURN: The number of tables pointed to by the RSDT or XSDT. | ||
65 | * | ||
66 | * DESCRIPTION: Calculate the number of tables. Automatically handles either | ||
67 | * an RSDT or XSDT. | ||
68 | * | ||
69 | ******************************************************************************/ | ||
70 | |||
71 | u32 | ||
72 | acpi_tb_get_table_count ( | ||
73 | struct rsdp_descriptor *RSDP, | ||
74 | struct acpi_table_header *RSDT) | ||
75 | { | ||
76 | u32 pointer_size; | ||
77 | |||
78 | |||
79 | ACPI_FUNCTION_ENTRY (); | ||
80 | |||
81 | |||
82 | if (RSDP->revision < 2) { | ||
83 | pointer_size = sizeof (u32); | ||
84 | } | ||
85 | else { | ||
86 | pointer_size = sizeof (u64); | ||
87 | } | ||
88 | |||
89 | /* | ||
90 | * Determine the number of tables pointed to by the RSDT/XSDT. | ||
91 | * This is defined by the ACPI Specification to be the number of | ||
92 | * pointers contained within the RSDT/XSDT. The size of the pointers | ||
93 | * is architecture-dependent. | ||
94 | */ | ||
95 | return ((RSDT->length - sizeof (struct acpi_table_header)) / pointer_size); | ||
96 | } | ||
97 | |||
98 | |||
99 | /******************************************************************************* | ||
100 | * | ||
101 | * FUNCTION: acpi_tb_convert_to_xsdt | ||
102 | * | ||
103 | * PARAMETERS: table_info - Info about the RSDT | ||
104 | * | ||
105 | * RETURN: Status | ||
106 | * | ||
107 | * DESCRIPTION: Convert an RSDT to an XSDT (internal common format) | ||
108 | * | ||
109 | ******************************************************************************/ | ||
110 | |||
111 | acpi_status | ||
112 | acpi_tb_convert_to_xsdt ( | ||
113 | struct acpi_table_desc *table_info) | ||
114 | { | ||
115 | acpi_size table_size; | ||
116 | u32 i; | ||
117 | XSDT_DESCRIPTOR *new_table; | ||
118 | |||
119 | |||
120 | ACPI_FUNCTION_ENTRY (); | ||
121 | |||
122 | |||
123 | /* Compute size of the converted XSDT */ | ||
124 | |||
125 | table_size = ((acpi_size) acpi_gbl_rsdt_table_count * sizeof (u64)) + | ||
126 | sizeof (struct acpi_table_header); | ||
127 | |||
128 | /* Allocate an XSDT */ | ||
129 | |||
130 | new_table = ACPI_MEM_CALLOCATE (table_size); | ||
131 | if (!new_table) { | ||
132 | return (AE_NO_MEMORY); | ||
133 | } | ||
134 | |||
135 | /* Copy the header and set the length */ | ||
136 | |||
137 | ACPI_MEMCPY (new_table, table_info->pointer, sizeof (struct acpi_table_header)); | ||
138 | new_table->length = (u32) table_size; | ||
139 | |||
140 | /* Copy the table pointers */ | ||
141 | |||
142 | for (i = 0; i < acpi_gbl_rsdt_table_count; i++) { | ||
143 | if (acpi_gbl_RSDP->revision < 2) { | ||
144 | ACPI_STORE_ADDRESS (new_table->table_offset_entry[i], | ||
145 | (ACPI_CAST_PTR (struct rsdt_descriptor_rev1, table_info->pointer))->table_offset_entry[i]); | ||
146 | } | ||
147 | else { | ||
148 | new_table->table_offset_entry[i] = | ||
149 | (ACPI_CAST_PTR (XSDT_DESCRIPTOR, table_info->pointer))->table_offset_entry[i]; | ||
150 | } | ||
151 | } | ||
152 | |||
153 | /* Delete the original table (either mapped or in a buffer) */ | ||
154 | |||
155 | acpi_tb_delete_single_table (table_info); | ||
156 | |||
157 | /* Point the table descriptor to the new table */ | ||
158 | |||
159 | table_info->pointer = ACPI_CAST_PTR (struct acpi_table_header, new_table); | ||
160 | table_info->length = table_size; | ||
161 | table_info->allocation = ACPI_MEM_ALLOCATED; | ||
162 | |||
163 | return (AE_OK); | ||
164 | } | ||
165 | |||
166 | |||
167 | /****************************************************************************** | ||
168 | * | ||
169 | * FUNCTION: acpi_tb_init_generic_address | ||
170 | * | ||
171 | * PARAMETERS: new_gas_struct - GAS struct to be initialized | ||
172 | * register_bit_width - Width of this register | ||
173 | * Address - Address of the register | ||
174 | * | ||
175 | * RETURN: None | ||
176 | * | ||
177 | * DESCRIPTION: Initialize a GAS structure. | ||
178 | * | ||
179 | ******************************************************************************/ | ||
180 | |||
181 | static void | ||
182 | acpi_tb_init_generic_address ( | ||
183 | struct acpi_generic_address *new_gas_struct, | ||
184 | u8 register_bit_width, | ||
185 | acpi_physical_address address) | ||
186 | { | ||
187 | |||
188 | ACPI_STORE_ADDRESS (new_gas_struct->address, address); | ||
189 | |||
190 | new_gas_struct->address_space_id = ACPI_ADR_SPACE_SYSTEM_IO; | ||
191 | new_gas_struct->register_bit_width = register_bit_width; | ||
192 | new_gas_struct->register_bit_offset = 0; | ||
193 | new_gas_struct->access_width = 0; | ||
194 | } | ||
195 | |||
196 | |||
197 | /******************************************************************************* | ||
198 | * | ||
199 | * FUNCTION: acpi_tb_convert_fadt1 | ||
200 | * | ||
201 | * PARAMETERS: local_fadt - Pointer to new FADT | ||
202 | * original_fadt - Pointer to old FADT | ||
203 | * | ||
204 | * RETURN: Populates local_fadt | ||
205 | * | ||
206 | * DESCRIPTION: Convert an ACPI 1.0 FADT to common internal format | ||
207 | * | ||
208 | ******************************************************************************/ | ||
209 | |||
210 | static void | ||
211 | acpi_tb_convert_fadt1 ( | ||
212 | struct fadt_descriptor_rev2 *local_fadt, | ||
213 | struct fadt_descriptor_rev1 *original_fadt) | ||
214 | { | ||
215 | |||
216 | |||
217 | /* ACPI 1.0 FACS */ | ||
218 | /* The BIOS stored FADT should agree with Revision 1.0 */ | ||
219 | acpi_fadt_is_v1 = 1; | ||
220 | |||
221 | /* | ||
222 | * Copy the table header and the common part of the tables. | ||
223 | * | ||
224 | * The 2.0 table is an extension of the 1.0 table, so the entire 1.0 | ||
225 | * table can be copied first, then expand some fields to 64 bits. | ||
226 | */ | ||
227 | ACPI_MEMCPY (local_fadt, original_fadt, sizeof (struct fadt_descriptor_rev1)); | ||
228 | |||
229 | /* Convert table pointers to 64-bit fields */ | ||
230 | |||
231 | ACPI_STORE_ADDRESS (local_fadt->xfirmware_ctrl, local_fadt->V1_firmware_ctrl); | ||
232 | ACPI_STORE_ADDRESS (local_fadt->Xdsdt, local_fadt->V1_dsdt); | ||
233 | |||
234 | /* | ||
235 | * System Interrupt Model isn't used in ACPI 2.0 (local_fadt->Reserved1 = 0;) | ||
236 | */ | ||
237 | |||
238 | /* | ||
239 | * This field is set by the OEM to convey the preferred power management | ||
240 | * profile to OSPM. It doesn't have any 1.0 equivalence. Since we don't | ||
241 | * know what kind of 32-bit system this is, we will use "unspecified". | ||
242 | */ | ||
243 | local_fadt->prefer_PM_profile = PM_UNSPECIFIED; | ||
244 | |||
245 | /* | ||
246 | * Processor Performance State Control. This is the value OSPM writes to | ||
247 | * the SMI_CMD register to assume processor performance state control | ||
248 | * responsibility. There isn't any equivalence in 1.0, but as many 1.x | ||
249 | * ACPI tables contain _PCT and _PSS we also keep this value, unless | ||
250 | * acpi_strict is set. | ||
251 | */ | ||
252 | if (acpi_strict) | ||
253 | local_fadt->pstate_cnt = 0; | ||
254 | |||
255 | /* | ||
256 | * Support for the _CST object and C States change notification. | ||
257 | * This data item hasn't any 1.0 equivalence so leave it zero. | ||
258 | */ | ||
259 | local_fadt->cst_cnt = 0; | ||
260 | |||
261 | /* | ||
262 | * FADT Rev 2 was an interim FADT released between ACPI 1.0 and ACPI 2.0. | ||
263 | * It primarily adds the FADT reset mechanism. | ||
264 | */ | ||
265 | if ((original_fadt->revision == 2) && | ||
266 | (original_fadt->length == sizeof (struct fadt_descriptor_rev2_minus))) { | ||
267 | /* | ||
268 | * Grab the entire generic address struct, plus the 1-byte reset value | ||
269 | * that immediately follows. | ||
270 | */ | ||
271 | ACPI_MEMCPY (&local_fadt->reset_register, | ||
272 | &(ACPI_CAST_PTR (struct fadt_descriptor_rev2_minus, original_fadt))->reset_register, | ||
273 | sizeof (struct acpi_generic_address) + 1); | ||
274 | } | ||
275 | else { | ||
276 | /* | ||
277 | * Since there isn't any equivalence in 1.0 and since it is highly | ||
278 | * likely that a 1.0 system has legacy support. | ||
279 | */ | ||
280 | local_fadt->iapc_boot_arch = BAF_LEGACY_DEVICES; | ||
281 | } | ||
282 | |||
283 | /* | ||
284 | * Convert the V1.0 block addresses to V2.0 GAS structures | ||
285 | */ | ||
286 | acpi_tb_init_generic_address (&local_fadt->xpm1a_evt_blk, local_fadt->pm1_evt_len, | ||
287 | (acpi_physical_address) local_fadt->V1_pm1a_evt_blk); | ||
288 | acpi_tb_init_generic_address (&local_fadt->xpm1b_evt_blk, local_fadt->pm1_evt_len, | ||
289 | (acpi_physical_address) local_fadt->V1_pm1b_evt_blk); | ||
290 | acpi_tb_init_generic_address (&local_fadt->xpm1a_cnt_blk, local_fadt->pm1_cnt_len, | ||
291 | (acpi_physical_address) local_fadt->V1_pm1a_cnt_blk); | ||
292 | acpi_tb_init_generic_address (&local_fadt->xpm1b_cnt_blk, local_fadt->pm1_cnt_len, | ||
293 | (acpi_physical_address) local_fadt->V1_pm1b_cnt_blk); | ||
294 | acpi_tb_init_generic_address (&local_fadt->xpm2_cnt_blk, local_fadt->pm2_cnt_len, | ||
295 | (acpi_physical_address) local_fadt->V1_pm2_cnt_blk); | ||
296 | acpi_tb_init_generic_address (&local_fadt->xpm_tmr_blk, local_fadt->pm_tm_len, | ||
297 | (acpi_physical_address) local_fadt->V1_pm_tmr_blk); | ||
298 | acpi_tb_init_generic_address (&local_fadt->xgpe0_blk, 0, | ||
299 | (acpi_physical_address) local_fadt->V1_gpe0_blk); | ||
300 | acpi_tb_init_generic_address (&local_fadt->xgpe1_blk, 0, | ||
301 | (acpi_physical_address) local_fadt->V1_gpe1_blk); | ||
302 | |||
303 | /* Create separate GAS structs for the PM1 Enable registers */ | ||
304 | |||
305 | acpi_tb_init_generic_address (&acpi_gbl_xpm1a_enable, | ||
306 | (u8) ACPI_DIV_2 (acpi_gbl_FADT->pm1_evt_len), | ||
307 | (acpi_physical_address) (local_fadt->xpm1a_evt_blk.address + | ||
308 | ACPI_DIV_2 (acpi_gbl_FADT->pm1_evt_len))); | ||
309 | |||
310 | /* PM1B is optional; leave null if not present */ | ||
311 | |||
312 | if (local_fadt->xpm1b_evt_blk.address) { | ||
313 | acpi_tb_init_generic_address (&acpi_gbl_xpm1b_enable, | ||
314 | (u8) ACPI_DIV_2 (acpi_gbl_FADT->pm1_evt_len), | ||
315 | (acpi_physical_address) (local_fadt->xpm1b_evt_blk.address + | ||
316 | ACPI_DIV_2 (acpi_gbl_FADT->pm1_evt_len))); | ||
317 | } | ||
318 | } | ||
319 | |||
320 | |||
321 | /******************************************************************************* | ||
322 | * | ||
323 | * FUNCTION: acpi_tb_convert_fadt2 | ||
324 | * | ||
325 | * PARAMETERS: local_fadt - Pointer to new FADT | ||
326 | * original_fadt - Pointer to old FADT | ||
327 | * | ||
328 | * RETURN: Populates local_fadt | ||
329 | * | ||
330 | * DESCRIPTION: Convert an ACPI 2.0 FADT to common internal format. | ||
331 | * Handles optional "X" fields. | ||
332 | * | ||
333 | ******************************************************************************/ | ||
334 | |||
335 | static void | ||
336 | acpi_tb_convert_fadt2 ( | ||
337 | struct fadt_descriptor_rev2 *local_fadt, | ||
338 | struct fadt_descriptor_rev2 *original_fadt) | ||
339 | { | ||
340 | |||
341 | /* We have an ACPI 2.0 FADT but we must copy it to our local buffer */ | ||
342 | |||
343 | ACPI_MEMCPY (local_fadt, original_fadt, sizeof (struct fadt_descriptor_rev2)); | ||
344 | |||
345 | /* | ||
346 | * "X" fields are optional extensions to the original V1.0 fields, so | ||
347 | * we must selectively expand V1.0 fields if the corresponding X field | ||
348 | * is zero. | ||
349 | */ | ||
350 | if (!(local_fadt->xfirmware_ctrl)) { | ||
351 | ACPI_STORE_ADDRESS (local_fadt->xfirmware_ctrl, local_fadt->V1_firmware_ctrl); | ||
352 | } | ||
353 | |||
354 | if (!(local_fadt->Xdsdt)) { | ||
355 | ACPI_STORE_ADDRESS (local_fadt->Xdsdt, local_fadt->V1_dsdt); | ||
356 | } | ||
357 | |||
358 | if (!(local_fadt->xpm1a_evt_blk.address)) { | ||
359 | acpi_tb_init_generic_address (&local_fadt->xpm1a_evt_blk, | ||
360 | local_fadt->pm1_evt_len, (acpi_physical_address) local_fadt->V1_pm1a_evt_blk); | ||
361 | } | ||
362 | |||
363 | if (!(local_fadt->xpm1b_evt_blk.address)) { | ||
364 | acpi_tb_init_generic_address (&local_fadt->xpm1b_evt_blk, | ||
365 | local_fadt->pm1_evt_len, (acpi_physical_address) local_fadt->V1_pm1b_evt_blk); | ||
366 | } | ||
367 | |||
368 | if (!(local_fadt->xpm1a_cnt_blk.address)) { | ||
369 | acpi_tb_init_generic_address (&local_fadt->xpm1a_cnt_blk, | ||
370 | local_fadt->pm1_cnt_len, (acpi_physical_address) local_fadt->V1_pm1a_cnt_blk); | ||
371 | } | ||
372 | |||
373 | if (!(local_fadt->xpm1b_cnt_blk.address)) { | ||
374 | acpi_tb_init_generic_address (&local_fadt->xpm1b_cnt_blk, | ||
375 | local_fadt->pm1_cnt_len, (acpi_physical_address) local_fadt->V1_pm1b_cnt_blk); | ||
376 | } | ||
377 | |||
378 | if (!(local_fadt->xpm2_cnt_blk.address)) { | ||
379 | acpi_tb_init_generic_address (&local_fadt->xpm2_cnt_blk, | ||
380 | local_fadt->pm2_cnt_len, (acpi_physical_address) local_fadt->V1_pm2_cnt_blk); | ||
381 | } | ||
382 | |||
383 | if (!(local_fadt->xpm_tmr_blk.address)) { | ||
384 | acpi_tb_init_generic_address (&local_fadt->xpm_tmr_blk, | ||
385 | local_fadt->pm_tm_len, (acpi_physical_address) local_fadt->V1_pm_tmr_blk); | ||
386 | } | ||
387 | |||
388 | if (!(local_fadt->xgpe0_blk.address)) { | ||
389 | acpi_tb_init_generic_address (&local_fadt->xgpe0_blk, | ||
390 | 0, (acpi_physical_address) local_fadt->V1_gpe0_blk); | ||
391 | } | ||
392 | |||
393 | if (!(local_fadt->xgpe1_blk.address)) { | ||
394 | acpi_tb_init_generic_address (&local_fadt->xgpe1_blk, | ||
395 | 0, (acpi_physical_address) local_fadt->V1_gpe1_blk); | ||
396 | } | ||
397 | |||
398 | /* Create separate GAS structs for the PM1 Enable registers */ | ||
399 | |||
400 | acpi_tb_init_generic_address (&acpi_gbl_xpm1a_enable, | ||
401 | (u8) ACPI_DIV_2 (acpi_gbl_FADT->pm1_evt_len), | ||
402 | (acpi_physical_address) (local_fadt->xpm1a_evt_blk.address + | ||
403 | ACPI_DIV_2 (acpi_gbl_FADT->pm1_evt_len))); | ||
404 | acpi_gbl_xpm1a_enable.address_space_id = local_fadt->xpm1a_evt_blk.address_space_id; | ||
405 | |||
406 | /* PM1B is optional; leave null if not present */ | ||
407 | |||
408 | if (local_fadt->xpm1b_evt_blk.address) { | ||
409 | acpi_tb_init_generic_address (&acpi_gbl_xpm1b_enable, | ||
410 | (u8) ACPI_DIV_2 (acpi_gbl_FADT->pm1_evt_len), | ||
411 | (acpi_physical_address) (local_fadt->xpm1b_evt_blk.address + | ||
412 | ACPI_DIV_2 (acpi_gbl_FADT->pm1_evt_len))); | ||
413 | acpi_gbl_xpm1b_enable.address_space_id = local_fadt->xpm1b_evt_blk.address_space_id; | ||
414 | } | ||
415 | } | ||
416 | |||
417 | |||
418 | /******************************************************************************* | ||
419 | * | ||
420 | * FUNCTION: acpi_tb_convert_table_fadt | ||
421 | * | ||
422 | * PARAMETERS: None | ||
423 | * | ||
424 | * RETURN: Status | ||
425 | * | ||
426 | * DESCRIPTION: Converts a BIOS supplied ACPI 1.0 FADT to a local | ||
427 | * ACPI 2.0 FADT. If the BIOS supplied a 2.0 FADT then it is simply | ||
428 | * copied to the local FADT. The ACPI CA software uses this | ||
429 | * local FADT. Thus a significant amount of special #ifdef | ||
430 | * type codeing is saved. | ||
431 | * | ||
432 | ******************************************************************************/ | ||
433 | |||
434 | acpi_status | ||
435 | acpi_tb_convert_table_fadt (void) | ||
436 | { | ||
437 | struct fadt_descriptor_rev2 *local_fadt; | ||
438 | struct acpi_table_desc *table_desc; | ||
439 | |||
440 | |||
441 | ACPI_FUNCTION_TRACE ("tb_convert_table_fadt"); | ||
442 | |||
443 | |||
444 | /* | ||
445 | * acpi_gbl_FADT is valid. Validate the FADT length. The table must be | ||
446 | * at least as long as the version 1.0 FADT | ||
447 | */ | ||
448 | if (acpi_gbl_FADT->length < sizeof (struct fadt_descriptor_rev1)) { | ||
449 | ACPI_REPORT_ERROR (("FADT is invalid, too short: 0x%X\n", acpi_gbl_FADT->length)); | ||
450 | return_ACPI_STATUS (AE_INVALID_TABLE_LENGTH); | ||
451 | } | ||
452 | |||
453 | /* Allocate buffer for the ACPI 2.0(+) FADT */ | ||
454 | |||
455 | local_fadt = ACPI_MEM_CALLOCATE (sizeof (struct fadt_descriptor_rev2)); | ||
456 | if (!local_fadt) { | ||
457 | return_ACPI_STATUS (AE_NO_MEMORY); | ||
458 | } | ||
459 | |||
460 | if (acpi_gbl_FADT->revision >= FADT2_REVISION_ID) { | ||
461 | if (acpi_gbl_FADT->length < sizeof (struct fadt_descriptor_rev2)) { | ||
462 | /* Length is too short to be a V2.0 table */ | ||
463 | |||
464 | ACPI_REPORT_WARNING (("Inconsistent FADT length (0x%X) and revision (0x%X), using FADT V1.0 portion of table\n", | ||
465 | acpi_gbl_FADT->length, acpi_gbl_FADT->revision)); | ||
466 | |||
467 | acpi_tb_convert_fadt1 (local_fadt, (void *) acpi_gbl_FADT); | ||
468 | } | ||
469 | else { | ||
470 | /* Valid V2.0 table */ | ||
471 | |||
472 | acpi_tb_convert_fadt2 (local_fadt, acpi_gbl_FADT); | ||
473 | } | ||
474 | } | ||
475 | else { | ||
476 | /* Valid V1.0 table */ | ||
477 | |||
478 | acpi_tb_convert_fadt1 (local_fadt, (void *) acpi_gbl_FADT); | ||
479 | } | ||
480 | |||
481 | /* | ||
482 | * Global FADT pointer will point to the new common V2.0 FADT | ||
483 | */ | ||
484 | acpi_gbl_FADT = local_fadt; | ||
485 | acpi_gbl_FADT->length = sizeof (FADT_DESCRIPTOR); | ||
486 | |||
487 | /* Free the original table */ | ||
488 | |||
489 | table_desc = acpi_gbl_table_lists[ACPI_TABLE_FADT].next; | ||
490 | acpi_tb_delete_single_table (table_desc); | ||
491 | |||
492 | /* Install the new table */ | ||
493 | |||
494 | table_desc->pointer = ACPI_CAST_PTR (struct acpi_table_header, acpi_gbl_FADT); | ||
495 | table_desc->allocation = ACPI_MEM_ALLOCATED; | ||
496 | table_desc->length = sizeof (struct fadt_descriptor_rev2); | ||
497 | |||
498 | /* Dump the entire FADT */ | ||
499 | |||
500 | ACPI_DEBUG_PRINT ((ACPI_DB_TABLES, | ||
501 | "Hex dump of common internal FADT, size %d (%X)\n", | ||
502 | acpi_gbl_FADT->length, acpi_gbl_FADT->length)); | ||
503 | ACPI_DUMP_BUFFER ((u8 *) (acpi_gbl_FADT), acpi_gbl_FADT->length); | ||
504 | |||
505 | return_ACPI_STATUS (AE_OK); | ||
506 | } | ||
507 | |||
508 | |||
509 | /******************************************************************************* | ||
510 | * | ||
511 | * FUNCTION: acpi_tb_convert_table_facs | ||
512 | * | ||
513 | * PARAMETERS: table_info - Info for currently installed FACS | ||
514 | * | ||
515 | * RETURN: Status | ||
516 | * | ||
517 | * DESCRIPTION: Convert ACPI 1.0 and ACPI 2.0 FACS to a common internal | ||
518 | * table format. | ||
519 | * | ||
520 | ******************************************************************************/ | ||
521 | |||
522 | acpi_status | ||
523 | acpi_tb_build_common_facs ( | ||
524 | struct acpi_table_desc *table_info) | ||
525 | { | ||
526 | |||
527 | ACPI_FUNCTION_TRACE ("tb_build_common_facs"); | ||
528 | |||
529 | |||
530 | /* Absolute minimum length is 24, but the ACPI spec says 64 */ | ||
531 | |||
532 | if (acpi_gbl_FACS->length < 24) { | ||
533 | ACPI_REPORT_ERROR (("Invalid FACS table length: 0x%X\n", acpi_gbl_FACS->length)); | ||
534 | return_ACPI_STATUS (AE_INVALID_TABLE_LENGTH); | ||
535 | } | ||
536 | |||
537 | if (acpi_gbl_FACS->length < 64) { | ||
538 | ACPI_REPORT_WARNING (("FACS is shorter than the ACPI specification allows: 0x%X, using anyway\n", | ||
539 | acpi_gbl_FACS->length)); | ||
540 | } | ||
541 | |||
542 | /* Copy fields to the new FACS */ | ||
543 | |||
544 | acpi_gbl_common_fACS.global_lock = &(acpi_gbl_FACS->global_lock); | ||
545 | |||
546 | if ((acpi_gbl_RSDP->revision < 2) || | ||
547 | (acpi_gbl_FACS->length < 32) || | ||
548 | (!(acpi_gbl_FACS->xfirmware_waking_vector))) { | ||
549 | /* ACPI 1.0 FACS or short table or optional X_ field is zero */ | ||
550 | |||
551 | acpi_gbl_common_fACS.firmware_waking_vector = ACPI_CAST_PTR (u64, &(acpi_gbl_FACS->firmware_waking_vector)); | ||
552 | acpi_gbl_common_fACS.vector_width = 32; | ||
553 | } | ||
554 | else { | ||
555 | /* ACPI 2.0 FACS with valid X_ field */ | ||
556 | |||
557 | acpi_gbl_common_fACS.firmware_waking_vector = &acpi_gbl_FACS->xfirmware_waking_vector; | ||
558 | acpi_gbl_common_fACS.vector_width = 64; | ||
559 | } | ||
560 | |||
561 | return_ACPI_STATUS (AE_OK); | ||
562 | } | ||
563 | |||
564 | |||
diff --git a/drivers/acpi/tables/tbget.c b/drivers/acpi/tables/tbget.c new file mode 100644 index 00000000000..896f3ddda62 --- /dev/null +++ b/drivers/acpi/tables/tbget.c | |||
@@ -0,0 +1,493 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Module Name: tbget - ACPI Table get* routines | ||
4 | * | ||
5 | *****************************************************************************/ | ||
6 | |||
7 | /* | ||
8 | * Copyright (C) 2000 - 2005, 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 | |||
45 | #include <acpi/acpi.h> | ||
46 | #include <acpi/actables.h> | ||
47 | |||
48 | |||
49 | #define _COMPONENT ACPI_TABLES | ||
50 | ACPI_MODULE_NAME ("tbget") | ||
51 | |||
52 | |||
53 | /******************************************************************************* | ||
54 | * | ||
55 | * FUNCTION: acpi_tb_get_table | ||
56 | * | ||
57 | * PARAMETERS: Address - Address of table to retrieve. Can be | ||
58 | * Logical or Physical | ||
59 | * table_info - Where table info is returned | ||
60 | * | ||
61 | * RETURN: None | ||
62 | * | ||
63 | * DESCRIPTION: Get entire table of unknown size. | ||
64 | * | ||
65 | ******************************************************************************/ | ||
66 | |||
67 | acpi_status | ||
68 | acpi_tb_get_table ( | ||
69 | struct acpi_pointer *address, | ||
70 | struct acpi_table_desc *table_info) | ||
71 | { | ||
72 | acpi_status status; | ||
73 | struct acpi_table_header header; | ||
74 | |||
75 | |||
76 | ACPI_FUNCTION_TRACE ("tb_get_table"); | ||
77 | |||
78 | |||
79 | /* | ||
80 | * Get the header in order to get signature and table size | ||
81 | */ | ||
82 | status = acpi_tb_get_table_header (address, &header); | ||
83 | if (ACPI_FAILURE (status)) { | ||
84 | return_ACPI_STATUS (status); | ||
85 | } | ||
86 | |||
87 | /* Get the entire table */ | ||
88 | |||
89 | status = acpi_tb_get_table_body (address, &header, table_info); | ||
90 | if (ACPI_FAILURE (status)) { | ||
91 | ACPI_REPORT_ERROR (("Could not get ACPI table (size %X), %s\n", | ||
92 | header.length, acpi_format_exception (status))); | ||
93 | return_ACPI_STATUS (status); | ||
94 | } | ||
95 | |||
96 | return_ACPI_STATUS (AE_OK); | ||
97 | } | ||
98 | |||
99 | |||
100 | /******************************************************************************* | ||
101 | * | ||
102 | * FUNCTION: acpi_tb_get_table_header | ||
103 | * | ||
104 | * PARAMETERS: Address - Address of table to retrieve. Can be | ||
105 | * Logical or Physical | ||
106 | * return_header - Where the table header is returned | ||
107 | * | ||
108 | * RETURN: Status | ||
109 | * | ||
110 | * DESCRIPTION: Get an ACPI table header. Works in both physical or virtual | ||
111 | * addressing mode. Works with both physical or logical pointers. | ||
112 | * Table is either copied or mapped, depending on the pointer | ||
113 | * type and mode of the processor. | ||
114 | * | ||
115 | ******************************************************************************/ | ||
116 | |||
117 | acpi_status | ||
118 | acpi_tb_get_table_header ( | ||
119 | struct acpi_pointer *address, | ||
120 | struct acpi_table_header *return_header) | ||
121 | { | ||
122 | acpi_status status = AE_OK; | ||
123 | struct acpi_table_header *header = NULL; | ||
124 | |||
125 | |||
126 | ACPI_FUNCTION_TRACE ("tb_get_table_header"); | ||
127 | |||
128 | |||
129 | /* | ||
130 | * Flags contains the current processor mode (Virtual or Physical addressing) | ||
131 | * 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, sizeof (struct acpi_table_header)); | ||
140 | break; | ||
141 | |||
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, sizeof (struct acpi_table_header), | ||
148 | (void *) &header); | ||
149 | if (ACPI_FAILURE (status)) { | ||
150 | ACPI_REPORT_ERROR (("Could not map memory at %8.8X%8.8X for length %X\n", | ||
151 | ACPI_FORMAT_UINT64 (address->pointer.physical), | ||
152 | sizeof (struct acpi_table_header))); | ||
153 | return_ACPI_STATUS (status); | ||
154 | } | ||
155 | |||
156 | /* Copy header and delete mapping */ | ||
157 | |||
158 | ACPI_MEMCPY (return_header, header, sizeof (struct acpi_table_header)); | ||
159 | acpi_os_unmap_memory (header, sizeof (struct acpi_table_header)); | ||
160 | break; | ||
161 | |||
162 | |||
163 | default: | ||
164 | |||
165 | ACPI_REPORT_ERROR (("Invalid address flags %X\n", | ||
166 | address->pointer_type)); | ||
167 | return_ACPI_STATUS (AE_BAD_PARAMETER); | ||
168 | } | ||
169 | |||
170 | ACPI_DEBUG_PRINT ((ACPI_DB_TABLES, "Table Signature: [%4.4s]\n", | ||
171 | return_header->signature)); | ||
172 | |||
173 | return_ACPI_STATUS (AE_OK); | ||
174 | } | ||
175 | |||
176 | |||
177 | /******************************************************************************* | ||
178 | * | ||
179 | * FUNCTION: acpi_tb_get_table_body | ||
180 | * | ||
181 | * PARAMETERS: Address - Address of table to retrieve. Can be | ||
182 | * Logical or Physical | ||
183 | * Header - Header of the table to retrieve | ||
184 | * table_info - Where the table info is returned | ||
185 | * | ||
186 | * RETURN: Status | ||
187 | * | ||
188 | * DESCRIPTION: Get an entire ACPI table with support to allow the host OS to | ||
189 | * replace the table with a newer version (table override.) | ||
190 | * Works in both physical or virtual | ||
191 | * addressing mode. Works with both physical or logical pointers. | ||
192 | * Table is either copied or mapped, depending on the pointer | ||
193 | * type and mode of the processor. | ||
194 | * | ||
195 | ******************************************************************************/ | ||
196 | |||
197 | acpi_status | ||
198 | acpi_tb_get_table_body ( | ||
199 | struct acpi_pointer *address, | ||
200 | struct acpi_table_header *header, | ||
201 | struct acpi_table_desc *table_info) | ||
202 | { | ||
203 | acpi_status status; | ||
204 | |||
205 | |||
206 | ACPI_FUNCTION_TRACE ("tb_get_table_body"); | ||
207 | |||
208 | |||
209 | if (!table_info || !address) { | ||
210 | return_ACPI_STATUS (AE_BAD_PARAMETER); | ||
211 | } | ||
212 | |||
213 | /* | ||
214 | * Attempt table override. | ||
215 | */ | ||
216 | status = acpi_tb_table_override (header, table_info); | ||
217 | if (ACPI_SUCCESS (status)) { | ||
218 | /* Table was overridden by the host OS */ | ||
219 | |||
220 | return_ACPI_STATUS (status); | ||
221 | } | ||
222 | |||
223 | /* No override, get the original table */ | ||
224 | |||
225 | status = acpi_tb_get_this_table (address, header, table_info); | ||
226 | return_ACPI_STATUS (status); | ||
227 | } | ||
228 | |||
229 | |||
230 | /******************************************************************************* | ||
231 | * | ||
232 | * FUNCTION: acpi_tb_table_override | ||
233 | * | ||
234 | * PARAMETERS: Header - Pointer to table header | ||
235 | * table_info - Return info if table is overridden | ||
236 | * | ||
237 | * RETURN: None | ||
238 | * | ||
239 | * DESCRIPTION: Attempts override of current table with a new one if provided | ||
240 | * by the host OS. | ||
241 | * | ||
242 | ******************************************************************************/ | ||
243 | |||
244 | acpi_status | ||
245 | acpi_tb_table_override ( | ||
246 | struct acpi_table_header *header, | ||
247 | struct acpi_table_desc *table_info) | ||
248 | { | ||
249 | struct acpi_table_header *new_table; | ||
250 | acpi_status status; | ||
251 | struct acpi_pointer address; | ||
252 | |||
253 | |||
254 | ACPI_FUNCTION_TRACE ("tb_table_override"); | ||
255 | |||
256 | |||
257 | /* | ||
258 | * The OSL will examine the header and decide whether to override this | ||
259 | * table. If it decides to override, a table will be returned in new_table, | ||
260 | * which we will then copy. | ||
261 | */ | ||
262 | status = acpi_os_table_override (header, &new_table); | ||
263 | if (ACPI_FAILURE (status)) { | ||
264 | /* Some severe error from the OSL, but we basically ignore it */ | ||
265 | |||
266 | ACPI_REPORT_ERROR (("Could not override ACPI table, %s\n", | ||
267 | acpi_format_exception (status))); | ||
268 | return_ACPI_STATUS (status); | ||
269 | } | ||
270 | |||
271 | if (!new_table) { | ||
272 | /* No table override */ | ||
273 | |||
274 | return_ACPI_STATUS (AE_NO_ACPI_TABLES); | ||
275 | } | ||
276 | |||
277 | /* | ||
278 | * We have a new table to override the old one. Get a copy of | ||
279 | * the new one. We know that the new table has a logical pointer. | ||
280 | */ | ||
281 | address.pointer_type = ACPI_LOGICAL_POINTER | ACPI_LOGICAL_ADDRESSING; | ||
282 | address.pointer.logical = new_table; | ||
283 | |||
284 | status = acpi_tb_get_this_table (&address, new_table, table_info); | ||
285 | if (ACPI_FAILURE (status)) { | ||
286 | ACPI_REPORT_ERROR (("Could not copy override ACPI table, %s\n", | ||
287 | acpi_format_exception (status))); | ||
288 | return_ACPI_STATUS (status); | ||
289 | } | ||
290 | |||
291 | /* Copy the table info */ | ||
292 | |||
293 | ACPI_REPORT_INFO (("Table [%4.4s] replaced by host OS\n", | ||
294 | table_info->pointer->signature)); | ||
295 | |||
296 | return_ACPI_STATUS (AE_OK); | ||
297 | } | ||
298 | |||
299 | |||
300 | /******************************************************************************* | ||
301 | * | ||
302 | * FUNCTION: acpi_tb_get_this_table | ||
303 | * | ||
304 | * PARAMETERS: Address - Address of table to retrieve. Can be | ||
305 | * Logical or Physical | ||
306 | * Header - Header of the table to retrieve | ||
307 | * table_info - Where the table info is returned | ||
308 | * | ||
309 | * RETURN: Status | ||
310 | * | ||
311 | * DESCRIPTION: Get an entire ACPI table. Works in both physical or virtual | ||
312 | * addressing mode. Works with both physical or logical pointers. | ||
313 | * Table is either copied or mapped, depending on the pointer | ||
314 | * type and mode of the processor. | ||
315 | * | ||
316 | ******************************************************************************/ | ||
317 | |||
318 | acpi_status | ||
319 | acpi_tb_get_this_table ( | ||
320 | struct acpi_pointer *address, | ||
321 | struct acpi_table_header *header, | ||
322 | struct acpi_table_desc *table_info) | ||
323 | { | ||
324 | struct acpi_table_header *full_table = NULL; | ||
325 | u8 allocation; | ||
326 | acpi_status status = AE_OK; | ||
327 | |||
328 | |||
329 | ACPI_FUNCTION_TRACE ("tb_get_this_table"); | ||
330 | |||
331 | |||
332 | /* | ||
333 | * Flags contains the current processor mode (Virtual or Physical addressing) | ||
334 | * The pointer_type is either Logical or Physical | ||
335 | */ | ||
336 | switch (address->pointer_type) { | ||
337 | case ACPI_PHYSMODE_PHYSPTR: | ||
338 | case ACPI_LOGMODE_LOGPTR: | ||
339 | |||
340 | /* Pointer matches processor mode, copy the table to a new buffer */ | ||
341 | |||
342 | full_table = ACPI_MEM_ALLOCATE (header->length); | ||
343 | if (!full_table) { | ||
344 | ACPI_REPORT_ERROR (("Could not allocate table memory for [%4.4s] length %X\n", | ||
345 | header->signature, header->length)); | ||
346 | return_ACPI_STATUS (AE_NO_MEMORY); | ||
347 | } | ||
348 | |||
349 | /* Copy the entire table (including header) to the local buffer */ | ||
350 | |||
351 | ACPI_MEMCPY (full_table, address->pointer.logical, header->length); | ||
352 | |||
353 | /* Save allocation type */ | ||
354 | |||
355 | allocation = ACPI_MEM_ALLOCATED; | ||
356 | break; | ||
357 | |||
358 | |||
359 | case ACPI_LOGMODE_PHYSPTR: | ||
360 | |||
361 | /* | ||
362 | * Just map the table's physical memory | ||
363 | * into our address space. | ||
364 | */ | ||
365 | status = acpi_os_map_memory (address->pointer.physical, (acpi_size) header->length, | ||
366 | (void *) &full_table); | ||
367 | if (ACPI_FAILURE (status)) { | ||
368 | ACPI_REPORT_ERROR (("Could not map memory for table [%4.4s] at %8.8X%8.8X for length %X\n", | ||
369 | header->signature, | ||
370 | ACPI_FORMAT_UINT64 (address->pointer.physical), header->length)); | ||
371 | return (status); | ||
372 | } | ||
373 | |||
374 | /* Save allocation type */ | ||
375 | |||
376 | allocation = ACPI_MEM_MAPPED; | ||
377 | break; | ||
378 | |||
379 | |||
380 | default: | ||
381 | |||
382 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Invalid address flags %X\n", | ||
383 | address->pointer_type)); | ||
384 | return_ACPI_STATUS (AE_BAD_PARAMETER); | ||
385 | } | ||
386 | |||
387 | /* | ||
388 | * Validate checksum for _most_ tables, | ||
389 | * even the ones whose signature we don't recognize | ||
390 | */ | ||
391 | if (table_info->type != ACPI_TABLE_FACS) { | ||
392 | status = acpi_tb_verify_table_checksum (full_table); | ||
393 | |||
394 | #if (!ACPI_CHECKSUM_ABORT) | ||
395 | if (ACPI_FAILURE (status)) { | ||
396 | /* Ignore the error if configuration says so */ | ||
397 | |||
398 | status = AE_OK; | ||
399 | } | ||
400 | #endif | ||
401 | } | ||
402 | |||
403 | /* Return values */ | ||
404 | |||
405 | table_info->pointer = full_table; | ||
406 | table_info->length = (acpi_size) header->length; | ||
407 | table_info->allocation = allocation; | ||
408 | |||
409 | ACPI_DEBUG_PRINT ((ACPI_DB_INFO, | ||
410 | "Found table [%4.4s] at %8.8X%8.8X, mapped/copied to %p\n", | ||
411 | full_table->signature, | ||
412 | ACPI_FORMAT_UINT64 (address->pointer.physical), full_table)); | ||
413 | |||
414 | return_ACPI_STATUS (status); | ||
415 | } | ||
416 | |||
417 | |||
418 | /******************************************************************************* | ||
419 | * | ||
420 | * FUNCTION: acpi_tb_get_table_ptr | ||
421 | * | ||
422 | * PARAMETERS: table_type - one of the defined table types | ||
423 | * Instance - Which table of this type | ||
424 | * table_ptr_loc - pointer to location to place the pointer for | ||
425 | * return | ||
426 | * | ||
427 | * RETURN: Status | ||
428 | * | ||
429 | * DESCRIPTION: This function is called to get the pointer to an ACPI table. | ||
430 | * | ||
431 | ******************************************************************************/ | ||
432 | |||
433 | acpi_status | ||
434 | acpi_tb_get_table_ptr ( | ||
435 | acpi_table_type table_type, | ||
436 | u32 instance, | ||
437 | struct acpi_table_header **table_ptr_loc) | ||
438 | { | ||
439 | struct acpi_table_desc *table_desc; | ||
440 | u32 i; | ||
441 | |||
442 | |||
443 | ACPI_FUNCTION_TRACE ("tb_get_table_ptr"); | ||
444 | |||
445 | |||
446 | if (!acpi_gbl_DSDT) { | ||
447 | return_ACPI_STATUS (AE_NO_ACPI_TABLES); | ||
448 | } | ||
449 | |||
450 | if (table_type > ACPI_TABLE_MAX) { | ||
451 | return_ACPI_STATUS (AE_BAD_PARAMETER); | ||
452 | } | ||
453 | |||
454 | /* | ||
455 | * For all table types (Single/Multiple), the first | ||
456 | * instance is always in the list head. | ||
457 | */ | ||
458 | if (instance == 1) { | ||
459 | /* Get the first */ | ||
460 | |||
461 | *table_ptr_loc = NULL; | ||
462 | if (acpi_gbl_table_lists[table_type].next) { | ||
463 | *table_ptr_loc = acpi_gbl_table_lists[table_type].next->pointer; | ||
464 | } | ||
465 | return_ACPI_STATUS (AE_OK); | ||
466 | } | ||
467 | |||
468 | /* | ||
469 | * Check for instance out of range | ||
470 | */ | ||
471 | if (instance > acpi_gbl_table_lists[table_type].count) { | ||
472 | return_ACPI_STATUS (AE_NOT_EXIST); | ||
473 | } | ||
474 | |||
475 | /* Walk the list to get the desired table | ||
476 | * Since the if (Instance == 1) check above checked for the | ||
477 | * first table, setting table_desc equal to the .Next member | ||
478 | * is actually pointing to the second table. Therefore, we | ||
479 | * need to walk from the 2nd table until we reach the Instance | ||
480 | * that the user is looking for and return its table pointer. | ||
481 | */ | ||
482 | table_desc = acpi_gbl_table_lists[table_type].next; | ||
483 | for (i = 2; i < instance; i++) { | ||
484 | table_desc = table_desc->next; | ||
485 | } | ||
486 | |||
487 | /* We are now pointing to the requested table's descriptor */ | ||
488 | |||
489 | *table_ptr_loc = table_desc->pointer; | ||
490 | |||
491 | return_ACPI_STATUS (AE_OK); | ||
492 | } | ||
493 | |||
diff --git a/drivers/acpi/tables/tbgetall.c b/drivers/acpi/tables/tbgetall.c new file mode 100644 index 00000000000..adc4270988b --- /dev/null +++ b/drivers/acpi/tables/tbgetall.c | |||
@@ -0,0 +1,313 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Module Name: tbgetall - Get all required ACPI tables | ||
4 | * | ||
5 | *****************************************************************************/ | ||
6 | |||
7 | /* | ||
8 | * Copyright (C) 2000 - 2005, 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 | |||
45 | #include <acpi/acpi.h> | ||
46 | #include <acpi/actables.h> | ||
47 | |||
48 | |||
49 | #define _COMPONENT ACPI_TABLES | ||
50 | ACPI_MODULE_NAME ("tbgetall") | ||
51 | |||
52 | |||
53 | /******************************************************************************* | ||
54 | * | ||
55 | * FUNCTION: acpi_tb_get_primary_table | ||
56 | * | ||
57 | * PARAMETERS: Address - Physical address of table to retrieve | ||
58 | * *table_info - Where the table info is returned | ||
59 | * | ||
60 | * RETURN: Status | ||
61 | * | ||
62 | * DESCRIPTION: Maps the physical address of table into a logical address | ||
63 | * | ||
64 | ******************************************************************************/ | ||
65 | |||
66 | acpi_status | ||
67 | acpi_tb_get_primary_table ( | ||
68 | struct acpi_pointer *address, | ||
69 | struct acpi_table_desc *table_info) | ||
70 | { | ||
71 | acpi_status status; | ||
72 | struct acpi_table_header header; | ||
73 | |||
74 | |||
75 | ACPI_FUNCTION_TRACE ("tb_get_primary_table"); | ||
76 | |||
77 | |||
78 | /* Ignore a NULL address in the RSDT */ | ||
79 | |||
80 | if (!address->pointer.value) { | ||
81 | return_ACPI_STATUS (AE_OK); | ||
82 | } | ||
83 | |||
84 | /* | ||
85 | * Get the header in order to get signature and table size | ||
86 | */ | ||
87 | status = acpi_tb_get_table_header (address, &header); | ||
88 | if (ACPI_FAILURE (status)) { | ||
89 | return_ACPI_STATUS (status); | ||
90 | } | ||
91 | |||
92 | /* Clear the table_info */ | ||
93 | |||
94 | ACPI_MEMSET (table_info, 0, sizeof (struct acpi_table_desc)); | ||
95 | |||
96 | /* | ||
97 | * Check the table signature and make sure it is recognized. | ||
98 | * Also checks the header checksum | ||
99 | */ | ||
100 | table_info->pointer = &header; | ||
101 | status = acpi_tb_recognize_table (table_info, ACPI_TABLE_PRIMARY); | ||
102 | if (ACPI_FAILURE (status)) { | ||
103 | return_ACPI_STATUS (status); | ||
104 | } | ||
105 | |||
106 | /* Get the entire table */ | ||
107 | |||
108 | status = acpi_tb_get_table_body (address, &header, table_info); | ||
109 | if (ACPI_FAILURE (status)) { | ||
110 | return_ACPI_STATUS (status); | ||
111 | } | ||
112 | |||
113 | /* Install the table */ | ||
114 | |||
115 | status = acpi_tb_install_table (table_info); | ||
116 | return_ACPI_STATUS (status); | ||
117 | } | ||
118 | |||
119 | |||
120 | /******************************************************************************* | ||
121 | * | ||
122 | * FUNCTION: acpi_tb_get_secondary_table | ||
123 | * | ||
124 | * PARAMETERS: Address - Physical address of table to retrieve | ||
125 | * *table_info - Where the table info is returned | ||
126 | * | ||
127 | * RETURN: Status | ||
128 | * | ||
129 | * DESCRIPTION: Maps the physical address of table into a logical address | ||
130 | * | ||
131 | ******************************************************************************/ | ||
132 | |||
133 | acpi_status | ||
134 | acpi_tb_get_secondary_table ( | ||
135 | struct acpi_pointer *address, | ||
136 | acpi_string signature, | ||
137 | struct acpi_table_desc *table_info) | ||
138 | { | ||
139 | acpi_status status; | ||
140 | struct acpi_table_header header; | ||
141 | |||
142 | |||
143 | ACPI_FUNCTION_TRACE_STR ("tb_get_secondary_table", signature); | ||
144 | |||
145 | |||
146 | /* Get the header in order to match the signature */ | ||
147 | |||
148 | status = acpi_tb_get_table_header (address, &header); | ||
149 | if (ACPI_FAILURE (status)) { | ||
150 | return_ACPI_STATUS (status); | ||
151 | } | ||
152 | |||
153 | /* Signature must match request */ | ||
154 | |||
155 | if (ACPI_STRNCMP (header.signature, signature, ACPI_NAME_SIZE)) { | ||
156 | ACPI_REPORT_ERROR (("Incorrect table signature - wanted [%s] found [%4.4s]\n", | ||
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 | * | ||
187 | * FUNCTION: acpi_tb_get_required_tables | ||
188 | * | ||
189 | * PARAMETERS: None | ||
190 | * | ||
191 | * RETURN: Status | ||
192 | * | ||
193 | * DESCRIPTION: Load and validate tables other than the RSDT. The RSDT must | ||
194 | * already be loaded and validated. | ||
195 | * | ||
196 | * Get the minimum set of ACPI tables, namely: | ||
197 | * | ||
198 | * 1) FADT (via RSDT in loop below) | ||
199 | * 2) FACS (via FADT) | ||
200 | * 3) DSDT (via FADT) | ||
201 | * | ||
202 | ******************************************************************************/ | ||
203 | |||
204 | acpi_status | ||
205 | acpi_tb_get_required_tables ( | ||
206 | void) | ||
207 | { | ||
208 | acpi_status status = AE_OK; | ||
209 | u32 i; | ||
210 | struct acpi_table_desc table_info; | ||
211 | struct acpi_pointer address; | ||
212 | |||
213 | |||
214 | ACPI_FUNCTION_TRACE ("tb_get_required_tables"); | ||
215 | |||
216 | ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "%d ACPI tables in RSDT\n", | ||
217 | acpi_gbl_rsdt_table_count)); | ||
218 | |||
219 | |||
220 | address.pointer_type = acpi_gbl_table_flags | ACPI_LOGICAL_ADDRESSING; | ||
221 | |||
222 | /* | ||
223 | * Loop through all table pointers found in RSDT. | ||
224 | * This will NOT include the FACS and DSDT - we must get | ||
225 | * them after the loop. | ||
226 | * | ||
227 | * The only tables we are interested in getting here is the FADT and | ||
228 | * any SSDTs. | ||
229 | */ | ||
230 | for (i = 0; i < acpi_gbl_rsdt_table_count; i++) { | ||
231 | /* Get the table address from the common internal XSDT */ | ||
232 | |||
233 | address.pointer.value = acpi_gbl_XSDT->table_offset_entry[i]; | ||
234 | |||
235 | /* | ||
236 | * Get the tables needed by this subsystem (FADT and any SSDTs). | ||
237 | * NOTE: All other tables are completely ignored at this time. | ||
238 | */ | ||
239 | status = acpi_tb_get_primary_table (&address, &table_info); | ||
240 | if ((status != AE_OK) && (status != AE_TABLE_NOT_SUPPORTED)) { | ||
241 | ACPI_REPORT_WARNING (("%s, while getting table at %8.8X%8.8X\n", | ||
242 | acpi_format_exception (status), | ||
243 | ACPI_FORMAT_UINT64 (address.pointer.value))); | ||
244 | } | ||
245 | } | ||
246 | |||
247 | /* We must have a FADT to continue */ | ||
248 | |||
249 | if (!acpi_gbl_FADT) { | ||
250 | ACPI_REPORT_ERROR (("No FADT present in RSDT/XSDT\n")); | ||
251 | return_ACPI_STATUS (AE_NO_ACPI_TABLES); | ||
252 | } | ||
253 | |||
254 | /* | ||
255 | * Convert the FADT to a common format. This allows earlier revisions of the | ||
256 | * table to coexist with newer versions, using common access code. | ||
257 | */ | ||
258 | status = acpi_tb_convert_table_fadt (); | ||
259 | if (ACPI_FAILURE (status)) { | ||
260 | ACPI_REPORT_ERROR (("Could not convert FADT to internal common format\n")); | ||
261 | return_ACPI_STATUS (status); | ||
262 | } | ||
263 | |||
264 | /* | ||
265 | * Get the FACS (Pointed to by the FADT) | ||
266 | */ | ||
267 | address.pointer.value = acpi_gbl_FADT->xfirmware_ctrl; | ||
268 | |||
269 | status = acpi_tb_get_secondary_table (&address, FACS_SIG, &table_info); | ||
270 | if (ACPI_FAILURE (status)) { | ||
271 | ACPI_REPORT_ERROR (("Could not get/install the FACS, %s\n", | ||
272 | acpi_format_exception (status))); | ||
273 | return_ACPI_STATUS (status); | ||
274 | } | ||
275 | |||
276 | /* | ||
277 | * Create the common FACS pointer table | ||
278 | * (Contains pointers to the original table) | ||
279 | */ | ||
280 | status = acpi_tb_build_common_facs (&table_info); | ||
281 | if (ACPI_FAILURE (status)) { | ||
282 | return_ACPI_STATUS (status); | ||
283 | } | ||
284 | |||
285 | /* | ||
286 | * Get/install the DSDT (Pointed to by the FADT) | ||
287 | */ | ||
288 | address.pointer.value = acpi_gbl_FADT->Xdsdt; | ||
289 | |||
290 | status = acpi_tb_get_secondary_table (&address, DSDT_SIG, &table_info); | ||
291 | if (ACPI_FAILURE (status)) { | ||
292 | ACPI_REPORT_ERROR (("Could not get/install the DSDT\n")); | ||
293 | return_ACPI_STATUS (status); | ||
294 | } | ||
295 | |||
296 | /* Set Integer Width (32/64) based upon DSDT revision */ | ||
297 | |||
298 | acpi_ut_set_integer_width (acpi_gbl_DSDT->revision); | ||
299 | |||
300 | /* Dump the entire DSDT */ | ||
301 | |||
302 | ACPI_DEBUG_PRINT ((ACPI_DB_TABLES, | ||
303 | "Hex dump of entire DSDT, size %d (0x%X), Integer width = %d\n", | ||
304 | acpi_gbl_DSDT->length, acpi_gbl_DSDT->length, acpi_gbl_integer_bit_width)); | ||
305 | ACPI_DUMP_BUFFER ((u8 *) acpi_gbl_DSDT, 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_RSDP); | ||
310 | return_ACPI_STATUS (status); | ||
311 | } | ||
312 | |||
313 | |||
diff --git a/drivers/acpi/tables/tbinstal.c b/drivers/acpi/tables/tbinstal.c new file mode 100644 index 00000000000..85d5bb01022 --- /dev/null +++ b/drivers/acpi/tables/tbinstal.c | |||
@@ -0,0 +1,553 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Module Name: tbinstal - ACPI table installation and removal | ||
4 | * | ||
5 | *****************************************************************************/ | ||
6 | |||
7 | /* | ||
8 | * Copyright (C) 2000 - 2005, 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 | |||
45 | #include <acpi/acpi.h> | ||
46 | #include <acpi/actables.h> | ||
47 | |||
48 | |||
49 | #define _COMPONENT ACPI_TABLES | ||
50 | ACPI_MODULE_NAME ("tbinstal") | ||
51 | |||
52 | |||
53 | /******************************************************************************* | ||
54 | * | ||
55 | * FUNCTION: acpi_tb_match_signature | ||
56 | * | ||
57 | * PARAMETERS: Signature - Table signature to match | ||
58 | * table_info - Return data | ||
59 | * | ||
60 | * RETURN: Status | ||
61 | * | ||
62 | * DESCRIPTION: Compare signature against the list of "ACPI-subsystem-owned" | ||
63 | * tables (DSDT/FADT/SSDT, etc.) Returns the table_type_iD on match. | ||
64 | * | ||
65 | ******************************************************************************/ | ||
66 | |||
67 | acpi_status | ||
68 | acpi_tb_match_signature ( | ||
69 | char *signature, | ||
70 | struct acpi_table_desc *table_info, | ||
71 | u8 search_type) | ||
72 | { | ||
73 | acpi_native_uint i; | ||
74 | |||
75 | |||
76 | ACPI_FUNCTION_TRACE ("tb_match_signature"); | ||
77 | |||
78 | |||
79 | /* | ||
80 | * Search for a signature match among the known table types | ||
81 | */ | ||
82 | for (i = 0; i < NUM_ACPI_TABLE_TYPES; i++) { | ||
83 | if (!(acpi_gbl_table_data[i].flags & search_type)) { | ||
84 | continue; | ||
85 | } | ||
86 | |||
87 | if (!ACPI_STRNCMP (signature, acpi_gbl_table_data[i].signature, | ||
88 | acpi_gbl_table_data[i].sig_length)) { | ||
89 | /* Found a signature match, return index if requested */ | ||
90 | |||
91 | if (table_info) { | ||
92 | table_info->type = (u8) i; | ||
93 | } | ||
94 | |||
95 | ACPI_DEBUG_PRINT ((ACPI_DB_INFO, | ||
96 | "Table [%4.4s] is an ACPI table consumed by the core subsystem\n", | ||
97 | (char *) acpi_gbl_table_data[i].signature)); | ||
98 | |||
99 | return_ACPI_STATUS (AE_OK); | ||
100 | } | ||
101 | } | ||
102 | |||
103 | ACPI_DEBUG_PRINT ((ACPI_DB_INFO, | ||
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 | } | ||
109 | |||
110 | |||
111 | /******************************************************************************* | ||
112 | * | ||
113 | * FUNCTION: acpi_tb_install_table | ||
114 | * | ||
115 | * PARAMETERS: table_info - Return value from acpi_tb_get_table_body | ||
116 | * | ||
117 | * RETURN: Status | ||
118 | * | ||
119 | * DESCRIPTION: Load and validate all tables other than the RSDT. The RSDT must | ||
120 | * already be loaded and validated. | ||
121 | * Install the table into the global data structs. | ||
122 | * | ||
123 | ******************************************************************************/ | ||
124 | |||
125 | acpi_status | ||
126 | acpi_tb_install_table ( | ||
127 | struct acpi_table_desc *table_info) | ||
128 | { | ||
129 | acpi_status status; | ||
130 | |||
131 | ACPI_FUNCTION_TRACE ("tb_install_table"); | ||
132 | |||
133 | |||
134 | /* Lock tables while installing */ | ||
135 | |||
136 | status = acpi_ut_acquire_mutex (ACPI_MTX_TABLES); | ||
137 | if (ACPI_FAILURE (status)) { | ||
138 | ACPI_REPORT_ERROR (("Could not acquire table mutex for [%4.4s], %s\n", | ||
139 | table_info->pointer->signature, acpi_format_exception (status))); | ||
140 | return_ACPI_STATUS (status); | ||
141 | } | ||
142 | |||
143 | /* Install the table into the global data structure */ | ||
144 | |||
145 | status = acpi_tb_init_table_descriptor (table_info->type, table_info); | ||
146 | if (ACPI_FAILURE (status)) { | ||
147 | ACPI_REPORT_ERROR (("Could not install ACPI table [%4.4s], %s\n", | ||
148 | table_info->pointer->signature, acpi_format_exception (status))); | ||
149 | } | ||
150 | |||
151 | ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "%s located at %p\n", | ||
152 | acpi_gbl_table_data[table_info->type].name, table_info->pointer)); | ||
153 | |||
154 | (void) acpi_ut_release_mutex (ACPI_MTX_TABLES); | ||
155 | return_ACPI_STATUS (status); | ||
156 | } | ||
157 | |||
158 | |||
159 | /******************************************************************************* | ||
160 | * | ||
161 | * FUNCTION: acpi_tb_recognize_table | ||
162 | * | ||
163 | * PARAMETERS: table_info - Return value from acpi_tb_get_table_body | ||
164 | * | ||
165 | * RETURN: Status | ||
166 | * | ||
167 | * DESCRIPTION: Check a table signature for a match against known table types | ||
168 | * | ||
169 | * NOTE: All table pointers are validated as follows: | ||
170 | * 1) Table pointer must point to valid physical memory | ||
171 | * 2) Signature must be 4 ASCII chars, even if we don't recognize the | ||
172 | * name | ||
173 | * 3) Table must be readable for length specified in the header | ||
174 | * 4) Table checksum must be valid (with the exception of the FACS | ||
175 | * which has no checksum for some odd reason) | ||
176 | * | ||
177 | ******************************************************************************/ | ||
178 | |||
179 | acpi_status | ||
180 | acpi_tb_recognize_table ( | ||
181 | struct acpi_table_desc *table_info, | ||
182 | u8 search_type) | ||
183 | { | ||
184 | struct acpi_table_header *table_header; | ||
185 | acpi_status status; | ||
186 | |||
187 | |||
188 | ACPI_FUNCTION_TRACE ("tb_recognize_table"); | ||
189 | |||
190 | |||
191 | /* Ensure that we have a valid table pointer */ | ||
192 | |||
193 | table_header = (struct acpi_table_header *) table_info->pointer; | ||
194 | if (!table_header) { | ||
195 | return_ACPI_STATUS (AE_BAD_PARAMETER); | ||
196 | } | ||
197 | |||
198 | /* | ||
199 | * We only "recognize" a limited number of ACPI tables -- namely, the | ||
200 | * ones that are used by the subsystem (DSDT, FADT, etc.) | ||
201 | * | ||
202 | * An AE_TABLE_NOT_SUPPORTED means that the table was not recognized. | ||
203 | * This can be any one of many valid ACPI tables, it just isn't one of | ||
204 | * the tables that is consumed by the core subsystem | ||
205 | */ | ||
206 | status = acpi_tb_match_signature (table_header->signature, table_info, search_type); | ||
207 | if (ACPI_FAILURE (status)) { | ||
208 | return_ACPI_STATUS (status); | ||
209 | } | ||
210 | |||
211 | status = acpi_tb_validate_table_header (table_header); | ||
212 | if (ACPI_FAILURE (status)) { | ||
213 | return_ACPI_STATUS (status); | ||
214 | } | ||
215 | |||
216 | /* Return the table type and length via the info struct */ | ||
217 | |||
218 | table_info->length = (acpi_size) table_header->length; | ||
219 | |||
220 | return_ACPI_STATUS (status); | ||
221 | } | ||
222 | |||
223 | |||
224 | /******************************************************************************* | ||
225 | * | ||
226 | * FUNCTION: acpi_tb_init_table_descriptor | ||
227 | * | ||
228 | * PARAMETERS: table_type - The type of the table | ||
229 | * table_info - A table info struct | ||
230 | * | ||
231 | * RETURN: None. | ||
232 | * | ||
233 | * DESCRIPTION: Install a table into the global data structs. | ||
234 | * | ||
235 | ******************************************************************************/ | ||
236 | |||
237 | acpi_status | ||
238 | acpi_tb_init_table_descriptor ( | ||
239 | acpi_table_type table_type, | ||
240 | struct acpi_table_desc *table_info) | ||
241 | { | ||
242 | struct acpi_table_list *list_head; | ||
243 | struct acpi_table_desc *table_desc; | ||
244 | |||
245 | |||
246 | ACPI_FUNCTION_TRACE_U32 ("tb_init_table_descriptor", table_type); | ||
247 | |||
248 | |||
249 | /* Allocate a descriptor for this table */ | ||
250 | |||
251 | table_desc = ACPI_MEM_CALLOCATE (sizeof (struct acpi_table_desc)); | ||
252 | if (!table_desc) { | ||
253 | return_ACPI_STATUS (AE_NO_MEMORY); | ||
254 | } | ||
255 | |||
256 | /* | ||
257 | * Install the table into the global data structure | ||
258 | */ | ||
259 | list_head = &acpi_gbl_table_lists[table_type]; | ||
260 | |||
261 | /* | ||
262 | * Two major types of tables: 1) Only one instance is allowed. This | ||
263 | * includes most ACPI tables such as the DSDT. 2) Multiple instances of | ||
264 | * the table are allowed. This includes SSDT and PSDTs. | ||
265 | */ | ||
266 | if (ACPI_IS_SINGLE_TABLE (acpi_gbl_table_data[table_type].flags)) { | ||
267 | /* | ||
268 | * Only one table allowed, and a table has alread been installed | ||
269 | * at this location, so return an error. | ||
270 | */ | ||
271 | if (list_head->next) { | ||
272 | ACPI_MEM_FREE (table_desc); | ||
273 | return_ACPI_STATUS (AE_ALREADY_EXISTS); | ||
274 | } | ||
275 | |||
276 | table_desc->next = list_head->next; | ||
277 | list_head->next = table_desc; | ||
278 | |||
279 | if (table_desc->next) { | ||
280 | table_desc->next->prev = table_desc; | ||
281 | } | ||
282 | |||
283 | list_head->count++; | ||
284 | } | ||
285 | else { | ||
286 | /* | ||
287 | * Link the new table in to the list of tables of this type. | ||
288 | * Insert at the end of the list, order IS IMPORTANT. | ||
289 | * | ||
290 | * table_desc->Prev & Next are already NULL from calloc() | ||
291 | */ | ||
292 | list_head->count++; | ||
293 | |||
294 | if (!list_head->next) { | ||
295 | list_head->next = table_desc; | ||
296 | } | ||
297 | else { | ||
298 | table_desc->next = list_head->next; | ||
299 | |||
300 | while (table_desc->next->next) { | ||
301 | table_desc->next = table_desc->next->next; | ||
302 | } | ||
303 | |||
304 | table_desc->next->next = table_desc; | ||
305 | table_desc->prev = table_desc->next; | ||
306 | table_desc->next = NULL; | ||
307 | } | ||
308 | } | ||
309 | |||
310 | /* Finish initialization of the table descriptor */ | ||
311 | |||
312 | table_desc->type = (u8) table_type; | ||
313 | table_desc->pointer = table_info->pointer; | ||
314 | table_desc->length = table_info->length; | ||
315 | table_desc->allocation = table_info->allocation; | ||
316 | table_desc->aml_start = (u8 *) (table_desc->pointer + 1), | ||
317 | table_desc->aml_length = (u32) (table_desc->length - | ||
318 | (u32) sizeof (struct acpi_table_header)); | ||
319 | table_desc->table_id = acpi_ut_allocate_owner_id (ACPI_OWNER_TYPE_TABLE); | ||
320 | table_desc->loaded_into_namespace = FALSE; | ||
321 | |||
322 | /* | ||
323 | * Set the appropriate global pointer (if there is one) to point to the | ||
324 | * newly installed table | ||
325 | */ | ||
326 | if (acpi_gbl_table_data[table_type].global_ptr) { | ||
327 | *(acpi_gbl_table_data[table_type].global_ptr) = table_info->pointer; | ||
328 | } | ||
329 | |||
330 | /* Return Data */ | ||
331 | |||
332 | table_info->table_id = table_desc->table_id; | ||
333 | table_info->installed_desc = table_desc; | ||
334 | |||
335 | return_ACPI_STATUS (AE_OK); | ||
336 | } | ||
337 | |||
338 | |||
339 | /******************************************************************************* | ||
340 | * | ||
341 | * FUNCTION: acpi_tb_delete_all_tables | ||
342 | * | ||
343 | * PARAMETERS: None. | ||
344 | * | ||
345 | * RETURN: None. | ||
346 | * | ||
347 | * DESCRIPTION: Delete all internal ACPI tables | ||
348 | * | ||
349 | ******************************************************************************/ | ||
350 | |||
351 | void | ||
352 | acpi_tb_delete_all_tables (void) | ||
353 | { | ||
354 | acpi_table_type type; | ||
355 | |||
356 | |||
357 | /* | ||
358 | * Free memory allocated for ACPI tables | ||
359 | * Memory can either be mapped or allocated | ||
360 | */ | ||
361 | for (type = 0; type < NUM_ACPI_TABLE_TYPES; type++) { | ||
362 | acpi_tb_delete_tables_by_type (type); | ||
363 | } | ||
364 | } | ||
365 | |||
366 | |||
367 | /******************************************************************************* | ||
368 | * | ||
369 | * FUNCTION: acpi_tb_delete_tables_by_type | ||
370 | * | ||
371 | * PARAMETERS: Type - The table type to be deleted | ||
372 | * | ||
373 | * RETURN: None. | ||
374 | * | ||
375 | * DESCRIPTION: Delete an internal ACPI table | ||
376 | * Locks the ACPI table mutex | ||
377 | * | ||
378 | ******************************************************************************/ | ||
379 | |||
380 | void | ||
381 | acpi_tb_delete_tables_by_type ( | ||
382 | acpi_table_type type) | ||
383 | { | ||
384 | struct acpi_table_desc *table_desc; | ||
385 | u32 count; | ||
386 | u32 i; | ||
387 | |||
388 | |||
389 | ACPI_FUNCTION_TRACE_U32 ("tb_delete_tables_by_type", type); | ||
390 | |||
391 | |||
392 | if (type > ACPI_TABLE_MAX) { | ||
393 | return_VOID; | ||
394 | } | ||
395 | |||
396 | if (ACPI_FAILURE (acpi_ut_acquire_mutex (ACPI_MTX_TABLES))) { | ||
397 | return; | ||
398 | } | ||
399 | |||
400 | /* Clear the appropriate "typed" global table pointer */ | ||
401 | |||
402 | switch (type) { | ||
403 | case ACPI_TABLE_RSDP: | ||
404 | acpi_gbl_RSDP = NULL; | ||
405 | break; | ||
406 | |||
407 | case ACPI_TABLE_DSDT: | ||
408 | acpi_gbl_DSDT = NULL; | ||
409 | break; | ||
410 | |||
411 | case ACPI_TABLE_FADT: | ||
412 | acpi_gbl_FADT = NULL; | ||
413 | break; | ||
414 | |||
415 | case ACPI_TABLE_FACS: | ||
416 | acpi_gbl_FACS = NULL; | ||
417 | break; | ||
418 | |||
419 | case ACPI_TABLE_XSDT: | ||
420 | acpi_gbl_XSDT = NULL; | ||
421 | break; | ||
422 | |||
423 | case ACPI_TABLE_SSDT: | ||
424 | case ACPI_TABLE_PSDT: | ||
425 | default: | ||
426 | break; | ||
427 | } | ||
428 | |||
429 | /* | ||
430 | * Free the table | ||
431 | * 1) Get the head of the list | ||
432 | */ | ||
433 | table_desc = acpi_gbl_table_lists[type].next; | ||
434 | count = acpi_gbl_table_lists[type].count; | ||
435 | |||
436 | /* | ||
437 | * 2) Walk the entire list, deleting both the allocated tables | ||
438 | * and the table descriptors | ||
439 | */ | ||
440 | for (i = 0; i < count; i++) { | ||
441 | table_desc = acpi_tb_uninstall_table (table_desc); | ||
442 | } | ||
443 | |||
444 | (void) acpi_ut_release_mutex (ACPI_MTX_TABLES); | ||
445 | return_VOID; | ||
446 | } | ||
447 | |||
448 | |||
449 | /******************************************************************************* | ||
450 | * | ||
451 | * FUNCTION: acpi_tb_delete_single_table | ||
452 | * | ||
453 | * PARAMETERS: table_info - A table info struct | ||
454 | * | ||
455 | * RETURN: None. | ||
456 | * | ||
457 | * DESCRIPTION: Low-level free for a single ACPI table. Handles cases where | ||
458 | * the table was allocated a buffer or was mapped. | ||
459 | * | ||
460 | ******************************************************************************/ | ||
461 | |||
462 | void | ||
463 | acpi_tb_delete_single_table ( | ||
464 | struct acpi_table_desc *table_desc) | ||
465 | { | ||
466 | |||
467 | /* Must have a valid table descriptor and pointer */ | ||
468 | |||
469 | if ((!table_desc) || | ||
470 | (!table_desc->pointer)) { | ||
471 | return; | ||
472 | } | ||
473 | |||
474 | /* Valid table, determine type of memory allocation */ | ||
475 | |||
476 | switch (table_desc->allocation) { | ||
477 | case ACPI_MEM_NOT_ALLOCATED: | ||
478 | break; | ||
479 | |||
480 | case ACPI_MEM_ALLOCATED: | ||
481 | |||
482 | ACPI_MEM_FREE (table_desc->pointer); | ||
483 | break; | ||
484 | |||
485 | case ACPI_MEM_MAPPED: | ||
486 | |||
487 | acpi_os_unmap_memory (table_desc->pointer, table_desc->length); | ||
488 | break; | ||
489 | |||
490 | default: | ||
491 | break; | ||
492 | } | ||
493 | } | ||
494 | |||
495 | |||
496 | /******************************************************************************* | ||
497 | * | ||
498 | * FUNCTION: acpi_tb_uninstall_table | ||
499 | * | ||
500 | * PARAMETERS: table_info - A table info struct | ||
501 | * | ||
502 | * RETURN: Pointer to the next table in the list (of same type) | ||
503 | * | ||
504 | * DESCRIPTION: Free the memory associated with an internal ACPI table that | ||
505 | * is either installed or has never been installed. | ||
506 | * Table mutex should be locked. | ||
507 | * | ||
508 | ******************************************************************************/ | ||
509 | |||
510 | struct acpi_table_desc * | ||
511 | acpi_tb_uninstall_table ( | ||
512 | struct acpi_table_desc *table_desc) | ||
513 | { | ||
514 | struct acpi_table_desc *next_desc; | ||
515 | |||
516 | |||
517 | ACPI_FUNCTION_TRACE_PTR ("tb_uninstall_table", table_desc); | ||
518 | |||
519 | |||
520 | if (!table_desc) { | ||
521 | return_PTR (NULL); | ||
522 | } | ||
523 | |||
524 | /* Unlink the descriptor from the doubly linked list */ | ||
525 | |||
526 | if (table_desc->prev) { | ||
527 | table_desc->prev->next = table_desc->next; | ||
528 | } | ||
529 | else { | ||
530 | /* Is first on list, update list head */ | ||
531 | |||
532 | acpi_gbl_table_lists[table_desc->type].next = table_desc->next; | ||
533 | } | ||
534 | |||
535 | if (table_desc->next) { | ||
536 | table_desc->next->prev = table_desc->prev; | ||
537 | } | ||
538 | |||
539 | /* Free the memory allocated for the table itself */ | ||
540 | |||
541 | acpi_tb_delete_single_table (table_desc); | ||
542 | |||
543 | /* Free the table descriptor */ | ||
544 | |||
545 | next_desc = table_desc->next; | ||
546 | ACPI_MEM_FREE (table_desc); | ||
547 | |||
548 | /* Return pointer to the next descriptor */ | ||
549 | |||
550 | return_PTR (next_desc); | ||
551 | } | ||
552 | |||
553 | |||
diff --git a/drivers/acpi/tables/tbrsdt.c b/drivers/acpi/tables/tbrsdt.c new file mode 100644 index 00000000000..9c6913238d5 --- /dev/null +++ b/drivers/acpi/tables/tbrsdt.c | |||
@@ -0,0 +1,324 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Module Name: tbrsdt - ACPI RSDT table utilities | ||
4 | * | ||
5 | *****************************************************************************/ | ||
6 | |||
7 | /* | ||
8 | * Copyright (C) 2000 - 2005, 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 | |||
45 | #include <acpi/acpi.h> | ||
46 | #include <acpi/actables.h> | ||
47 | |||
48 | |||
49 | #define _COMPONENT ACPI_TABLES | ||
50 | ACPI_MODULE_NAME ("tbrsdt") | ||
51 | |||
52 | |||
53 | /******************************************************************************* | ||
54 | * | ||
55 | * FUNCTION: acpi_tb_verify_rsdp | ||
56 | * | ||
57 | * PARAMETERS: Address - RSDP (Pointer to RSDT) | ||
58 | * | ||
59 | * RETURN: Status | ||
60 | * | ||
61 | * DESCRIPTION: Load and validate the RSDP (ptr) and RSDT (table) | ||
62 | * | ||
63 | ******************************************************************************/ | ||
64 | |||
65 | acpi_status | ||
66 | acpi_tb_verify_rsdp ( | ||
67 | struct acpi_pointer *address) | ||
68 | { | ||
69 | struct acpi_table_desc table_info; | ||
70 | acpi_status status; | ||
71 | struct rsdp_descriptor *rsdp; | ||
72 | |||
73 | |||
74 | ACPI_FUNCTION_TRACE ("tb_verify_rsdp"); | ||
75 | |||
76 | |||
77 | switch (address->pointer_type) { | ||
78 | case ACPI_LOGICAL_POINTER: | ||
79 | |||
80 | rsdp = address->pointer.logical; | ||
81 | break; | ||
82 | |||
83 | case ACPI_PHYSICAL_POINTER: | ||
84 | /* | ||
85 | * Obtain access to the RSDP structure | ||
86 | */ | ||
87 | status = acpi_os_map_memory (address->pointer.physical, sizeof (struct rsdp_descriptor), | ||
88 | (void *) &rsdp); | ||
89 | if (ACPI_FAILURE (status)) { | ||
90 | return_ACPI_STATUS (status); | ||
91 | } | ||
92 | break; | ||
93 | |||
94 | default: | ||
95 | return_ACPI_STATUS (AE_BAD_PARAMETER); | ||
96 | } | ||
97 | |||
98 | /* | ||
99 | * The signature and checksum must both be correct | ||
100 | */ | ||
101 | if (ACPI_STRNCMP ((char *) rsdp, RSDP_SIG, sizeof (RSDP_SIG)-1) != 0) { | ||
102 | /* Nope, BAD Signature */ | ||
103 | |||
104 | status = AE_BAD_SIGNATURE; | ||
105 | goto cleanup; | ||
106 | } | ||
107 | |||
108 | /* Check the standard checksum */ | ||
109 | |||
110 | if (acpi_tb_checksum (rsdp, ACPI_RSDP_CHECKSUM_LENGTH) != 0) { | ||
111 | status = AE_BAD_CHECKSUM; | ||
112 | goto cleanup; | ||
113 | } | ||
114 | |||
115 | /* Check extended checksum if table version >= 2 */ | ||
116 | |||
117 | if (rsdp->revision >= 2) { | ||
118 | if (acpi_tb_checksum (rsdp, ACPI_RSDP_XCHECKSUM_LENGTH) != 0) { | ||
119 | status = AE_BAD_CHECKSUM; | ||
120 | goto cleanup; | ||
121 | } | ||
122 | } | ||
123 | |||
124 | /* The RSDP supplied is OK */ | ||
125 | |||
126 | table_info.pointer = ACPI_CAST_PTR (struct acpi_table_header, rsdp); | ||
127 | table_info.length = sizeof (struct rsdp_descriptor); | ||
128 | table_info.allocation = ACPI_MEM_MAPPED; | ||
129 | |||
130 | /* Save the table pointers and allocation info */ | ||
131 | |||
132 | status = acpi_tb_init_table_descriptor (ACPI_TABLE_RSDP, &table_info); | ||
133 | if (ACPI_FAILURE (status)) { | ||
134 | goto cleanup; | ||
135 | } | ||
136 | |||
137 | /* Save the RSDP in a global for easy access */ | ||
138 | |||
139 | acpi_gbl_RSDP = ACPI_CAST_PTR (struct rsdp_descriptor, table_info.pointer); | ||
140 | return_ACPI_STATUS (status); | ||
141 | |||
142 | |||
143 | /* Error exit */ | ||
144 | cleanup: | ||
145 | |||
146 | if (acpi_gbl_table_flags & ACPI_PHYSICAL_POINTER) { | ||
147 | acpi_os_unmap_memory (rsdp, sizeof (struct rsdp_descriptor)); | ||
148 | } | ||
149 | return_ACPI_STATUS (status); | ||
150 | } | ||
151 | |||
152 | |||
153 | /******************************************************************************* | ||
154 | * | ||
155 | * FUNCTION: acpi_tb_get_rsdt_address | ||
156 | * | ||
157 | * PARAMETERS: None | ||
158 | * | ||
159 | * RETURN: RSDT physical address | ||
160 | * | ||
161 | * DESCRIPTION: Extract the address of the RSDT or XSDT, depending on the | ||
162 | * version of the RSDP | ||
163 | * | ||
164 | ******************************************************************************/ | ||
165 | |||
166 | void | ||
167 | acpi_tb_get_rsdt_address ( | ||
168 | struct acpi_pointer *out_address) | ||
169 | { | ||
170 | |||
171 | ACPI_FUNCTION_ENTRY (); | ||
172 | |||
173 | |||
174 | out_address->pointer_type = acpi_gbl_table_flags | ACPI_LOGICAL_ADDRESSING; | ||
175 | |||
176 | /* | ||
177 | * For RSDP revision 0 or 1, we use the RSDT. | ||
178 | * For RSDP revision 2 (and above), we use the XSDT | ||
179 | */ | ||
180 | if (acpi_gbl_RSDP->revision < 2) { | ||
181 | out_address->pointer.value = acpi_gbl_RSDP->rsdt_physical_address; | ||
182 | } | ||
183 | else { | ||
184 | out_address->pointer.value = acpi_gbl_RSDP->xsdt_physical_address; | ||
185 | } | ||
186 | } | ||
187 | |||
188 | |||
189 | /******************************************************************************* | ||
190 | * | ||
191 | * FUNCTION: acpi_tb_validate_rsdt | ||
192 | * | ||
193 | * PARAMETERS: table_ptr - Addressable pointer to the RSDT. | ||
194 | * | ||
195 | * RETURN: Status | ||
196 | * | ||
197 | * DESCRIPTION: Validate signature for the RSDT or XSDT | ||
198 | * | ||
199 | ******************************************************************************/ | ||
200 | |||
201 | acpi_status | ||
202 | acpi_tb_validate_rsdt ( | ||
203 | struct acpi_table_header *table_ptr) | ||
204 | { | ||
205 | int no_match; | ||
206 | |||
207 | |||
208 | ACPI_FUNCTION_NAME ("tb_validate_rsdt"); | ||
209 | |||
210 | |||
211 | /* | ||
212 | * For RSDP revision 0 or 1, we use the RSDT. | ||
213 | * For RSDP revision 2 and above, we use the XSDT | ||
214 | */ | ||
215 | if (acpi_gbl_RSDP->revision < 2) { | ||
216 | no_match = ACPI_STRNCMP ((char *) table_ptr, RSDT_SIG, | ||
217 | sizeof (RSDT_SIG) -1); | ||
218 | } | ||
219 | else { | ||
220 | no_match = ACPI_STRNCMP ((char *) table_ptr, XSDT_SIG, | ||
221 | sizeof (XSDT_SIG) -1); | ||
222 | } | ||
223 | |||
224 | if (no_match) { | ||
225 | /* Invalid RSDT or XSDT signature */ | ||
226 | |||
227 | ACPI_REPORT_ERROR (("Invalid signature where RSDP indicates RSDT/XSDT should be located\n")); | ||
228 | |||
229 | ACPI_DUMP_BUFFER (acpi_gbl_RSDP, 20); | ||
230 | |||
231 | ACPI_DEBUG_PRINT_RAW ((ACPI_DB_ERROR, | ||
232 | "RSDT/XSDT signature at %X (%p) is invalid\n", | ||
233 | acpi_gbl_RSDP->rsdt_physical_address, | ||
234 | (void *) (acpi_native_uint) acpi_gbl_RSDP->rsdt_physical_address)); | ||
235 | |||
236 | if (acpi_gbl_RSDP->revision < 2) { | ||
237 | ACPI_REPORT_ERROR (("Looking for RSDT (RSDP->Rev < 2)\n")) | ||
238 | } | ||
239 | else { | ||
240 | ACPI_REPORT_ERROR (("Looking for XSDT (RSDP->Rev >= 2)\n")) | ||
241 | } | ||
242 | |||
243 | ACPI_DUMP_BUFFER ((char *) table_ptr, 48); | ||
244 | |||
245 | return (AE_BAD_SIGNATURE); | ||
246 | } | ||
247 | |||
248 | return (AE_OK); | ||
249 | } | ||
250 | |||
251 | |||
252 | /******************************************************************************* | ||
253 | * | ||
254 | * FUNCTION: acpi_tb_get_table_rsdt | ||
255 | * | ||
256 | * PARAMETERS: None | ||
257 | * | ||
258 | * RETURN: Status | ||
259 | * | ||
260 | * DESCRIPTION: Load and validate the RSDP (ptr) and RSDT (table) | ||
261 | * | ||
262 | ******************************************************************************/ | ||
263 | |||
264 | acpi_status | ||
265 | acpi_tb_get_table_rsdt ( | ||
266 | void) | ||
267 | { | ||
268 | struct acpi_table_desc table_info; | ||
269 | acpi_status status; | ||
270 | struct acpi_pointer address; | ||
271 | |||
272 | |||
273 | ACPI_FUNCTION_TRACE ("tb_get_table_rsdt"); | ||
274 | |||
275 | |||
276 | /* Get the RSDT/XSDT via the RSDP */ | ||
277 | |||
278 | acpi_tb_get_rsdt_address (&address); | ||
279 | |||
280 | table_info.type = ACPI_TABLE_XSDT; | ||
281 | status = acpi_tb_get_table (&address, &table_info); | ||
282 | if (ACPI_FAILURE (status)) { | ||
283 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not get the RSDT/XSDT, %s\n", | ||
284 | acpi_format_exception (status))); | ||
285 | return_ACPI_STATUS (status); | ||
286 | } | ||
287 | |||
288 | ACPI_DEBUG_PRINT ((ACPI_DB_INFO, | ||
289 | "RSDP located at %p, points to RSDT physical=%8.8X%8.8X \n", | ||
290 | acpi_gbl_RSDP, | ||
291 | ACPI_FORMAT_UINT64 (address.pointer.value))); | ||
292 | |||
293 | /* Check the RSDT or XSDT signature */ | ||
294 | |||
295 | status = acpi_tb_validate_rsdt (table_info.pointer); | ||
296 | if (ACPI_FAILURE (status)) { | ||
297 | return_ACPI_STATUS (status); | ||
298 | } | ||
299 | |||
300 | /* Get the number of tables defined in the RSDT or XSDT */ | ||
301 | |||
302 | acpi_gbl_rsdt_table_count = acpi_tb_get_table_count (acpi_gbl_RSDP, table_info.pointer); | ||
303 | |||
304 | /* Convert and/or copy to an XSDT structure */ | ||
305 | |||
306 | status = acpi_tb_convert_to_xsdt (&table_info); | ||
307 | if (ACPI_FAILURE (status)) { | ||
308 | return_ACPI_STATUS (status); | ||
309 | } | ||
310 | |||
311 | /* Save the table pointers and allocation info */ | ||
312 | |||
313 | status = acpi_tb_init_table_descriptor (ACPI_TABLE_XSDT, &table_info); | ||
314 | if (ACPI_FAILURE (status)) { | ||
315 | return_ACPI_STATUS (status); | ||
316 | } | ||
317 | |||
318 | acpi_gbl_XSDT = ACPI_CAST_PTR (XSDT_DESCRIPTOR, table_info.pointer); | ||
319 | |||
320 | ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "XSDT located at %p\n", acpi_gbl_XSDT)); | ||
321 | return_ACPI_STATUS (status); | ||
322 | } | ||
323 | |||
324 | |||
diff --git a/drivers/acpi/tables/tbutils.c b/drivers/acpi/tables/tbutils.c new file mode 100644 index 00000000000..fede5804c78 --- /dev/null +++ b/drivers/acpi/tables/tbutils.c | |||
@@ -0,0 +1,240 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Module Name: tbutils - Table manipulation utilities | ||
4 | * | ||
5 | *****************************************************************************/ | ||
6 | |||
7 | /* | ||
8 | * Copyright (C) 2000 - 2005, 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 | |||
45 | #include <acpi/acpi.h> | ||
46 | #include <acpi/actables.h> | ||
47 | |||
48 | |||
49 | #define _COMPONENT ACPI_TABLES | ||
50 | ACPI_MODULE_NAME ("tbutils") | ||
51 | |||
52 | |||
53 | /******************************************************************************* | ||
54 | * | ||
55 | * FUNCTION: acpi_tb_handle_to_object | ||
56 | * | ||
57 | * PARAMETERS: table_id - Id for which the function is searching | ||
58 | * table_desc - Pointer to return the matching table | ||
59 | * descriptor. | ||
60 | * | ||
61 | * RETURN: Search the tables to find one with a matching table_id and | ||
62 | * return a pointer to that table descriptor. | ||
63 | * | ||
64 | ******************************************************************************/ | ||
65 | #ifdef ACPI_FUTURE_USAGE | ||
66 | acpi_status | ||
67 | acpi_tb_handle_to_object ( | ||
68 | u16 table_id, | ||
69 | struct acpi_table_desc **return_table_desc) | ||
70 | { | ||
71 | u32 i; | ||
72 | struct acpi_table_desc *table_desc; | ||
73 | |||
74 | |||
75 | ACPI_FUNCTION_NAME ("tb_handle_to_object"); | ||
76 | |||
77 | |||
78 | for (i = 0; i < ACPI_TABLE_MAX; i++) { | ||
79 | table_desc = acpi_gbl_table_lists[i].next; | ||
80 | while (table_desc) { | ||
81 | if (table_desc->table_id == table_id) { | ||
82 | *return_table_desc = table_desc; | ||
83 | return (AE_OK); | ||
84 | } | ||
85 | |||
86 | table_desc = table_desc->next; | ||
87 | } | ||
88 | } | ||
89 | |||
90 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "table_id=%X does not exist\n", table_id)); | ||
91 | return (AE_BAD_PARAMETER); | ||
92 | } | ||
93 | #endif /* ACPI_FUTURE_USAGE */ | ||
94 | |||
95 | |||
96 | /******************************************************************************* | ||
97 | * | ||
98 | * FUNCTION: acpi_tb_validate_table_header | ||
99 | * | ||
100 | * PARAMETERS: table_header - Logical pointer to the table | ||
101 | * | ||
102 | * RETURN: Status | ||
103 | * | ||
104 | * DESCRIPTION: Check an ACPI table header for validity | ||
105 | * | ||
106 | * NOTE: Table pointers are validated as follows: | ||
107 | * 1) Table pointer must point to valid physical memory | ||
108 | * 2) Signature must be 4 ASCII chars, even if we don't recognize the | ||
109 | * name | ||
110 | * 3) Table must be readable for length specified in the header | ||
111 | * 4) Table checksum must be valid (with the exception of the FACS | ||
112 | * which has no checksum because it contains variable fields) | ||
113 | * | ||
114 | ******************************************************************************/ | ||
115 | |||
116 | acpi_status | ||
117 | acpi_tb_validate_table_header ( | ||
118 | struct acpi_table_header *table_header) | ||
119 | { | ||
120 | acpi_name signature; | ||
121 | |||
122 | |||
123 | ACPI_FUNCTION_NAME ("tb_validate_table_header"); | ||
124 | |||
125 | |||
126 | /* Verify that this is a valid address */ | ||
127 | |||
128 | if (!acpi_os_readable (table_header, sizeof (struct acpi_table_header))) { | ||
129 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, | ||
130 | "Cannot read table header at %p\n", table_header)); | ||
131 | return (AE_BAD_ADDRESS); | ||
132 | } | ||
133 | |||
134 | /* Ensure that the signature is 4 ASCII characters */ | ||
135 | |||
136 | ACPI_MOVE_32_TO_32 (&signature, table_header->signature); | ||
137 | if (!acpi_ut_valid_acpi_name (signature)) { | ||
138 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, | ||
139 | "Table signature at %p [%p] has invalid characters\n", | ||
140 | table_header, &signature)); | ||
141 | |||
142 | ACPI_REPORT_WARNING (("Invalid table signature found: [%4.4s]\n", | ||
143 | (char *) &signature)); | ||
144 | ACPI_DUMP_BUFFER (table_header, sizeof (struct acpi_table_header)); | ||
145 | return (AE_BAD_SIGNATURE); | ||
146 | } | ||
147 | |||
148 | /* Validate the table length */ | ||
149 | |||
150 | if (table_header->length < sizeof (struct acpi_table_header)) { | ||
151 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, | ||
152 | "Invalid length in table header %p name %4.4s\n", | ||
153 | table_header, (char *) &signature)); | ||
154 | |||
155 | ACPI_REPORT_WARNING (("Invalid table header length (0x%X) found\n", | ||
156 | (u32) table_header->length)); | ||
157 | ACPI_DUMP_BUFFER (table_header, sizeof (struct acpi_table_header)); | ||
158 | return (AE_BAD_HEADER); | ||
159 | } | ||
160 | |||
161 | return (AE_OK); | ||
162 | } | ||
163 | |||
164 | |||
165 | /******************************************************************************* | ||
166 | * | ||
167 | * FUNCTION: acpi_tb_verify_table_checksum | ||
168 | * | ||
169 | * PARAMETERS: *table_header - ACPI table to verify | ||
170 | * | ||
171 | * RETURN: 8 bit checksum of table | ||
172 | * | ||
173 | * DESCRIPTION: Does an 8 bit checksum of table and returns status. A correct | ||
174 | * table should have a checksum of 0. | ||
175 | * | ||
176 | ******************************************************************************/ | ||
177 | |||
178 | acpi_status | ||
179 | acpi_tb_verify_table_checksum ( | ||
180 | struct acpi_table_header *table_header) | ||
181 | { | ||
182 | u8 checksum; | ||
183 | acpi_status status = AE_OK; | ||
184 | |||
185 | |||
186 | ACPI_FUNCTION_TRACE ("tb_verify_table_checksum"); | ||
187 | |||
188 | |||
189 | /* Compute the checksum on the table */ | ||
190 | |||
191 | checksum = acpi_tb_checksum (table_header, table_header->length); | ||
192 | |||
193 | /* Return the appropriate exception */ | ||
194 | |||
195 | if (checksum) { | ||
196 | ACPI_REPORT_WARNING (("Invalid checksum in table [%4.4s] (%02X, sum %02X is not zero)\n", | ||
197 | table_header->signature, (u32) table_header->checksum, (u32) checksum)); | ||
198 | |||
199 | status = AE_BAD_CHECKSUM; | ||
200 | } | ||
201 | return_ACPI_STATUS (status); | ||
202 | } | ||
203 | |||
204 | |||
205 | /******************************************************************************* | ||
206 | * | ||
207 | * FUNCTION: acpi_tb_checksum | ||
208 | * | ||
209 | * PARAMETERS: Buffer - Buffer to checksum | ||
210 | * Length - Size of the buffer | ||
211 | * | ||
212 | * RETURNS 8 bit checksum of buffer | ||
213 | * | ||
214 | * DESCRIPTION: Computes an 8 bit checksum of the buffer(length) and returns it. | ||
215 | * | ||
216 | ******************************************************************************/ | ||
217 | |||
218 | u8 | ||
219 | acpi_tb_checksum ( | ||
220 | void *buffer, | ||
221 | u32 length) | ||
222 | { | ||
223 | const u8 *limit; | ||
224 | const u8 *rover; | ||
225 | u8 sum = 0; | ||
226 | |||
227 | |||
228 | if (buffer && length) { | ||
229 | /* Buffer and Length are valid */ | ||
230 | |||
231 | limit = (u8 *) buffer + length; | ||
232 | |||
233 | for (rover = buffer; rover < limit; rover++) { | ||
234 | sum = (u8) (sum + *rover); | ||
235 | } | ||
236 | } | ||
237 | return (sum); | ||
238 | } | ||
239 | |||
240 | |||
diff --git a/drivers/acpi/tables/tbxface.c b/drivers/acpi/tables/tbxface.c new file mode 100644 index 00000000000..7715043461c --- /dev/null +++ b/drivers/acpi/tables/tbxface.c | |||
@@ -0,0 +1,448 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Module Name: tbxface - Public interfaces to the ACPI subsystem | ||
4 | * ACPI table oriented interfaces | ||
5 | * | ||
6 | *****************************************************************************/ | ||
7 | |||
8 | /* | ||
9 | * Copyright (C) 2000 - 2005, R. Byron Moore | ||
10 | * All rights reserved. | ||
11 | * | ||
12 | * Redistribution and use in source and binary forms, with or without | ||
13 | * modification, are permitted provided that the following conditions | ||
14 | * are met: | ||
15 | * 1. Redistributions of source code must retain the above copyright | ||
16 | * notice, this list of conditions, and the following disclaimer, | ||
17 | * without modification. | ||
18 | * 2. Redistributions in binary form must reproduce at minimum a disclaimer | ||
19 | * substantially similar to the "NO WARRANTY" disclaimer below | ||
20 | * ("Disclaimer") and any redistribution must be conditioned upon | ||
21 | * including a substantially similar Disclaimer requirement for further | ||
22 | * binary redistribution. | ||
23 | * 3. Neither the names of the above-listed copyright holders nor the names | ||
24 | * of any contributors may be used to endorse or promote products derived | ||
25 | * from this software without specific prior written permission. | ||
26 | * | ||
27 | * Alternatively, this software may be distributed under the terms of the | ||
28 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
29 | * Software Foundation. | ||
30 | * | ||
31 | * NO WARRANTY | ||
32 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
33 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
34 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR | ||
35 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
36 | * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
37 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
38 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
39 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | ||
40 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING | ||
41 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
42 | * POSSIBILITY OF SUCH DAMAGES. | ||
43 | */ | ||
44 | |||
45 | #include <linux/module.h> | ||
46 | |||
47 | #include <acpi/acpi.h> | ||
48 | #include <acpi/acnamesp.h> | ||
49 | #include <acpi/actables.h> | ||
50 | |||
51 | |||
52 | #define _COMPONENT ACPI_TABLES | ||
53 | ACPI_MODULE_NAME ("tbxface") | ||
54 | |||
55 | |||
56 | /******************************************************************************* | ||
57 | * | ||
58 | * FUNCTION: acpi_load_tables | ||
59 | * | ||
60 | * PARAMETERS: None | ||
61 | * | ||
62 | * RETURN: Status | ||
63 | * | ||
64 | * DESCRIPTION: This function is called to load the ACPI tables from the | ||
65 | * provided RSDT | ||
66 | * | ||
67 | ******************************************************************************/ | ||
68 | |||
69 | acpi_status | ||
70 | acpi_load_tables (void) | ||
71 | { | ||
72 | struct acpi_pointer rsdp_address; | ||
73 | acpi_status status; | ||
74 | |||
75 | |||
76 | ACPI_FUNCTION_TRACE ("acpi_load_tables"); | ||
77 | |||
78 | |||
79 | /* Get the RSDP */ | ||
80 | |||
81 | status = acpi_os_get_root_pointer (ACPI_LOGICAL_ADDRESSING, | ||
82 | &rsdp_address); | ||
83 | if (ACPI_FAILURE (status)) { | ||
84 | ACPI_REPORT_ERROR (("acpi_load_tables: Could not get RSDP, %s\n", | ||
85 | acpi_format_exception (status))); | ||
86 | goto error_exit; | ||
87 | } | ||
88 | |||
89 | /* Map and validate the RSDP */ | ||
90 | |||
91 | acpi_gbl_table_flags = rsdp_address.pointer_type; | ||
92 | |||
93 | status = acpi_tb_verify_rsdp (&rsdp_address); | ||
94 | if (ACPI_FAILURE (status)) { | ||
95 | ACPI_REPORT_ERROR (("acpi_load_tables: RSDP Failed validation: %s\n", | ||
96 | acpi_format_exception (status))); | ||
97 | goto error_exit; | ||
98 | } | ||
99 | |||
100 | /* Get the RSDT via the RSDP */ | ||
101 | |||
102 | status = acpi_tb_get_table_rsdt (); | ||
103 | if (ACPI_FAILURE (status)) { | ||
104 | ACPI_REPORT_ERROR (("acpi_load_tables: Could not load RSDT: %s\n", | ||
105 | acpi_format_exception (status))); | ||
106 | goto error_exit; | ||
107 | } | ||
108 | |||
109 | /* Now get the tables needed by this subsystem (FADT, DSDT, etc.) */ | ||
110 | |||
111 | status = acpi_tb_get_required_tables (); | ||
112 | if (ACPI_FAILURE (status)) { | ||
113 | ACPI_REPORT_ERROR (("acpi_load_tables: Error getting required tables (DSDT/FADT/FACS): %s\n", | ||
114 | acpi_format_exception (status))); | ||
115 | goto error_exit; | ||
116 | } | ||
117 | |||
118 | ACPI_DEBUG_PRINT ((ACPI_DB_INIT, "ACPI Tables successfully acquired\n")); | ||
119 | |||
120 | |||
121 | /* Load the namespace from the tables */ | ||
122 | |||
123 | status = acpi_ns_load_namespace (); | ||
124 | if (ACPI_FAILURE (status)) { | ||
125 | ACPI_REPORT_ERROR (("acpi_load_tables: Could not load namespace: %s\n", | ||
126 | acpi_format_exception (status))); | ||
127 | goto error_exit; | ||
128 | } | ||
129 | |||
130 | return_ACPI_STATUS (AE_OK); | ||
131 | |||
132 | |||
133 | error_exit: | ||
134 | ACPI_REPORT_ERROR (("acpi_load_tables: Could not load tables: %s\n", | ||
135 | acpi_format_exception (status))); | ||
136 | |||
137 | return_ACPI_STATUS (status); | ||
138 | } | ||
139 | |||
140 | |||
141 | #ifdef ACPI_FUTURE_USAGE | ||
142 | |||
143 | /******************************************************************************* | ||
144 | * | ||
145 | * FUNCTION: acpi_load_table | ||
146 | * | ||
147 | * PARAMETERS: table_ptr - pointer to a buffer containing the entire | ||
148 | * table to be loaded | ||
149 | * | ||
150 | * RETURN: Status | ||
151 | * | ||
152 | * DESCRIPTION: This function is called to load a table from the caller's | ||
153 | * buffer. The buffer must contain an entire ACPI Table including | ||
154 | * a valid header. The header fields will be verified, and if it | ||
155 | * is determined that the table is invalid, the call will fail. | ||
156 | * | ||
157 | ******************************************************************************/ | ||
158 | |||
159 | acpi_status | ||
160 | acpi_load_table ( | ||
161 | struct acpi_table_header *table_ptr) | ||
162 | { | ||
163 | acpi_status status; | ||
164 | struct acpi_table_desc table_info; | ||
165 | struct acpi_pointer address; | ||
166 | |||
167 | |||
168 | ACPI_FUNCTION_TRACE ("acpi_load_table"); | ||
169 | |||
170 | |||
171 | if (!table_ptr) { | ||
172 | return_ACPI_STATUS (AE_BAD_PARAMETER); | ||
173 | } | ||
174 | |||
175 | /* Copy the table to a local buffer */ | ||
176 | |||
177 | address.pointer_type = ACPI_LOGICAL_POINTER | ACPI_LOGICAL_ADDRESSING; | ||
178 | address.pointer.logical = table_ptr; | ||
179 | |||
180 | status = acpi_tb_get_table_body (&address, table_ptr, &table_info); | ||
181 | if (ACPI_FAILURE (status)) { | ||
182 | return_ACPI_STATUS (status); | ||
183 | } | ||
184 | |||
185 | /* Install the new table into the local data structures */ | ||
186 | |||
187 | status = acpi_tb_install_table (&table_info); | ||
188 | if (ACPI_FAILURE (status)) { | ||
189 | /* Free table allocated by acpi_tb_get_table_body */ | ||
190 | |||
191 | acpi_tb_delete_single_table (&table_info); | ||
192 | return_ACPI_STATUS (status); | ||
193 | } | ||
194 | |||
195 | /* Convert the table to common format if necessary */ | ||
196 | |||
197 | switch (table_info.type) { | ||
198 | case ACPI_TABLE_FADT: | ||
199 | |||
200 | status = acpi_tb_convert_table_fadt (); | ||
201 | break; | ||
202 | |||
203 | case ACPI_TABLE_FACS: | ||
204 | |||
205 | status = acpi_tb_build_common_facs (&table_info); | ||
206 | break; | ||
207 | |||
208 | default: | ||
209 | /* Load table into namespace if it contains executable AML */ | ||
210 | |||
211 | status = acpi_ns_load_table (table_info.installed_desc, acpi_gbl_root_node); | ||
212 | break; | ||
213 | } | ||
214 | |||
215 | if (ACPI_FAILURE (status)) { | ||
216 | /* Uninstall table and free the buffer */ | ||
217 | |||
218 | (void) acpi_tb_uninstall_table (table_info.installed_desc); | ||
219 | } | ||
220 | |||
221 | return_ACPI_STATUS (status); | ||
222 | } | ||
223 | |||
224 | |||
225 | /******************************************************************************* | ||
226 | * | ||
227 | * FUNCTION: acpi_unload_table | ||
228 | * | ||
229 | * PARAMETERS: table_type - Type of table to be unloaded | ||
230 | * | ||
231 | * RETURN: Status | ||
232 | * | ||
233 | * DESCRIPTION: This routine is used to force the unload of a table | ||
234 | * | ||
235 | ******************************************************************************/ | ||
236 | |||
237 | acpi_status | ||
238 | acpi_unload_table ( | ||
239 | acpi_table_type table_type) | ||
240 | { | ||
241 | struct acpi_table_desc *table_desc; | ||
242 | |||
243 | |||
244 | ACPI_FUNCTION_TRACE ("acpi_unload_table"); | ||
245 | |||
246 | |||
247 | /* Parameter validation */ | ||
248 | |||
249 | if (table_type > ACPI_TABLE_MAX) { | ||
250 | return_ACPI_STATUS (AE_BAD_PARAMETER); | ||
251 | } | ||
252 | |||
253 | |||
254 | /* Find all tables of the requested type */ | ||
255 | |||
256 | table_desc = acpi_gbl_table_lists[table_type].next; | ||
257 | while (table_desc) { | ||
258 | /* | ||
259 | * Delete all namespace entries owned by this table. Note that these | ||
260 | * entries can appear anywhere in the namespace by virtue of the AML | ||
261 | * "Scope" operator. Thus, we need to track ownership by an ID, not | ||
262 | * simply a position within the hierarchy | ||
263 | */ | ||
264 | acpi_ns_delete_namespace_by_owner (table_desc->table_id); | ||
265 | |||
266 | table_desc = table_desc->next; | ||
267 | } | ||
268 | |||
269 | /* Delete (or unmap) all tables of this type */ | ||
270 | |||
271 | acpi_tb_delete_tables_by_type (table_type); | ||
272 | return_ACPI_STATUS (AE_OK); | ||
273 | } | ||
274 | |||
275 | |||
276 | /******************************************************************************* | ||
277 | * | ||
278 | * FUNCTION: acpi_get_table_header | ||
279 | * | ||
280 | * PARAMETERS: table_type - one of the defined table types | ||
281 | * Instance - the non zero instance of the table, allows | ||
282 | * support for multiple tables of the same type | ||
283 | * see acpi_gbl_acpi_table_flag | ||
284 | * out_table_header - pointer to the struct acpi_table_header if successful | ||
285 | * | ||
286 | * DESCRIPTION: This function is called to get an ACPI table header. The caller | ||
287 | * supplies an pointer to a data area sufficient to contain an ACPI | ||
288 | * struct acpi_table_header structure. | ||
289 | * | ||
290 | * The header contains a length field that can be used to determine | ||
291 | * the size of the buffer needed to contain the entire table. This | ||
292 | * function is not valid for the RSD PTR table since it does not | ||
293 | * have a standard header and is fixed length. | ||
294 | * | ||
295 | ******************************************************************************/ | ||
296 | |||
297 | acpi_status | ||
298 | acpi_get_table_header ( | ||
299 | acpi_table_type table_type, | ||
300 | u32 instance, | ||
301 | struct acpi_table_header *out_table_header) | ||
302 | { | ||
303 | struct acpi_table_header *tbl_ptr; | ||
304 | acpi_status status; | ||
305 | |||
306 | |||
307 | ACPI_FUNCTION_TRACE ("acpi_get_table_header"); | ||
308 | |||
309 | |||
310 | if ((instance == 0) || | ||
311 | (table_type == ACPI_TABLE_RSDP) || | ||
312 | (!out_table_header)) { | ||
313 | return_ACPI_STATUS (AE_BAD_PARAMETER); | ||
314 | } | ||
315 | |||
316 | /* Check the table type and instance */ | ||
317 | |||
318 | if ((table_type > ACPI_TABLE_MAX) || | ||
319 | (ACPI_IS_SINGLE_TABLE (acpi_gbl_table_data[table_type].flags) && | ||
320 | instance > 1)) { | ||
321 | return_ACPI_STATUS (AE_BAD_PARAMETER); | ||
322 | } | ||
323 | |||
324 | |||
325 | /* Get a pointer to the entire table */ | ||
326 | |||
327 | status = acpi_tb_get_table_ptr (table_type, instance, &tbl_ptr); | ||
328 | if (ACPI_FAILURE (status)) { | ||
329 | return_ACPI_STATUS (status); | ||
330 | } | ||
331 | |||
332 | /* | ||
333 | * The function will return a NULL pointer if the table is not loaded | ||
334 | */ | ||
335 | if (tbl_ptr == NULL) { | ||
336 | return_ACPI_STATUS (AE_NOT_EXIST); | ||
337 | } | ||
338 | |||
339 | /* | ||
340 | * Copy the header to the caller's buffer | ||
341 | */ | ||
342 | ACPI_MEMCPY ((void *) out_table_header, (void *) tbl_ptr, | ||
343 | sizeof (struct acpi_table_header)); | ||
344 | |||
345 | return_ACPI_STATUS (status); | ||
346 | } | ||
347 | |||
348 | |||
349 | #endif /* ACPI_FUTURE_USAGE */ | ||
350 | |||
351 | /******************************************************************************* | ||
352 | * | ||
353 | * FUNCTION: acpi_get_table | ||
354 | * | ||
355 | * PARAMETERS: table_type - one of the defined table types | ||
356 | * Instance - the non zero instance of the table, allows | ||
357 | * support for multiple tables of the same type | ||
358 | * see acpi_gbl_acpi_table_flag | ||
359 | * ret_buffer - pointer to a structure containing a buffer to | ||
360 | * receive the table | ||
361 | * | ||
362 | * RETURN: Status | ||
363 | * | ||
364 | * DESCRIPTION: This function is called to get an ACPI table. The caller | ||
365 | * supplies an out_buffer large enough to contain the entire ACPI | ||
366 | * table. The caller should call the acpi_get_table_header function | ||
367 | * first to determine the buffer size needed. Upon completion | ||
368 | * the out_buffer->Length field will indicate the number of bytes | ||
369 | * copied into the out_buffer->buf_ptr buffer. This table will be | ||
370 | * a complete table including the header. | ||
371 | * | ||
372 | ******************************************************************************/ | ||
373 | |||
374 | acpi_status | ||
375 | acpi_get_table ( | ||
376 | acpi_table_type table_type, | ||
377 | u32 instance, | ||
378 | struct acpi_buffer *ret_buffer) | ||
379 | { | ||
380 | struct acpi_table_header *tbl_ptr; | ||
381 | acpi_status status; | ||
382 | acpi_size table_length; | ||
383 | |||
384 | |||
385 | ACPI_FUNCTION_TRACE ("acpi_get_table"); | ||
386 | |||
387 | |||
388 | /* Parameter validation */ | ||
389 | |||
390 | if (instance == 0) { | ||
391 | return_ACPI_STATUS (AE_BAD_PARAMETER); | ||
392 | } | ||
393 | |||
394 | status = acpi_ut_validate_buffer (ret_buffer); | ||
395 | if (ACPI_FAILURE (status)) { | ||
396 | return_ACPI_STATUS (status); | ||
397 | } | ||
398 | |||
399 | /* Check the table type and instance */ | ||
400 | |||
401 | if ((table_type > ACPI_TABLE_MAX) || | ||
402 | (ACPI_IS_SINGLE_TABLE (acpi_gbl_table_data[table_type].flags) && | ||
403 | instance > 1)) { | ||
404 | return_ACPI_STATUS (AE_BAD_PARAMETER); | ||
405 | } | ||
406 | |||
407 | |||
408 | /* Get a pointer to the entire table */ | ||
409 | |||
410 | status = acpi_tb_get_table_ptr (table_type, instance, &tbl_ptr); | ||
411 | if (ACPI_FAILURE (status)) { | ||
412 | return_ACPI_STATUS (status); | ||
413 | } | ||
414 | |||
415 | /* | ||
416 | * acpi_tb_get_table_ptr will return a NULL pointer if the | ||
417 | * table is not loaded. | ||
418 | */ | ||
419 | if (tbl_ptr == NULL) { | ||
420 | return_ACPI_STATUS (AE_NOT_EXIST); | ||
421 | } | ||
422 | |||
423 | /* Get the table length */ | ||
424 | |||
425 | if (table_type == ACPI_TABLE_RSDP) { | ||
426 | /* | ||
427 | * RSD PTR is the only "table" without a header | ||
428 | */ | ||
429 | table_length = sizeof (struct rsdp_descriptor); | ||
430 | } | ||
431 | else { | ||
432 | table_length = (acpi_size) tbl_ptr->length; | ||
433 | } | ||
434 | |||
435 | /* Validate/Allocate/Clear caller buffer */ | ||
436 | |||
437 | status = acpi_ut_initialize_buffer (ret_buffer, table_length); | ||
438 | if (ACPI_FAILURE (status)) { | ||
439 | return_ACPI_STATUS (status); | ||
440 | } | ||
441 | |||
442 | /* Copy the table to the buffer */ | ||
443 | |||
444 | ACPI_MEMCPY ((void *) ret_buffer->pointer, (void *) tbl_ptr, table_length); | ||
445 | return_ACPI_STATUS (AE_OK); | ||
446 | } | ||
447 | EXPORT_SYMBOL(acpi_get_table); | ||
448 | |||
diff --git a/drivers/acpi/tables/tbxfroot.c b/drivers/acpi/tables/tbxfroot.c new file mode 100644 index 00000000000..6e8072ebbac --- /dev/null +++ b/drivers/acpi/tables/tbxfroot.c | |||
@@ -0,0 +1,606 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Module Name: tbxfroot - Find the root ACPI table (RSDT) | ||
4 | * | ||
5 | *****************************************************************************/ | ||
6 | |||
7 | /* | ||
8 | * Copyright (C) 2000 - 2005, 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 <linux/module.h> | ||
45 | |||
46 | #include <acpi/acpi.h> | ||
47 | #include <acpi/actables.h> | ||
48 | |||
49 | |||
50 | #define _COMPONENT ACPI_TABLES | ||
51 | ACPI_MODULE_NAME ("tbxfroot") | ||
52 | |||
53 | |||
54 | /******************************************************************************* | ||
55 | * | ||
56 | * FUNCTION: acpi_tb_find_table | ||
57 | * | ||
58 | * PARAMETERS: Signature - String with ACPI table signature | ||
59 | * oem_id - String with the table OEM ID | ||
60 | * oem_table_id - String with the OEM Table ID. | ||
61 | * | ||
62 | * RETURN: Status | ||
63 | * | ||
64 | * DESCRIPTION: Find an ACPI table (in the RSDT/XSDT) that matches the | ||
65 | * Signature, OEM ID and OEM Table ID. | ||
66 | * | ||
67 | ******************************************************************************/ | ||
68 | |||
69 | acpi_status | ||
70 | acpi_tb_find_table ( | ||
71 | char *signature, | ||
72 | char *oem_id, | ||
73 | char *oem_table_id, | ||
74 | struct acpi_table_header **table_ptr) | ||
75 | { | ||
76 | acpi_status status; | ||
77 | struct acpi_table_header *table; | ||
78 | |||
79 | |||
80 | ACPI_FUNCTION_TRACE ("tb_find_table"); | ||
81 | |||
82 | |||
83 | /* Validate string lengths */ | ||
84 | |||
85 | if ((ACPI_STRLEN (signature) > ACPI_NAME_SIZE) || | ||
86 | (ACPI_STRLEN (oem_id) > sizeof (table->oem_id)) || | ||
87 | (ACPI_STRLEN (oem_table_id) > sizeof (table->oem_table_id))) { | ||
88 | return_ACPI_STATUS (AE_AML_STRING_LIMIT); | ||
89 | } | ||
90 | |||
91 | if (!ACPI_STRNCMP (signature, DSDT_SIG, ACPI_NAME_SIZE)) { | ||
92 | /* | ||
93 | * The DSDT pointer is contained in the FADT, not the RSDT. | ||
94 | * This code should suffice, because the only code that would perform | ||
95 | * a "find" on the DSDT is the data_table_region() AML opcode -- in | ||
96 | * which case, the DSDT is guaranteed to be already loaded. | ||
97 | * If this becomes insufficient, the FADT will have to be found first. | ||
98 | */ | ||
99 | if (!acpi_gbl_DSDT) { | ||
100 | return_ACPI_STATUS (AE_NO_ACPI_TABLES); | ||
101 | } | ||
102 | |||
103 | table = acpi_gbl_DSDT; | ||
104 | } | ||
105 | else { | ||
106 | /* Find the table */ | ||
107 | |||
108 | status = acpi_get_firmware_table (signature, 1, | ||
109 | ACPI_LOGICAL_ADDRESSING, &table); | ||
110 | if (ACPI_FAILURE (status)) { | ||
111 | return_ACPI_STATUS (status); | ||
112 | } | ||
113 | } | ||
114 | |||
115 | /* Check oem_id and oem_table_id */ | ||
116 | |||
117 | if ((oem_id[0] && ACPI_STRNCMP ( | ||
118 | oem_id, table->oem_id, sizeof (table->oem_id))) || | ||
119 | (oem_table_id[0] && ACPI_STRNCMP ( | ||
120 | oem_table_id, table->oem_table_id, sizeof (table->oem_table_id)))) { | ||
121 | return_ACPI_STATUS (AE_AML_NAME_NOT_FOUND); | ||
122 | } | ||
123 | |||
124 | ACPI_DEBUG_PRINT ((ACPI_DB_TABLES, "Found table [%4.4s]\n", table->signature)); | ||
125 | *table_ptr = table; | ||
126 | return_ACPI_STATUS (AE_OK); | ||
127 | } | ||
128 | |||
129 | |||
130 | /******************************************************************************* | ||
131 | * | ||
132 | * FUNCTION: acpi_get_firmware_table | ||
133 | * | ||
134 | * PARAMETERS: Signature - Any ACPI table signature | ||
135 | * Instance - the non zero instance of the table, allows | ||
136 | * support for multiple tables of the same type | ||
137 | * Flags - Physical/Virtual support | ||
138 | * table_pointer - Where a buffer containing the table is | ||
139 | * returned | ||
140 | * | ||
141 | * RETURN: Status | ||
142 | * | ||
143 | * DESCRIPTION: This function is called to get an ACPI table. A buffer is | ||
144 | * allocated for the table and returned in table_pointer. | ||
145 | * This table will be a complete table including the header. | ||
146 | * | ||
147 | ******************************************************************************/ | ||
148 | |||
149 | acpi_status | ||
150 | acpi_get_firmware_table ( | ||
151 | acpi_string signature, | ||
152 | u32 instance, | ||
153 | u32 flags, | ||
154 | struct acpi_table_header **table_pointer) | ||
155 | { | ||
156 | acpi_status status; | ||
157 | struct acpi_pointer address; | ||
158 | struct acpi_table_header *header = NULL; | ||
159 | struct acpi_table_desc *table_info = NULL; | ||
160 | struct acpi_table_desc *rsdt_info; | ||
161 | u32 table_count; | ||
162 | u32 i; | ||
163 | u32 j; | ||
164 | |||
165 | |||
166 | ACPI_FUNCTION_TRACE ("acpi_get_firmware_table"); | ||
167 | |||
168 | |||
169 | /* | ||
170 | * Ensure that at least the table manager is initialized. We don't | ||
171 | * require that the entire ACPI subsystem is up for this interface. | ||
172 | * If we have a buffer, we must have a length too | ||
173 | */ | ||
174 | if ((instance == 0) || | ||
175 | (!signature) || | ||
176 | (!table_pointer)) { | ||
177 | return_ACPI_STATUS (AE_BAD_PARAMETER); | ||
178 | } | ||
179 | |||
180 | /* Ensure that we have a RSDP */ | ||
181 | |||
182 | if (!acpi_gbl_RSDP) { | ||
183 | /* Get the RSDP */ | ||
184 | |||
185 | status = acpi_os_get_root_pointer (flags, &address); | ||
186 | if (ACPI_FAILURE (status)) { | ||
187 | ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "RSDP not found\n")); | ||
188 | return_ACPI_STATUS (AE_NO_ACPI_TABLES); | ||
189 | } | ||
190 | |||
191 | /* Map and validate the RSDP */ | ||
192 | |||
193 | if ((flags & ACPI_MEMORY_MODE) == ACPI_LOGICAL_ADDRESSING) { | ||
194 | status = acpi_os_map_memory (address.pointer.physical, sizeof (struct rsdp_descriptor), | ||
195 | (void *) &acpi_gbl_RSDP); | ||
196 | if (ACPI_FAILURE (status)) { | ||
197 | return_ACPI_STATUS (status); | ||
198 | } | ||
199 | } | ||
200 | else { | ||
201 | acpi_gbl_RSDP = address.pointer.logical; | ||
202 | } | ||
203 | |||
204 | /* The signature and checksum must both be correct */ | ||
205 | |||
206 | if (ACPI_STRNCMP ((char *) acpi_gbl_RSDP, RSDP_SIG, sizeof (RSDP_SIG)-1) != 0) { | ||
207 | /* Nope, BAD Signature */ | ||
208 | |||
209 | return_ACPI_STATUS (AE_BAD_SIGNATURE); | ||
210 | } | ||
211 | |||
212 | if (acpi_tb_checksum (acpi_gbl_RSDP, ACPI_RSDP_CHECKSUM_LENGTH) != 0) { | ||
213 | /* Nope, BAD Checksum */ | ||
214 | |||
215 | return_ACPI_STATUS (AE_BAD_CHECKSUM); | ||
216 | } | ||
217 | } | ||
218 | |||
219 | /* Get the RSDT address via the RSDP */ | ||
220 | |||
221 | acpi_tb_get_rsdt_address (&address); | ||
222 | ACPI_DEBUG_PRINT ((ACPI_DB_INFO, | ||
223 | "RSDP located at %p, RSDT physical=%8.8X%8.8X \n", | ||
224 | acpi_gbl_RSDP, | ||
225 | ACPI_FORMAT_UINT64 (address.pointer.value))); | ||
226 | |||
227 | /* Insert processor_mode flags */ | ||
228 | |||
229 | address.pointer_type |= flags; | ||
230 | |||
231 | /* Get and validate the RSDT */ | ||
232 | |||
233 | rsdt_info = ACPI_MEM_CALLOCATE (sizeof (struct acpi_table_desc)); | ||
234 | if (!rsdt_info) { | ||
235 | return_ACPI_STATUS (AE_NO_MEMORY); | ||
236 | } | ||
237 | |||
238 | status = acpi_tb_get_table (&address, rsdt_info); | ||
239 | if (ACPI_FAILURE (status)) { | ||
240 | goto cleanup; | ||
241 | } | ||
242 | |||
243 | status = acpi_tb_validate_rsdt (rsdt_info->pointer); | ||
244 | if (ACPI_FAILURE (status)) { | ||
245 | goto cleanup; | ||
246 | } | ||
247 | |||
248 | /* Allocate a scratch table header and table descriptor */ | ||
249 | |||
250 | header = ACPI_MEM_ALLOCATE (sizeof (struct acpi_table_header)); | ||
251 | if (!header) { | ||
252 | status = AE_NO_MEMORY; | ||
253 | goto cleanup; | ||
254 | } | ||
255 | |||
256 | table_info = ACPI_MEM_ALLOCATE (sizeof (struct acpi_table_desc)); | ||
257 | if (!table_info) { | ||
258 | status = AE_NO_MEMORY; | ||
259 | goto cleanup; | ||
260 | } | ||
261 | |||
262 | /* Get the number of table pointers within the RSDT */ | ||
263 | |||
264 | table_count = acpi_tb_get_table_count (acpi_gbl_RSDP, rsdt_info->pointer); | ||
265 | address.pointer_type = acpi_gbl_table_flags | flags; | ||
266 | |||
267 | /* | ||
268 | * Search the RSDT/XSDT for the correct instance of the | ||
269 | * requested table | ||
270 | */ | ||
271 | for (i = 0, j = 0; i < table_count; i++) { | ||
272 | /* Get the next table pointer, handle RSDT vs. XSDT */ | ||
273 | |||
274 | if (acpi_gbl_RSDP->revision < 2) { | ||
275 | address.pointer.value = (ACPI_CAST_PTR ( | ||
276 | RSDT_DESCRIPTOR, rsdt_info->pointer))->table_offset_entry[i]; | ||
277 | } | ||
278 | else { | ||
279 | address.pointer.value = (ACPI_CAST_PTR ( | ||
280 | XSDT_DESCRIPTOR, rsdt_info->pointer))->table_offset_entry[i]; | ||
281 | } | ||
282 | |||
283 | /* Get the table header */ | ||
284 | |||
285 | status = acpi_tb_get_table_header (&address, header); | ||
286 | if (ACPI_FAILURE (status)) { | ||
287 | goto cleanup; | ||
288 | } | ||
289 | |||
290 | /* Compare table signatures and table instance */ | ||
291 | |||
292 | if (!ACPI_STRNCMP (header->signature, signature, ACPI_NAME_SIZE)) { | ||
293 | /* An instance of the table was found */ | ||
294 | |||
295 | j++; | ||
296 | if (j >= instance) { | ||
297 | /* Found the correct instance, get the entire table */ | ||
298 | |||
299 | status = acpi_tb_get_table_body (&address, header, table_info); | ||
300 | if (ACPI_FAILURE (status)) { | ||
301 | goto cleanup; | ||
302 | } | ||
303 | |||
304 | *table_pointer = table_info->pointer; | ||
305 | goto cleanup; | ||
306 | } | ||
307 | } | ||
308 | } | ||
309 | |||
310 | /* Did not find the table */ | ||
311 | |||
312 | status = AE_NOT_EXIST; | ||
313 | |||
314 | |||
315 | cleanup: | ||
316 | acpi_os_unmap_memory (rsdt_info->pointer, (acpi_size) rsdt_info->pointer->length); | ||
317 | ACPI_MEM_FREE (rsdt_info); | ||
318 | |||
319 | if (header) { | ||
320 | ACPI_MEM_FREE (header); | ||
321 | } | ||
322 | if (table_info) { | ||
323 | ACPI_MEM_FREE (table_info); | ||
324 | } | ||
325 | return_ACPI_STATUS (status); | ||
326 | } | ||
327 | EXPORT_SYMBOL(acpi_get_firmware_table); | ||
328 | |||
329 | |||
330 | /* TBD: Move to a new file */ | ||
331 | |||
332 | #if ACPI_MACHINE_WIDTH != 16 | ||
333 | |||
334 | /******************************************************************************* | ||
335 | * | ||
336 | * FUNCTION: acpi_find_root_pointer | ||
337 | * | ||
338 | * PARAMETERS: **rsdp_address - Where to place the RSDP address | ||
339 | * Flags - Logical/Physical addressing | ||
340 | * | ||
341 | * RETURN: Status, Physical address of the RSDP | ||
342 | * | ||
343 | * DESCRIPTION: Find the RSDP | ||
344 | * | ||
345 | ******************************************************************************/ | ||
346 | |||
347 | acpi_status | ||
348 | acpi_find_root_pointer ( | ||
349 | u32 flags, | ||
350 | struct acpi_pointer *rsdp_address) | ||
351 | { | ||
352 | struct acpi_table_desc table_info; | ||
353 | acpi_status status; | ||
354 | |||
355 | |||
356 | ACPI_FUNCTION_TRACE ("acpi_find_root_pointer"); | ||
357 | |||
358 | |||
359 | /* Get the RSDP */ | ||
360 | |||
361 | status = acpi_tb_find_rsdp (&table_info, flags); | ||
362 | if (ACPI_FAILURE (status)) { | ||
363 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, | ||
364 | "RSDP structure not found, %s Flags=%X\n", | ||
365 | acpi_format_exception (status), flags)); | ||
366 | return_ACPI_STATUS (AE_NO_ACPI_TABLES); | ||
367 | } | ||
368 | |||
369 | rsdp_address->pointer_type = ACPI_PHYSICAL_POINTER; | ||
370 | rsdp_address->pointer.physical = table_info.physical_address; | ||
371 | return_ACPI_STATUS (AE_OK); | ||
372 | } | ||
373 | |||
374 | |||
375 | /******************************************************************************* | ||
376 | * | ||
377 | * FUNCTION: acpi_tb_scan_memory_for_rsdp | ||
378 | * | ||
379 | * PARAMETERS: start_address - Starting pointer for search | ||
380 | * Length - Maximum length to search | ||
381 | * | ||
382 | * RETURN: Pointer to the RSDP if found, otherwise NULL. | ||
383 | * | ||
384 | * DESCRIPTION: Search a block of memory for the RSDP signature | ||
385 | * | ||
386 | ******************************************************************************/ | ||
387 | |||
388 | u8 * | ||
389 | acpi_tb_scan_memory_for_rsdp ( | ||
390 | u8 *start_address, | ||
391 | u32 length) | ||
392 | { | ||
393 | u8 *mem_rover; | ||
394 | u8 *end_address; | ||
395 | u8 checksum; | ||
396 | |||
397 | |||
398 | ACPI_FUNCTION_TRACE ("tb_scan_memory_for_rsdp"); | ||
399 | |||
400 | |||
401 | end_address = start_address + length; | ||
402 | |||
403 | /* Search from given start address for the requested length */ | ||
404 | |||
405 | for (mem_rover = start_address; mem_rover < end_address; | ||
406 | mem_rover += ACPI_RSDP_SCAN_STEP) { | ||
407 | /* The signature and checksum must both be correct */ | ||
408 | |||
409 | if (ACPI_STRNCMP ((char *) mem_rover, RSDP_SIG, sizeof (RSDP_SIG)-1) != 0) { | ||
410 | /* No signature match, keep looking */ | ||
411 | |||
412 | continue; | ||
413 | } | ||
414 | |||
415 | /* Signature matches, check the appropriate checksum */ | ||
416 | |||
417 | if ((ACPI_CAST_PTR (struct rsdp_descriptor, mem_rover))->revision < 2) { | ||
418 | /* ACPI version 1.0 */ | ||
419 | |||
420 | checksum = acpi_tb_checksum (mem_rover, ACPI_RSDP_CHECKSUM_LENGTH); | ||
421 | } | ||
422 | else { | ||
423 | /* Post ACPI 1.0, use extended_checksum */ | ||
424 | |||
425 | checksum = acpi_tb_checksum (mem_rover, ACPI_RSDP_XCHECKSUM_LENGTH); | ||
426 | } | ||
427 | |||
428 | if (checksum == 0) { | ||
429 | /* Checksum valid, we have found a valid RSDP */ | ||
430 | |||
431 | ACPI_DEBUG_PRINT ((ACPI_DB_INFO, | ||
432 | "RSDP located at physical address %p\n", mem_rover)); | ||
433 | return_PTR (mem_rover); | ||
434 | } | ||
435 | |||
436 | ACPI_DEBUG_PRINT ((ACPI_DB_INFO, | ||
437 | "Found an RSDP at physical address %p, but it has a bad checksum\n", | ||
438 | mem_rover)); | ||
439 | } | ||
440 | |||
441 | /* Searched entire block, no RSDP was found */ | ||
442 | |||
443 | ACPI_DEBUG_PRINT ((ACPI_DB_INFO, | ||
444 | "Searched entire block, no valid RSDP was found.\n")); | ||
445 | return_PTR (NULL); | ||
446 | } | ||
447 | |||
448 | |||
449 | /******************************************************************************* | ||
450 | * | ||
451 | * FUNCTION: acpi_tb_find_rsdp | ||
452 | * | ||
453 | * PARAMETERS: *table_info - Where the table info is returned | ||
454 | * Flags - Current memory mode (logical vs. | ||
455 | * physical addressing) | ||
456 | * | ||
457 | * RETURN: Status, RSDP physical address | ||
458 | * | ||
459 | * DESCRIPTION: search lower 1_mbyte of memory for the root system descriptor | ||
460 | * pointer structure. If it is found, set *RSDP to point to it. | ||
461 | * | ||
462 | * NOTE1: The RSDp must be either in the first 1_k of the Extended | ||
463 | * BIOS Data Area or between E0000 and FFFFF (From ACPI Spec.) | ||
464 | * Only a 32-bit physical address is necessary. | ||
465 | * | ||
466 | * NOTE2: This function is always available, regardless of the | ||
467 | * initialization state of the rest of ACPI. | ||
468 | * | ||
469 | ******************************************************************************/ | ||
470 | |||
471 | acpi_status | ||
472 | acpi_tb_find_rsdp ( | ||
473 | struct acpi_table_desc *table_info, | ||
474 | u32 flags) | ||
475 | { | ||
476 | u8 *table_ptr; | ||
477 | u8 *mem_rover; | ||
478 | u32 physical_address; | ||
479 | acpi_status status; | ||
480 | |||
481 | |||
482 | ACPI_FUNCTION_TRACE ("tb_find_rsdp"); | ||
483 | |||
484 | |||
485 | /* | ||
486 | * Scan supports either 1) Logical addressing or 2) Physical addressing | ||
487 | */ | ||
488 | if ((flags & ACPI_MEMORY_MODE) == ACPI_LOGICAL_ADDRESSING) { | ||
489 | /* | ||
490 | * 1a) Get the location of the EBDA | ||
491 | */ | ||
492 | status = acpi_os_map_memory ((acpi_physical_address) ACPI_EBDA_PTR_LOCATION, | ||
493 | ACPI_EBDA_PTR_LENGTH, | ||
494 | (void *) &table_ptr); | ||
495 | if (ACPI_FAILURE (status)) { | ||
496 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, | ||
497 | "Could not map memory at %8.8X for length %X\n", | ||
498 | ACPI_EBDA_PTR_LOCATION, ACPI_EBDA_PTR_LENGTH)); | ||
499 | return_ACPI_STATUS (status); | ||
500 | } | ||
501 | |||
502 | ACPI_MOVE_16_TO_32 (&physical_address, table_ptr); | ||
503 | physical_address <<= 4; /* Convert segment to physical address */ | ||
504 | acpi_os_unmap_memory (table_ptr, ACPI_EBDA_PTR_LENGTH); | ||
505 | |||
506 | /* EBDA present? */ | ||
507 | |||
508 | if (physical_address > 0x400) { | ||
509 | /* | ||
510 | * 1b) Search EBDA paragraphs (EBDa is required to be a minimum of 1_k length) | ||
511 | */ | ||
512 | status = acpi_os_map_memory ((acpi_physical_address) physical_address, | ||
513 | ACPI_EBDA_WINDOW_SIZE, | ||
514 | (void *) &table_ptr); | ||
515 | if (ACPI_FAILURE (status)) { | ||
516 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, | ||
517 | "Could not map memory at %8.8X for length %X\n", | ||
518 | physical_address, ACPI_EBDA_WINDOW_SIZE)); | ||
519 | return_ACPI_STATUS (status); | ||
520 | } | ||
521 | |||
522 | mem_rover = acpi_tb_scan_memory_for_rsdp (table_ptr, ACPI_EBDA_WINDOW_SIZE); | ||
523 | acpi_os_unmap_memory (table_ptr, ACPI_EBDA_WINDOW_SIZE); | ||
524 | |||
525 | if (mem_rover) { | ||
526 | /* Found it, return the physical address */ | ||
527 | |||
528 | physical_address += ACPI_PTR_DIFF (mem_rover, table_ptr); | ||
529 | |||
530 | table_info->physical_address = (acpi_physical_address) physical_address; | ||
531 | return_ACPI_STATUS (AE_OK); | ||
532 | } | ||
533 | } | ||
534 | |||
535 | /* | ||
536 | * 2) Search upper memory: 16-byte boundaries in E0000h-FFFFFh | ||
537 | */ | ||
538 | status = acpi_os_map_memory ((acpi_physical_address) ACPI_HI_RSDP_WINDOW_BASE, | ||
539 | ACPI_HI_RSDP_WINDOW_SIZE, | ||
540 | (void *) &table_ptr); | ||
541 | if (ACPI_FAILURE (status)) { | ||
542 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, | ||
543 | "Could not map memory at %8.8X for length %X\n", | ||
544 | ACPI_HI_RSDP_WINDOW_BASE, ACPI_HI_RSDP_WINDOW_SIZE)); | ||
545 | return_ACPI_STATUS (status); | ||
546 | } | ||
547 | |||
548 | mem_rover = acpi_tb_scan_memory_for_rsdp (table_ptr, ACPI_HI_RSDP_WINDOW_SIZE); | ||
549 | acpi_os_unmap_memory (table_ptr, ACPI_HI_RSDP_WINDOW_SIZE); | ||
550 | |||
551 | if (mem_rover) { | ||
552 | /* Found it, return the physical address */ | ||
553 | |||
554 | physical_address = ACPI_HI_RSDP_WINDOW_BASE + ACPI_PTR_DIFF (mem_rover, table_ptr); | ||
555 | |||
556 | table_info->physical_address = (acpi_physical_address) physical_address; | ||
557 | return_ACPI_STATUS (AE_OK); | ||
558 | } | ||
559 | } | ||
560 | |||
561 | /* | ||
562 | * Physical addressing | ||
563 | */ | ||
564 | else { | ||
565 | /* | ||
566 | * 1a) Get the location of the EBDA | ||
567 | */ | ||
568 | ACPI_MOVE_16_TO_32 (&physical_address, ACPI_EBDA_PTR_LOCATION); | ||
569 | physical_address <<= 4; /* Convert segment to physical address */ | ||
570 | |||
571 | /* EBDA present? */ | ||
572 | |||
573 | if (physical_address > 0x400) { | ||
574 | /* | ||
575 | * 1b) Search EBDA paragraphs (EBDa is required to be a minimum of 1_k length) | ||
576 | */ | ||
577 | mem_rover = acpi_tb_scan_memory_for_rsdp (ACPI_PHYSADDR_TO_PTR (physical_address), | ||
578 | ACPI_EBDA_WINDOW_SIZE); | ||
579 | if (mem_rover) { | ||
580 | /* Found it, return the physical address */ | ||
581 | |||
582 | table_info->physical_address = ACPI_TO_INTEGER (mem_rover); | ||
583 | return_ACPI_STATUS (AE_OK); | ||
584 | } | ||
585 | } | ||
586 | |||
587 | /* | ||
588 | * 2) Search upper memory: 16-byte boundaries in E0000h-FFFFFh | ||
589 | */ | ||
590 | mem_rover = acpi_tb_scan_memory_for_rsdp (ACPI_PHYSADDR_TO_PTR (ACPI_HI_RSDP_WINDOW_BASE), | ||
591 | ACPI_HI_RSDP_WINDOW_SIZE); | ||
592 | if (mem_rover) { | ||
593 | /* Found it, return the physical address */ | ||
594 | |||
595 | table_info->physical_address = ACPI_TO_INTEGER (mem_rover); | ||
596 | return_ACPI_STATUS (AE_OK); | ||
597 | } | ||
598 | } | ||
599 | |||
600 | /* RSDP signature was not found */ | ||
601 | |||
602 | return_ACPI_STATUS (AE_NOT_FOUND); | ||
603 | } | ||
604 | |||
605 | #endif | ||
606 | |||