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 - 2021, 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 ACPI_TABLE_HEADER **Table); 196 197 static ACPI_STATUS 198 OslMapTable ( 199 ACPI_SIZE Address, 200 char *Signature, 201 ACPI_TABLE_HEADER **Table); 202 203 static void 204 OslUnmapTable ( 205 ACPI_TABLE_HEADER *Table); 206 207 static ACPI_PHYSICAL_ADDRESS 208 OslFindRsdpViaEfiByKeyword ( 209 FILE *File, 210 const char *Keyword); 211 212 static ACPI_PHYSICAL_ADDRESS 213 OslFindRsdpViaEfi ( 214 void); 215 216 static ACPI_STATUS 217 OslLoadRsdp ( 218 void); 219 220 static ACPI_STATUS 221 OslListCustomizedTables ( 222 char *Directory); 223 224 static ACPI_STATUS 225 OslGetCustomizedTable ( 226 char *Pathname, 227 char *Signature, 228 UINT32 Instance, 229 ACPI_TABLE_HEADER **Table, 230 ACPI_PHYSICAL_ADDRESS *Address); 231 232 static ACPI_STATUS 233 OslListBiosTables ( 234 void); 235 236 static ACPI_STATUS 237 OslGetBiosTable ( 238 char *Signature, 239 UINT32 Instance, 240 ACPI_TABLE_HEADER **Table, 241 ACPI_PHYSICAL_ADDRESS *Address); 242 243 static ACPI_STATUS 244 OslGetLastStatus ( 245 ACPI_STATUS DefaultStatus); 246 247 248 /* File locations */ 249 250 #define DYNAMIC_TABLE_DIR "/sys/firmware/acpi/tables/dynamic" 251 #define STATIC_TABLE_DIR "/sys/firmware/acpi/tables" 252 #define EFI_SYSTAB "/sys/firmware/efi/systab" 253 254 /* Should we get dynamically loaded SSDTs from DYNAMIC_TABLE_DIR? */ 255 256 UINT8 Gbl_DumpDynamicTables = TRUE; 257 258 /* Initialization flags */ 259 260 UINT8 Gbl_TableListInitialized = FALSE; 261 262 /* Local copies of main ACPI tables */ 263 264 ACPI_TABLE_RSDP Gbl_Rsdp; 265 ACPI_TABLE_FADT *Gbl_Fadt = NULL; 266 ACPI_TABLE_RSDT *Gbl_Rsdt = NULL; 267 ACPI_TABLE_XSDT *Gbl_Xsdt = NULL; 268 269 /* Table addresses */ 270 271 ACPI_PHYSICAL_ADDRESS Gbl_FadtAddress = 0; 272 ACPI_PHYSICAL_ADDRESS Gbl_RsdpAddress = 0; 273 274 /* Revision of RSD PTR */ 275 276 UINT8 Gbl_Revision = 0; 277 278 OSL_TABLE_INFO *Gbl_TableListHead = NULL; 279 UINT32 Gbl_TableCount = 0; 280 281 282 /****************************************************************************** 283 * 284 * FUNCTION: OslGetLastStatus 285 * 286 * PARAMETERS: DefaultStatus - Default error status to return 287 * 288 * RETURN: Status; Converted from errno. 289 * 290 * DESCRIPTION: Get last errno and convert it to ACPI_STATUS. 291 * 292 *****************************************************************************/ 293 294 static ACPI_STATUS 295 OslGetLastStatus ( 296 ACPI_STATUS DefaultStatus) 297 { 298 299 switch (errno) 300 { 301 case EACCES: 302 case EPERM: 303 304 return (AE_ACCESS); 305 306 case ENOENT: 307 308 return (AE_NOT_FOUND); 309 310 case ENOMEM: 311 312 return (AE_NO_MEMORY); 313 314 default: 315 316 return (DefaultStatus); 317 } 318 } 319 320 321 /****************************************************************************** 322 * 323 * FUNCTION: AcpiOsGetTableByAddress 324 * 325 * PARAMETERS: Address - Physical address of the ACPI table 326 * Table - Where a pointer to the table is returned 327 * 328 * RETURN: Status; Table buffer is returned if AE_OK. 329 * AE_NOT_FOUND: A valid table was not found at the address 330 * 331 * DESCRIPTION: Get an ACPI table via a physical memory address. 332 * 333 *****************************************************************************/ 334 335 ACPI_STATUS 336 AcpiOsGetTableByAddress ( 337 ACPI_PHYSICAL_ADDRESS Address, 338 ACPI_TABLE_HEADER **Table) 339 { 340 UINT32 TableLength; 341 ACPI_TABLE_HEADER *MappedTable; 342 ACPI_TABLE_HEADER *LocalTable = NULL; 343 ACPI_STATUS Status = AE_OK; 344 345 346 /* Get main ACPI tables from memory on first invocation of this function */ 347 348 Status = OslTableInitialize (); 349 if (ACPI_FAILURE (Status)) 350 { 351 return (Status); 352 } 353 354 /* Map the table and validate it */ 355 356 Status = OslMapTable (Address, NULL, &MappedTable); 357 if (ACPI_FAILURE (Status)) 358 { 359 return (Status); 360 } 361 362 /* Copy table to local buffer and return it */ 363 364 TableLength = ApGetTableLength (MappedTable); 365 if (TableLength == 0) 366 { 367 Status = AE_BAD_HEADER; 368 goto Exit; 369 } 370 371 LocalTable = calloc (1, TableLength); 372 if (!LocalTable) 373 { 374 Status = AE_NO_MEMORY; 375 goto Exit; 376 } 377 378 memcpy (LocalTable, MappedTable, TableLength); 379 380 Exit: 381 OslUnmapTable (MappedTable); 382 *Table = LocalTable; 383 return (Status); 384 } 385 386 387 /****************************************************************************** 388 * 389 * FUNCTION: AcpiOsGetTableByName 390 * 391 * PARAMETERS: Signature - ACPI Signature for desired table. Must be 392 * a null terminated 4-character string. 393 * Instance - Multiple table support for SSDT/UEFI (0...n) 394 * Must be 0 for other tables. 395 * Table - Where a pointer to the table is returned 396 * Address - Where the table physical address is returned 397 * 398 * RETURN: Status; Table buffer and physical address returned if AE_OK. 399 * AE_LIMIT: Instance is beyond valid limit 400 * AE_NOT_FOUND: A table with the signature was not found 401 * 402 * NOTE: Assumes the input signature is uppercase. 403 * 404 *****************************************************************************/ 405 406 ACPI_STATUS 407 AcpiOsGetTableByName ( 408 char *Signature, 409 UINT32 Instance, 410 ACPI_TABLE_HEADER **Table, 411 ACPI_PHYSICAL_ADDRESS *Address) 412 { 413 ACPI_STATUS Status; 414 415 416 /* Get main ACPI tables from memory on first invocation of this function */ 417 418 Status = OslTableInitialize (); 419 if (ACPI_FAILURE (Status)) 420 { 421 return (Status); 422 } 423 424 /* Not a main ACPI table, attempt to extract it from the RSDT/XSDT */ 425 426 if (!Gbl_DumpCustomizedTables) 427 { 428 /* Attempt to get the table from the memory */ 429 430 Status = OslGetBiosTable (Signature, Instance, Table, Address); 431 } 432 else 433 { 434 /* Attempt to get the table from the static directory */ 435 436 Status = OslGetCustomizedTable (STATIC_TABLE_DIR, Signature, 437 Instance, Table, Address); 438 } 439 440 if (ACPI_FAILURE (Status) && Status == AE_LIMIT) 441 { 442 if (Gbl_DumpDynamicTables) 443 { 444 /* Attempt to get a dynamic table */ 445 446 Status = OslGetCustomizedTable (DYNAMIC_TABLE_DIR, Signature, 447 Instance, Table, Address); 448 } 449 } 450 451 return (Status); 452 } 453 454 455 /****************************************************************************** 456 * 457 * FUNCTION: OslAddTableToList 458 * 459 * PARAMETERS: Signature - Table signature 460 * Instance - Table instance 461 * 462 * RETURN: Status; Successfully added if AE_OK. 463 * AE_NO_MEMORY: Memory allocation error 464 * 465 * DESCRIPTION: Insert a table structure into OSL table list. 466 * 467 *****************************************************************************/ 468 469 static ACPI_STATUS 470 OslAddTableToList ( 471 char *Signature, 472 UINT32 Instance) 473 { 474 OSL_TABLE_INFO *NewInfo; 475 OSL_TABLE_INFO *Next; 476 UINT32 NextInstance = 0; 477 BOOLEAN Found = FALSE; 478 479 480 NewInfo = calloc (1, sizeof (OSL_TABLE_INFO)); 481 if (!NewInfo) 482 { 483 return (AE_NO_MEMORY); 484 } 485 486 ACPI_COPY_NAMESEG (NewInfo->Signature, Signature); 487 488 if (!Gbl_TableListHead) 489 { 490 Gbl_TableListHead = NewInfo; 491 } 492 else 493 { 494 Next = Gbl_TableListHead; 495 while (1) 496 { 497 if (ACPI_COMPARE_NAMESEG (Next->Signature, Signature)) 498 { 499 if (Next->Instance == Instance) 500 { 501 Found = TRUE; 502 } 503 if (Next->Instance >= NextInstance) 504 { 505 NextInstance = Next->Instance + 1; 506 } 507 } 508 509 if (!Next->Next) 510 { 511 break; 512 } 513 Next = Next->Next; 514 } 515 Next->Next = NewInfo; 516 } 517 518 if (Found) 519 { 520 if (Instance) 521 { 522 fprintf (stderr, 523 "%4.4s: Warning unmatched table instance %d, expected %d\n", 524 Signature, Instance, NextInstance); 525 } 526 Instance = NextInstance; 527 } 528 529 NewInfo->Instance = Instance; 530 Gbl_TableCount++; 531 532 return (AE_OK); 533 } 534 535 536 /****************************************************************************** 537 * 538 * FUNCTION: AcpiOsGetTableByIndex 539 * 540 * PARAMETERS: Index - Which table to get 541 * Table - Where a pointer to the table is returned 542 * Instance - Where a pointer to the table instance no. is 543 * returned 544 * Address - Where the table physical address is returned 545 * 546 * RETURN: Status; Table buffer and physical address returned if AE_OK. 547 * AE_LIMIT: Index is beyond valid limit 548 * 549 * DESCRIPTION: Get an ACPI table via an index value (0 through n). Returns 550 * AE_LIMIT when an invalid index is reached. Index is not 551 * necessarily an index into the RSDT/XSDT. 552 * 553 *****************************************************************************/ 554 555 ACPI_STATUS 556 AcpiOsGetTableByIndex ( 557 UINT32 Index, 558 ACPI_TABLE_HEADER **Table, 559 UINT32 *Instance, 560 ACPI_PHYSICAL_ADDRESS *Address) 561 { 562 OSL_TABLE_INFO *Info; 563 ACPI_STATUS Status; 564 UINT32 i; 565 566 567 /* Get main ACPI tables from memory on first invocation of this function */ 568 569 Status = OslTableInitialize (); 570 if (ACPI_FAILURE (Status)) 571 { 572 return (Status); 573 } 574 575 /* Validate Index */ 576 577 if (Index >= Gbl_TableCount) 578 { 579 return (AE_LIMIT); 580 } 581 582 /* Point to the table list entry specified by the Index argument */ 583 584 Info = Gbl_TableListHead; 585 for (i = 0; i < Index; i++) 586 { 587 Info = Info->Next; 588 } 589 590 /* Now we can just get the table via the signature */ 591 592 Status = AcpiOsGetTableByName (Info->Signature, Info->Instance, 593 Table, Address); 594 595 if (ACPI_SUCCESS (Status)) 596 { 597 *Instance = Info->Instance; 598 } 599 return (Status); 600 } 601 602 603 /****************************************************************************** 604 * 605 * FUNCTION: OslFindRsdpViaEfiByKeyword 606 * 607 * PARAMETERS: Keyword - Character string indicating ACPI GUID version 608 * in the EFI table 609 * 610 * RETURN: RSDP address if found 611 * 612 * DESCRIPTION: Find RSDP address via EFI using keyword indicating the ACPI 613 * GUID version. 614 * 615 *****************************************************************************/ 616 617 static ACPI_PHYSICAL_ADDRESS 618 OslFindRsdpViaEfiByKeyword ( 619 FILE *File, 620 const char *Keyword) 621 { 622 char Buffer[80]; 623 unsigned long long Address = 0; 624 char Format[32]; 625 626 627 snprintf (Format, 32, "%s=%s", Keyword, "%llx"); 628 fseek (File, 0, SEEK_SET); 629 while (fgets (Buffer, 80, File)) 630 { 631 if (sscanf (Buffer, Format, &Address) == 1) 632 { 633 break; 634 } 635 } 636 637 return ((ACPI_PHYSICAL_ADDRESS) (Address)); 638 } 639 640 641 /****************************************************************************** 642 * 643 * FUNCTION: OslFindRsdpViaEfi 644 * 645 * PARAMETERS: None 646 * 647 * RETURN: RSDP address if found 648 * 649 * DESCRIPTION: Find RSDP address via EFI. 650 * 651 *****************************************************************************/ 652 653 static ACPI_PHYSICAL_ADDRESS 654 OslFindRsdpViaEfi ( 655 void) 656 { 657 FILE *File; 658 ACPI_PHYSICAL_ADDRESS Address = 0; 659 660 661 File = fopen (EFI_SYSTAB, "r"); 662 if (File) 663 { 664 Address = OslFindRsdpViaEfiByKeyword (File, "ACPI20"); 665 if (!Address) 666 { 667 Address = OslFindRsdpViaEfiByKeyword (File, "ACPI"); 668 } 669 fclose (File); 670 } 671 672 return (Address); 673 } 674 675 676 /****************************************************************************** 677 * 678 * FUNCTION: OslLoadRsdp 679 * 680 * PARAMETERS: None 681 * 682 * RETURN: Status 683 * 684 * DESCRIPTION: Scan and load RSDP. 685 * 686 *****************************************************************************/ 687 688 static ACPI_STATUS 689 OslLoadRsdp ( 690 void) 691 { 692 ACPI_TABLE_HEADER *MappedTable; 693 UINT8 *RsdpAddress; 694 ACPI_PHYSICAL_ADDRESS RsdpBase; 695 ACPI_SIZE RsdpSize; 696 697 698 /* Get RSDP from memory */ 699 700 RsdpSize = sizeof (ACPI_TABLE_RSDP); 701 if (Gbl_RsdpBase) 702 { 703 RsdpBase = Gbl_RsdpBase; 704 } 705 else 706 { 707 RsdpBase = OslFindRsdpViaEfi (); 708 } 709 710 if (!RsdpBase) 711 { 712 RsdpBase = ACPI_HI_RSDP_WINDOW_BASE; 713 RsdpSize = ACPI_HI_RSDP_WINDOW_SIZE; 714 } 715 716 RsdpAddress = AcpiOsMapMemory (RsdpBase, RsdpSize); 717 if (!RsdpAddress) 718 { 719 return (OslGetLastStatus (AE_BAD_ADDRESS)); 720 } 721 722 /* Search low memory for the RSDP */ 723 724 MappedTable = ACPI_CAST_PTR (ACPI_TABLE_HEADER, 725 AcpiTbScanMemoryForRsdp (RsdpAddress, RsdpSize)); 726 if (!MappedTable) 727 { 728 AcpiOsUnmapMemory (RsdpAddress, RsdpSize); 729 return (AE_NOT_FOUND); 730 } 731 732 Gbl_RsdpAddress = RsdpBase + (ACPI_CAST8 (MappedTable) - RsdpAddress); 733 734 memcpy (&Gbl_Rsdp, MappedTable, sizeof (ACPI_TABLE_RSDP)); 735 AcpiOsUnmapMemory (RsdpAddress, RsdpSize); 736 737 return (AE_OK); 738 } 739 740 741 /****************************************************************************** 742 * 743 * FUNCTION: OslCanUseXsdt 744 * 745 * PARAMETERS: None 746 * 747 * RETURN: TRUE if XSDT is allowed to be used. 748 * 749 * DESCRIPTION: This function collects logic that can be used to determine if 750 * XSDT should be used instead of RSDT. 751 * 752 *****************************************************************************/ 753 754 static BOOLEAN 755 OslCanUseXsdt ( 756 void) 757 { 758 if (Gbl_Revision && !AcpiGbl_DoNotUseXsdt) 759 { 760 return (TRUE); 761 } 762 else 763 { 764 return (FALSE); 765 } 766 } 767 768 769 /****************************************************************************** 770 * 771 * FUNCTION: OslTableInitialize 772 * 773 * PARAMETERS: None 774 * 775 * RETURN: Status 776 * 777 * DESCRIPTION: Initialize ACPI table data. Get and store main ACPI tables to 778 * local variables. Main ACPI tables include RSDT, FADT, RSDT, 779 * and/or XSDT. 780 * 781 *****************************************************************************/ 782 783 static ACPI_STATUS 784 OslTableInitialize ( 785 void) 786 { 787 ACPI_STATUS Status; 788 ACPI_PHYSICAL_ADDRESS Address; 789 790 791 if (Gbl_TableListInitialized) 792 { 793 return (AE_OK); 794 } 795 796 if (!Gbl_DumpCustomizedTables) 797 { 798 /* Get RSDP from memory */ 799 800 Status = OslLoadRsdp (); 801 if (ACPI_FAILURE (Status)) 802 { 803 return (Status); 804 } 805 806 /* Get XSDT from memory */ 807 808 if (Gbl_Rsdp.Revision && !Gbl_DoNotDumpXsdt) 809 { 810 if (Gbl_Xsdt) 811 { 812 free (Gbl_Xsdt); 813 Gbl_Xsdt = NULL; 814 } 815 816 Gbl_Revision = 2; 817 Status = OslGetBiosTable (ACPI_SIG_XSDT, 0, 818 ACPI_CAST_PTR (ACPI_TABLE_HEADER *, &Gbl_Xsdt), &Address); 819 if (ACPI_FAILURE (Status)) 820 { 821 return (Status); 822 } 823 } 824 825 /* Get RSDT from memory */ 826 827 if (Gbl_Rsdp.RsdtPhysicalAddress) 828 { 829 if (Gbl_Rsdt) 830 { 831 free (Gbl_Rsdt); 832 Gbl_Rsdt = NULL; 833 } 834 835 Status = OslGetBiosTable (ACPI_SIG_RSDT, 0, 836 ACPI_CAST_PTR (ACPI_TABLE_HEADER *, &Gbl_Rsdt), &Address); 837 if (ACPI_FAILURE (Status)) 838 { 839 return (Status); 840 } 841 } 842 843 /* Get FADT from memory */ 844 845 if (Gbl_Fadt) 846 { 847 free (Gbl_Fadt); 848 Gbl_Fadt = NULL; 849 } 850 851 Status = OslGetBiosTable (ACPI_SIG_FADT, 0, 852 ACPI_CAST_PTR (ACPI_TABLE_HEADER *, &Gbl_Fadt), &Gbl_FadtAddress); 853 if (ACPI_FAILURE (Status)) 854 { 855 return (Status); 856 } 857 858 /* Add mandatory tables to global table list first */ 859 860 Status = OslAddTableToList (ACPI_RSDP_NAME, 0); 861 if (ACPI_FAILURE (Status)) 862 { 863 return (Status); 864 } 865 866 Status = OslAddTableToList (ACPI_SIG_RSDT, 0); 867 if (ACPI_FAILURE (Status)) 868 { 869 return (Status); 870 } 871 872 if (Gbl_Revision == 2) 873 { 874 Status = OslAddTableToList (ACPI_SIG_XSDT, 0); 875 if (ACPI_FAILURE (Status)) 876 { 877 return (Status); 878 } 879 } 880 881 Status = OslAddTableToList (ACPI_SIG_DSDT, 0); 882 if (ACPI_FAILURE (Status)) 883 { 884 return (Status); 885 } 886 887 Status = OslAddTableToList (ACPI_SIG_FACS, 0); 888 if (ACPI_FAILURE (Status)) 889 { 890 return (Status); 891 } 892 893 /* Add all tables found in the memory */ 894 895 Status = OslListBiosTables (); 896 if (ACPI_FAILURE (Status)) 897 { 898 return (Status); 899 } 900 } 901 else 902 { 903 /* Add all tables found in the static directory */ 904 905 Status = OslListCustomizedTables (STATIC_TABLE_DIR); 906 if (ACPI_FAILURE (Status)) 907 { 908 return (Status); 909 } 910 } 911 912 if (Gbl_DumpDynamicTables) 913 { 914 /* Add all dynamically loaded tables in the dynamic directory */ 915 916 Status = OslListCustomizedTables (DYNAMIC_TABLE_DIR); 917 if (ACPI_FAILURE (Status)) 918 { 919 return (Status); 920 } 921 } 922 923 Gbl_TableListInitialized = TRUE; 924 return (AE_OK); 925 } 926 927 928 /****************************************************************************** 929 * 930 * FUNCTION: OslListBiosTables 931 * 932 * PARAMETERS: None 933 * 934 * RETURN: Status; Table list is initialized if AE_OK. 935 * 936 * DESCRIPTION: Add ACPI tables to the table list from memory. 937 * 938 * NOTE: This works on Linux as table customization does not modify the 939 * addresses stored in RSDP/RSDT/XSDT/FADT. 940 * 941 *****************************************************************************/ 942 943 static ACPI_STATUS 944 OslListBiosTables ( 945 void) 946 { 947 ACPI_TABLE_HEADER *MappedTable = NULL; 948 UINT8 *TableData; 949 UINT8 NumberOfTables; 950 UINT8 ItemSize; 951 ACPI_PHYSICAL_ADDRESS TableAddress = 0; 952 ACPI_STATUS Status = AE_OK; 953 UINT32 i; 954 955 956 if (OslCanUseXsdt ()) 957 { 958 ItemSize = sizeof (UINT64); 959 TableData = ACPI_CAST8 (Gbl_Xsdt) + sizeof (ACPI_TABLE_HEADER); 960 NumberOfTables = 961 (UINT8) ((Gbl_Xsdt->Header.Length - sizeof (ACPI_TABLE_HEADER)) 962 / ItemSize); 963 } 964 else /* Use RSDT if XSDT is not available */ 965 { 966 ItemSize = sizeof (UINT32); 967 TableData = ACPI_CAST8 (Gbl_Rsdt) + sizeof (ACPI_TABLE_HEADER); 968 NumberOfTables = 969 (UINT8) ((Gbl_Rsdt->Header.Length - sizeof (ACPI_TABLE_HEADER)) 970 / ItemSize); 971 } 972 973 /* Search RSDT/XSDT for the requested table */ 974 975 for (i = 0; i < NumberOfTables; ++i, TableData += ItemSize) 976 { 977 if (OslCanUseXsdt ()) 978 { 979 TableAddress = 980 (ACPI_PHYSICAL_ADDRESS) (*ACPI_CAST64 (TableData)); 981 } 982 else 983 { 984 TableAddress = 985 (ACPI_PHYSICAL_ADDRESS) (*ACPI_CAST32 (TableData)); 986 } 987 988 /* Skip NULL entries in RSDT/XSDT */ 989 990 if (TableAddress == 0) 991 { 992 continue; 993 } 994 995 Status = OslMapTable (TableAddress, NULL, &MappedTable); 996 if (ACPI_FAILURE (Status)) 997 { 998 return (Status); 999 } 1000 1001 OslAddTableToList (MappedTable->Signature, 0); 1002 OslUnmapTable (MappedTable); 1003 } 1004 1005 return (AE_OK); 1006 } 1007 1008 1009 /****************************************************************************** 1010 * 1011 * FUNCTION: OslGetBiosTable 1012 * 1013 * PARAMETERS: Signature - ACPI Signature for common table. Must be 1014 * a null terminated 4-character string. 1015 * Instance - Multiple table support for SSDT/UEFI (0...n) 1016 * Must be 0 for other tables. 1017 * Table - Where a pointer to the table is returned 1018 * Address - Where the table physical address is returned 1019 * 1020 * RETURN: Status; Table buffer and physical address returned if AE_OK. 1021 * AE_LIMIT: Instance is beyond valid limit 1022 * AE_NOT_FOUND: A table with the signature was not found 1023 * 1024 * DESCRIPTION: Get a BIOS provided ACPI table 1025 * 1026 * NOTE: Assumes the input signature is uppercase. 1027 * 1028 *****************************************************************************/ 1029 1030 static ACPI_STATUS 1031 OslGetBiosTable ( 1032 char *Signature, 1033 UINT32 Instance, 1034 ACPI_TABLE_HEADER **Table, 1035 ACPI_PHYSICAL_ADDRESS *Address) 1036 { 1037 ACPI_TABLE_HEADER *LocalTable = NULL; 1038 ACPI_TABLE_HEADER *MappedTable = NULL; 1039 UINT8 *TableData; 1040 UINT8 NumberOfTables; 1041 UINT8 ItemSize; 1042 UINT32 CurrentInstance = 0; 1043 ACPI_PHYSICAL_ADDRESS TableAddress; 1044 ACPI_PHYSICAL_ADDRESS FirstTableAddress = 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_NAMESEG (Signature, ACPI_RSDP_NAME) || 1053 ACPI_COMPARE_NAMESEG (Signature, ACPI_SIG_RSDT) || 1054 ACPI_COMPARE_NAMESEG (Signature, ACPI_SIG_XSDT) || 1055 ACPI_COMPARE_NAMESEG (Signature, ACPI_SIG_DSDT) || 1056 ACPI_COMPARE_NAMESEG (Signature, ACPI_SIG_FACS)) 1057 { 1058 1059 FindNextInstance: 1060 1061 TableAddress = 0; 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_NAMESEG (Signature, ACPI_SIG_DSDT)) 1069 { 1070 if (CurrentInstance < 2) 1071 { 1072 if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_XDSDT) && 1073 Gbl_Fadt->XDsdt && CurrentInstance == 0) 1074 { 1075 TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->XDsdt; 1076 } 1077 else if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_DSDT) && 1078 Gbl_Fadt->Dsdt != FirstTableAddress) 1079 { 1080 TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->Dsdt; 1081 } 1082 } 1083 } 1084 else if (ACPI_COMPARE_NAMESEG (Signature, ACPI_SIG_FACS)) 1085 { 1086 if (CurrentInstance < 2) 1087 { 1088 if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_XFACS) && 1089 Gbl_Fadt->XFacs && CurrentInstance == 0) 1090 { 1091 TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->XFacs; 1092 } 1093 else if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_FACS) && 1094 Gbl_Fadt->Facs != FirstTableAddress) 1095 { 1096 TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->Facs; 1097 } 1098 } 1099 } 1100 else if (ACPI_COMPARE_NAMESEG (Signature, ACPI_SIG_XSDT)) 1101 { 1102 if (!Gbl_Revision) 1103 { 1104 return (AE_BAD_SIGNATURE); 1105 } 1106 if (CurrentInstance == 0) 1107 { 1108 TableAddress = 1109 (ACPI_PHYSICAL_ADDRESS) Gbl_Rsdp.XsdtPhysicalAddress; 1110 } 1111 } 1112 else if (ACPI_COMPARE_NAMESEG (Signature, ACPI_SIG_RSDT)) 1113 { 1114 if (CurrentInstance == 0) 1115 { 1116 TableAddress = 1117 (ACPI_PHYSICAL_ADDRESS) Gbl_Rsdp.RsdtPhysicalAddress; 1118 } 1119 } 1120 else 1121 { 1122 if (CurrentInstance == 0) 1123 { 1124 TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_RsdpAddress; 1125 Signature = ACPI_SIG_RSDP; 1126 } 1127 } 1128 1129 if (TableAddress == 0) 1130 { 1131 goto ExitFindTable; 1132 } 1133 1134 /* Now we can get the requested special table */ 1135 1136 Status = OslMapTable (TableAddress, Signature, &MappedTable); 1137 if (ACPI_FAILURE (Status)) 1138 { 1139 return (Status); 1140 } 1141 1142 TableLength = ApGetTableLength (MappedTable); 1143 if (FirstTableAddress == 0) 1144 { 1145 FirstTableAddress = TableAddress; 1146 } 1147 1148 /* Match table instance */ 1149 1150 if (CurrentInstance != Instance) 1151 { 1152 OslUnmapTable (MappedTable); 1153 MappedTable = NULL; 1154 CurrentInstance++; 1155 goto FindNextInstance; 1156 } 1157 } 1158 else /* Case for a normal ACPI table */ 1159 { 1160 if (OslCanUseXsdt ()) 1161 { 1162 ItemSize = sizeof (UINT64); 1163 TableData = ACPI_CAST8 (Gbl_Xsdt) + sizeof (ACPI_TABLE_HEADER); 1164 NumberOfTables = 1165 (UINT8) ((Gbl_Xsdt->Header.Length - sizeof (ACPI_TABLE_HEADER)) 1166 / ItemSize); 1167 } 1168 else /* Use RSDT if XSDT is not available */ 1169 { 1170 ItemSize = sizeof (UINT32); 1171 TableData = ACPI_CAST8 (Gbl_Rsdt) + sizeof (ACPI_TABLE_HEADER); 1172 NumberOfTables = 1173 (UINT8) ((Gbl_Rsdt->Header.Length - sizeof (ACPI_TABLE_HEADER)) 1174 / ItemSize); 1175 } 1176 1177 /* Search RSDT/XSDT for the requested table */ 1178 1179 for (i = 0; i < NumberOfTables; ++i, TableData += ItemSize) 1180 { 1181 if (OslCanUseXsdt ()) 1182 { 1183 TableAddress = 1184 (ACPI_PHYSICAL_ADDRESS) (*ACPI_CAST64 (TableData)); 1185 } 1186 else 1187 { 1188 TableAddress = 1189 (ACPI_PHYSICAL_ADDRESS) (*ACPI_CAST32 (TableData)); 1190 } 1191 1192 /* Skip NULL entries in RSDT/XSDT */ 1193 1194 if (TableAddress == 0) 1195 { 1196 continue; 1197 } 1198 1199 Status = OslMapTable (TableAddress, NULL, &MappedTable); 1200 if (ACPI_FAILURE (Status)) 1201 { 1202 return (Status); 1203 } 1204 TableLength = MappedTable->Length; 1205 1206 /* Does this table match the requested signature? */ 1207 1208 if (!ACPI_COMPARE_NAMESEG (MappedTable->Signature, Signature)) 1209 { 1210 OslUnmapTable (MappedTable); 1211 MappedTable = NULL; 1212 continue; 1213 } 1214 1215 /* Match table instance (for SSDT/UEFI tables) */ 1216 1217 if (CurrentInstance != Instance) 1218 { 1219 OslUnmapTable (MappedTable); 1220 MappedTable = NULL; 1221 CurrentInstance++; 1222 continue; 1223 } 1224 1225 break; 1226 } 1227 } 1228 1229 ExitFindTable: 1230 1231 if (!MappedTable) 1232 { 1233 return (AE_LIMIT); 1234 } 1235 1236 if (TableLength == 0) 1237 { 1238 Status = AE_BAD_HEADER; 1239 goto Exit; 1240 } 1241 1242 /* Copy table to local buffer and return it */ 1243 1244 LocalTable = calloc (1, TableLength); 1245 if (!LocalTable) 1246 { 1247 Status = AE_NO_MEMORY; 1248 goto Exit; 1249 } 1250 1251 memcpy (LocalTable, MappedTable, TableLength); 1252 *Address = TableAddress; 1253 *Table = LocalTable; 1254 1255 Exit: 1256 OslUnmapTable (MappedTable); 1257 return (Status); 1258 } 1259 1260 1261 /****************************************************************************** 1262 * 1263 * FUNCTION: OslListCustomizedTables 1264 * 1265 * PARAMETERS: Directory - Directory that contains the tables 1266 * 1267 * RETURN: Status; Table list is initialized if AE_OK. 1268 * 1269 * DESCRIPTION: Add ACPI tables to the table list from a directory. 1270 * 1271 *****************************************************************************/ 1272 1273 static ACPI_STATUS 1274 OslListCustomizedTables ( 1275 char *Directory) 1276 { 1277 void *TableDir; 1278 UINT32 Instance; 1279 char TempName[ACPI_NAMESEG_SIZE]; 1280 char *Filename; 1281 ACPI_STATUS Status = AE_OK; 1282 1283 1284 /* Open the requested directory */ 1285 1286 TableDir = AcpiOsOpenDirectory (Directory, "*", REQUEST_FILE_ONLY); 1287 if (!TableDir) 1288 { 1289 return (OslGetLastStatus (AE_NOT_FOUND)); 1290 } 1291 1292 /* Examine all entries in this directory */ 1293 1294 while ((Filename = AcpiOsGetNextFilename (TableDir))) 1295 { 1296 /* Extract table name and instance number */ 1297 1298 Status = OslTableNameFromFile (Filename, TempName, &Instance); 1299 1300 /* Ignore meaningless files */ 1301 1302 if (ACPI_FAILURE (Status)) 1303 { 1304 continue; 1305 } 1306 1307 /* Add new info node to global table list */ 1308 1309 Status = OslAddTableToList (TempName, Instance); 1310 if (ACPI_FAILURE (Status)) 1311 { 1312 break; 1313 } 1314 } 1315 1316 AcpiOsCloseDirectory (TableDir); 1317 return (Status); 1318 } 1319 1320 1321 /****************************************************************************** 1322 * 1323 * FUNCTION: OslMapTable 1324 * 1325 * PARAMETERS: Address - Address of the table in memory 1326 * Signature - Optional ACPI Signature for desired table. 1327 * Null terminated 4-character string. 1328 * Table - Where a pointer to the mapped table is 1329 * returned 1330 * 1331 * RETURN: Status; Mapped table is returned if AE_OK. 1332 * AE_NOT_FOUND: A valid table was not found at the address 1333 * 1334 * DESCRIPTION: Map entire ACPI table into caller's address space. 1335 * 1336 *****************************************************************************/ 1337 1338 static ACPI_STATUS 1339 OslMapTable ( 1340 ACPI_SIZE Address, 1341 char *Signature, 1342 ACPI_TABLE_HEADER **Table) 1343 { 1344 ACPI_TABLE_HEADER *MappedTable; 1345 UINT32 Length; 1346 1347 1348 if (!Address) 1349 { 1350 return (AE_BAD_ADDRESS); 1351 } 1352 1353 /* 1354 * Map the header so we can get the table length. 1355 * Use sizeof (ACPI_TABLE_HEADER) as: 1356 * 1. it is bigger than 24 to include RSDP->Length 1357 * 2. it is smaller than sizeof (ACPI_TABLE_RSDP) 1358 */ 1359 MappedTable = AcpiOsMapMemory (Address, sizeof (ACPI_TABLE_HEADER)); 1360 if (!MappedTable) 1361 { 1362 fprintf (stderr, "Could not map table header at 0x%8.8X%8.8X\n", 1363 ACPI_FORMAT_UINT64 (Address)); 1364 return (OslGetLastStatus (AE_BAD_ADDRESS)); 1365 } 1366 1367 /* If specified, signature must match */ 1368 1369 if (Signature) 1370 { 1371 if (ACPI_VALIDATE_RSDP_SIG (Signature)) 1372 { 1373 if (!ACPI_VALIDATE_RSDP_SIG (MappedTable->Signature)) 1374 { 1375 AcpiOsUnmapMemory (MappedTable, sizeof (ACPI_TABLE_HEADER)); 1376 return (AE_BAD_SIGNATURE); 1377 } 1378 } 1379 else if (!ACPI_COMPARE_NAMESEG (Signature, MappedTable->Signature)) 1380 { 1381 AcpiOsUnmapMemory (MappedTable, sizeof (ACPI_TABLE_HEADER)); 1382 return (AE_BAD_SIGNATURE); 1383 } 1384 } 1385 1386 /* Map the entire table */ 1387 1388 Length = ApGetTableLength (MappedTable); 1389 AcpiOsUnmapMemory (MappedTable, sizeof (ACPI_TABLE_HEADER)); 1390 if (Length == 0) 1391 { 1392 return (AE_BAD_HEADER); 1393 } 1394 1395 MappedTable = AcpiOsMapMemory (Address, Length); 1396 if (!MappedTable) 1397 { 1398 fprintf (stderr, "Could not map table at 0x%8.8X%8.8X length %8.8X\n", 1399 ACPI_FORMAT_UINT64 (Address), Length); 1400 return (OslGetLastStatus (AE_INVALID_TABLE_LENGTH)); 1401 } 1402 1403 (void) ApIsValidChecksum (MappedTable); 1404 1405 *Table = MappedTable; 1406 return (AE_OK); 1407 } 1408 1409 1410 /****************************************************************************** 1411 * 1412 * FUNCTION: OslUnmapTable 1413 * 1414 * PARAMETERS: Table - A pointer to the mapped table 1415 * 1416 * RETURN: None 1417 * 1418 * DESCRIPTION: Unmap entire ACPI table. 1419 * 1420 *****************************************************************************/ 1421 1422 static void 1423 OslUnmapTable ( 1424 ACPI_TABLE_HEADER *Table) 1425 { 1426 if (Table) 1427 { 1428 AcpiOsUnmapMemory (Table, ApGetTableLength (Table)); 1429 } 1430 } 1431 1432 1433 /****************************************************************************** 1434 * 1435 * FUNCTION: OslTableNameFromFile 1436 * 1437 * PARAMETERS: Filename - File that contains the desired table 1438 * Signature - Pointer to 4-character buffer to store 1439 * extracted table signature. 1440 * Instance - Pointer to integer to store extracted 1441 * table instance number. 1442 * 1443 * RETURN: Status; Table name is extracted if AE_OK. 1444 * 1445 * DESCRIPTION: Extract table signature and instance number from a table file 1446 * name. 1447 * 1448 *****************************************************************************/ 1449 1450 static ACPI_STATUS 1451 OslTableNameFromFile ( 1452 char *Filename, 1453 char *Signature, 1454 UINT32 *Instance) 1455 { 1456 1457 /* Ignore meaningless files */ 1458 1459 if (strlen (Filename) < ACPI_NAMESEG_SIZE) 1460 { 1461 return (AE_BAD_SIGNATURE); 1462 } 1463 1464 /* Extract instance number */ 1465 1466 if (isdigit ((int) Filename[ACPI_NAMESEG_SIZE])) 1467 { 1468 sscanf (&Filename[ACPI_NAMESEG_SIZE], "%u", Instance); 1469 } 1470 else if (strlen (Filename) != ACPI_NAMESEG_SIZE) 1471 { 1472 return (AE_BAD_SIGNATURE); 1473 } 1474 else 1475 { 1476 *Instance = 0; 1477 } 1478 1479 /* Extract signature */ 1480 1481 ACPI_COPY_NAMESEG (Signature, Filename); 1482 return (AE_OK); 1483 } 1484 1485 1486 /****************************************************************************** 1487 * 1488 * FUNCTION: OslReadTableFromFile 1489 * 1490 * PARAMETERS: Filename - File that contains the desired table 1491 * FileOffset - Offset of the table in file 1492 * Table - Where a pointer to the table is returned 1493 * 1494 * RETURN: Status; Table buffer is returned if AE_OK. 1495 * 1496 * DESCRIPTION: Read a ACPI table from a file. 1497 * 1498 *****************************************************************************/ 1499 1500 static ACPI_STATUS 1501 OslReadTableFromFile ( 1502 char *Filename, 1503 ACPI_SIZE FileOffset, 1504 ACPI_TABLE_HEADER **Table) 1505 { 1506 FILE *TableFile; 1507 ACPI_TABLE_HEADER Header; 1508 ACPI_TABLE_HEADER *LocalTable = NULL; 1509 UINT32 TableLength; 1510 INT32 Count; 1511 ACPI_STATUS Status = AE_OK; 1512 1513 1514 /* Open the file */ 1515 1516 TableFile = fopen (Filename, "rb"); 1517 if (TableFile == NULL) 1518 { 1519 fprintf (stderr, "Could not open table file: %s\n", Filename); 1520 return (OslGetLastStatus (AE_NOT_FOUND)); 1521 } 1522 1523 fseek (TableFile, FileOffset, SEEK_SET); 1524 1525 /* Read the Table header to get the table length */ 1526 1527 Count = fread (&Header, 1, sizeof (ACPI_TABLE_HEADER), TableFile); 1528 if (Count != sizeof (ACPI_TABLE_HEADER)) 1529 { 1530 fprintf (stderr, "Could not read table header: %s\n", Filename); 1531 Status = AE_BAD_HEADER; 1532 goto Exit; 1533 } 1534 1535 #ifdef ACPI_OBSOLETE_FUNCTIONS 1536 1537 /* If signature is specified, it must match the table */ 1538 1539 if (Signature) 1540 { 1541 if (ACPI_VALIDATE_RSDP_SIG (Signature)) 1542 { 1543 if (!ACPI_VALIDATE_RSDP_SIG (Header.Signature)) { 1544 fprintf (stderr, "Incorrect RSDP signature: found %8.8s\n", 1545 Header.Signature); 1546 Status = AE_BAD_SIGNATURE; 1547 goto Exit; 1548 } 1549 } 1550 else if (!ACPI_COMPARE_NAMESEG (Signature, Header.Signature)) 1551 { 1552 fprintf (stderr, "Incorrect signature: Expecting %4.4s, found %4.4s\n", 1553 Signature, Header.Signature); 1554 Status = AE_BAD_SIGNATURE; 1555 goto Exit; 1556 } 1557 } 1558 #endif 1559 1560 TableLength = ApGetTableLength (&Header); 1561 if (TableLength == 0) 1562 { 1563 Status = AE_BAD_HEADER; 1564 goto Exit; 1565 } 1566 1567 /* Read the entire table into a local buffer */ 1568 1569 LocalTable = calloc (1, TableLength); 1570 if (!LocalTable) 1571 { 1572 fprintf (stderr, 1573 "%4.4s: Could not allocate buffer for table of length %X\n", 1574 Header.Signature, TableLength); 1575 Status = AE_NO_MEMORY; 1576 goto Exit; 1577 } 1578 1579 fseek (TableFile, FileOffset, SEEK_SET); 1580 1581 Count = fread (LocalTable, 1, TableLength, TableFile); 1582 if (Count != TableLength) 1583 { 1584 fprintf (stderr, "%4.4s: Could not read table content\n", 1585 Header.Signature); 1586 Status = AE_INVALID_TABLE_LENGTH; 1587 goto Exit; 1588 } 1589 1590 /* Validate checksum */ 1591 1592 (void) ApIsValidChecksum (LocalTable); 1593 1594 Exit: 1595 fclose (TableFile); 1596 *Table = LocalTable; 1597 return (Status); 1598 } 1599 1600 1601 /****************************************************************************** 1602 * 1603 * FUNCTION: OslGetCustomizedTable 1604 * 1605 * PARAMETERS: Pathname - Directory to find Linux customized table 1606 * Signature - ACPI Signature for desired table. Must be 1607 * a null terminated 4-character string. 1608 * Instance - Multiple table support for SSDT/UEFI (0...n) 1609 * Must be 0 for other tables. 1610 * Table - Where a pointer to the table is returned 1611 * Address - Where the table physical address is returned 1612 * 1613 * RETURN: Status; Table buffer is returned if AE_OK. 1614 * AE_LIMIT: Instance is beyond valid limit 1615 * AE_NOT_FOUND: A table with the signature was not found 1616 * 1617 * DESCRIPTION: Get an OS customized table. 1618 * 1619 *****************************************************************************/ 1620 1621 static ACPI_STATUS 1622 OslGetCustomizedTable ( 1623 char *Pathname, 1624 char *Signature, 1625 UINT32 Instance, 1626 ACPI_TABLE_HEADER **Table, 1627 ACPI_PHYSICAL_ADDRESS *Address) 1628 { 1629 void *TableDir; 1630 UINT32 CurrentInstance = 0; 1631 char TempName[ACPI_NAMESEG_SIZE]; 1632 char TableFilename[PATH_MAX]; 1633 char *Filename; 1634 ACPI_STATUS Status; 1635 1636 1637 /* Open the directory for customized tables */ 1638 1639 TableDir = AcpiOsOpenDirectory (Pathname, "*", REQUEST_FILE_ONLY); 1640 if (!TableDir) 1641 { 1642 return (OslGetLastStatus (AE_NOT_FOUND)); 1643 } 1644 1645 /* Attempt to find the table in the directory */ 1646 1647 while ((Filename = AcpiOsGetNextFilename (TableDir))) 1648 { 1649 /* Ignore meaningless files */ 1650 1651 if (!ACPI_COMPARE_NAMESEG (Filename, Signature)) 1652 { 1653 continue; 1654 } 1655 1656 /* Extract table name and instance number */ 1657 1658 Status = OslTableNameFromFile (Filename, TempName, &CurrentInstance); 1659 1660 /* Ignore meaningless files */ 1661 1662 if (ACPI_FAILURE (Status) || CurrentInstance != Instance) 1663 { 1664 continue; 1665 } 1666 1667 /* Create the table pathname */ 1668 1669 if (Instance != 0) 1670 { 1671 sprintf (TableFilename, "%s/%4.4s%d", Pathname, TempName, Instance); 1672 } 1673 else 1674 { 1675 sprintf (TableFilename, "%s/%4.4s", Pathname, TempName); 1676 } 1677 break; 1678 } 1679 1680 AcpiOsCloseDirectory (TableDir); 1681 1682 if (!Filename) 1683 { 1684 return (AE_LIMIT); 1685 } 1686 1687 /* There is no physical address saved for customized tables, use zero */ 1688 1689 *Address = 0; 1690 Status = OslReadTableFromFile (TableFilename, 0, Table); 1691 1692 return (Status); 1693 } 1694