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