Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /****************************************************************************** |
2 | * | |
3 | * Module Name: tbconvrt - ACPI Table conversion utilities | |
4 | * | |
5 | *****************************************************************************/ | |
6 | ||
7 | /* | |
4a90c7e8 | 8 | * Copyright (C) 2000 - 2006, R. Byron Moore |
1da177e4 LT |
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 | ||
1da177e4 | 49 | #define _COMPONENT ACPI_TABLES |
4be44fcd | 50 | ACPI_MODULE_NAME("tbconvrt") |
1da177e4 | 51 | |
44f6c012 | 52 | /* Local prototypes */ |
44f6c012 | 53 | static void |
4be44fcd LB |
54 | acpi_tb_init_generic_address(struct acpi_generic_address *new_gas_struct, |
55 | u8 register_bit_width, | |
56 | acpi_physical_address address); | |
44f6c012 RM |
57 | |
58 | static void | |
4be44fcd LB |
59 | acpi_tb_convert_fadt1(struct fadt_descriptor_rev2 *local_fadt, |
60 | struct fadt_descriptor_rev1 *original_fadt); | |
44f6c012 RM |
61 | |
62 | static void | |
4be44fcd LB |
63 | acpi_tb_convert_fadt2(struct fadt_descriptor_rev2 *local_fadt, |
64 | struct fadt_descriptor_rev2 *original_fadt); | |
1da177e4 LT |
65 | |
66 | u8 acpi_fadt_is_v1; | |
67 | EXPORT_SYMBOL(acpi_fadt_is_v1); | |
68 | ||
69 | /******************************************************************************* | |
70 | * | |
71 | * FUNCTION: acpi_tb_get_table_count | |
72 | * | |
73 | * PARAMETERS: RSDP - Pointer to the RSDP | |
74 | * RSDT - Pointer to the RSDT/XSDT | |
75 | * | |
76 | * RETURN: The number of tables pointed to by the RSDT or XSDT. | |
77 | * | |
78 | * DESCRIPTION: Calculate the number of tables. Automatically handles either | |
79 | * an RSDT or XSDT. | |
80 | * | |
81 | ******************************************************************************/ | |
82 | ||
83 | u32 | |
4be44fcd LB |
84 | acpi_tb_get_table_count(struct rsdp_descriptor *RSDP, |
85 | struct acpi_table_header *RSDT) | |
1da177e4 | 86 | { |
4be44fcd | 87 | u32 pointer_size; |
1da177e4 | 88 | |
4be44fcd | 89 | ACPI_FUNCTION_ENTRY(); |
1da177e4 | 90 | |
73459f73 RM |
91 | /* RSDT pointers are 32 bits, XSDT pointers are 64 bits */ |
92 | ||
93 | if (acpi_gbl_root_table_type == ACPI_TABLE_TYPE_RSDT) { | |
4be44fcd LB |
94 | pointer_size = sizeof(u32); |
95 | } else { | |
96 | pointer_size = sizeof(u64); | |
1da177e4 LT |
97 | } |
98 | ||
99 | /* | |
100 | * Determine the number of tables pointed to by the RSDT/XSDT. | |
101 | * This is defined by the ACPI Specification to be the number of | |
102 | * pointers contained within the RSDT/XSDT. The size of the pointers | |
103 | * is architecture-dependent. | |
104 | */ | |
4be44fcd LB |
105 | return ((RSDT->length - |
106 | sizeof(struct acpi_table_header)) / pointer_size); | |
1da177e4 LT |
107 | } |
108 | ||
1da177e4 LT |
109 | /******************************************************************************* |
110 | * | |
111 | * FUNCTION: acpi_tb_convert_to_xsdt | |
112 | * | |
113 | * PARAMETERS: table_info - Info about the RSDT | |
114 | * | |
115 | * RETURN: Status | |
116 | * | |
117 | * DESCRIPTION: Convert an RSDT to an XSDT (internal common format) | |
118 | * | |
119 | ******************************************************************************/ | |
120 | ||
4be44fcd | 121 | acpi_status acpi_tb_convert_to_xsdt(struct acpi_table_desc *table_info) |
1da177e4 | 122 | { |
4be44fcd LB |
123 | acpi_size table_size; |
124 | u32 i; | |
125 | XSDT_DESCRIPTOR *new_table; | |
1da177e4 | 126 | |
4be44fcd | 127 | ACPI_FUNCTION_ENTRY(); |
1da177e4 LT |
128 | |
129 | /* Compute size of the converted XSDT */ | |
130 | ||
4be44fcd LB |
131 | table_size = ((acpi_size) acpi_gbl_rsdt_table_count * sizeof(u64)) + |
132 | sizeof(struct acpi_table_header); | |
1da177e4 LT |
133 | |
134 | /* Allocate an XSDT */ | |
135 | ||
4be44fcd | 136 | new_table = ACPI_MEM_CALLOCATE(table_size); |
1da177e4 LT |
137 | if (!new_table) { |
138 | return (AE_NO_MEMORY); | |
139 | } | |
140 | ||
141 | /* Copy the header and set the length */ | |
142 | ||
4be44fcd LB |
143 | ACPI_MEMCPY(new_table, table_info->pointer, |
144 | sizeof(struct acpi_table_header)); | |
1da177e4 LT |
145 | new_table->length = (u32) table_size; |
146 | ||
147 | /* Copy the table pointers */ | |
148 | ||
149 | for (i = 0; i < acpi_gbl_rsdt_table_count; i++) { | |
73459f73 RM |
150 | /* RSDT pointers are 32 bits, XSDT pointers are 64 bits */ |
151 | ||
152 | if (acpi_gbl_root_table_type == ACPI_TABLE_TYPE_RSDT) { | |
4be44fcd LB |
153 | ACPI_STORE_ADDRESS(new_table->table_offset_entry[i], |
154 | (ACPI_CAST_PTR | |
155 | (struct rsdt_descriptor_rev1, | |
156 | table_info->pointer))-> | |
157 | table_offset_entry[i]); | |
158 | } else { | |
1da177e4 | 159 | new_table->table_offset_entry[i] = |
4be44fcd LB |
160 | (ACPI_CAST_PTR(XSDT_DESCRIPTOR, |
161 | table_info->pointer))-> | |
162 | table_offset_entry[i]; | |
1da177e4 LT |
163 | } |
164 | } | |
165 | ||
166 | /* Delete the original table (either mapped or in a buffer) */ | |
167 | ||
4be44fcd | 168 | acpi_tb_delete_single_table(table_info); |
1da177e4 LT |
169 | |
170 | /* Point the table descriptor to the new table */ | |
171 | ||
4be44fcd LB |
172 | table_info->pointer = |
173 | ACPI_CAST_PTR(struct acpi_table_header, new_table); | |
174 | table_info->length = table_size; | |
175 | table_info->allocation = ACPI_MEM_ALLOCATED; | |
1da177e4 LT |
176 | |
177 | return (AE_OK); | |
178 | } | |
179 | ||
44f6c012 | 180 | /******************************************************************************* |
1da177e4 LT |
181 | * |
182 | * FUNCTION: acpi_tb_init_generic_address | |
183 | * | |
184 | * PARAMETERS: new_gas_struct - GAS struct to be initialized | |
185 | * register_bit_width - Width of this register | |
186 | * Address - Address of the register | |
187 | * | |
188 | * RETURN: None | |
189 | * | |
190 | * DESCRIPTION: Initialize a GAS structure. | |
191 | * | |
192 | ******************************************************************************/ | |
193 | ||
194 | static void | |
4be44fcd LB |
195 | acpi_tb_init_generic_address(struct acpi_generic_address *new_gas_struct, |
196 | u8 register_bit_width, | |
197 | acpi_physical_address address) | |
1da177e4 LT |
198 | { |
199 | ||
4be44fcd | 200 | ACPI_STORE_ADDRESS(new_gas_struct->address, address); |
1da177e4 LT |
201 | |
202 | new_gas_struct->address_space_id = ACPI_ADR_SPACE_SYSTEM_IO; | |
203 | new_gas_struct->register_bit_width = register_bit_width; | |
204 | new_gas_struct->register_bit_offset = 0; | |
4be44fcd | 205 | new_gas_struct->access_width = 0; |
1da177e4 LT |
206 | } |
207 | ||
1da177e4 LT |
208 | /******************************************************************************* |
209 | * | |
210 | * FUNCTION: acpi_tb_convert_fadt1 | |
211 | * | |
212 | * PARAMETERS: local_fadt - Pointer to new FADT | |
213 | * original_fadt - Pointer to old FADT | |
214 | * | |
44f6c012 | 215 | * RETURN: None, populates local_fadt |
1da177e4 LT |
216 | * |
217 | * DESCRIPTION: Convert an ACPI 1.0 FADT to common internal format | |
218 | * | |
219 | ******************************************************************************/ | |
220 | ||
221 | static void | |
4be44fcd LB |
222 | acpi_tb_convert_fadt1(struct fadt_descriptor_rev2 *local_fadt, |
223 | struct fadt_descriptor_rev1 *original_fadt) | |
1da177e4 LT |
224 | { |
225 | ||
1da177e4 LT |
226 | /* ACPI 1.0 FACS */ |
227 | /* The BIOS stored FADT should agree with Revision 1.0 */ | |
228 | acpi_fadt_is_v1 = 1; | |
229 | ||
230 | /* | |
231 | * Copy the table header and the common part of the tables. | |
232 | * | |
233 | * The 2.0 table is an extension of the 1.0 table, so the entire 1.0 | |
234 | * table can be copied first, then expand some fields to 64 bits. | |
235 | */ | |
4be44fcd LB |
236 | ACPI_MEMCPY(local_fadt, original_fadt, |
237 | sizeof(struct fadt_descriptor_rev1)); | |
1da177e4 LT |
238 | |
239 | /* Convert table pointers to 64-bit fields */ | |
240 | ||
4be44fcd LB |
241 | ACPI_STORE_ADDRESS(local_fadt->xfirmware_ctrl, |
242 | local_fadt->V1_firmware_ctrl); | |
243 | ACPI_STORE_ADDRESS(local_fadt->Xdsdt, local_fadt->V1_dsdt); | |
1da177e4 LT |
244 | |
245 | /* | |
44f6c012 RM |
246 | * System Interrupt Model isn't used in ACPI 2.0 |
247 | * (local_fadt->Reserved1 = 0;) | |
1da177e4 LT |
248 | */ |
249 | ||
250 | /* | |
251 | * This field is set by the OEM to convey the preferred power management | |
252 | * profile to OSPM. It doesn't have any 1.0 equivalence. Since we don't | |
253 | * know what kind of 32-bit system this is, we will use "unspecified". | |
254 | */ | |
255 | local_fadt->prefer_PM_profile = PM_UNSPECIFIED; | |
256 | ||
257 | /* | |
258 | * Processor Performance State Control. This is the value OSPM writes to | |
259 | * the SMI_CMD register to assume processor performance state control | |
260 | * responsibility. There isn't any equivalence in 1.0, but as many 1.x | |
261 | * ACPI tables contain _PCT and _PSS we also keep this value, unless | |
262 | * acpi_strict is set. | |
263 | */ | |
264 | if (acpi_strict) | |
265 | local_fadt->pstate_cnt = 0; | |
266 | ||
267 | /* | |
268 | * Support for the _CST object and C States change notification. | |
269 | * This data item hasn't any 1.0 equivalence so leave it zero. | |
270 | */ | |
271 | local_fadt->cst_cnt = 0; | |
272 | ||
273 | /* | |
274 | * FADT Rev 2 was an interim FADT released between ACPI 1.0 and ACPI 2.0. | |
275 | * It primarily adds the FADT reset mechanism. | |
276 | */ | |
277 | if ((original_fadt->revision == 2) && | |
4be44fcd LB |
278 | (original_fadt->length == |
279 | sizeof(struct fadt_descriptor_rev2_minus))) { | |
1da177e4 LT |
280 | /* |
281 | * Grab the entire generic address struct, plus the 1-byte reset value | |
282 | * that immediately follows. | |
283 | */ | |
4be44fcd LB |
284 | ACPI_MEMCPY(&local_fadt->reset_register, |
285 | &(ACPI_CAST_PTR(struct fadt_descriptor_rev2_minus, | |
286 | original_fadt))->reset_register, | |
287 | sizeof(struct acpi_generic_address) + 1); | |
288 | } else { | |
1da177e4 LT |
289 | /* |
290 | * Since there isn't any equivalence in 1.0 and since it is highly | |
291 | * likely that a 1.0 system has legacy support. | |
292 | */ | |
293 | local_fadt->iapc_boot_arch = BAF_LEGACY_DEVICES; | |
294 | } | |
295 | ||
296 | /* | |
297 | * Convert the V1.0 block addresses to V2.0 GAS structures | |
298 | */ | |
4be44fcd LB |
299 | acpi_tb_init_generic_address(&local_fadt->xpm1a_evt_blk, |
300 | local_fadt->pm1_evt_len, | |
301 | (acpi_physical_address) local_fadt-> | |
302 | V1_pm1a_evt_blk); | |
303 | acpi_tb_init_generic_address(&local_fadt->xpm1b_evt_blk, | |
304 | local_fadt->pm1_evt_len, | |
305 | (acpi_physical_address) local_fadt-> | |
306 | V1_pm1b_evt_blk); | |
307 | acpi_tb_init_generic_address(&local_fadt->xpm1a_cnt_blk, | |
308 | local_fadt->pm1_cnt_len, | |
309 | (acpi_physical_address) local_fadt-> | |
310 | V1_pm1a_cnt_blk); | |
311 | acpi_tb_init_generic_address(&local_fadt->xpm1b_cnt_blk, | |
312 | local_fadt->pm1_cnt_len, | |
313 | (acpi_physical_address) local_fadt-> | |
314 | V1_pm1b_cnt_blk); | |
315 | acpi_tb_init_generic_address(&local_fadt->xpm2_cnt_blk, | |
316 | local_fadt->pm2_cnt_len, | |
317 | (acpi_physical_address) local_fadt-> | |
318 | V1_pm2_cnt_blk); | |
319 | acpi_tb_init_generic_address(&local_fadt->xpm_tmr_blk, | |
320 | local_fadt->pm_tm_len, | |
321 | (acpi_physical_address) local_fadt-> | |
322 | V1_pm_tmr_blk); | |
323 | acpi_tb_init_generic_address(&local_fadt->xgpe0_blk, 0, | |
324 | (acpi_physical_address) local_fadt-> | |
325 | V1_gpe0_blk); | |
326 | acpi_tb_init_generic_address(&local_fadt->xgpe1_blk, 0, | |
327 | (acpi_physical_address) local_fadt-> | |
328 | V1_gpe1_blk); | |
1da177e4 LT |
329 | |
330 | /* Create separate GAS structs for the PM1 Enable registers */ | |
331 | ||
4be44fcd LB |
332 | acpi_tb_init_generic_address(&acpi_gbl_xpm1a_enable, |
333 | (u8) ACPI_DIV_2(acpi_gbl_FADT-> | |
334 | pm1_evt_len), | |
335 | (acpi_physical_address) | |
336 | (local_fadt->xpm1a_evt_blk.address + | |
337 | ACPI_DIV_2(acpi_gbl_FADT->pm1_evt_len))); | |
1da177e4 LT |
338 | |
339 | /* PM1B is optional; leave null if not present */ | |
340 | ||
341 | if (local_fadt->xpm1b_evt_blk.address) { | |
4be44fcd LB |
342 | acpi_tb_init_generic_address(&acpi_gbl_xpm1b_enable, |
343 | (u8) ACPI_DIV_2(acpi_gbl_FADT-> | |
344 | pm1_evt_len), | |
345 | (acpi_physical_address) | |
346 | (local_fadt->xpm1b_evt_blk. | |
347 | address + | |
348 | ACPI_DIV_2(acpi_gbl_FADT-> | |
349 | pm1_evt_len))); | |
1da177e4 LT |
350 | } |
351 | } | |
352 | ||
1da177e4 LT |
353 | /******************************************************************************* |
354 | * | |
355 | * FUNCTION: acpi_tb_convert_fadt2 | |
356 | * | |
357 | * PARAMETERS: local_fadt - Pointer to new FADT | |
358 | * original_fadt - Pointer to old FADT | |
359 | * | |
44f6c012 | 360 | * RETURN: None, populates local_fadt |
1da177e4 LT |
361 | * |
362 | * DESCRIPTION: Convert an ACPI 2.0 FADT to common internal format. | |
363 | * Handles optional "X" fields. | |
364 | * | |
365 | ******************************************************************************/ | |
366 | ||
367 | static void | |
4be44fcd LB |
368 | acpi_tb_convert_fadt2(struct fadt_descriptor_rev2 *local_fadt, |
369 | struct fadt_descriptor_rev2 *original_fadt) | |
1da177e4 LT |
370 | { |
371 | ||
372 | /* We have an ACPI 2.0 FADT but we must copy it to our local buffer */ | |
373 | ||
4be44fcd LB |
374 | ACPI_MEMCPY(local_fadt, original_fadt, |
375 | sizeof(struct fadt_descriptor_rev2)); | |
1da177e4 LT |
376 | |
377 | /* | |
378 | * "X" fields are optional extensions to the original V1.0 fields, so | |
379 | * we must selectively expand V1.0 fields if the corresponding X field | |
380 | * is zero. | |
381 | */ | |
382 | if (!(local_fadt->xfirmware_ctrl)) { | |
4be44fcd LB |
383 | ACPI_STORE_ADDRESS(local_fadt->xfirmware_ctrl, |
384 | local_fadt->V1_firmware_ctrl); | |
1da177e4 LT |
385 | } |
386 | ||
387 | if (!(local_fadt->Xdsdt)) { | |
4be44fcd | 388 | ACPI_STORE_ADDRESS(local_fadt->Xdsdt, local_fadt->V1_dsdt); |
1da177e4 LT |
389 | } |
390 | ||
391 | if (!(local_fadt->xpm1a_evt_blk.address)) { | |
4be44fcd LB |
392 | acpi_tb_init_generic_address(&local_fadt->xpm1a_evt_blk, |
393 | local_fadt->pm1_evt_len, | |
394 | (acpi_physical_address) | |
395 | local_fadt->V1_pm1a_evt_blk); | |
1da177e4 LT |
396 | } |
397 | ||
398 | if (!(local_fadt->xpm1b_evt_blk.address)) { | |
4be44fcd LB |
399 | acpi_tb_init_generic_address(&local_fadt->xpm1b_evt_blk, |
400 | local_fadt->pm1_evt_len, | |
401 | (acpi_physical_address) | |
402 | local_fadt->V1_pm1b_evt_blk); | |
1da177e4 LT |
403 | } |
404 | ||
405 | if (!(local_fadt->xpm1a_cnt_blk.address)) { | |
4be44fcd LB |
406 | acpi_tb_init_generic_address(&local_fadt->xpm1a_cnt_blk, |
407 | local_fadt->pm1_cnt_len, | |
408 | (acpi_physical_address) | |
409 | local_fadt->V1_pm1a_cnt_blk); | |
1da177e4 LT |
410 | } |
411 | ||
412 | if (!(local_fadt->xpm1b_cnt_blk.address)) { | |
4be44fcd LB |
413 | acpi_tb_init_generic_address(&local_fadt->xpm1b_cnt_blk, |
414 | local_fadt->pm1_cnt_len, | |
415 | (acpi_physical_address) | |
416 | local_fadt->V1_pm1b_cnt_blk); | |
1da177e4 LT |
417 | } |
418 | ||
419 | if (!(local_fadt->xpm2_cnt_blk.address)) { | |
4be44fcd LB |
420 | acpi_tb_init_generic_address(&local_fadt->xpm2_cnt_blk, |
421 | local_fadt->pm2_cnt_len, | |
422 | (acpi_physical_address) | |
423 | local_fadt->V1_pm2_cnt_blk); | |
1da177e4 LT |
424 | } |
425 | ||
426 | if (!(local_fadt->xpm_tmr_blk.address)) { | |
4be44fcd LB |
427 | acpi_tb_init_generic_address(&local_fadt->xpm_tmr_blk, |
428 | local_fadt->pm_tm_len, | |
429 | (acpi_physical_address) | |
430 | local_fadt->V1_pm_tmr_blk); | |
1da177e4 LT |
431 | } |
432 | ||
433 | if (!(local_fadt->xgpe0_blk.address)) { | |
4be44fcd LB |
434 | acpi_tb_init_generic_address(&local_fadt->xgpe0_blk, |
435 | 0, | |
436 | (acpi_physical_address) | |
437 | local_fadt->V1_gpe0_blk); | |
1da177e4 LT |
438 | } |
439 | ||
440 | if (!(local_fadt->xgpe1_blk.address)) { | |
4be44fcd LB |
441 | acpi_tb_init_generic_address(&local_fadt->xgpe1_blk, |
442 | 0, | |
443 | (acpi_physical_address) | |
444 | local_fadt->V1_gpe1_blk); | |
1da177e4 LT |
445 | } |
446 | ||
447 | /* Create separate GAS structs for the PM1 Enable registers */ | |
448 | ||
4be44fcd LB |
449 | acpi_tb_init_generic_address(&acpi_gbl_xpm1a_enable, |
450 | (u8) ACPI_DIV_2(acpi_gbl_FADT-> | |
451 | pm1_evt_len), | |
452 | (acpi_physical_address) | |
453 | (local_fadt->xpm1a_evt_blk.address + | |
454 | ACPI_DIV_2(acpi_gbl_FADT->pm1_evt_len))); | |
44f6c012 RM |
455 | |
456 | acpi_gbl_xpm1a_enable.address_space_id = | |
4be44fcd | 457 | local_fadt->xpm1a_evt_blk.address_space_id; |
1da177e4 LT |
458 | |
459 | /* PM1B is optional; leave null if not present */ | |
460 | ||
461 | if (local_fadt->xpm1b_evt_blk.address) { | |
4be44fcd LB |
462 | acpi_tb_init_generic_address(&acpi_gbl_xpm1b_enable, |
463 | (u8) ACPI_DIV_2(acpi_gbl_FADT-> | |
464 | pm1_evt_len), | |
465 | (acpi_physical_address) | |
466 | (local_fadt->xpm1b_evt_blk. | |
467 | address + | |
468 | ACPI_DIV_2(acpi_gbl_FADT-> | |
469 | pm1_evt_len))); | |
44f6c012 RM |
470 | |
471 | acpi_gbl_xpm1b_enable.address_space_id = | |
4be44fcd | 472 | local_fadt->xpm1b_evt_blk.address_space_id; |
1da177e4 LT |
473 | } |
474 | } | |
475 | ||
1da177e4 LT |
476 | /******************************************************************************* |
477 | * | |
478 | * FUNCTION: acpi_tb_convert_table_fadt | |
479 | * | |
480 | * PARAMETERS: None | |
481 | * | |
482 | * RETURN: Status | |
483 | * | |
484 | * DESCRIPTION: Converts a BIOS supplied ACPI 1.0 FADT to a local | |
485 | * ACPI 2.0 FADT. If the BIOS supplied a 2.0 FADT then it is simply | |
486 | * copied to the local FADT. The ACPI CA software uses this | |
487 | * local FADT. Thus a significant amount of special #ifdef | |
488 | * type codeing is saved. | |
489 | * | |
490 | ******************************************************************************/ | |
491 | ||
4be44fcd | 492 | acpi_status acpi_tb_convert_table_fadt(void) |
1da177e4 | 493 | { |
4be44fcd LB |
494 | struct fadt_descriptor_rev2 *local_fadt; |
495 | struct acpi_table_desc *table_desc; | |
1da177e4 | 496 | |
4be44fcd | 497 | ACPI_FUNCTION_TRACE("tb_convert_table_fadt"); |
1da177e4 LT |
498 | |
499 | /* | |
500 | * acpi_gbl_FADT is valid. Validate the FADT length. The table must be | |
501 | * at least as long as the version 1.0 FADT | |
502 | */ | |
4be44fcd | 503 | if (acpi_gbl_FADT->length < sizeof(struct fadt_descriptor_rev1)) { |
b8e4d893 BM |
504 | ACPI_ERROR((AE_INFO, "FADT is invalid, too short: 0x%X", |
505 | acpi_gbl_FADT->length)); | |
4be44fcd | 506 | return_ACPI_STATUS(AE_INVALID_TABLE_LENGTH); |
1da177e4 LT |
507 | } |
508 | ||
509 | /* Allocate buffer for the ACPI 2.0(+) FADT */ | |
510 | ||
4be44fcd | 511 | local_fadt = ACPI_MEM_CALLOCATE(sizeof(struct fadt_descriptor_rev2)); |
1da177e4 | 512 | if (!local_fadt) { |
4be44fcd | 513 | return_ACPI_STATUS(AE_NO_MEMORY); |
1da177e4 LT |
514 | } |
515 | ||
516 | if (acpi_gbl_FADT->revision >= FADT2_REVISION_ID) { | |
4be44fcd | 517 | if (acpi_gbl_FADT->length < sizeof(struct fadt_descriptor_rev2)) { |
1da177e4 LT |
518 | /* Length is too short to be a V2.0 table */ |
519 | ||
b8e4d893 BM |
520 | ACPI_WARNING((AE_INFO, |
521 | "Inconsistent FADT length (0x%X) and revision (0x%X), using FADT V1.0 portion of table", | |
522 | acpi_gbl_FADT->length, | |
523 | acpi_gbl_FADT->revision)); | |
1da177e4 | 524 | |
4be44fcd LB |
525 | acpi_tb_convert_fadt1(local_fadt, |
526 | (void *)acpi_gbl_FADT); | |
527 | } else { | |
1da177e4 LT |
528 | /* Valid V2.0 table */ |
529 | ||
4be44fcd | 530 | acpi_tb_convert_fadt2(local_fadt, acpi_gbl_FADT); |
1da177e4 | 531 | } |
4be44fcd | 532 | } else { |
1da177e4 LT |
533 | /* Valid V1.0 table */ |
534 | ||
4be44fcd | 535 | acpi_tb_convert_fadt1(local_fadt, (void *)acpi_gbl_FADT); |
1da177e4 LT |
536 | } |
537 | ||
44f6c012 RM |
538 | /* Global FADT pointer will point to the new common V2.0 FADT */ |
539 | ||
1da177e4 | 540 | acpi_gbl_FADT = local_fadt; |
4be44fcd | 541 | acpi_gbl_FADT->length = sizeof(FADT_DESCRIPTOR); |
1da177e4 LT |
542 | |
543 | /* Free the original table */ | |
544 | ||
545 | table_desc = acpi_gbl_table_lists[ACPI_TABLE_FADT].next; | |
4be44fcd | 546 | acpi_tb_delete_single_table(table_desc); |
1da177e4 LT |
547 | |
548 | /* Install the new table */ | |
549 | ||
4be44fcd LB |
550 | table_desc->pointer = |
551 | ACPI_CAST_PTR(struct acpi_table_header, acpi_gbl_FADT); | |
552 | table_desc->allocation = ACPI_MEM_ALLOCATED; | |
553 | table_desc->length = sizeof(struct fadt_descriptor_rev2); | |
1da177e4 LT |
554 | |
555 | /* Dump the entire FADT */ | |
556 | ||
4be44fcd LB |
557 | ACPI_DEBUG_PRINT((ACPI_DB_TABLES, |
558 | "Hex dump of common internal FADT, size %d (%X)\n", | |
559 | acpi_gbl_FADT->length, acpi_gbl_FADT->length)); | |
c51a4de8 BM |
560 | |
561 | ACPI_DUMP_BUFFER(ACPI_CAST_PTR(u8, acpi_gbl_FADT), | |
562 | acpi_gbl_FADT->length); | |
1da177e4 | 563 | |
4be44fcd | 564 | return_ACPI_STATUS(AE_OK); |
1da177e4 LT |
565 | } |
566 | ||
1da177e4 LT |
567 | /******************************************************************************* |
568 | * | |
44f6c012 | 569 | * FUNCTION: acpi_tb_build_common_facs |
1da177e4 LT |
570 | * |
571 | * PARAMETERS: table_info - Info for currently installed FACS | |
572 | * | |
573 | * RETURN: Status | |
574 | * | |
575 | * DESCRIPTION: Convert ACPI 1.0 and ACPI 2.0 FACS to a common internal | |
576 | * table format. | |
577 | * | |
578 | ******************************************************************************/ | |
579 | ||
4be44fcd | 580 | acpi_status acpi_tb_build_common_facs(struct acpi_table_desc *table_info) |
1da177e4 LT |
581 | { |
582 | ||
4be44fcd | 583 | ACPI_FUNCTION_TRACE("tb_build_common_facs"); |
1da177e4 LT |
584 | |
585 | /* Absolute minimum length is 24, but the ACPI spec says 64 */ | |
586 | ||
587 | if (acpi_gbl_FACS->length < 24) { | |
b8e4d893 BM |
588 | ACPI_ERROR((AE_INFO, "Invalid FACS table length: 0x%X", |
589 | acpi_gbl_FACS->length)); | |
4be44fcd | 590 | return_ACPI_STATUS(AE_INVALID_TABLE_LENGTH); |
1da177e4 LT |
591 | } |
592 | ||
593 | if (acpi_gbl_FACS->length < 64) { | |
b8e4d893 BM |
594 | ACPI_WARNING((AE_INFO, |
595 | "FACS is shorter than the ACPI specification allows: 0x%X, using anyway", | |
596 | acpi_gbl_FACS->length)); | |
1da177e4 LT |
597 | } |
598 | ||
599 | /* Copy fields to the new FACS */ | |
600 | ||
601 | acpi_gbl_common_fACS.global_lock = &(acpi_gbl_FACS->global_lock); | |
602 | ||
603 | if ((acpi_gbl_RSDP->revision < 2) || | |
4be44fcd LB |
604 | (acpi_gbl_FACS->length < 32) || |
605 | (!(acpi_gbl_FACS->xfirmware_waking_vector))) { | |
1da177e4 LT |
606 | /* ACPI 1.0 FACS or short table or optional X_ field is zero */ |
607 | ||
4be44fcd LB |
608 | acpi_gbl_common_fACS.firmware_waking_vector = ACPI_CAST_PTR(u64, |
609 | & | |
610 | (acpi_gbl_FACS-> | |
611 | firmware_waking_vector)); | |
1da177e4 | 612 | acpi_gbl_common_fACS.vector_width = 32; |
4be44fcd | 613 | } else { |
1da177e4 LT |
614 | /* ACPI 2.0 FACS with valid X_ field */ |
615 | ||
4be44fcd LB |
616 | acpi_gbl_common_fACS.firmware_waking_vector = |
617 | &acpi_gbl_FACS->xfirmware_waking_vector; | |
1da177e4 LT |
618 | acpi_gbl_common_fACS.vector_width = 64; |
619 | } | |
620 | ||
4be44fcd | 621 | return_ACPI_STATUS(AE_OK); |
1da177e4 | 622 | } |