1 /****************************************************************************** 2 * 3 * Module Name: oslinuxtbl - Linux OSL for obtaining ACPI tables 4 * 5 *****************************************************************************/ 6 7 /****************************************************************************** 8 * 9 * 1. Copyright Notice 10 * 11 * Some or all of this work - Copyright (c) 1999 - 2017, Intel Corp. 12 * All rights reserved. 13 * 14 * 2. License 15 * 16 * 2.1. This is your license from Intel Corp. under its intellectual property 17 * rights. You may have additional license terms from the party that provided 18 * you this software, covering your right to use that party's intellectual 19 * property rights. 20 * 21 * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a 22 * copy of the source code appearing in this file ("Covered Code") an 23 * irrevocable, perpetual, worldwide license under Intel's copyrights in the 24 * base code distributed originally by Intel ("Original Intel Code") to copy, 25 * make derivatives, distribute, use and display any portion of the Covered 26 * Code in any form, with the right to sublicense such rights; and 27 * 28 * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent 29 * license (with the right to sublicense), under only those claims of Intel 30 * patents that are infringed by the Original Intel Code, to make, use, sell, 31 * offer to sell, and import the Covered Code and derivative works thereof 32 * solely to the minimum extent necessary to exercise the above copyright 33 * license, and in no event shall the patent license extend to any additions 34 * to or modifications of the Original Intel Code. No other license or right 35 * is granted directly or by implication, estoppel or otherwise; 36 * 37 * The above copyright and patent license is granted only if the following 38 * conditions are met: 39 * 40 * 3. Conditions 41 * 42 * 3.1. Redistribution of Source with Rights to Further Distribute Source. 43 * Redistribution of source code of any substantial portion of the Covered 44 * Code or modification with rights to further distribute source must include 45 * the above Copyright Notice, the above License, this list of Conditions, 46 * and the following Disclaimer and Export Compliance provision. In addition, 47 * Licensee must cause all Covered Code to which Licensee contributes to 48 * contain a file documenting the changes Licensee made to create that Covered 49 * Code and the date of any change. Licensee must include in that file the 50 * documentation of any changes made by any predecessor Licensee. Licensee 51 * must include a prominent statement that the modification is derived, 52 * directly or indirectly, from Original Intel Code. 53 * 54 * 3.2. Redistribution of Source with no Rights to Further Distribute Source. 55 * Redistribution of source code of any substantial portion of the Covered 56 * Code or modification without rights to further distribute source must 57 * include the following Disclaimer and Export Compliance provision in the 58 * documentation and/or other materials provided with distribution. In 59 * addition, Licensee may not authorize further sublicense of source of any 60 * portion of the Covered Code, and must include terms to the effect that the 61 * license from Licensee to its licensee is limited to the intellectual 62 * property embodied in the software Licensee provides to its licensee, and 63 * not to intellectual property embodied in modifications its licensee may 64 * make. 65 * 66 * 3.3. Redistribution of Executable. Redistribution in executable form of any 67 * substantial portion of the Covered Code or modification must reproduce the 68 * above Copyright Notice, and the following Disclaimer and Export Compliance 69 * provision in the documentation and/or other materials provided with the 70 * distribution. 71 * 72 * 3.4. Intel retains all right, title, and interest in and to the Original 73 * Intel Code. 74 * 75 * 3.5. Neither the name Intel nor any other trademark owned or controlled by 76 * Intel shall be used in advertising or otherwise to promote the sale, use or 77 * other dealings in products derived from or relating to the Covered Code 78 * without prior written authorization from Intel. 79 * 80 * 4. Disclaimer and Export Compliance 81 * 82 * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED 83 * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE 84 * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, 85 * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY 86 * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY 87 * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A 88 * PARTICULAR PURPOSE. 89 * 90 * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES 91 * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR 92 * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT, 93 * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY 94 * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL 95 * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS 96 * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY 97 * LIMITED REMEDY. 98 * 99 * 4.3. Licensee shall not export, either directly or indirectly, any of this 100 * software or system incorporating such software without first obtaining any 101 * required license or other approval from the U. S. Department of Commerce or 102 * any other agency or department of the United States Government. In the 103 * event Licensee exports any such software from the United States or 104 * re-exports any such software from a foreign destination, Licensee shall 105 * ensure that the distribution and export/re-export of the software is in 106 * compliance with all laws, regulations, orders, or other restrictions of the 107 * U.S. Export Administration Regulations. Licensee agrees that neither it nor 108 * any of its subsidiaries will export/re-export any technical data, process, 109 * software, or service, directly or indirectly, to any country for which the 110 * United States government or any agency thereof requires an export license, 111 * other governmental approval, or letter of assurance, without first obtaining 112 * such license, approval or letter. 113 * 114 ***************************************************************************** 115 * 116 * Alternatively, you may choose to be licensed under the terms of the 117 * following license: 118 * 119 * Redistribution and use in source and binary forms, with or without 120 * modification, are permitted provided that the following conditions 121 * are met: 122 * 1. Redistributions of source code must retain the above copyright 123 * notice, this list of conditions, and the following disclaimer, 124 * without modification. 125 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 126 * substantially similar to the "NO WARRANTY" disclaimer below 127 * ("Disclaimer") and any redistribution must be conditioned upon 128 * including a substantially similar Disclaimer requirement for further 129 * binary redistribution. 130 * 3. Neither the names of the above-listed copyright holders nor the names 131 * of any contributors may be used to endorse or promote products derived 132 * from this software without specific prior written permission. 133 * 134 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 135 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 136 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 137 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 138 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 139 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 140 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 141 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 142 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 143 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 144 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 145 * 146 * Alternatively, you may choose to be licensed under the terms of the 147 * GNU General Public License ("GPL") version 2 as published by the Free 148 * Software Foundation. 149 * 150 *****************************************************************************/ 151 152 #include "acpidump.h" 153 154 155 #define _COMPONENT ACPI_OS_SERVICES 156 ACPI_MODULE_NAME ("oslinuxtbl") 157 158 159 #ifndef PATH_MAX 160 #define PATH_MAX 256 161 #endif 162 163 164 /* List of information about obtained ACPI tables */ 165 166 typedef struct osl_table_info 167 { 168 struct osl_table_info *Next; 169 UINT32 Instance; 170 char Signature[ACPI_NAME_SIZE]; 171 172 } OSL_TABLE_INFO; 173 174 /* Local prototypes */ 175 176 static ACPI_STATUS 177 OslTableInitialize ( 178 void); 179 180 static ACPI_STATUS 181 OslTableNameFromFile ( 182 char *Filename, 183 char *Signature, 184 UINT32 *Instance); 185 186 static ACPI_STATUS 187 OslAddTableToList ( 188 char *Signature, 189 UINT32 Instance); 190 191 static ACPI_STATUS 192 OslReadTableFromFile ( 193 char *Filename, 194 ACPI_SIZE FileOffset, 195 char *Signature, 196 ACPI_TABLE_HEADER **Table); 197 198 static ACPI_STATUS 199 OslMapTable ( 200 ACPI_SIZE Address, 201 char *Signature, 202 ACPI_TABLE_HEADER **Table); 203 204 static void 205 OslUnmapTable ( 206 ACPI_TABLE_HEADER *Table); 207 208 static ACPI_PHYSICAL_ADDRESS 209 OslFindRsdpViaEfiByKeyword ( 210 FILE *File, 211 const char *Keyword); 212 213 static ACPI_PHYSICAL_ADDRESS 214 OslFindRsdpViaEfi ( 215 void); 216 217 static ACPI_STATUS 218 OslLoadRsdp ( 219 void); 220 221 static ACPI_STATUS 222 OslListCustomizedTables ( 223 char *Directory); 224 225 static ACPI_STATUS 226 OslGetCustomizedTable ( 227 char *Pathname, 228 char *Signature, 229 UINT32 Instance, 230 ACPI_TABLE_HEADER **Table, 231 ACPI_PHYSICAL_ADDRESS *Address); 232 233 static ACPI_STATUS 234 OslListBiosTables ( 235 void); 236 237 static ACPI_STATUS 238 OslGetBiosTable ( 239 char *Signature, 240 UINT32 Instance, 241 ACPI_TABLE_HEADER **Table, 242 ACPI_PHYSICAL_ADDRESS *Address); 243 244 static ACPI_STATUS 245 OslGetLastStatus ( 246 ACPI_STATUS DefaultStatus); 247 248 249 /* File locations */ 250 251 #define DYNAMIC_TABLE_DIR "/sys/firmware/acpi/tables/dynamic" 252 #define STATIC_TABLE_DIR "/sys/firmware/acpi/tables" 253 #define EFI_SYSTAB "/sys/firmware/efi/systab" 254 255 /* Should we get dynamically loaded SSDTs from DYNAMIC_TABLE_DIR? */ 256 257 UINT8 Gbl_DumpDynamicTables = TRUE; 258 259 /* Initialization flags */ 260 261 UINT8 Gbl_TableListInitialized = FALSE; 262 263 /* Local copies of main ACPI tables */ 264 265 ACPI_TABLE_RSDP Gbl_Rsdp; 266 ACPI_TABLE_FADT *Gbl_Fadt = NULL; 267 ACPI_TABLE_RSDT *Gbl_Rsdt = NULL; 268 ACPI_TABLE_XSDT *Gbl_Xsdt = NULL; 269 270 /* Table addresses */ 271 272 ACPI_PHYSICAL_ADDRESS Gbl_FadtAddress = 0; 273 ACPI_PHYSICAL_ADDRESS Gbl_RsdpAddress = 0; 274 275 /* Revision of RSD PTR */ 276 277 UINT8 Gbl_Revision = 0; 278 279 OSL_TABLE_INFO *Gbl_TableListHead = NULL; 280 UINT32 Gbl_TableCount = 0; 281 282 283 /****************************************************************************** 284 * 285 * FUNCTION: OslGetLastStatus 286 * 287 * PARAMETERS: DefaultStatus - Default error status to return 288 * 289 * RETURN: Status; Converted from errno. 290 * 291 * DESCRIPTION: Get last errno and conver it to ACPI_STATUS. 292 * 293 *****************************************************************************/ 294 295 static ACPI_STATUS 296 OslGetLastStatus ( 297 ACPI_STATUS DefaultStatus) 298 { 299 300 switch (errno) 301 { 302 case EACCES: 303 case EPERM: 304 305 return (AE_ACCESS); 306 307 case ENOENT: 308 309 return (AE_NOT_FOUND); 310 311 case ENOMEM: 312 313 return (AE_NO_MEMORY); 314 315 default: 316 317 return (DefaultStatus); 318 } 319 } 320 321 322 /****************************************************************************** 323 * 324 * FUNCTION: AcpiOsGetTableByAddress 325 * 326 * PARAMETERS: Address - Physical address of the ACPI table 327 * Table - Where a pointer to the table is returned 328 * 329 * RETURN: Status; Table buffer is returned if AE_OK. 330 * AE_NOT_FOUND: A valid table was not found at the address 331 * 332 * DESCRIPTION: Get an ACPI table via a physical memory address. 333 * 334 *****************************************************************************/ 335 336 ACPI_STATUS 337 AcpiOsGetTableByAddress ( 338 ACPI_PHYSICAL_ADDRESS Address, 339 ACPI_TABLE_HEADER **Table) 340 { 341 UINT32 TableLength; 342 ACPI_TABLE_HEADER *MappedTable; 343 ACPI_TABLE_HEADER *LocalTable = NULL; 344 ACPI_STATUS Status = AE_OK; 345 346 347 /* Get main ACPI tables from memory on first invocation of this function */ 348 349 Status = OslTableInitialize (); 350 if (ACPI_FAILURE (Status)) 351 { 352 return (Status); 353 } 354 355 /* Map the table and validate it */ 356 357 Status = OslMapTable (Address, NULL, &MappedTable); 358 if (ACPI_FAILURE (Status)) 359 { 360 return (Status); 361 } 362 363 /* Copy table to local buffer and return it */ 364 365 TableLength = ApGetTableLength (MappedTable); 366 if (TableLength == 0) 367 { 368 Status = AE_BAD_HEADER; 369 goto Exit; 370 } 371 372 LocalTable = calloc (1, TableLength); 373 if (!LocalTable) 374 { 375 Status = AE_NO_MEMORY; 376 goto Exit; 377 } 378 379 memcpy (LocalTable, MappedTable, TableLength); 380 381 Exit: 382 OslUnmapTable (MappedTable); 383 *Table = LocalTable; 384 return (Status); 385 } 386 387 388 /****************************************************************************** 389 * 390 * FUNCTION: AcpiOsGetTableByName 391 * 392 * PARAMETERS: Signature - ACPI Signature for desired table. Must be 393 * a null terminated 4-character string. 394 * Instance - Multiple table support for SSDT/UEFI (0...n) 395 * Must be 0 for other tables. 396 * Table - Where a pointer to the table is returned 397 * Address - Where the table physical address is returned 398 * 399 * RETURN: Status; Table buffer and physical address returned if AE_OK. 400 * AE_LIMIT: Instance is beyond valid limit 401 * AE_NOT_FOUND: A table with the signature was not found 402 * 403 * NOTE: Assumes the input signature is uppercase. 404 * 405 *****************************************************************************/ 406 407 ACPI_STATUS 408 AcpiOsGetTableByName ( 409 char *Signature, 410 UINT32 Instance, 411 ACPI_TABLE_HEADER **Table, 412 ACPI_PHYSICAL_ADDRESS *Address) 413 { 414 ACPI_STATUS Status; 415 416 417 /* Get main ACPI tables from memory on first invocation of this function */ 418 419 Status = OslTableInitialize (); 420 if (ACPI_FAILURE (Status)) 421 { 422 return (Status); 423 } 424 425 /* Not a main ACPI table, attempt to extract it from the RSDT/XSDT */ 426 427 if (!Gbl_DumpCustomizedTables) 428 { 429 /* Attempt to get the table from the memory */ 430 431 Status = OslGetBiosTable (Signature, Instance, Table, Address); 432 } 433 else 434 { 435 /* Attempt to get the table from the static directory */ 436 437 Status = OslGetCustomizedTable (STATIC_TABLE_DIR, Signature, 438 Instance, Table, Address); 439 } 440 441 if (ACPI_FAILURE (Status) && Status == AE_LIMIT) 442 { 443 if (Gbl_DumpDynamicTables) 444 { 445 /* Attempt to get a dynamic table */ 446 447 Status = OslGetCustomizedTable (DYNAMIC_TABLE_DIR, Signature, 448 Instance, Table, Address); 449 } 450 } 451 452 return (Status); 453 } 454 455 456 /****************************************************************************** 457 * 458 * FUNCTION: OslAddTableToList 459 * 460 * PARAMETERS: Signature - Table signature 461 * Instance - Table instance 462 * 463 * RETURN: Status; Successfully added if AE_OK. 464 * AE_NO_MEMORY: Memory allocation error 465 * 466 * DESCRIPTION: Insert a table structure into OSL table list. 467 * 468 *****************************************************************************/ 469 470 static ACPI_STATUS 471 OslAddTableToList ( 472 char *Signature, 473 UINT32 Instance) 474 { 475 OSL_TABLE_INFO *NewInfo; 476 OSL_TABLE_INFO *Next; 477 UINT32 NextInstance = 0; 478 BOOLEAN Found = FALSE; 479 480 481 NewInfo = calloc (1, sizeof (OSL_TABLE_INFO)); 482 if (!NewInfo) 483 { 484 return (AE_NO_MEMORY); 485 } 486 487 ACPI_MOVE_NAME (NewInfo->Signature, Signature); 488 489 if (!Gbl_TableListHead) 490 { 491 Gbl_TableListHead = NewInfo; 492 } 493 else 494 { 495 Next = Gbl_TableListHead; 496 while (1) 497 { 498 if (ACPI_COMPARE_NAME (Next->Signature, Signature)) 499 { 500 if (Next->Instance == Instance) 501 { 502 Found = TRUE; 503 } 504 if (Next->Instance >= NextInstance) 505 { 506 NextInstance = Next->Instance + 1; 507 } 508 } 509 510 if (!Next->Next) 511 { 512 break; 513 } 514 Next = Next->Next; 515 } 516 Next->Next = NewInfo; 517 } 518 519 if (Found) 520 { 521 if (Instance) 522 { 523 fprintf (stderr, 524 "%4.4s: Warning unmatched table instance %d, expected %d\n", 525 Signature, Instance, NextInstance); 526 } 527 Instance = NextInstance; 528 } 529 530 NewInfo->Instance = Instance; 531 Gbl_TableCount++; 532 533 return (AE_OK); 534 } 535 536 537 /****************************************************************************** 538 * 539 * FUNCTION: AcpiOsGetTableByIndex 540 * 541 * PARAMETERS: Index - Which table to get 542 * Table - Where a pointer to the table is returned 543 * Instance - Where a pointer to the table instance no. is 544 * returned 545 * Address - Where the table physical address is returned 546 * 547 * RETURN: Status; Table buffer and physical address returned if AE_OK. 548 * AE_LIMIT: Index is beyond valid limit 549 * 550 * DESCRIPTION: Get an ACPI table via an index value (0 through n). Returns 551 * AE_LIMIT when an invalid index is reached. Index is not 552 * necessarily an index into the RSDT/XSDT. 553 * 554 *****************************************************************************/ 555 556 ACPI_STATUS 557 AcpiOsGetTableByIndex ( 558 UINT32 Index, 559 ACPI_TABLE_HEADER **Table, 560 UINT32 *Instance, 561 ACPI_PHYSICAL_ADDRESS *Address) 562 { 563 OSL_TABLE_INFO *Info; 564 ACPI_STATUS Status; 565 UINT32 i; 566 567 568 /* Get main ACPI tables from memory on first invocation of this function */ 569 570 Status = OslTableInitialize (); 571 if (ACPI_FAILURE (Status)) 572 { 573 return (Status); 574 } 575 576 /* Validate Index */ 577 578 if (Index >= Gbl_TableCount) 579 { 580 return (AE_LIMIT); 581 } 582 583 /* Point to the table list entry specified by the Index argument */ 584 585 Info = Gbl_TableListHead; 586 for (i = 0; i < Index; i++) 587 { 588 Info = Info->Next; 589 } 590 591 /* Now we can just get the table via the signature */ 592 593 Status = AcpiOsGetTableByName (Info->Signature, Info->Instance, 594 Table, Address); 595 596 if (ACPI_SUCCESS (Status)) 597 { 598 *Instance = Info->Instance; 599 } 600 return (Status); 601 } 602 603 604 /****************************************************************************** 605 * 606 * FUNCTION: OslFindRsdpViaEfiByKeyword 607 * 608 * PARAMETERS: Keyword - Character string indicating ACPI GUID version 609 * in the EFI table 610 * 611 * RETURN: RSDP address if found 612 * 613 * DESCRIPTION: Find RSDP address via EFI using keyword indicating the ACPI 614 * GUID version. 615 * 616 *****************************************************************************/ 617 618 static ACPI_PHYSICAL_ADDRESS 619 OslFindRsdpViaEfiByKeyword ( 620 FILE *File, 621 const char *Keyword) 622 { 623 char Buffer[80]; 624 unsigned long long Address = 0; 625 char Format[32]; 626 627 628 snprintf (Format, 32, "%s=%s", Keyword, "%llx"); 629 fseek (File, 0, SEEK_SET); 630 while (fgets (Buffer, 80, File)) 631 { 632 if (sscanf (Buffer, Format, &Address) == 1) 633 { 634 break; 635 } 636 } 637 638 return ((ACPI_PHYSICAL_ADDRESS) (Address)); 639 } 640 641 642 /****************************************************************************** 643 * 644 * FUNCTION: OslFindRsdpViaEfi 645 * 646 * PARAMETERS: None 647 * 648 * RETURN: RSDP address if found 649 * 650 * DESCRIPTION: Find RSDP address via EFI. 651 * 652 *****************************************************************************/ 653 654 static ACPI_PHYSICAL_ADDRESS 655 OslFindRsdpViaEfi ( 656 void) 657 { 658 FILE *File; 659 ACPI_PHYSICAL_ADDRESS Address = 0; 660 661 662 File = fopen (EFI_SYSTAB, "r"); 663 if (File) 664 { 665 Address = OslFindRsdpViaEfiByKeyword (File, "ACPI20"); 666 if (!Address) 667 { 668 Address = OslFindRsdpViaEfiByKeyword (File, "ACPI"); 669 } 670 fclose (File); 671 } 672 673 return (Address); 674 } 675 676 677 /****************************************************************************** 678 * 679 * FUNCTION: OslLoadRsdp 680 * 681 * PARAMETERS: None 682 * 683 * RETURN: Status 684 * 685 * DESCRIPTION: Scan and load RSDP. 686 * 687 *****************************************************************************/ 688 689 static ACPI_STATUS 690 OslLoadRsdp ( 691 void) 692 { 693 ACPI_TABLE_HEADER *MappedTable; 694 UINT8 *RsdpAddress; 695 ACPI_PHYSICAL_ADDRESS RsdpBase; 696 ACPI_SIZE RsdpSize; 697 698 699 /* Get RSDP from memory */ 700 701 RsdpSize = sizeof (ACPI_TABLE_RSDP); 702 if (Gbl_RsdpBase) 703 { 704 RsdpBase = Gbl_RsdpBase; 705 } 706 else 707 { 708 RsdpBase = OslFindRsdpViaEfi (); 709 } 710 711 if (!RsdpBase) 712 { 713 RsdpBase = ACPI_HI_RSDP_WINDOW_BASE; 714 RsdpSize = ACPI_HI_RSDP_WINDOW_SIZE; 715 } 716 717 RsdpAddress = AcpiOsMapMemory (RsdpBase, RsdpSize); 718 if (!RsdpAddress) 719 { 720 return (OslGetLastStatus (AE_BAD_ADDRESS)); 721 } 722 723 /* Search low memory for the RSDP */ 724 725 MappedTable = ACPI_CAST_PTR (ACPI_TABLE_HEADER, 726 AcpiTbScanMemoryForRsdp (RsdpAddress, RsdpSize)); 727 if (!MappedTable) 728 { 729 AcpiOsUnmapMemory (RsdpAddress, RsdpSize); 730 return (AE_NOT_FOUND); 731 } 732 733 Gbl_RsdpAddress = RsdpBase + (ACPI_CAST8 (MappedTable) - RsdpAddress); 734 735 memcpy (&Gbl_Rsdp, MappedTable, sizeof (ACPI_TABLE_RSDP)); 736 AcpiOsUnmapMemory (RsdpAddress, RsdpSize); 737 738 return (AE_OK); 739 } 740 741 742 /****************************************************************************** 743 * 744 * FUNCTION: OslCanUseXsdt 745 * 746 * PARAMETERS: None 747 * 748 * RETURN: TRUE if XSDT is allowed to be used. 749 * 750 * DESCRIPTION: This function collects logic that can be used to determine if 751 * XSDT should be used instead of RSDT. 752 * 753 *****************************************************************************/ 754 755 static BOOLEAN 756 OslCanUseXsdt ( 757 void) 758 { 759 if (Gbl_Revision && !AcpiGbl_DoNotUseXsdt) 760 { 761 return (TRUE); 762 } 763 else 764 { 765 return (FALSE); 766 } 767 } 768 769 770 /****************************************************************************** 771 * 772 * FUNCTION: OslTableInitialize 773 * 774 * PARAMETERS: None 775 * 776 * RETURN: Status 777 * 778 * DESCRIPTION: Initialize ACPI table data. Get and store main ACPI tables to 779 * local variables. Main ACPI tables include RSDT, FADT, RSDT, 780 * and/or XSDT. 781 * 782 *****************************************************************************/ 783 784 static ACPI_STATUS 785 OslTableInitialize ( 786 void) 787 { 788 ACPI_STATUS Status; 789 ACPI_PHYSICAL_ADDRESS Address; 790 791 792 if (Gbl_TableListInitialized) 793 { 794 return (AE_OK); 795 } 796 797 if (!Gbl_DumpCustomizedTables) 798 { 799 /* Get RSDP from memory */ 800 801 Status = OslLoadRsdp (); 802 if (ACPI_FAILURE (Status)) 803 { 804 return (Status); 805 } 806 807 /* Get XSDT from memory */ 808 809 if (Gbl_Rsdp.Revision && !Gbl_DoNotDumpXsdt) 810 { 811 if (Gbl_Xsdt) 812 { 813 free (Gbl_Xsdt); 814 Gbl_Xsdt = NULL; 815 } 816 817 Gbl_Revision = 2; 818 Status = OslGetBiosTable (ACPI_SIG_XSDT, 0, 819 ACPI_CAST_PTR (ACPI_TABLE_HEADER *, &Gbl_Xsdt), &Address); 820 if (ACPI_FAILURE (Status)) 821 { 822 return (Status); 823 } 824 } 825 826 /* Get RSDT from memory */ 827 828 if (Gbl_Rsdp.RsdtPhysicalAddress) 829 { 830 if (Gbl_Rsdt) 831 { 832 free (Gbl_Rsdt); 833 Gbl_Rsdt = NULL; 834 } 835 836 Status = OslGetBiosTable (ACPI_SIG_RSDT, 0, 837 ACPI_CAST_PTR (ACPI_TABLE_HEADER *, &Gbl_Rsdt), &Address); 838 if (ACPI_FAILURE (Status)) 839 { 840 return (Status); 841 } 842 } 843 844 /* Get FADT from memory */ 845 846 if (Gbl_Fadt) 847 { 848 free (Gbl_Fadt); 849 Gbl_Fadt = NULL; 850 } 851 852 Status = OslGetBiosTable (ACPI_SIG_FADT, 0, 853 ACPI_CAST_PTR (ACPI_TABLE_HEADER *, &Gbl_Fadt), &Gbl_FadtAddress); 854 if (ACPI_FAILURE (Status)) 855 { 856 return (Status); 857 } 858 859 /* Add mandatory tables to global table list first */ 860 861 Status = OslAddTableToList (ACPI_RSDP_NAME, 0); 862 if (ACPI_FAILURE (Status)) 863 { 864 return (Status); 865 } 866 867 Status = OslAddTableToList (ACPI_SIG_RSDT, 0); 868 if (ACPI_FAILURE (Status)) 869 { 870 return (Status); 871 } 872 873 if (Gbl_Revision == 2) 874 { 875 Status = OslAddTableToList (ACPI_SIG_XSDT, 0); 876 if (ACPI_FAILURE (Status)) 877 { 878 return (Status); 879 } 880 } 881 882 Status = OslAddTableToList (ACPI_SIG_DSDT, 0); 883 if (ACPI_FAILURE (Status)) 884 { 885 return (Status); 886 } 887 888 Status = OslAddTableToList (ACPI_SIG_FACS, 0); 889 if (ACPI_FAILURE (Status)) 890 { 891 return (Status); 892 } 893 894 /* Add all tables found in the memory */ 895 896 Status = OslListBiosTables (); 897 if (ACPI_FAILURE (Status)) 898 { 899 return (Status); 900 } 901 } 902 else 903 { 904 /* Add all tables found in the static directory */ 905 906 Status = OslListCustomizedTables (STATIC_TABLE_DIR); 907 if (ACPI_FAILURE (Status)) 908 { 909 return (Status); 910 } 911 } 912 913 if (Gbl_DumpDynamicTables) 914 { 915 /* Add all dynamically loaded tables in the dynamic directory */ 916 917 Status = OslListCustomizedTables (DYNAMIC_TABLE_DIR); 918 if (ACPI_FAILURE (Status)) 919 { 920 return (Status); 921 } 922 } 923 924 Gbl_TableListInitialized = TRUE; 925 return (AE_OK); 926 } 927 928 929 /****************************************************************************** 930 * 931 * FUNCTION: OslListBiosTables 932 * 933 * PARAMETERS: None 934 * 935 * RETURN: Status; Table list is initialized if AE_OK. 936 * 937 * DESCRIPTION: Add ACPI tables to the table list from memory. 938 * 939 * NOTE: This works on Linux as table customization does not modify the 940 * addresses stored in RSDP/RSDT/XSDT/FADT. 941 * 942 *****************************************************************************/ 943 944 static ACPI_STATUS 945 OslListBiosTables ( 946 void) 947 { 948 ACPI_TABLE_HEADER *MappedTable = NULL; 949 UINT8 *TableData; 950 UINT8 NumberOfTables; 951 UINT8 ItemSize; 952 ACPI_PHYSICAL_ADDRESS TableAddress = 0; 953 ACPI_STATUS Status = AE_OK; 954 UINT32 i; 955 956 957 if (OslCanUseXsdt ()) 958 { 959 ItemSize = sizeof (UINT64); 960 TableData = ACPI_CAST8 (Gbl_Xsdt) + sizeof (ACPI_TABLE_HEADER); 961 NumberOfTables = 962 (UINT8) ((Gbl_Xsdt->Header.Length - sizeof (ACPI_TABLE_HEADER)) 963 / ItemSize); 964 } 965 else /* Use RSDT if XSDT is not available */ 966 { 967 ItemSize = sizeof (UINT32); 968 TableData = ACPI_CAST8 (Gbl_Rsdt) + sizeof (ACPI_TABLE_HEADER); 969 NumberOfTables = 970 (UINT8) ((Gbl_Rsdt->Header.Length - sizeof (ACPI_TABLE_HEADER)) 971 / ItemSize); 972 } 973 974 /* Search RSDT/XSDT for the requested table */ 975 976 for (i = 0; i < NumberOfTables; ++i, TableData += ItemSize) 977 { 978 if (OslCanUseXsdt ()) 979 { 980 TableAddress = 981 (ACPI_PHYSICAL_ADDRESS) (*ACPI_CAST64 (TableData)); 982 } 983 else 984 { 985 TableAddress = 986 (ACPI_PHYSICAL_ADDRESS) (*ACPI_CAST32 (TableData)); 987 } 988 989 /* Skip NULL entries in RSDT/XSDT */ 990 991 if (!TableAddress) 992 { 993 continue; 994 } 995 996 Status = OslMapTable (TableAddress, NULL, &MappedTable); 997 if (ACPI_FAILURE (Status)) 998 { 999 return (Status); 1000 } 1001 1002 OslAddTableToList (MappedTable->Signature, 0); 1003 OslUnmapTable (MappedTable); 1004 } 1005 1006 return (AE_OK); 1007 } 1008 1009 1010 /****************************************************************************** 1011 * 1012 * FUNCTION: OslGetBiosTable 1013 * 1014 * PARAMETERS: Signature - ACPI Signature for common table. Must be 1015 * a null terminated 4-character string. 1016 * Instance - Multiple table support for SSDT/UEFI (0...n) 1017 * Must be 0 for other tables. 1018 * Table - Where a pointer to the table is returned 1019 * Address - Where the table physical address is returned 1020 * 1021 * RETURN: Status; Table buffer and physical address returned if AE_OK. 1022 * AE_LIMIT: Instance is beyond valid limit 1023 * AE_NOT_FOUND: A table with the signature was not found 1024 * 1025 * DESCRIPTION: Get a BIOS provided ACPI table 1026 * 1027 * NOTE: Assumes the input signature is uppercase. 1028 * 1029 *****************************************************************************/ 1030 1031 static ACPI_STATUS 1032 OslGetBiosTable ( 1033 char *Signature, 1034 UINT32 Instance, 1035 ACPI_TABLE_HEADER **Table, 1036 ACPI_PHYSICAL_ADDRESS *Address) 1037 { 1038 ACPI_TABLE_HEADER *LocalTable = NULL; 1039 ACPI_TABLE_HEADER *MappedTable = NULL; 1040 UINT8 *TableData; 1041 UINT8 NumberOfTables; 1042 UINT8 ItemSize; 1043 UINT32 CurrentInstance = 0; 1044 ACPI_PHYSICAL_ADDRESS TableAddress = 0; 1045 UINT32 TableLength = 0; 1046 ACPI_STATUS Status = AE_OK; 1047 UINT32 i; 1048 1049 1050 /* Handle special tables whose addresses are not in RSDT/XSDT */ 1051 1052 if (ACPI_COMPARE_NAME (Signature, ACPI_RSDP_NAME) || 1053 ACPI_COMPARE_NAME (Signature, ACPI_SIG_RSDT) || 1054 ACPI_COMPARE_NAME (Signature, ACPI_SIG_XSDT) || 1055 ACPI_COMPARE_NAME (Signature, ACPI_SIG_DSDT) || 1056 ACPI_COMPARE_NAME (Signature, ACPI_SIG_FACS)) 1057 { 1058 if (Instance > 0) 1059 { 1060 return (AE_LIMIT); 1061 } 1062 1063 /* 1064 * Get the appropriate address, either 32-bit or 64-bit. Be very 1065 * careful about the FADT length and validate table addresses. 1066 * Note: The 64-bit addresses have priority. 1067 */ 1068 if (ACPI_COMPARE_NAME (Signature, ACPI_SIG_DSDT)) 1069 { 1070 if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_XDSDT) && 1071 Gbl_Fadt->XDsdt) 1072 { 1073 TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->XDsdt; 1074 } 1075 else if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_DSDT) && 1076 Gbl_Fadt->Dsdt) 1077 { 1078 TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->Dsdt; 1079 } 1080 } 1081 else if (ACPI_COMPARE_NAME (Signature, ACPI_SIG_FACS)) 1082 { 1083 if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_XFACS) && 1084 Gbl_Fadt->XFacs) 1085 { 1086 TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->XFacs; 1087 } 1088 else if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_FACS) && 1089 Gbl_Fadt->Facs) 1090 { 1091 TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->Facs; 1092 } 1093 } 1094 else if (ACPI_COMPARE_NAME (Signature, ACPI_SIG_XSDT)) 1095 { 1096 if (!Gbl_Revision) 1097 { 1098 return (AE_BAD_SIGNATURE); 1099 } 1100 TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Rsdp.XsdtPhysicalAddress; 1101 } 1102 else if (ACPI_COMPARE_NAME (Signature, ACPI_SIG_RSDT)) 1103 { 1104 TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Rsdp.RsdtPhysicalAddress; 1105 } 1106 else 1107 { 1108 TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_RsdpAddress; 1109 Signature = ACPI_SIG_RSDP; 1110 } 1111 1112 /* Now we can get the requested special table */ 1113 1114 Status = OslMapTable (TableAddress, Signature, &MappedTable); 1115 if (ACPI_FAILURE (Status)) 1116 { 1117 return (Status); 1118 } 1119 1120 TableLength = ApGetTableLength (MappedTable); 1121 } 1122 else /* Case for a normal ACPI table */ 1123 { 1124 if (OslCanUseXsdt ()) 1125 { 1126 ItemSize = sizeof (UINT64); 1127 TableData = ACPI_CAST8 (Gbl_Xsdt) + sizeof (ACPI_TABLE_HEADER); 1128 NumberOfTables = 1129 (UINT8) ((Gbl_Xsdt->Header.Length - sizeof (ACPI_TABLE_HEADER)) 1130 / ItemSize); 1131 } 1132 else /* Use RSDT if XSDT is not available */ 1133 { 1134 ItemSize = sizeof (UINT32); 1135 TableData = ACPI_CAST8 (Gbl_Rsdt) + sizeof (ACPI_TABLE_HEADER); 1136 NumberOfTables = 1137 (UINT8) ((Gbl_Rsdt->Header.Length - sizeof (ACPI_TABLE_HEADER)) 1138 / ItemSize); 1139 } 1140 1141 /* Search RSDT/XSDT for the requested table */ 1142 1143 for (i = 0; i < NumberOfTables; ++i, TableData += ItemSize) 1144 { 1145 if (OslCanUseXsdt ()) 1146 { 1147 TableAddress = 1148 (ACPI_PHYSICAL_ADDRESS) (*ACPI_CAST64 (TableData)); 1149 } 1150 else 1151 { 1152 TableAddress = 1153 (ACPI_PHYSICAL_ADDRESS) (*ACPI_CAST32 (TableData)); 1154 } 1155 1156 /* Skip NULL entries in RSDT/XSDT */ 1157 1158 if (!TableAddress) 1159 { 1160 continue; 1161 } 1162 1163 Status = OslMapTable (TableAddress, NULL, &MappedTable); 1164 if (ACPI_FAILURE (Status)) 1165 { 1166 return (Status); 1167 } 1168 TableLength = MappedTable->Length; 1169 1170 /* Does this table match the requested signature? */ 1171 1172 if (!ACPI_COMPARE_NAME (MappedTable->Signature, Signature)) 1173 { 1174 OslUnmapTable (MappedTable); 1175 MappedTable = NULL; 1176 continue; 1177 } 1178 1179 /* Match table instance (for SSDT/UEFI tables) */ 1180 1181 if (CurrentInstance != Instance) 1182 { 1183 OslUnmapTable (MappedTable); 1184 MappedTable = NULL; 1185 CurrentInstance++; 1186 continue; 1187 } 1188 1189 break; 1190 } 1191 } 1192 1193 if (!MappedTable) 1194 { 1195 return (AE_LIMIT); 1196 } 1197 1198 if (TableLength == 0) 1199 { 1200 Status = AE_BAD_HEADER; 1201 goto Exit; 1202 } 1203 1204 /* Copy table to local buffer and return it */ 1205 1206 LocalTable = calloc (1, TableLength); 1207 if (!LocalTable) 1208 { 1209 Status = AE_NO_MEMORY; 1210 goto Exit; 1211 } 1212 1213 memcpy (LocalTable, MappedTable, TableLength); 1214 *Address = TableAddress; 1215 *Table = LocalTable; 1216 1217 Exit: 1218 OslUnmapTable (MappedTable); 1219 return (Status); 1220 } 1221 1222 1223 /****************************************************************************** 1224 * 1225 * FUNCTION: OslListCustomizedTables 1226 * 1227 * PARAMETERS: Directory - Directory that contains the tables 1228 * 1229 * RETURN: Status; Table list is initialized if AE_OK. 1230 * 1231 * DESCRIPTION: Add ACPI tables to the table list from a directory. 1232 * 1233 *****************************************************************************/ 1234 1235 static ACPI_STATUS 1236 OslListCustomizedTables ( 1237 char *Directory) 1238 { 1239 void *TableDir; 1240 UINT32 Instance; 1241 char TempName[ACPI_NAME_SIZE]; 1242 char *Filename; 1243 ACPI_STATUS Status = AE_OK; 1244 1245 1246 /* Open the requested directory */ 1247 1248 TableDir = AcpiOsOpenDirectory (Directory, "*", REQUEST_FILE_ONLY); 1249 if (!TableDir) 1250 { 1251 return (OslGetLastStatus (AE_NOT_FOUND)); 1252 } 1253 1254 /* Examine all entries in this directory */ 1255 1256 while ((Filename = AcpiOsGetNextFilename (TableDir))) 1257 { 1258 /* Extract table name and instance number */ 1259 1260 Status = OslTableNameFromFile (Filename, TempName, &Instance); 1261 1262 /* Ignore meaningless files */ 1263 1264 if (ACPI_FAILURE (Status)) 1265 { 1266 continue; 1267 } 1268 1269 /* Add new info node to global table list */ 1270 1271 Status = OslAddTableToList (TempName, Instance); 1272 if (ACPI_FAILURE (Status)) 1273 { 1274 break; 1275 } 1276 } 1277 1278 AcpiOsCloseDirectory (TableDir); 1279 return (Status); 1280 } 1281 1282 1283 /****************************************************************************** 1284 * 1285 * FUNCTION: OslMapTable 1286 * 1287 * PARAMETERS: Address - Address of the table in memory 1288 * Signature - Optional ACPI Signature for desired table. 1289 * Null terminated 4-character string. 1290 * Table - Where a pointer to the mapped table is 1291 * returned 1292 * 1293 * RETURN: Status; Mapped table is returned if AE_OK. 1294 * AE_NOT_FOUND: A valid table was not found at the address 1295 * 1296 * DESCRIPTION: Map entire ACPI table into caller's address space. 1297 * 1298 *****************************************************************************/ 1299 1300 static ACPI_STATUS 1301 OslMapTable ( 1302 ACPI_SIZE Address, 1303 char *Signature, 1304 ACPI_TABLE_HEADER **Table) 1305 { 1306 ACPI_TABLE_HEADER *MappedTable; 1307 UINT32 Length; 1308 1309 1310 if (!Address) 1311 { 1312 return (AE_BAD_ADDRESS); 1313 } 1314 1315 /* 1316 * Map the header so we can get the table length. 1317 * Use sizeof (ACPI_TABLE_HEADER) as: 1318 * 1. it is bigger than 24 to include RSDP->Length 1319 * 2. it is smaller than sizeof (ACPI_TABLE_RSDP) 1320 */ 1321 MappedTable = AcpiOsMapMemory (Address, sizeof (ACPI_TABLE_HEADER)); 1322 if (!MappedTable) 1323 { 1324 fprintf (stderr, "Could not map table header at 0x%8.8X%8.8X\n", 1325 ACPI_FORMAT_UINT64 (Address)); 1326 return (OslGetLastStatus (AE_BAD_ADDRESS)); 1327 } 1328 1329 /* If specified, signature must match */ 1330 1331 if (Signature) 1332 { 1333 if (ACPI_VALIDATE_RSDP_SIG (Signature)) 1334 { 1335 if (!ACPI_VALIDATE_RSDP_SIG (MappedTable->Signature)) 1336 { 1337 AcpiOsUnmapMemory (MappedTable, sizeof (ACPI_TABLE_HEADER)); 1338 return (AE_BAD_SIGNATURE); 1339 } 1340 } 1341 else if (!ACPI_COMPARE_NAME (Signature, MappedTable->Signature)) 1342 { 1343 AcpiOsUnmapMemory (MappedTable, sizeof (ACPI_TABLE_HEADER)); 1344 return (AE_BAD_SIGNATURE); 1345 } 1346 } 1347 1348 /* Map the entire table */ 1349 1350 Length = ApGetTableLength (MappedTable); 1351 AcpiOsUnmapMemory (MappedTable, sizeof (ACPI_TABLE_HEADER)); 1352 if (Length == 0) 1353 { 1354 return (AE_BAD_HEADER); 1355 } 1356 1357 MappedTable = AcpiOsMapMemory (Address, Length); 1358 if (!MappedTable) 1359 { 1360 fprintf (stderr, "Could not map table at 0x%8.8X%8.8X length %8.8X\n", 1361 ACPI_FORMAT_UINT64 (Address), Length); 1362 return (OslGetLastStatus (AE_INVALID_TABLE_LENGTH)); 1363 } 1364 1365 (void) ApIsValidChecksum (MappedTable); 1366 1367 *Table = MappedTable; 1368 return (AE_OK); 1369 } 1370 1371 1372 /****************************************************************************** 1373 * 1374 * FUNCTION: OslUnmapTable 1375 * 1376 * PARAMETERS: Table - A pointer to the mapped table 1377 * 1378 * RETURN: None 1379 * 1380 * DESCRIPTION: Unmap entire ACPI table. 1381 * 1382 *****************************************************************************/ 1383 1384 static void 1385 OslUnmapTable ( 1386 ACPI_TABLE_HEADER *Table) 1387 { 1388 if (Table) 1389 { 1390 AcpiOsUnmapMemory (Table, ApGetTableLength (Table)); 1391 } 1392 } 1393 1394 1395 /****************************************************************************** 1396 * 1397 * FUNCTION: OslTableNameFromFile 1398 * 1399 * PARAMETERS: Filename - File that contains the desired table 1400 * Signature - Pointer to 4-character buffer to store 1401 * extracted table signature. 1402 * Instance - Pointer to integer to store extracted 1403 * table instance number. 1404 * 1405 * RETURN: Status; Table name is extracted if AE_OK. 1406 * 1407 * DESCRIPTION: Extract table signature and instance number from a table file 1408 * name. 1409 * 1410 *****************************************************************************/ 1411 1412 static ACPI_STATUS 1413 OslTableNameFromFile ( 1414 char *Filename, 1415 char *Signature, 1416 UINT32 *Instance) 1417 { 1418 1419 /* Ignore meaningless files */ 1420 1421 if (strlen (Filename) < ACPI_NAME_SIZE) 1422 { 1423 return (AE_BAD_SIGNATURE); 1424 } 1425 1426 /* Extract instance number */ 1427 1428 if (isdigit ((int) Filename[ACPI_NAME_SIZE])) 1429 { 1430 sscanf (&Filename[ACPI_NAME_SIZE], "%u", Instance); 1431 } 1432 else if (strlen (Filename) != ACPI_NAME_SIZE) 1433 { 1434 return (AE_BAD_SIGNATURE); 1435 } 1436 else 1437 { 1438 *Instance = 0; 1439 } 1440 1441 /* Extract signature */ 1442 1443 ACPI_MOVE_NAME (Signature, Filename); 1444 return (AE_OK); 1445 } 1446 1447 1448 /****************************************************************************** 1449 * 1450 * FUNCTION: OslReadTableFromFile 1451 * 1452 * PARAMETERS: Filename - File that contains the desired table 1453 * FileOffset - Offset of the table in file 1454 * Signature - Optional ACPI Signature for desired table. 1455 * A null terminated 4-character string. 1456 * Table - Where a pointer to the table is returned 1457 * 1458 * RETURN: Status; Table buffer is returned if AE_OK. 1459 * 1460 * DESCRIPTION: Read a ACPI table from a file. 1461 * 1462 *****************************************************************************/ 1463 1464 static ACPI_STATUS 1465 OslReadTableFromFile ( 1466 char *Filename, 1467 ACPI_SIZE FileOffset, 1468 char *Signature, 1469 ACPI_TABLE_HEADER **Table) 1470 { 1471 FILE *TableFile; 1472 ACPI_TABLE_HEADER Header; 1473 ACPI_TABLE_HEADER *LocalTable = NULL; 1474 UINT32 TableLength; 1475 INT32 Count; 1476 ACPI_STATUS Status = AE_OK; 1477 1478 1479 /* Open the file */ 1480 1481 TableFile = fopen (Filename, "rb"); 1482 if (TableFile == NULL) 1483 { 1484 fprintf (stderr, "Could not open table file: %s\n", Filename); 1485 return (OslGetLastStatus (AE_NOT_FOUND)); 1486 } 1487 1488 fseek (TableFile, FileOffset, SEEK_SET); 1489 1490 /* Read the Table header to get the table length */ 1491 1492 Count = fread (&Header, 1, sizeof (ACPI_TABLE_HEADER), TableFile); 1493 if (Count != sizeof (ACPI_TABLE_HEADER)) 1494 { 1495 fprintf (stderr, "Could not read table header: %s\n", Filename); 1496 Status = AE_BAD_HEADER; 1497 goto Exit; 1498 } 1499 1500 /* If signature is specified, it must match the table */ 1501 1502 if (Signature) 1503 { 1504 if (ACPI_VALIDATE_RSDP_SIG (Signature)) 1505 { 1506 if (!ACPI_VALIDATE_RSDP_SIG (Header.Signature)) { 1507 fprintf (stderr, "Incorrect RSDP signature: found %8.8s\n", 1508 Header.Signature); 1509 Status = AE_BAD_SIGNATURE; 1510 goto Exit; 1511 } 1512 } 1513 else if (!ACPI_COMPARE_NAME (Signature, Header.Signature)) 1514 { 1515 fprintf (stderr, "Incorrect signature: Expecting %4.4s, found %4.4s\n", 1516 Signature, Header.Signature); 1517 Status = AE_BAD_SIGNATURE; 1518 goto Exit; 1519 } 1520 } 1521 1522 TableLength = ApGetTableLength (&Header); 1523 if (TableLength == 0) 1524 { 1525 Status = AE_BAD_HEADER; 1526 goto Exit; 1527 } 1528 1529 /* Read the entire table into a local buffer */ 1530 1531 LocalTable = calloc (1, TableLength); 1532 if (!LocalTable) 1533 { 1534 fprintf (stderr, 1535 "%4.4s: Could not allocate buffer for table of length %X\n", 1536 Header.Signature, TableLength); 1537 Status = AE_NO_MEMORY; 1538 goto Exit; 1539 } 1540 1541 fseek (TableFile, FileOffset, SEEK_SET); 1542 1543 Count = fread (LocalTable, 1, TableLength, TableFile); 1544 if (Count != TableLength) 1545 { 1546 fprintf (stderr, "%4.4s: Could not read table content\n", 1547 Header.Signature); 1548 Status = AE_INVALID_TABLE_LENGTH; 1549 goto Exit; 1550 } 1551 1552 /* Validate checksum */ 1553 1554 (void) ApIsValidChecksum (LocalTable); 1555 1556 Exit: 1557 fclose (TableFile); 1558 *Table = LocalTable; 1559 return (Status); 1560 } 1561 1562 1563 /****************************************************************************** 1564 * 1565 * FUNCTION: OslGetCustomizedTable 1566 * 1567 * PARAMETERS: Pathname - Directory to find Linux customized table 1568 * Signature - ACPI Signature for desired table. Must be 1569 * a null terminated 4-character string. 1570 * Instance - Multiple table support for SSDT/UEFI (0...n) 1571 * Must be 0 for other tables. 1572 * Table - Where a pointer to the table is returned 1573 * Address - Where the table physical address is returned 1574 * 1575 * RETURN: Status; Table buffer is returned if AE_OK. 1576 * AE_LIMIT: Instance is beyond valid limit 1577 * AE_NOT_FOUND: A table with the signature was not found 1578 * 1579 * DESCRIPTION: Get an OS customized table. 1580 * 1581 *****************************************************************************/ 1582 1583 static ACPI_STATUS 1584 OslGetCustomizedTable ( 1585 char *Pathname, 1586 char *Signature, 1587 UINT32 Instance, 1588 ACPI_TABLE_HEADER **Table, 1589 ACPI_PHYSICAL_ADDRESS *Address) 1590 { 1591 void *TableDir; 1592 UINT32 CurrentInstance = 0; 1593 char TempName[ACPI_NAME_SIZE]; 1594 char TableFilename[PATH_MAX]; 1595 char *Filename; 1596 ACPI_STATUS Status; 1597 1598 1599 /* Open the directory for customized tables */ 1600 1601 TableDir = AcpiOsOpenDirectory (Pathname, "*", REQUEST_FILE_ONLY); 1602 if (!TableDir) 1603 { 1604 return (OslGetLastStatus (AE_NOT_FOUND)); 1605 } 1606 1607 /* Attempt to find the table in the directory */ 1608 1609 while ((Filename = AcpiOsGetNextFilename (TableDir))) 1610 { 1611 /* Ignore meaningless files */ 1612 1613 if (!ACPI_COMPARE_NAME (Filename, Signature)) 1614 { 1615 continue; 1616 } 1617 1618 /* Extract table name and instance number */ 1619 1620 Status = OslTableNameFromFile (Filename, TempName, &CurrentInstance); 1621 1622 /* Ignore meaningless files */ 1623 1624 if (ACPI_FAILURE (Status) || CurrentInstance != Instance) 1625 { 1626 continue; 1627 } 1628 1629 /* Create the table pathname */ 1630 1631 if (Instance != 0) 1632 { 1633 sprintf (TableFilename, "%s/%4.4s%d", Pathname, TempName, Instance); 1634 } 1635 else 1636 { 1637 sprintf (TableFilename, "%s/%4.4s", Pathname, TempName); 1638 } 1639 break; 1640 } 1641 1642 AcpiOsCloseDirectory (TableDir); 1643 1644 if (!Filename) 1645 { 1646 return (AE_LIMIT); 1647 } 1648 1649 /* There is no physical address saved for customized tables, use zero */ 1650 1651 *Address = 0; 1652 Status = OslReadTableFromFile (TableFilename, 0, NULL, Table); 1653 1654 return (Status); 1655 } 1656