1 /****************************************************************************** 2 * 3 * Module Name: tbutils - table utilities 4 * $Revision: 1.91 $ 5 * 6 *****************************************************************************/ 7 8 /****************************************************************************** 9 * 10 * 1. Copyright Notice 11 * 12 * Some or all of this work - Copyright (c) 1999 - 2008, Intel Corp. 13 * All rights reserved. 14 * 15 * 2. License 16 * 17 * 2.1. This is your license from Intel Corp. under its intellectual property 18 * rights. You may have additional license terms from the party that provided 19 * you this software, covering your right to use that party's intellectual 20 * property rights. 21 * 22 * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a 23 * copy of the source code appearing in this file ("Covered Code") an 24 * irrevocable, perpetual, worldwide license under Intel's copyrights in the 25 * base code distributed originally by Intel ("Original Intel Code") to copy, 26 * make derivatives, distribute, use and display any portion of the Covered 27 * Code in any form, with the right to sublicense such rights; and 28 * 29 * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent 30 * license (with the right to sublicense), under only those claims of Intel 31 * patents that are infringed by the Original Intel Code, to make, use, sell, 32 * offer to sell, and import the Covered Code and derivative works thereof 33 * solely to the minimum extent necessary to exercise the above copyright 34 * license, and in no event shall the patent license extend to any additions 35 * to or modifications of the Original Intel Code. No other license or right 36 * is granted directly or by implication, estoppel or otherwise; 37 * 38 * The above copyright and patent license is granted only if the following 39 * conditions are met: 40 * 41 * 3. Conditions 42 * 43 * 3.1. Redistribution of Source with Rights to Further Distribute Source. 44 * Redistribution of source code of any substantial portion of the Covered 45 * Code or modification with rights to further distribute source must include 46 * the above Copyright Notice, the above License, this list of Conditions, 47 * and the following Disclaimer and Export Compliance provision. In addition, 48 * Licensee must cause all Covered Code to which Licensee contributes to 49 * contain a file documenting the changes Licensee made to create that Covered 50 * Code and the date of any change. Licensee must include in that file the 51 * documentation of any changes made by any predecessor Licensee. Licensee 52 * must include a prominent statement that the modification is derived, 53 * directly or indirectly, from Original Intel Code. 54 * 55 * 3.2. Redistribution of Source with no Rights to Further Distribute Source. 56 * Redistribution of source code of any substantial portion of the Covered 57 * Code or modification without rights to further distribute source must 58 * include the following Disclaimer and Export Compliance provision in the 59 * documentation and/or other materials provided with distribution. In 60 * addition, Licensee may not authorize further sublicense of source of any 61 * portion of the Covered Code, and must include terms to the effect that the 62 * license from Licensee to its licensee is limited to the intellectual 63 * property embodied in the software Licensee provides to its licensee, and 64 * not to intellectual property embodied in modifications its licensee may 65 * make. 66 * 67 * 3.3. Redistribution of Executable. Redistribution in executable form of any 68 * substantial portion of the Covered Code or modification must reproduce the 69 * above Copyright Notice, and the following Disclaimer and Export Compliance 70 * provision in the documentation and/or other materials provided with the 71 * distribution. 72 * 73 * 3.4. Intel retains all right, title, and interest in and to the Original 74 * Intel Code. 75 * 76 * 3.5. Neither the name Intel nor any other trademark owned or controlled by 77 * Intel shall be used in advertising or otherwise to promote the sale, use or 78 * other dealings in products derived from or relating to the Covered Code 79 * without prior written authorization from Intel. 80 * 81 * 4. Disclaimer and Export Compliance 82 * 83 * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED 84 * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE 85 * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, 86 * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY 87 * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY 88 * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A 89 * PARTICULAR PURPOSE. 90 * 91 * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES 92 * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR 93 * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT, 94 * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY 95 * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL 96 * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS 97 * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY 98 * LIMITED REMEDY. 99 * 100 * 4.3. Licensee shall not export, either directly or indirectly, any of this 101 * software or system incorporating such software without first obtaining any 102 * required license or other approval from the U. S. Department of Commerce or 103 * any other agency or department of the United States Government. In the 104 * event Licensee exports any such software from the United States or 105 * re-exports any such software from a foreign destination, Licensee shall 106 * ensure that the distribution and export/re-export of the software is in 107 * compliance with all laws, regulations, orders, or other restrictions of the 108 * U.S. Export Administration Regulations. Licensee agrees that neither it nor 109 * any of its subsidiaries will export/re-export any technical data, process, 110 * software, or service, directly or indirectly, to any country for which the 111 * United States government or any agency thereof requires an export license, 112 * other governmental approval, or letter of assurance, without first obtaining 113 * such license, approval or letter. 114 * 115 *****************************************************************************/ 116 117 #define __TBUTILS_C__ 118 119 #include "acpi.h" 120 #include "actables.h" 121 122 #define _COMPONENT ACPI_TABLES 123 ACPI_MODULE_NAME ("tbutils") 124 125 /* Local prototypes */ 126 127 static ACPI_PHYSICAL_ADDRESS 128 AcpiTbGetRootTableEntry ( 129 UINT8 *TableEntry, 130 UINT32 TableEntrySize); 131 132 133 /******************************************************************************* 134 * 135 * FUNCTION: AcpiTbTablesLoaded 136 * 137 * PARAMETERS: None 138 * 139 * RETURN: TRUE if required ACPI tables are loaded 140 * 141 * DESCRIPTION: Determine if the minimum required ACPI tables are present 142 * (FADT, FACS, DSDT) 143 * 144 ******************************************************************************/ 145 146 BOOLEAN 147 AcpiTbTablesLoaded ( 148 void) 149 { 150 151 if (AcpiGbl_RootTableList.Count >= 3) 152 { 153 return (TRUE); 154 } 155 156 return (FALSE); 157 } 158 159 160 /******************************************************************************* 161 * 162 * FUNCTION: AcpiTbPrintTableHeader 163 * 164 * PARAMETERS: Address - Table physical address 165 * Header - Table header 166 * 167 * RETURN: None 168 * 169 * DESCRIPTION: Print an ACPI table header. Special cases for FACS and RSDP. 170 * 171 ******************************************************************************/ 172 173 void 174 AcpiTbPrintTableHeader ( 175 ACPI_PHYSICAL_ADDRESS Address, 176 ACPI_TABLE_HEADER *Header) 177 { 178 179 if (ACPI_COMPARE_NAME (Header->Signature, ACPI_SIG_FACS)) 180 { 181 /* FACS only has signature and length fields of common table header */ 182 183 ACPI_INFO ((AE_INFO, "%4.4s @ 0x%p/0x%04X", 184 Header->Signature, ACPI_CAST_PTR (UINT64, Address), Header->Length)); 185 } 186 else if (ACPI_COMPARE_NAME (Header->Signature, ACPI_SIG_RSDP)) 187 { 188 /* RSDP has no common fields */ 189 190 ACPI_INFO ((AE_INFO, "RSDP @ 0x%p/0x%04X (v%3.3d %6.6s)", 191 ACPI_CAST_PTR (void, Address), 192 (ACPI_CAST_PTR (ACPI_TABLE_RSDP, Header)->Revision > 0) ? 193 ACPI_CAST_PTR (ACPI_TABLE_RSDP, Header)->Length : 20, 194 ACPI_CAST_PTR (ACPI_TABLE_RSDP, Header)->Revision, 195 ACPI_CAST_PTR (ACPI_TABLE_RSDP, Header)->OemId)); 196 } 197 else 198 { 199 /* Standard ACPI table with full common header */ 200 201 ACPI_INFO ((AE_INFO, 202 "%4.4s @ 0x%p/0x%04X (v%3.3d %6.6s %8.8s 0x%08X %4.4s 0x%08X)", 203 Header->Signature, ACPI_CAST_PTR (void, Address), 204 Header->Length, Header->Revision, Header->OemId, 205 Header->OemTableId, Header->OemRevision, Header->AslCompilerId, 206 Header->AslCompilerRevision)); 207 } 208 } 209 210 211 /******************************************************************************* 212 * 213 * FUNCTION: AcpiTbValidateChecksum 214 * 215 * PARAMETERS: Table - ACPI table to verify 216 * Length - Length of entire table 217 * 218 * RETURN: Status 219 * 220 * DESCRIPTION: Verifies that the table checksums to zero. Optionally returns 221 * exception on bad checksum. 222 * 223 ******************************************************************************/ 224 225 ACPI_STATUS 226 AcpiTbVerifyChecksum ( 227 ACPI_TABLE_HEADER *Table, 228 UINT32 Length) 229 { 230 UINT8 Checksum; 231 232 233 /* Compute the checksum on the table */ 234 235 Checksum = AcpiTbChecksum (ACPI_CAST_PTR (UINT8, Table), Length); 236 237 /* Checksum ok? (should be zero) */ 238 239 if (Checksum) 240 { 241 ACPI_WARNING ((AE_INFO, 242 "Incorrect checksum in table [%4.4s] - %2.2X, should be %2.2X", 243 Table->Signature, Table->Checksum, (UINT8) (Table->Checksum - Checksum))); 244 245 #if (ACPI_CHECKSUM_ABORT) 246 return (AE_BAD_CHECKSUM); 247 #endif 248 } 249 250 return (AE_OK); 251 } 252 253 254 /******************************************************************************* 255 * 256 * FUNCTION: AcpiTbChecksum 257 * 258 * PARAMETERS: Buffer - Pointer to memory region to be checked 259 * Length - Length of this memory region 260 * 261 * RETURN: Checksum (UINT8) 262 * 263 * DESCRIPTION: Calculates circular checksum of memory region. 264 * 265 ******************************************************************************/ 266 267 UINT8 268 AcpiTbChecksum ( 269 UINT8 *Buffer, 270 UINT32 Length) 271 { 272 UINT8 Sum = 0; 273 UINT8 *End = Buffer + Length; 274 275 276 while (Buffer < End) 277 { 278 Sum = (UINT8) (Sum + *(Buffer++)); 279 } 280 281 return Sum; 282 } 283 284 285 /******************************************************************************* 286 * 287 * FUNCTION: AcpiTbInstallTable 288 * 289 * PARAMETERS: Address - Physical address of DSDT or FACS 290 * Flags - Flags 291 * Signature - Table signature, NULL if no need to 292 * match 293 * TableIndex - Index into root table array 294 * 295 * RETURN: None 296 * 297 * DESCRIPTION: Install an ACPI table into the global data structure. 298 * 299 ******************************************************************************/ 300 301 void 302 AcpiTbInstallTable ( 303 ACPI_PHYSICAL_ADDRESS Address, 304 UINT8 Flags, 305 char *Signature, 306 UINT32 TableIndex) 307 { 308 ACPI_TABLE_HEADER *Table; 309 310 311 if (!Address) 312 { 313 ACPI_ERROR ((AE_INFO, "Null physical address for ACPI table [%s]", 314 Signature)); 315 return; 316 } 317 318 /* Map just the table header */ 319 320 Table = AcpiOsMapMemory (Address, sizeof (ACPI_TABLE_HEADER)); 321 if (!Table) 322 { 323 return; 324 } 325 326 /* If a particular signature is expected, signature must match */ 327 328 if (Signature && 329 !ACPI_COMPARE_NAME (Table->Signature, Signature)) 330 { 331 ACPI_ERROR ((AE_INFO, "Invalid signature 0x%X for ACPI table [%s]", 332 *ACPI_CAST_PTR (UINT32, Table->Signature), Signature)); 333 goto UnmapAndExit; 334 } 335 336 /* Initialize the table entry */ 337 338 AcpiGbl_RootTableList.Tables[TableIndex].Address = Address; 339 AcpiGbl_RootTableList.Tables[TableIndex].Length = Table->Length; 340 AcpiGbl_RootTableList.Tables[TableIndex].Flags = Flags; 341 342 ACPI_MOVE_32_TO_32 ( 343 &(AcpiGbl_RootTableList.Tables[TableIndex].Signature), 344 Table->Signature); 345 346 AcpiTbPrintTableHeader (Address, Table); 347 348 if (TableIndex == ACPI_TABLE_INDEX_DSDT) 349 { 350 /* Global integer width is based upon revision of the DSDT */ 351 352 AcpiUtSetIntegerWidth (Table->Revision); 353 } 354 355 UnmapAndExit: 356 AcpiOsUnmapMemory (Table, sizeof (ACPI_TABLE_HEADER)); 357 } 358 359 360 /******************************************************************************* 361 * 362 * FUNCTION: AcpiTbGetRootTableEntry 363 * 364 * PARAMETERS: TableEntry - Pointer to the RSDT/XSDT table entry 365 * TableEntrySize - sizeof 32 or 64 (RSDT or XSDT) 366 * 367 * RETURN: Physical address extracted from the root table 368 * 369 * DESCRIPTION: Get one root table entry. Handles 32-bit and 64-bit cases on 370 * both 32-bit and 64-bit platforms 371 * 372 * NOTE: ACPI_PHYSICAL_ADDRESS is 32-bit on 32-bit platforms, 64-bit on 373 * 64-bit platforms. 374 * 375 ******************************************************************************/ 376 377 static ACPI_PHYSICAL_ADDRESS 378 AcpiTbGetRootTableEntry ( 379 UINT8 *TableEntry, 380 UINT32 TableEntrySize) 381 { 382 UINT64 Address64; 383 384 385 /* 386 * Get the table physical address (32-bit for RSDT, 64-bit for XSDT): 387 * Note: Addresses are 32-bit aligned (not 64) in both RSDT and XSDT 388 */ 389 if (TableEntrySize == sizeof (UINT32)) 390 { 391 /* 392 * 32-bit platform, RSDT: Return 32-bit table entry 393 * 64-bit platform, RSDT: Expand 32-bit to 64-bit and return 394 */ 395 return ((ACPI_PHYSICAL_ADDRESS) (*ACPI_CAST_PTR (UINT32, TableEntry))); 396 } 397 else 398 { 399 /* 400 * 32-bit platform, XSDT: Truncate 64-bit to 32-bit and return 401 * 64-bit platform, XSDT: Move (unaligned) 64-bit to local, return 64-bit 402 */ 403 ACPI_MOVE_64_TO_64 (&Address64, TableEntry); 404 405 #if ACPI_MACHINE_WIDTH == 32 406 if (Address64 > ACPI_UINT32_MAX) 407 { 408 /* Will truncate 64-bit address to 32 bits, issue warning */ 409 410 ACPI_WARNING ((AE_INFO, 411 "64-bit Physical Address in XSDT is too large (%8.8X%8.8X), truncating", 412 ACPI_FORMAT_UINT64 (Address64))); 413 } 414 #endif 415 return ((ACPI_PHYSICAL_ADDRESS) (Address64)); 416 } 417 } 418 419 420 /******************************************************************************* 421 * 422 * FUNCTION: AcpiTbParseRootTable 423 * 424 * PARAMETERS: Rsdp - Pointer to the RSDP 425 * Flags - Flags 426 * 427 * RETURN: Status 428 * 429 * DESCRIPTION: This function is called to parse the Root System Description 430 * Table (RSDT or XSDT) 431 * 432 * NOTE: Tables are mapped (not copied) for efficiency. The FACS must 433 * be mapped and cannot be copied because it contains the actual 434 * memory location of the ACPI Global Lock. 435 * 436 ******************************************************************************/ 437 438 ACPI_STATUS 439 AcpiTbParseRootTable ( 440 ACPI_PHYSICAL_ADDRESS RsdpAddress, 441 UINT8 Flags) 442 { 443 ACPI_TABLE_RSDP *Rsdp; 444 UINT32 TableEntrySize; 445 UINT32 i; 446 UINT32 TableCount; 447 ACPI_TABLE_HEADER *Table; 448 ACPI_PHYSICAL_ADDRESS Address; 449 UINT32 Length; 450 UINT8 *TableEntry; 451 ACPI_STATUS Status; 452 453 454 ACPI_FUNCTION_TRACE (TbParseRootTable); 455 456 457 /* 458 * Map the entire RSDP and extract the address of the RSDT or XSDT 459 */ 460 Rsdp = AcpiOsMapMemory (RsdpAddress, sizeof (ACPI_TABLE_RSDP)); 461 if (!Rsdp) 462 { 463 return_ACPI_STATUS (AE_NO_MEMORY); 464 } 465 466 AcpiTbPrintTableHeader (RsdpAddress, ACPI_CAST_PTR (ACPI_TABLE_HEADER, Rsdp)); 467 468 /* Differentiate between RSDT and XSDT root tables */ 469 470 if (Rsdp->Revision > 1 && Rsdp->XsdtPhysicalAddress) 471 { 472 /* 473 * Root table is an XSDT (64-bit physical addresses). We must use the 474 * XSDT if the revision is > 1 and the XSDT pointer is present, as per 475 * the ACPI specification. 476 */ 477 Address = (ACPI_PHYSICAL_ADDRESS) Rsdp->XsdtPhysicalAddress; 478 TableEntrySize = sizeof (UINT64); 479 } 480 else 481 { 482 /* Root table is an RSDT (32-bit physical addresses) */ 483 484 Address = (ACPI_PHYSICAL_ADDRESS) Rsdp->RsdtPhysicalAddress; 485 TableEntrySize = sizeof (UINT32); 486 } 487 488 /* 489 * It is not possible to map more than one entry in some environments, 490 * so unmap the RSDP here before mapping other tables 491 */ 492 AcpiOsUnmapMemory (Rsdp, sizeof (ACPI_TABLE_RSDP)); 493 494 495 /* Map the RSDT/XSDT table header to get the full table length */ 496 497 Table = AcpiOsMapMemory (Address, sizeof (ACPI_TABLE_HEADER)); 498 if (!Table) 499 { 500 return_ACPI_STATUS (AE_NO_MEMORY); 501 } 502 503 AcpiTbPrintTableHeader (Address, Table); 504 505 /* Get the length of the full table, verify length and map entire table */ 506 507 Length = Table->Length; 508 AcpiOsUnmapMemory (Table, sizeof (ACPI_TABLE_HEADER)); 509 510 if (Length < sizeof (ACPI_TABLE_HEADER)) 511 { 512 ACPI_ERROR ((AE_INFO, "Invalid length 0x%X in RSDT/XSDT", Length)); 513 return_ACPI_STATUS (AE_INVALID_TABLE_LENGTH); 514 } 515 516 Table = AcpiOsMapMemory (Address, Length); 517 if (!Table) 518 { 519 return_ACPI_STATUS (AE_NO_MEMORY); 520 } 521 522 /* Validate the root table checksum */ 523 524 Status = AcpiTbVerifyChecksum (Table, Length); 525 if (ACPI_FAILURE (Status)) 526 { 527 AcpiOsUnmapMemory (Table, Length); 528 return_ACPI_STATUS (Status); 529 } 530 531 /* Calculate the number of tables described in the root table */ 532 533 TableCount = (UINT32) ((Table->Length - sizeof (ACPI_TABLE_HEADER)) / TableEntrySize); 534 535 /* 536 * First two entries in the table array are reserved for the DSDT and FACS, 537 * which are not actually present in the RSDT/XSDT - they come from the FADT 538 */ 539 TableEntry = ACPI_CAST_PTR (UINT8, Table) + sizeof (ACPI_TABLE_HEADER); 540 AcpiGbl_RootTableList.Count = 2; 541 542 /* 543 * Initialize the root table array from the RSDT/XSDT 544 */ 545 for (i = 0; i < TableCount; i++) 546 { 547 if (AcpiGbl_RootTableList.Count >= AcpiGbl_RootTableList.Size) 548 { 549 /* There is no more room in the root table array, attempt resize */ 550 551 Status = AcpiTbResizeRootTableList (); 552 if (ACPI_FAILURE (Status)) 553 { 554 ACPI_WARNING ((AE_INFO, "Truncating %u table entries!", 555 (unsigned) (AcpiGbl_RootTableList.Size - AcpiGbl_RootTableList.Count))); 556 break; 557 } 558 } 559 560 /* Get the table physical address (32-bit for RSDT, 64-bit for XSDT) */ 561 562 AcpiGbl_RootTableList.Tables[AcpiGbl_RootTableList.Count].Address = 563 AcpiTbGetRootTableEntry (TableEntry, TableEntrySize); 564 565 TableEntry += TableEntrySize; 566 AcpiGbl_RootTableList.Count++; 567 } 568 569 /* 570 * It is not possible to map more than one entry in some environments, 571 * so unmap the root table here before mapping other tables 572 */ 573 AcpiOsUnmapMemory (Table, Length); 574 575 /* 576 * Complete the initialization of the root table array by examining 577 * the header of each table 578 */ 579 for (i = 2; i < AcpiGbl_RootTableList.Count; i++) 580 { 581 AcpiTbInstallTable (AcpiGbl_RootTableList.Tables[i].Address, 582 Flags, NULL, i); 583 584 /* Special case for FADT - get the DSDT and FACS */ 585 586 if (ACPI_COMPARE_NAME ( 587 &AcpiGbl_RootTableList.Tables[i].Signature, ACPI_SIG_FADT)) 588 { 589 AcpiTbParseFadt (i, Flags); 590 } 591 } 592 593 return_ACPI_STATUS (AE_OK); 594 } 595