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