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/tbconvrt.c |
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/tbconvrt.c')
-rw-r--r-- | drivers/acpi/tables/tbconvrt.c | 564 |
1 files changed, 564 insertions, 0 deletions
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 | |||