1/****************************************************************************** 2 * 3 * Module Name: tbfadt - FADT table utilities 4 * 5 *****************************************************************************/ 6 7/* 8 * Copyright (C) 2000 - 2007, R. Byron Moore 9 * All rights reserved. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions, and the following disclaimer, 16 * without modification. 17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18 * substantially similar to the "NO WARRANTY" disclaimer below 19 * ("Disclaimer") and any redistribution must be conditioned upon 20 * including a substantially similar Disclaimer requirement for further 21 * binary redistribution. 22 * 3. Neither the names of the above-listed copyright holders nor the names 23 * of any contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * Alternatively, this software may be distributed under the terms of the 27 * GNU General Public License ("GPL") version 2 as published by the Free 28 * Software Foundation. 29 * 30 * NO WARRANTY 31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41 * POSSIBILITY OF SUCH DAMAGES. 42 */ 43 44#include <acpi/acpi.h> 45#include <acpi/actables.h> 46 47#define _COMPONENT ACPI_TABLES 48ACPI_MODULE_NAME("tbfadt") 49 50/* Local prototypes */ 51static void inline 52acpi_tb_init_generic_address(struct acpi_generic_address *generic_address, 53 u8 bit_width, u64 address); 54 55static void acpi_tb_convert_fadt(void); 56 57static void acpi_tb_validate_fadt(void); 58 59/* Table for conversion of FADT to common internal format and FADT validation */ 60 61typedef struct acpi_fadt_info { 62 char *name; 63 u8 target; 64 u8 source; 65 u8 length; 66 u8 type; 67 68} acpi_fadt_info; 69 70#define ACPI_FADT_REQUIRED 1 71#define ACPI_FADT_SEPARATE_LENGTH 2 72 73static struct acpi_fadt_info fadt_info_table[] = { 74 {"Pm1aEventBlock", ACPI_FADT_OFFSET(xpm1a_event_block), 75 ACPI_FADT_OFFSET(pm1a_event_block), 76 ACPI_FADT_OFFSET(pm1_event_length), ACPI_FADT_REQUIRED}, 77 78 {"Pm1bEventBlock", ACPI_FADT_OFFSET(xpm1b_event_block), 79 ACPI_FADT_OFFSET(pm1b_event_block), 80 ACPI_FADT_OFFSET(pm1_event_length), 0}, 81 82 {"Pm1aControlBlock", ACPI_FADT_OFFSET(xpm1a_control_block), 83 ACPI_FADT_OFFSET(pm1a_control_block), 84 ACPI_FADT_OFFSET(pm1_control_length), ACPI_FADT_REQUIRED}, 85 86 {"Pm1bControlBlock", ACPI_FADT_OFFSET(xpm1b_control_block), 87 ACPI_FADT_OFFSET(pm1b_control_block), 88 ACPI_FADT_OFFSET(pm1_control_length), 0}, 89 90 {"Pm2ControlBlock", ACPI_FADT_OFFSET(xpm2_control_block), 91 ACPI_FADT_OFFSET(pm2_control_block), 92 ACPI_FADT_OFFSET(pm2_control_length), ACPI_FADT_SEPARATE_LENGTH}, 93 94 {"PmTimerBlock", ACPI_FADT_OFFSET(xpm_timer_block), 95 ACPI_FADT_OFFSET(pm_timer_block), 96 ACPI_FADT_OFFSET(pm_timer_length), ACPI_FADT_REQUIRED}, 97 98 {"Gpe0Block", ACPI_FADT_OFFSET(xgpe0_block), 99 ACPI_FADT_OFFSET(gpe0_block), 100 ACPI_FADT_OFFSET(gpe0_block_length), ACPI_FADT_SEPARATE_LENGTH}, 101 102 {"Gpe1Block", ACPI_FADT_OFFSET(xgpe1_block), 103 ACPI_FADT_OFFSET(gpe1_block), 104 ACPI_FADT_OFFSET(gpe1_block_length), ACPI_FADT_SEPARATE_LENGTH} 105}; 106 107#define ACPI_FADT_INFO_ENTRIES (sizeof (fadt_info_table) / sizeof (struct acpi_fadt_info)) 108 109/******************************************************************************* 110 * 111 * FUNCTION: acpi_tb_init_generic_address 112 * 113 * PARAMETERS: generic_address - GAS struct to be initialized 114 * bit_width - Width of this register 115 * Address - Address of the register 116 * 117 * RETURN: None 118 * 119 * DESCRIPTION: Initialize a Generic Address Structure (GAS) 120 * See the ACPI specification for a full description and 121 * definition of this structure. 122 * 123 ******************************************************************************/ 124 125static void inline 126acpi_tb_init_generic_address(struct acpi_generic_address *generic_address, 127 u8 bit_width, u64 address) 128{ 129 130 /* 131 * The 64-bit Address field is non-aligned in the byte packed 132 * GAS struct. 133 */ 134 ACPI_MOVE_64_TO_64(&generic_address->address, &address); 135 136 /* All other fields are byte-wide */ 137 138 generic_address->space_id = ACPI_ADR_SPACE_SYSTEM_IO; 139 generic_address->bit_width = bit_width; 140 generic_address->bit_offset = 0; 141 generic_address->access_width = 0; 142} 143 144/******************************************************************************* 145 * 146 * FUNCTION: acpi_tb_parse_fadt 147 * 148 * PARAMETERS: table_index - Index for the FADT 149 * Flags - Flags 150 * 151 * RETURN: None 152 * 153 * DESCRIPTION: Initialize the FADT, DSDT and FACS tables 154 * (FADT contains the addresses of the DSDT and FACS) 155 * 156 ******************************************************************************/ 157 158void acpi_tb_parse_fadt(acpi_native_uint table_index, u8 flags) 159{ 160 u32 length; 161 struct acpi_table_header *table; 162 163 /* 164 * The FADT has multiple versions with different lengths, 165 * and it contains pointers to both the DSDT and FACS tables. 166 * 167 * Get a local copy of the FADT and convert it to a common format 168 * Map entire FADT, assumed to be smaller than one page. 169 */ 170 length = acpi_gbl_root_table_list.tables[table_index].length; 171 172 table = 173 acpi_os_map_memory(acpi_gbl_root_table_list.tables[table_index]. 174 address, length); 175 if (!table) { 176 return; 177 } 178 179 /* 180 * Validate the FADT checksum before we copy the table. Ignore 181 * checksum error as we want to try to get the DSDT and FACS. 182 */ 183 (void)acpi_tb_verify_checksum(table, length); 184 185 /* Obtain a local copy of the FADT in common ACPI 2.0+ format */ 186 187 acpi_tb_create_local_fadt(table, length); 188 189 /* All done with the real FADT, unmap it */ 190 191 acpi_os_unmap_memory(table, length); 192 193 /* Obtain the DSDT and FACS tables via their addresses within the FADT */ 194 195 acpi_tb_install_table((acpi_physical_address) acpi_gbl_FADT.Xdsdt, 196 flags, ACPI_SIG_DSDT, ACPI_TABLE_INDEX_DSDT); 197 198 acpi_tb_install_table((acpi_physical_address) acpi_gbl_FADT.Xfacs, 199 flags, ACPI_SIG_FACS, ACPI_TABLE_INDEX_FACS); 200} 201 202/******************************************************************************* 203 * 204 * FUNCTION: acpi_tb_create_local_fadt 205 * 206 * PARAMETERS: Table - Pointer to BIOS FADT 207 * Length - Length of the table 208 * 209 * RETURN: None 210 * 211 * DESCRIPTION: Get a local copy of the FADT and convert it to a common format. 212 * Performs validation on some important FADT fields. 213 * 214 ******************************************************************************/ 215 216void acpi_tb_create_local_fadt(struct acpi_table_header *table, u32 length) 217{ 218 219 /* 220 * Check if the FADT is larger than what we know about (ACPI 2.0 version). 221 * Truncate the table, but make some noise. 222 */ 223 if (length > sizeof(struct acpi_table_fadt)) { 224 ACPI_WARNING((AE_INFO, 225 "FADT (revision %u) is longer than ACPI 2.0 version, truncating length 0x%X to 0x%zX", 226 table->revision, (unsigned)length, 227 sizeof(struct acpi_table_fadt))); 228 } 229 230 /* Copy the entire FADT locally. Zero first for tb_convert_fadt */ 231 232 ACPI_MEMSET(&acpi_gbl_FADT, 0, sizeof(struct acpi_table_fadt)); 233 234 ACPI_MEMCPY(&acpi_gbl_FADT, table, 235 ACPI_MIN(length, sizeof(struct acpi_table_fadt))); 236 237 /* 238 * 1) Convert the local copy of the FADT to the common internal format 239 * 2) Validate some of the important values within the FADT 240 */ 241 acpi_tb_convert_fadt(); 242 acpi_tb_validate_fadt(); 243} 244 245/******************************************************************************* 246 * 247 * FUNCTION: acpi_tb_convert_fadt 248 * 249 * PARAMETERS: None, uses acpi_gbl_FADT 250 * 251 * RETURN: None 252 * 253 * DESCRIPTION: Converts all versions of the FADT to a common internal format. 254 * -> Expand all 32-bit addresses to 64-bit. 255 * 256 * NOTE: acpi_gbl_FADT must be of size (struct acpi_table_fadt), 257 * and must contain a copy of the actual FADT. 258 * 259 * ACPICA will use the "X" fields of the FADT for all addresses. 260 * 261 * "X" fields are optional extensions to the original V1.0 fields. Even if 262 * they are present in the structure, they can be optionally not used by 263 * setting them to zero. Therefore, we must selectively expand V1.0 fields 264 * if the corresponding X field is zero. 265 * 266 * For ACPI 1.0 FADTs, all address fields are expanded to the corresponding 267 * "X" fields. 268 * 269 * For ACPI 2.0 FADTs, any "X" fields that are NULL are filled in by 270 * expanding the corresponding ACPI 1.0 field. 271 * 272 ******************************************************************************/ 273 274static void acpi_tb_convert_fadt(void) 275{ 276 u8 pm1_register_length; 277 struct acpi_generic_address *target; 278 acpi_native_uint i; 279 280 /* Update the local FADT table header length */ 281 282 acpi_gbl_FADT.header.length = sizeof(struct acpi_table_fadt); 283 284 /* Expand the 32-bit FACS and DSDT addresses to 64-bit as necessary */ 285 286 if (!acpi_gbl_FADT.Xfacs) { 287 acpi_gbl_FADT.Xfacs = (u64) acpi_gbl_FADT.facs; 288 } 289 290 if (!acpi_gbl_FADT.Xdsdt) { 291 acpi_gbl_FADT.Xdsdt = (u64) acpi_gbl_FADT.dsdt; 292 } 293 294 /* 295 * Expand the 32-bit V1.0 addresses to the 64-bit "X" generic address 296 * structures as necessary. 297 */ 298 for (i = 0; i < ACPI_FADT_INFO_ENTRIES; i++) { 299 target = 300 ACPI_ADD_PTR(struct acpi_generic_address, &acpi_gbl_FADT, 301 fadt_info_table[i].target); 302 303 /* Expand only if the X target is null */ 304 305 if (!target->address) { 306 acpi_tb_init_generic_address(target, 307 *ACPI_ADD_PTR(u8, 308 &acpi_gbl_FADT, 309 fadt_info_table 310 [i].length), 311 (u64) * ACPI_ADD_PTR(u32, 312 &acpi_gbl_FADT, 313 fadt_info_table 314 [i]. 315 source)); 316 } 317 } 318 319 /* 320 * Calculate separate GAS structs for the PM1 Enable registers. 321 * These addresses do not appear (directly) in the FADT, so it is 322 * useful to calculate them once, here. 323 * 324 * The PM event blocks are split into two register blocks, first is the 325 * PM Status Register block, followed immediately by the PM Enable Register 326 * block. Each is of length (pm1_event_length/2) 327 */ 328 pm1_register_length = (u8) ACPI_DIV_2(acpi_gbl_FADT.pm1_event_length); 329 330 /* The PM1A register block is required */ 331 332 acpi_tb_init_generic_address(&acpi_gbl_xpm1a_enable, 333 pm1_register_length, 334 (acpi_gbl_FADT.xpm1a_event_block.address + 335 pm1_register_length)); 336 /* Don't forget to copy space_id of the GAS */ 337 acpi_gbl_xpm1a_enable.space_id = 338 acpi_gbl_FADT.xpm1a_event_block.space_id; 339 340 /* The PM1B register block is optional, ignore if not present */ 341 342 if (acpi_gbl_FADT.xpm1b_event_block.address) { 343 acpi_tb_init_generic_address(&acpi_gbl_xpm1b_enable, 344 pm1_register_length, 345 (acpi_gbl_FADT.xpm1b_event_block. 346 address + pm1_register_length)); 347 /* Don't forget to copy space_id of the GAS */ 348 acpi_gbl_xpm1b_enable.space_id = 349 acpi_gbl_FADT.xpm1a_event_block.space_id; 350 351 } 352 353 if (acpi_gbl_FADT.header.revision < 3) { 354 acpi_gbl_FADT.preferred_profile = 0; 355 acpi_gbl_FADT.pstate_control = 0; 356 acpi_gbl_FADT.cst_control = 0; 357 acpi_gbl_FADT.boot_flags = 0; 358 } 359} 360 361/****************************************************************************** 362 * 363 * FUNCTION: acpi_tb_validate_fadt 364 * 365 * PARAMETERS: Table - Pointer to the FADT to be validated 366 * 367 * RETURN: None 368 * 369 * DESCRIPTION: Validate various important fields within the FADT. If a problem 370 * is found, issue a message, but no status is returned. 371 * Used by both the table manager and the disassembler. 372 * 373 * Possible additional checks: 374 * (acpi_gbl_FADT.pm1_event_length >= 4) 375 * (acpi_gbl_FADT.pm1_control_length >= 2) 376 * (acpi_gbl_FADT.pm_timer_length >= 4) 377 * Gpe block lengths must be multiple of 2 378 * 379 ******************************************************************************/ 380 381static void acpi_tb_validate_fadt(void) 382{ 383 u32 *address32; 384 struct acpi_generic_address *address64; 385 u8 length; 386 acpi_native_uint i; 387 388 /* Examine all of the 64-bit extended address fields (X fields) */ 389 390 for (i = 0; i < ACPI_FADT_INFO_ENTRIES; i++) { 391 392 /* Generate pointers to the 32-bit and 64-bit addresses and get the length */ 393 394 address64 = 395 ACPI_ADD_PTR(struct acpi_generic_address, &acpi_gbl_FADT, 396 fadt_info_table[i].target); 397 address32 = 398 ACPI_ADD_PTR(u32, &acpi_gbl_FADT, 399 fadt_info_table[i].source); 400 length = 401 *ACPI_ADD_PTR(u8, &acpi_gbl_FADT, 402 fadt_info_table[i].length); 403 404 if (fadt_info_table[i].type & ACPI_FADT_REQUIRED) { 405 /* 406 * Field is required (Pm1a_event, Pm1a_control, pm_timer). 407 * Both the address and length must be non-zero. 408 */ 409 if (!address64->address || !length) { 410 ACPI_ERROR((AE_INFO, 411 "Required field \"%s\" has zero address and/or length: %8.8X%8.8X/%X", 412 fadt_info_table[i].name, 413 ACPI_FORMAT_UINT64(address64-> 414 address), 415 length)); 416 } 417 } else if (fadt_info_table[i].type & ACPI_FADT_SEPARATE_LENGTH) { 418 /* 419 * Field is optional (PM2Control, GPE0, GPE1) AND has its own 420 * length field. If present, both the address and length must be valid. 421 */ 422 if ((address64->address && !length) 423 || (!address64->address && length)) { 424 ACPI_WARNING((AE_INFO, 425 "Optional field \"%s\" has zero address or length: %8.8X%8.8X/%X", 426 fadt_info_table[i].name, 427 ACPI_FORMAT_UINT64(address64-> 428 address), 429 length)); 430 } 431 } 432 433 /* If both 32- and 64-bit addresses are valid (non-zero), they must match */ 434 435 if (address64->address && *address32 && 436 (address64->address != (u64) * address32)) { 437 ACPI_ERROR((AE_INFO, 438 "32/64X address mismatch in \"%s\": [%8.8X] [%8.8X%8.8X], using 64X", 439 fadt_info_table[i].name, *address32, 440 ACPI_FORMAT_UINT64(address64->address))); 441 } 442 } 443} 444