1 /******************************************************************************
3 * Module Name: tbconvrt - ACPI Table conversion utilities
5 *****************************************************************************/
8 * Copyright (C) 2000 - 2004, R. Byron Moore
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
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.
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.
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.
45 #include <acpi/acpi.h>
46 #include <acpi/actables.h>
49 #define _COMPONENT ACPI_TABLES
50 ACPI_MODULE_NAME ("tbconvrt")
53 /*******************************************************************************
55 * FUNCTION: acpi_tb_get_table_count
57 * PARAMETERS: RSDP - Pointer to the RSDP
58 * RSDT - Pointer to the RSDT/XSDT
60 * RETURN: The number of tables pointed to by the RSDT or XSDT.
62 * DESCRIPTION: Calculate the number of tables. Automatically handles either
65 ******************************************************************************/
68 acpi_tb_get_table_count (
69 struct rsdp_descriptor
*RSDP
,
70 struct acpi_table_header
*RSDT
)
75 ACPI_FUNCTION_ENTRY ();
78 if (RSDP
->revision
< 2) {
79 pointer_size
= sizeof (u32
);
82 pointer_size
= sizeof (u64
);
86 * Determine the number of tables pointed to by the RSDT/XSDT.
87 * This is defined by the ACPI Specification to be the number of
88 * pointers contained within the RSDT/XSDT. The size of the pointers
89 * is architecture-dependent.
91 return ((RSDT
->length
- sizeof (struct acpi_table_header
)) / pointer_size
);
95 /*******************************************************************************
97 * FUNCTION: acpi_tb_convert_to_xsdt
99 * PARAMETERS: table_info - Info about the RSDT
103 * DESCRIPTION: Convert an RSDT to an XSDT (internal common format)
105 ******************************************************************************/
108 acpi_tb_convert_to_xsdt (
109 struct acpi_table_desc
*table_info
)
111 acpi_size table_size
;
113 XSDT_DESCRIPTOR
*new_table
;
116 ACPI_FUNCTION_ENTRY ();
119 /* Compute size of the converted XSDT */
121 table_size
= ((acpi_size
) acpi_gbl_rsdt_table_count
* sizeof (u64
)) +
122 sizeof (struct acpi_table_header
);
124 /* Allocate an XSDT */
126 new_table
= ACPI_MEM_CALLOCATE (table_size
);
128 return (AE_NO_MEMORY
);
131 /* Copy the header and set the length */
133 ACPI_MEMCPY (new_table
, table_info
->pointer
, sizeof (struct acpi_table_header
));
134 new_table
->length
= (u32
) table_size
;
136 /* Copy the table pointers */
138 for (i
= 0; i
< acpi_gbl_rsdt_table_count
; i
++) {
139 if (acpi_gbl_RSDP
->revision
< 2) {
140 ACPI_STORE_ADDRESS (new_table
->table_offset_entry
[i
],
141 (ACPI_CAST_PTR (struct rsdt_descriptor_rev1
, table_info
->pointer
))->table_offset_entry
[i
]);
144 new_table
->table_offset_entry
[i
] =
145 (ACPI_CAST_PTR (XSDT_DESCRIPTOR
, table_info
->pointer
))->table_offset_entry
[i
];
149 /* Delete the original table (either mapped or in a buffer) */
151 acpi_tb_delete_single_table (table_info
);
153 /* Point the table descriptor to the new table */
155 table_info
->pointer
= ACPI_CAST_PTR (struct acpi_table_header
, new_table
);
156 table_info
->length
= table_size
;
157 table_info
->allocation
= ACPI_MEM_ALLOCATED
;
163 /******************************************************************************
165 * FUNCTION: acpi_tb_init_generic_address
167 * PARAMETERS: new_gas_struct - GAS struct to be initialized
168 * register_bit_width - Width of this register
169 * Address - Address of the register
173 * DESCRIPTION: Initialize a GAS structure.
175 ******************************************************************************/
178 acpi_tb_init_generic_address (
179 struct acpi_generic_address
*new_gas_struct
,
180 u8 register_bit_width
,
181 acpi_physical_address address
)
184 ACPI_STORE_ADDRESS (new_gas_struct
->address
, address
);
186 new_gas_struct
->address_space_id
= ACPI_ADR_SPACE_SYSTEM_IO
;
187 new_gas_struct
->register_bit_width
= register_bit_width
;
188 new_gas_struct
->register_bit_offset
= 0;
189 new_gas_struct
->reserved
= 0;
193 /*******************************************************************************
195 * FUNCTION: acpi_tb_convert_fadt1
197 * PARAMETERS: local_fadt - Pointer to new FADT
198 * original_fadt - Pointer to old FADT
200 * RETURN: Populates local_fadt
202 * DESCRIPTION: Convert an ACPI 1.0 FADT to common internal format
204 ******************************************************************************/
207 acpi_tb_convert_fadt1 (
208 struct fadt_descriptor_rev2
*local_fadt
,
209 struct fadt_descriptor_rev1
*original_fadt
)
214 /* The BIOS stored FADT should agree with Revision 1.0 */
217 * Copy the table header and the common part of the tables.
219 * The 2.0 table is an extension of the 1.0 table, so the entire 1.0
220 * table can be copied first, then expand some fields to 64 bits.
222 ACPI_MEMCPY (local_fadt
, original_fadt
, sizeof (struct fadt_descriptor_rev1
));
224 /* Convert table pointers to 64-bit fields */
226 ACPI_STORE_ADDRESS (local_fadt
->xfirmware_ctrl
, local_fadt
->V1_firmware_ctrl
);
227 ACPI_STORE_ADDRESS (local_fadt
->Xdsdt
, local_fadt
->V1_dsdt
);
230 * System Interrupt Model isn't used in ACPI 2.0 (local_fadt->Reserved1 = 0;)
234 * This field is set by the OEM to convey the preferred power management
235 * profile to OSPM. It doesn't have any 1.0 equivalence. Since we don't
236 * know what kind of 32-bit system this is, we will use "unspecified".
238 local_fadt
->prefer_PM_profile
= PM_UNSPECIFIED
;
241 * Processor Performance State Control. This is the value OSPM writes to
242 * the SMI_CMD register to assume processor performance state control
243 * responsibility. There isn't any equivalence in 1.0, leave it zeroed.
245 local_fadt
->pstate_cnt
= 0;
248 * Support for the _CST object and C States change notification.
249 * This data item hasn't any 1.0 equivalence so leave it zero.
251 local_fadt
->cst_cnt
= 0;
254 * Since there isn't any equivalence in 1.0 and since it highly likely
255 * that a 1.0 system has legacy support.
257 local_fadt
->iapc_boot_arch
= BAF_LEGACY_DEVICES
;
260 * Convert the V1.0 block addresses to V2.0 GAS structures
262 acpi_tb_init_generic_address (&local_fadt
->xpm1a_evt_blk
, local_fadt
->pm1_evt_len
,
263 (acpi_physical_address
) local_fadt
->V1_pm1a_evt_blk
);
264 acpi_tb_init_generic_address (&local_fadt
->xpm1b_evt_blk
, local_fadt
->pm1_evt_len
,
265 (acpi_physical_address
) local_fadt
->V1_pm1b_evt_blk
);
266 acpi_tb_init_generic_address (&local_fadt
->xpm1a_cnt_blk
, local_fadt
->pm1_cnt_len
,
267 (acpi_physical_address
) local_fadt
->V1_pm1a_cnt_blk
);
268 acpi_tb_init_generic_address (&local_fadt
->xpm1b_cnt_blk
, local_fadt
->pm1_cnt_len
,
269 (acpi_physical_address
) local_fadt
->V1_pm1b_cnt_blk
);
270 acpi_tb_init_generic_address (&local_fadt
->xpm2_cnt_blk
, local_fadt
->pm2_cnt_len
,
271 (acpi_physical_address
) local_fadt
->V1_pm2_cnt_blk
);
272 acpi_tb_init_generic_address (&local_fadt
->xpm_tmr_blk
, local_fadt
->pm_tm_len
,
273 (acpi_physical_address
) local_fadt
->V1_pm_tmr_blk
);
274 acpi_tb_init_generic_address (&local_fadt
->xgpe0_blk
, 0,
275 (acpi_physical_address
) local_fadt
->V1_gpe0_blk
);
276 acpi_tb_init_generic_address (&local_fadt
->xgpe1_blk
, 0,
277 (acpi_physical_address
) local_fadt
->V1_gpe1_blk
);
279 /* Create separate GAS structs for the PM1 Enable registers */
281 acpi_tb_init_generic_address (&acpi_gbl_xpm1a_enable
,
282 (u8
) ACPI_DIV_2 (acpi_gbl_FADT
->pm1_evt_len
),
283 (acpi_physical_address
) (local_fadt
->xpm1a_evt_blk
.address
+
284 ACPI_DIV_2 (acpi_gbl_FADT
->pm1_evt_len
)));
286 /* PM1B is optional; leave null if not present */
288 if (local_fadt
->xpm1b_evt_blk
.address
) {
289 acpi_tb_init_generic_address (&acpi_gbl_xpm1b_enable
,
290 (u8
) ACPI_DIV_2 (acpi_gbl_FADT
->pm1_evt_len
),
291 (acpi_physical_address
) (local_fadt
->xpm1b_evt_blk
.address
+
292 ACPI_DIV_2 (acpi_gbl_FADT
->pm1_evt_len
)));
297 /*******************************************************************************
299 * FUNCTION: acpi_tb_convert_fadt2
301 * PARAMETERS: local_fadt - Pointer to new FADT
302 * original_fadt - Pointer to old FADT
304 * RETURN: Populates local_fadt
306 * DESCRIPTION: Convert an ACPI 2.0 FADT to common internal format.
307 * Handles optional "X" fields.
309 ******************************************************************************/
312 acpi_tb_convert_fadt2 (
313 struct fadt_descriptor_rev2
*local_fadt
,
314 struct fadt_descriptor_rev2
*original_fadt
)
317 /* We have an ACPI 2.0 FADT but we must copy it to our local buffer */
319 ACPI_MEMCPY (local_fadt
, original_fadt
, sizeof (struct fadt_descriptor_rev2
));
322 * "X" fields are optional extensions to the original V1.0 fields, so
323 * we must selectively expand V1.0 fields if the corresponding X field
326 if (!(local_fadt
->xfirmware_ctrl
)) {
327 ACPI_STORE_ADDRESS (local_fadt
->xfirmware_ctrl
, local_fadt
->V1_firmware_ctrl
);
330 if (!(local_fadt
->Xdsdt
)) {
331 ACPI_STORE_ADDRESS (local_fadt
->Xdsdt
, local_fadt
->V1_dsdt
);
334 if (!(local_fadt
->xpm1a_evt_blk
.address
)) {
335 acpi_tb_init_generic_address (&local_fadt
->xpm1a_evt_blk
,
336 local_fadt
->pm1_evt_len
, (acpi_physical_address
) local_fadt
->V1_pm1a_evt_blk
);
339 if (!(local_fadt
->xpm1b_evt_blk
.address
)) {
340 acpi_tb_init_generic_address (&local_fadt
->xpm1b_evt_blk
,
341 local_fadt
->pm1_evt_len
, (acpi_physical_address
) local_fadt
->V1_pm1b_evt_blk
);
344 if (!(local_fadt
->xpm1a_cnt_blk
.address
)) {
345 acpi_tb_init_generic_address (&local_fadt
->xpm1a_cnt_blk
,
346 local_fadt
->pm1_cnt_len
, (acpi_physical_address
) local_fadt
->V1_pm1a_cnt_blk
);
349 if (!(local_fadt
->xpm1b_cnt_blk
.address
)) {
350 acpi_tb_init_generic_address (&local_fadt
->xpm1b_cnt_blk
,
351 local_fadt
->pm1_cnt_len
, (acpi_physical_address
) local_fadt
->V1_pm1b_cnt_blk
);
354 if (!(local_fadt
->xpm2_cnt_blk
.address
)) {
355 acpi_tb_init_generic_address (&local_fadt
->xpm2_cnt_blk
,
356 local_fadt
->pm2_cnt_len
, (acpi_physical_address
) local_fadt
->V1_pm2_cnt_blk
);
359 if (!(local_fadt
->xpm_tmr_blk
.address
)) {
360 acpi_tb_init_generic_address (&local_fadt
->xpm_tmr_blk
,
361 local_fadt
->pm_tm_len
, (acpi_physical_address
) local_fadt
->V1_pm_tmr_blk
);
364 if (!(local_fadt
->xgpe0_blk
.address
)) {
365 acpi_tb_init_generic_address (&local_fadt
->xgpe0_blk
,
366 0, (acpi_physical_address
) local_fadt
->V1_gpe0_blk
);
369 if (!(local_fadt
->xgpe1_blk
.address
)) {
370 acpi_tb_init_generic_address (&local_fadt
->xgpe1_blk
,
371 0, (acpi_physical_address
) local_fadt
->V1_gpe1_blk
);
374 /* Create separate GAS structs for the PM1 Enable registers */
376 acpi_tb_init_generic_address (&acpi_gbl_xpm1a_enable
,
377 (u8
) ACPI_DIV_2 (acpi_gbl_FADT
->pm1_evt_len
),
378 (acpi_physical_address
) (local_fadt
->xpm1a_evt_blk
.address
+
379 ACPI_DIV_2 (acpi_gbl_FADT
->pm1_evt_len
)));
380 acpi_gbl_xpm1a_enable
.address_space_id
= local_fadt
->xpm1a_evt_blk
.address_space_id
;
382 /* PM1B is optional; leave null if not present */
384 if (local_fadt
->xpm1b_evt_blk
.address
) {
385 acpi_tb_init_generic_address (&acpi_gbl_xpm1b_enable
,
386 (u8
) ACPI_DIV_2 (acpi_gbl_FADT
->pm1_evt_len
),
387 (acpi_physical_address
) (local_fadt
->xpm1b_evt_blk
.address
+
388 ACPI_DIV_2 (acpi_gbl_FADT
->pm1_evt_len
)));
389 acpi_gbl_xpm1b_enable
.address_space_id
= local_fadt
->xpm1b_evt_blk
.address_space_id
;
394 /*******************************************************************************
396 * FUNCTION: acpi_tb_convert_table_fadt
402 * DESCRIPTION: Converts a BIOS supplied ACPI 1.0 FADT to a local
403 * ACPI 2.0 FADT. If the BIOS supplied a 2.0 FADT then it is simply
404 * copied to the local FADT. The ACPI CA software uses this
405 * local FADT. Thus a significant amount of special #ifdef
406 * type codeing is saved.
408 ******************************************************************************/
411 acpi_tb_convert_table_fadt (void)
413 struct fadt_descriptor_rev2
*local_fadt
;
414 struct acpi_table_desc
*table_desc
;
417 ACPI_FUNCTION_TRACE ("tb_convert_table_fadt");
421 * acpi_gbl_FADT is valid
422 * Allocate and zero the 2.0 FADT buffer
424 local_fadt
= ACPI_MEM_CALLOCATE (sizeof (struct fadt_descriptor_rev2
));
425 if (local_fadt
== NULL
) {
426 return_ACPI_STATUS (AE_NO_MEMORY
);
430 * FADT length and version validation. The table must be at least as
431 * long as the version 1.0 FADT
433 if (acpi_gbl_FADT
->length
< sizeof (struct fadt_descriptor_rev1
)) {
434 ACPI_REPORT_ERROR (("Invalid FADT table length: 0x%X\n", acpi_gbl_FADT
->length
));
435 return_ACPI_STATUS (AE_INVALID_TABLE_LENGTH
);
438 if (acpi_gbl_FADT
->revision
>= FADT2_REVISION_ID
) {
439 if (acpi_gbl_FADT
->length
< sizeof (struct fadt_descriptor_rev2
)) {
440 /* Length is too short to be a V2.0 table */
442 ACPI_REPORT_WARNING (("Inconsistent FADT length (0x%X) and revision (0x%X), using FADT V1.0 portion of table\n",
443 acpi_gbl_FADT
->length
, acpi_gbl_FADT
->revision
));
445 acpi_tb_convert_fadt1 (local_fadt
, (void *) acpi_gbl_FADT
);
448 /* Valid V2.0 table */
450 acpi_tb_convert_fadt2 (local_fadt
, acpi_gbl_FADT
);
454 /* Valid V1.0 table */
456 acpi_tb_convert_fadt1 (local_fadt
, (void *) acpi_gbl_FADT
);
460 * Global FADT pointer will point to the new common V2.0 FADT
462 acpi_gbl_FADT
= local_fadt
;
463 acpi_gbl_FADT
->length
= sizeof (FADT_DESCRIPTOR
);
465 /* Free the original table */
467 table_desc
= acpi_gbl_table_lists
[ACPI_TABLE_FADT
].next
;
468 acpi_tb_delete_single_table (table_desc
);
470 /* Install the new table */
472 table_desc
->pointer
= ACPI_CAST_PTR (struct acpi_table_header
, acpi_gbl_FADT
);
473 table_desc
->allocation
= ACPI_MEM_ALLOCATED
;
474 table_desc
->length
= sizeof (struct fadt_descriptor_rev2
);
476 /* Dump the entire FADT */
478 ACPI_DEBUG_PRINT ((ACPI_DB_TABLES
,
479 "Hex dump of common internal FADT, size %d (%X)\n",
480 acpi_gbl_FADT
->length
, acpi_gbl_FADT
->length
));
481 ACPI_DUMP_BUFFER ((u8
*) (acpi_gbl_FADT
), acpi_gbl_FADT
->length
);
483 return_ACPI_STATUS (AE_OK
);
487 /*******************************************************************************
489 * FUNCTION: acpi_tb_convert_table_facs
491 * PARAMETERS: table_info - Info for currently installad FACS
495 * DESCRIPTION: Convert ACPI 1.0 and ACPI 2.0 FACS to a common internal
498 ******************************************************************************/
501 acpi_tb_build_common_facs (
502 struct acpi_table_desc
*table_info
)
505 ACPI_FUNCTION_TRACE ("tb_build_common_facs");
508 /* Absolute minimum length is 24, but the ACPI spec says 64 */
510 if (acpi_gbl_FACS
->length
< 24) {
511 ACPI_REPORT_ERROR (("Invalid FACS table length: 0x%X\n", acpi_gbl_FACS
->length
));
512 return_ACPI_STATUS (AE_INVALID_TABLE_LENGTH
);
515 if (acpi_gbl_FACS
->length
< 64) {
516 ACPI_REPORT_WARNING (("FACS is shorter than the ACPI specification allows: 0x%X, using anyway\n",
517 acpi_gbl_FACS
->length
));
520 /* Copy fields to the new FACS */
522 acpi_gbl_common_fACS
.global_lock
= &(acpi_gbl_FACS
->global_lock
);
524 if ((acpi_gbl_RSDP
->revision
< 2) ||
525 (acpi_gbl_FACS
->length
< 32) ||
526 (!(acpi_gbl_FACS
->xfirmware_waking_vector
))) {
527 /* ACPI 1.0 FACS or short table or optional X_ field is zero */
529 acpi_gbl_common_fACS
.firmware_waking_vector
= ACPI_CAST_PTR (u64
, &(acpi_gbl_FACS
->firmware_waking_vector
));
530 acpi_gbl_common_fACS
.vector_width
= 32;
533 /* ACPI 2.0 FACS with valid X_ field */
535 acpi_gbl_common_fACS
.firmware_waking_vector
= &acpi_gbl_FACS
->xfirmware_waking_vector
;
536 acpi_gbl_common_fACS
.vector_width
= 64;
539 return_ACPI_STATUS (AE_OK
);