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 - 2019, 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_NAMESEG_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_COPY_NAMESEG (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_NAMESEG (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 == 0) 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; 1045 ACPI_PHYSICAL_ADDRESS FirstTableAddress = 0; 1046 UINT32 TableLength = 0; 1047 ACPI_STATUS Status = AE_OK; 1048 UINT32 i; 1049 1050 1051 /* Handle special tables whose addresses are not in RSDT/XSDT */ 1052 1053 if (ACPI_COMPARE_NAMESEG (Signature, ACPI_RSDP_NAME) || 1054 ACPI_COMPARE_NAMESEG (Signature, ACPI_SIG_RSDT) || 1055 ACPI_COMPARE_NAMESEG (Signature, ACPI_SIG_XSDT) || 1056 ACPI_COMPARE_NAMESEG (Signature, ACPI_SIG_DSDT) || 1057 ACPI_COMPARE_NAMESEG (Signature, ACPI_SIG_FACS)) 1058 { 1059 1060 FindNextInstance: 1061 1062 TableAddress = 0; 1063 1064 /* 1065 * Get the appropriate address, either 32-bit or 64-bit. Be very 1066 * careful about the FADT length and validate table addresses. 1067 * Note: The 64-bit addresses have priority. 1068 */ 1069 if (ACPI_COMPARE_NAMESEG (Signature, ACPI_SIG_DSDT)) 1070 { 1071 if (CurrentInstance < 2) 1072 { 1073 if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_XDSDT) && 1074 Gbl_Fadt->XDsdt && CurrentInstance == 0) 1075 { 1076 TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->XDsdt; 1077 } 1078 else if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_DSDT) && 1079 Gbl_Fadt->Dsdt != FirstTableAddress) 1080 { 1081 TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->Dsdt; 1082 } 1083 } 1084 } 1085 else if (ACPI_COMPARE_NAMESEG (Signature, ACPI_SIG_FACS)) 1086 { 1087 if (CurrentInstance < 2) 1088 { 1089 if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_XFACS) && 1090 Gbl_Fadt->XFacs && CurrentInstance == 0) 1091 { 1092 TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->XFacs; 1093 } 1094 else if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_FACS) && 1095 Gbl_Fadt->Facs != FirstTableAddress) 1096 { 1097 TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->Facs; 1098 } 1099 } 1100 } 1101 else if (ACPI_COMPARE_NAMESEG (Signature, ACPI_SIG_XSDT)) 1102 { 1103 if (!Gbl_Revision) 1104 { 1105 return (AE_BAD_SIGNATURE); 1106 } 1107 if (CurrentInstance == 0) 1108 { 1109 TableAddress = 1110 (ACPI_PHYSICAL_ADDRESS) Gbl_Rsdp.XsdtPhysicalAddress; 1111 } 1112 } 1113 else if (ACPI_COMPARE_NAMESEG (Signature, ACPI_SIG_RSDT)) 1114 { 1115 if (CurrentInstance == 0) 1116 { 1117 TableAddress = 1118 (ACPI_PHYSICAL_ADDRESS) Gbl_Rsdp.RsdtPhysicalAddress; 1119 } 1120 } 1121 else 1122 { 1123 if (CurrentInstance == 0) 1124 { 1125 TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_RsdpAddress; 1126 Signature = ACPI_SIG_RSDP; 1127 } 1128 } 1129 1130 if (TableAddress == 0) 1131 { 1132 goto ExitFindTable; 1133 } 1134 1135 /* Now we can get the requested special table */ 1136 1137 Status = OslMapTable (TableAddress, Signature, &MappedTable); 1138 if (ACPI_FAILURE (Status)) 1139 { 1140 return (Status); 1141 } 1142 1143 TableLength = ApGetTableLength (MappedTable); 1144 if (FirstTableAddress == 0) 1145 { 1146 FirstTableAddress = TableAddress; 1147 } 1148 1149 /* Match table instance */ 1150 1151 if (CurrentInstance != Instance) 1152 { 1153 OslUnmapTable (MappedTable); 1154 MappedTable = NULL; 1155 CurrentInstance++; 1156 goto FindNextInstance; 1157 } 1158 } 1159 else /* Case for a normal ACPI table */ 1160 { 1161 if (OslCanUseXsdt ()) 1162 { 1163 ItemSize = sizeof (UINT64); 1164 TableData = ACPI_CAST8 (Gbl_Xsdt) + sizeof (ACPI_TABLE_HEADER); 1165 NumberOfTables = 1166 (UINT8) ((Gbl_Xsdt->Header.Length - sizeof (ACPI_TABLE_HEADER)) 1167 / ItemSize); 1168 } 1169 else /* Use RSDT if XSDT is not available */ 1170 { 1171 ItemSize = sizeof (UINT32); 1172 TableData = ACPI_CAST8 (Gbl_Rsdt) + sizeof (ACPI_TABLE_HEADER); 1173 NumberOfTables = 1174 (UINT8) ((Gbl_Rsdt->Header.Length - sizeof (ACPI_TABLE_HEADER)) 1175 / ItemSize); 1176 } 1177 1178 /* Search RSDT/XSDT for the requested table */ 1179 1180 for (i = 0; i < NumberOfTables; ++i, TableData += ItemSize) 1181 { 1182 if (OslCanUseXsdt ()) 1183 { 1184 TableAddress = 1185 (ACPI_PHYSICAL_ADDRESS) (*ACPI_CAST64 (TableData)); 1186 } 1187 else 1188 { 1189 TableAddress = 1190 (ACPI_PHYSICAL_ADDRESS) (*ACPI_CAST32 (TableData)); 1191 } 1192 1193 /* Skip NULL entries in RSDT/XSDT */ 1194 1195 if (TableAddress == 0) 1196 { 1197 continue; 1198 } 1199 1200 Status = OslMapTable (TableAddress, NULL, &MappedTable); 1201 if (ACPI_FAILURE (Status)) 1202 { 1203 return (Status); 1204 } 1205 TableLength = MappedTable->Length; 1206 1207 /* Does this table match the requested signature? */ 1208 1209 if (!ACPI_COMPARE_NAMESEG (MappedTable->Signature, Signature)) 1210 { 1211 OslUnmapTable (MappedTable); 1212 MappedTable = NULL; 1213 continue; 1214 } 1215 1216 /* Match table instance (for SSDT/UEFI tables) */ 1217 1218 if (CurrentInstance != Instance) 1219 { 1220 OslUnmapTable (MappedTable); 1221 MappedTable = NULL; 1222 CurrentInstance++; 1223 continue; 1224 } 1225 1226 break; 1227 } 1228 } 1229 1230 ExitFindTable: 1231 1232 if (!MappedTable) 1233 { 1234 return (AE_LIMIT); 1235 } 1236 1237 if (TableLength == 0) 1238 { 1239 Status = AE_BAD_HEADER; 1240 goto Exit; 1241 } 1242 1243 /* Copy table to local buffer and return it */ 1244 1245 LocalTable = calloc (1, TableLength); 1246 if (!LocalTable) 1247 { 1248 Status = AE_NO_MEMORY; 1249 goto Exit; 1250 } 1251 1252 memcpy (LocalTable, MappedTable, TableLength); 1253 *Address = TableAddress; 1254 *Table = LocalTable; 1255 1256 Exit: 1257 OslUnmapTable (MappedTable); 1258 return (Status); 1259 } 1260 1261 1262 /****************************************************************************** 1263 * 1264 * FUNCTION: OslListCustomizedTables 1265 * 1266 * PARAMETERS: Directory - Directory that contains the tables 1267 * 1268 * RETURN: Status; Table list is initialized if AE_OK. 1269 * 1270 * DESCRIPTION: Add ACPI tables to the table list from a directory. 1271 * 1272 *****************************************************************************/ 1273 1274 static ACPI_STATUS 1275 OslListCustomizedTables ( 1276 char *Directory) 1277 { 1278 void *TableDir; 1279 UINT32 Instance; 1280 char TempName[ACPI_NAMESEG_SIZE]; 1281 char *Filename; 1282 ACPI_STATUS Status = AE_OK; 1283 1284 1285 /* Open the requested directory */ 1286 1287 TableDir = AcpiOsOpenDirectory (Directory, "*", REQUEST_FILE_ONLY); 1288 if (!TableDir) 1289 { 1290 return (OslGetLastStatus (AE_NOT_FOUND)); 1291 } 1292 1293 /* Examine all entries in this directory */ 1294 1295 while ((Filename = AcpiOsGetNextFilename (TableDir))) 1296 { 1297 /* Extract table name and instance number */ 1298 1299 Status = OslTableNameFromFile (Filename, TempName, &Instance); 1300 1301 /* Ignore meaningless files */ 1302 1303 if (ACPI_FAILURE (Status)) 1304 { 1305 continue; 1306 } 1307 1308 /* Add new info node to global table list */ 1309 1310 Status = OslAddTableToList (TempName, Instance); 1311 if (ACPI_FAILURE (Status)) 1312 { 1313 break; 1314 } 1315 } 1316 1317 AcpiOsCloseDirectory (TableDir); 1318 return (Status); 1319 } 1320 1321 1322 /****************************************************************************** 1323 * 1324 * FUNCTION: OslMapTable 1325 * 1326 * PARAMETERS: Address - Address of the table in memory 1327 * Signature - Optional ACPI Signature for desired table. 1328 * Null terminated 4-character string. 1329 * Table - Where a pointer to the mapped table is 1330 * returned 1331 * 1332 * RETURN: Status; Mapped table is returned if AE_OK. 1333 * AE_NOT_FOUND: A valid table was not found at the address 1334 * 1335 * DESCRIPTION: Map entire ACPI table into caller's address space. 1336 * 1337 *****************************************************************************/ 1338 1339 static ACPI_STATUS 1340 OslMapTable ( 1341 ACPI_SIZE Address, 1342 char *Signature, 1343 ACPI_TABLE_HEADER **Table) 1344 { 1345 ACPI_TABLE_HEADER *MappedTable; 1346 UINT32 Length; 1347 1348 1349 if (!Address) 1350 { 1351 return (AE_BAD_ADDRESS); 1352 } 1353 1354 /* 1355 * Map the header so we can get the table length. 1356 * Use sizeof (ACPI_TABLE_HEADER) as: 1357 * 1. it is bigger than 24 to include RSDP->Length 1358 * 2. it is smaller than sizeof (ACPI_TABLE_RSDP) 1359 */ 1360 MappedTable = AcpiOsMapMemory (Address, sizeof (ACPI_TABLE_HEADER)); 1361 if (!MappedTable) 1362 { 1363 fprintf (stderr, "Could not map table header at 0x%8.8X%8.8X\n", 1364 ACPI_FORMAT_UINT64 (Address)); 1365 return (OslGetLastStatus (AE_BAD_ADDRESS)); 1366 } 1367 1368 /* If specified, signature must match */ 1369 1370 if (Signature) 1371 { 1372 if (ACPI_VALIDATE_RSDP_SIG (Signature)) 1373 { 1374 if (!ACPI_VALIDATE_RSDP_SIG (MappedTable->Signature)) 1375 { 1376 AcpiOsUnmapMemory (MappedTable, sizeof (ACPI_TABLE_HEADER)); 1377 return (AE_BAD_SIGNATURE); 1378 } 1379 } 1380 else if (!ACPI_COMPARE_NAMESEG (Signature, MappedTable->Signature)) 1381 { 1382 AcpiOsUnmapMemory (MappedTable, sizeof (ACPI_TABLE_HEADER)); 1383 return (AE_BAD_SIGNATURE); 1384 } 1385 } 1386 1387 /* Map the entire table */ 1388 1389 Length = ApGetTableLength (MappedTable); 1390 AcpiOsUnmapMemory (MappedTable, sizeof (ACPI_TABLE_HEADER)); 1391 if (Length == 0) 1392 { 1393 return (AE_BAD_HEADER); 1394 } 1395 1396 MappedTable = AcpiOsMapMemory (Address, Length); 1397 if (!MappedTable) 1398 { 1399 fprintf (stderr, "Could not map table at 0x%8.8X%8.8X length %8.8X\n", 1400 ACPI_FORMAT_UINT64 (Address), Length); 1401 return (OslGetLastStatus (AE_INVALID_TABLE_LENGTH)); 1402 } 1403 1404 (void) ApIsValidChecksum (MappedTable); 1405 1406 *Table = MappedTable; 1407 return (AE_OK); 1408 } 1409 1410 1411 /****************************************************************************** 1412 * 1413 * FUNCTION: OslUnmapTable 1414 * 1415 * PARAMETERS: Table - A pointer to the mapped table 1416 * 1417 * RETURN: None 1418 * 1419 * DESCRIPTION: Unmap entire ACPI table. 1420 * 1421 *****************************************************************************/ 1422 1423 static void 1424 OslUnmapTable ( 1425 ACPI_TABLE_HEADER *Table) 1426 { 1427 if (Table) 1428 { 1429 AcpiOsUnmapMemory (Table, ApGetTableLength (Table)); 1430 } 1431 } 1432 1433 1434 /****************************************************************************** 1435 * 1436 * FUNCTION: OslTableNameFromFile 1437 * 1438 * PARAMETERS: Filename - File that contains the desired table 1439 * Signature - Pointer to 4-character buffer to store 1440 * extracted table signature. 1441 * Instance - Pointer to integer to store extracted 1442 * table instance number. 1443 * 1444 * RETURN: Status; Table name is extracted if AE_OK. 1445 * 1446 * DESCRIPTION: Extract table signature and instance number from a table file 1447 * name. 1448 * 1449 *****************************************************************************/ 1450 1451 static ACPI_STATUS 1452 OslTableNameFromFile ( 1453 char *Filename, 1454 char *Signature, 1455 UINT32 *Instance) 1456 { 1457 1458 /* Ignore meaningless files */ 1459 1460 if (strlen (Filename) < ACPI_NAMESEG_SIZE) 1461 { 1462 return (AE_BAD_SIGNATURE); 1463 } 1464 1465 /* Extract instance number */ 1466 1467 if (isdigit ((int) Filename[ACPI_NAMESEG_SIZE])) 1468 { 1469 sscanf (&Filename[ACPI_NAMESEG_SIZE], "%u", Instance); 1470 } 1471 else if (strlen (Filename) != ACPI_NAMESEG_SIZE) 1472 { 1473 return (AE_BAD_SIGNATURE); 1474 } 1475 else 1476 { 1477 *Instance = 0; 1478 } 1479 1480 /* Extract signature */ 1481 1482 ACPI_COPY_NAMESEG (Signature, Filename); 1483 return (AE_OK); 1484 } 1485 1486 1487 /****************************************************************************** 1488 * 1489 * FUNCTION: OslReadTableFromFile 1490 * 1491 * PARAMETERS: Filename - File that contains the desired table 1492 * FileOffset - Offset of the table in file 1493 * Signature - Optional ACPI Signature for desired table. 1494 * A null terminated 4-character string. 1495 * Table - Where a pointer to the table is returned 1496 * 1497 * RETURN: Status; Table buffer is returned if AE_OK. 1498 * 1499 * DESCRIPTION: Read a ACPI table from a file. 1500 * 1501 *****************************************************************************/ 1502 1503 static ACPI_STATUS 1504 OslReadTableFromFile ( 1505 char *Filename, 1506 ACPI_SIZE FileOffset, 1507 char *Signature, 1508 ACPI_TABLE_HEADER **Table) 1509 { 1510 FILE *TableFile; 1511 ACPI_TABLE_HEADER Header; 1512 ACPI_TABLE_HEADER *LocalTable = NULL; 1513 UINT32 TableLength; 1514 INT32 Count; 1515 ACPI_STATUS Status = AE_OK; 1516 1517 1518 /* Open the file */ 1519 1520 TableFile = fopen (Filename, "rb"); 1521 if (TableFile == NULL) 1522 { 1523 fprintf (stderr, "Could not open table file: %s\n", Filename); 1524 return (OslGetLastStatus (AE_NOT_FOUND)); 1525 } 1526 1527 fseek (TableFile, FileOffset, SEEK_SET); 1528 1529 /* Read the Table header to get the table length */ 1530 1531 Count = fread (&Header, 1, sizeof (ACPI_TABLE_HEADER), TableFile); 1532 if (Count != sizeof (ACPI_TABLE_HEADER)) 1533 { 1534 fprintf (stderr, "Could not read table header: %s\n", Filename); 1535 Status = AE_BAD_HEADER; 1536 goto Exit; 1537 } 1538 1539 /* If signature is specified, it must match the table */ 1540 1541 if (Signature) 1542 { 1543 if (ACPI_VALIDATE_RSDP_SIG (Signature)) 1544 { 1545 if (!ACPI_VALIDATE_RSDP_SIG (Header.Signature)) { 1546 fprintf (stderr, "Incorrect RSDP signature: found %8.8s\n", 1547 Header.Signature); 1548 Status = AE_BAD_SIGNATURE; 1549 goto Exit; 1550 } 1551 } 1552 else if (!ACPI_COMPARE_NAMESEG (Signature, Header.Signature)) 1553 { 1554 fprintf (stderr, "Incorrect signature: Expecting %4.4s, found %4.4s\n", 1555 Signature, Header.Signature); 1556 Status = AE_BAD_SIGNATURE; 1557 goto Exit; 1558 } 1559 } 1560 1561 TableLength = ApGetTableLength (&Header); 1562 if (TableLength == 0) 1563 { 1564 Status = AE_BAD_HEADER; 1565 goto Exit; 1566 } 1567 1568 /* Read the entire table into a local buffer */ 1569 1570 LocalTable = calloc (1, TableLength); 1571 if (!LocalTable) 1572 { 1573 fprintf (stderr, 1574 "%4.4s: Could not allocate buffer for table of length %X\n", 1575 Header.Signature, TableLength); 1576 Status = AE_NO_MEMORY; 1577 goto Exit; 1578 } 1579 1580 fseek (TableFile, FileOffset, SEEK_SET); 1581 1582 Count = fread (LocalTable, 1, TableLength, TableFile); 1583 if (Count != TableLength) 1584 { 1585 fprintf (stderr, "%4.4s: Could not read table content\n", 1586 Header.Signature); 1587 Status = AE_INVALID_TABLE_LENGTH; 1588 goto Exit; 1589 } 1590 1591 /* Validate checksum */ 1592 1593 (void) ApIsValidChecksum (LocalTable); 1594 1595 Exit: 1596 fclose (TableFile); 1597 *Table = LocalTable; 1598 return (Status); 1599 } 1600 1601 1602 /****************************************************************************** 1603 * 1604 * FUNCTION: OslGetCustomizedTable 1605 * 1606 * PARAMETERS: Pathname - Directory to find Linux customized table 1607 * Signature - ACPI Signature for desired table. Must be 1608 * a null terminated 4-character string. 1609 * Instance - Multiple table support for SSDT/UEFI (0...n) 1610 * Must be 0 for other tables. 1611 * Table - Where a pointer to the table is returned 1612 * Address - Where the table physical address is returned 1613 * 1614 * RETURN: Status; Table buffer is returned if AE_OK. 1615 * AE_LIMIT: Instance is beyond valid limit 1616 * AE_NOT_FOUND: A table with the signature was not found 1617 * 1618 * DESCRIPTION: Get an OS customized table. 1619 * 1620 *****************************************************************************/ 1621 1622 static ACPI_STATUS 1623 OslGetCustomizedTable ( 1624 char *Pathname, 1625 char *Signature, 1626 UINT32 Instance, 1627 ACPI_TABLE_HEADER **Table, 1628 ACPI_PHYSICAL_ADDRESS *Address) 1629 { 1630 void *TableDir; 1631 UINT32 CurrentInstance = 0; 1632 char TempName[ACPI_NAMESEG_SIZE]; 1633 char TableFilename[PATH_MAX]; 1634 char *Filename; 1635 ACPI_STATUS Status; 1636 1637 1638 /* Open the directory for customized tables */ 1639 1640 TableDir = AcpiOsOpenDirectory (Pathname, "*", REQUEST_FILE_ONLY); 1641 if (!TableDir) 1642 { 1643 return (OslGetLastStatus (AE_NOT_FOUND)); 1644 } 1645 1646 /* Attempt to find the table in the directory */ 1647 1648 while ((Filename = AcpiOsGetNextFilename (TableDir))) 1649 { 1650 /* Ignore meaningless files */ 1651 1652 if (!ACPI_COMPARE_NAMESEG (Filename, Signature)) 1653 { 1654 continue; 1655 } 1656 1657 /* Extract table name and instance number */ 1658 1659 Status = OslTableNameFromFile (Filename, TempName, &CurrentInstance); 1660 1661 /* Ignore meaningless files */ 1662 1663 if (ACPI_FAILURE (Status) || CurrentInstance != Instance) 1664 { 1665 continue; 1666 } 1667 1668 /* Create the table pathname */ 1669 1670 if (Instance != 0) 1671 { 1672 sprintf (TableFilename, "%s/%4.4s%d", Pathname, TempName, Instance); 1673 } 1674 else 1675 { 1676 sprintf (TableFilename, "%s/%4.4s", Pathname, TempName); 1677 } 1678 break; 1679 } 1680 1681 AcpiOsCloseDirectory (TableDir); 1682 1683 if (!Filename) 1684 { 1685 return (AE_LIMIT); 1686 } 1687 1688 /* There is no physical address saved for customized tables, use zero */ 1689 1690 *Address = 0; 1691 Status = OslReadTableFromFile (TableFilename, 0, NULL, Table); 1692 1693 return (Status); 1694 } 1695