1 /****************************************************************************** 2 * 3 * Module Name: osbsdtbl - BSD 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 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined (__DragonFly__) 47 #include <kenv.h> 48 #endif 49 #include <unistd.h> 50 #include <sys/param.h> 51 #include <sys/sysctl.h> 52 53 54 #define _COMPONENT ACPI_OS_SERVICES 55 ACPI_MODULE_NAME ("osbsdtbl") 56 57 58 /* Local prototypes */ 59 60 static ACPI_STATUS 61 OslTableInitialize ( 62 void); 63 64 static ACPI_STATUS 65 OslMapTable ( 66 ACPI_SIZE Address, 67 char *Signature, 68 ACPI_TABLE_HEADER **Table); 69 70 static ACPI_STATUS 71 OslAddTablesToList ( 72 void); 73 74 static ACPI_STATUS 75 OslGetTableViaRoot ( 76 char *Signature, 77 UINT32 Instance, 78 ACPI_TABLE_HEADER **Table, 79 ACPI_PHYSICAL_ADDRESS *Address); 80 81 82 /* Hints for RSDP */ 83 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) 84 #define SYSTEM_KENV "hint.acpi.0.rsdp" 85 #define SYSTEM_SYSCTL "machdep.acpi_root" 86 #elif defined(__NetBSD__) 87 #define SYSTEM_SYSCTL "hw.acpi.root" 88 #endif 89 90 /* Initialization flags */ 91 92 UINT8 Gbl_TableListInitialized = FALSE; 93 UINT8 Gbl_MainTableObtained = FALSE; 94 95 /* Local copies of main ACPI tables */ 96 97 ACPI_TABLE_RSDP Gbl_Rsdp; 98 ACPI_TABLE_FADT *Gbl_Fadt; 99 ACPI_TABLE_RSDT *Gbl_Rsdt; 100 ACPI_TABLE_XSDT *Gbl_Xsdt; 101 102 /* Fadt address */ 103 104 ACPI_PHYSICAL_ADDRESS Gbl_FadtAddress; 105 106 /* Revision of RSD PTR */ 107 108 UINT8 Gbl_Revision; 109 110 /* List of information about obtained ACPI tables */ 111 112 typedef struct table_info 113 { 114 struct table_info *Next; 115 char Signature[4]; 116 UINT32 Instance; 117 ACPI_PHYSICAL_ADDRESS Address; 118 119 } OSL_TABLE_INFO; 120 121 OSL_TABLE_INFO *Gbl_TableListHead = NULL; 122 123 124 /****************************************************************************** 125 * 126 * FUNCTION: AcpiOsGetTableByAddress 127 * 128 * PARAMETERS: Address - Physical address of the ACPI table 129 * Table - Where a pointer to the table is returned 130 * 131 * RETURN: Status; Table buffer is returned if AE_OK. 132 * AE_NOT_FOUND: A valid table was not found at the address 133 * 134 * DESCRIPTION: Get an ACPI table via a physical memory address. 135 * 136 *****************************************************************************/ 137 138 ACPI_STATUS 139 AcpiOsGetTableByAddress ( 140 ACPI_PHYSICAL_ADDRESS Address, 141 ACPI_TABLE_HEADER **Table) 142 { 143 ACPI_TABLE_HEADER *MappedTable; 144 ACPI_TABLE_HEADER *LocalTable; 145 ACPI_STATUS Status; 146 147 148 /* Validate the input physical address to avoid program crash */ 149 150 if (Address < ACPI_HI_RSDP_WINDOW_BASE) 151 { 152 fprintf (stderr, "Invalid table address: 0x%8.8X%8.8X\n", 153 ACPI_FORMAT_UINT64 (Address)); 154 return (AE_BAD_ADDRESS); 155 } 156 157 /* Map the table and validate it */ 158 159 Status = OslMapTable (Address, NULL, &MappedTable); 160 if (ACPI_FAILURE (Status)) 161 { 162 return (Status); 163 } 164 165 /* Copy table to local buffer and return it */ 166 167 LocalTable = calloc (1, MappedTable->Length); 168 if (!LocalTable) 169 { 170 AcpiOsUnmapMemory (MappedTable, MappedTable->Length); 171 return (AE_NO_MEMORY); 172 } 173 174 memcpy (LocalTable, MappedTable, MappedTable->Length); 175 AcpiOsUnmapMemory (MappedTable, MappedTable->Length); 176 177 *Table = LocalTable; 178 return (AE_OK); 179 } 180 181 182 /****************************************************************************** 183 * 184 * FUNCTION: AcpiOsGetTableByName 185 * 186 * PARAMETERS: Signature - ACPI Signature for desired table. Must be 187 * a null terminated 4-character string. 188 * Instance - Multiple table support for SSDT/UEFI (0...n) 189 * Must be 0 for other tables. 190 * Table - Where a pointer to the table is returned 191 * Address - Where the table physical address is returned 192 * 193 * RETURN: Status; Table buffer and physical address returned if AE_OK. 194 * AE_LIMIT: Instance is beyond valid limit 195 * AE_NOT_FOUND: A table with the signature was not found 196 * 197 * NOTE: Assumes the input signature is uppercase. 198 * 199 *****************************************************************************/ 200 201 ACPI_STATUS 202 AcpiOsGetTableByName ( 203 char *Signature, 204 UINT32 Instance, 205 ACPI_TABLE_HEADER **Table, 206 ACPI_PHYSICAL_ADDRESS *Address) 207 { 208 ACPI_STATUS Status; 209 210 211 /* Instance is only valid for SSDT/UEFI tables */ 212 213 if (Instance && 214 !ACPI_COMPARE_NAME (Signature, ACPI_SIG_SSDT) && 215 !ACPI_COMPARE_NAME (Signature, ACPI_SIG_UEFI)) 216 { 217 return (AE_LIMIT); 218 } 219 220 /* Initialize main tables */ 221 222 Status = OslTableInitialize (); 223 if (ACPI_FAILURE (Status)) 224 { 225 return (Status); 226 } 227 228 /* 229 * If one of the main ACPI tables was requested (RSDT/XSDT/FADT), 230 * simply return it immediately. 231 */ 232 if (ACPI_COMPARE_NAME (Signature, ACPI_SIG_XSDT)) 233 { 234 if (!Gbl_Revision) 235 { 236 return (AE_NOT_FOUND); 237 } 238 239 *Address = Gbl_Rsdp.XsdtPhysicalAddress; 240 *Table = (ACPI_TABLE_HEADER *) Gbl_Xsdt; 241 return (AE_OK); 242 } 243 244 if (ACPI_COMPARE_NAME (Signature, ACPI_SIG_RSDT)) 245 { 246 if (!Gbl_Rsdp.RsdtPhysicalAddress) 247 { 248 return (AE_NOT_FOUND); 249 } 250 251 *Address = Gbl_Rsdp.RsdtPhysicalAddress; 252 *Table = (ACPI_TABLE_HEADER *) Gbl_Rsdt; 253 return (AE_OK); 254 } 255 256 if (ACPI_COMPARE_NAME (Signature, ACPI_SIG_FADT)) 257 { 258 *Address = Gbl_FadtAddress; 259 *Table = (ACPI_TABLE_HEADER *) Gbl_Fadt; 260 return (AE_OK); 261 } 262 263 /* Not a main ACPI table, attempt to extract it from the RSDT/XSDT */ 264 265 Status = OslGetTableViaRoot (Signature, Instance, Table, Address); 266 if (ACPI_FAILURE (Status)) 267 { 268 return (Status); 269 } 270 271 return (AE_OK); 272 } 273 274 275 /****************************************************************************** 276 * 277 * FUNCTION: AcpiOsGetTableByIndex 278 * 279 * PARAMETERS: Index - Which table to get 280 * Table - Where a pointer to the table is returned 281 * Instance - Where a pointer to the table instance no. is 282 * returned 283 * Address - Where the table physical address is returned 284 * 285 * RETURN: Status; Table buffer and physical address returned if AE_OK. 286 * AE_LIMIT: Index is beyond valid limit 287 * 288 * DESCRIPTION: Get an ACPI table via an index value (0 through n). Returns 289 * AE_LIMIT when an invalid index is reached. Index is not 290 * necessarily an index into the RSDT/XSDT. 291 * 292 *****************************************************************************/ 293 294 ACPI_STATUS 295 AcpiOsGetTableByIndex ( 296 UINT32 Index, 297 ACPI_TABLE_HEADER **Table, 298 UINT32 *Instance, 299 ACPI_PHYSICAL_ADDRESS *Address) 300 { 301 OSL_TABLE_INFO *Info; 302 ACPI_STATUS Status; 303 UINT32 i; 304 305 306 /* Initialize main tables */ 307 308 Status = OslTableInitialize (); 309 if (ACPI_FAILURE (Status)) 310 { 311 return (Status); 312 } 313 314 /* Add all tables to list */ 315 316 Status = OslAddTablesToList (); 317 if (ACPI_FAILURE (Status)) 318 { 319 return (Status); 320 } 321 322 /* Validate Index */ 323 324 if (Index >= Gbl_TableListHead->Instance) 325 { 326 return (AE_LIMIT); 327 } 328 329 /* Point to the table list entry specified by the Index argument */ 330 331 Info = Gbl_TableListHead; 332 for (i = 0; i <= Index; i++) 333 { 334 Info = Info->Next; 335 } 336 337 /* Now we can just get the table via the address or name */ 338 339 if (Info->Address) 340 { 341 Status = AcpiOsGetTableByAddress (Info->Address, Table); 342 if (ACPI_SUCCESS (Status)) 343 { 344 *Address = Info->Address; 345 } 346 } 347 else 348 { 349 Status = AcpiOsGetTableByName (Info->Signature, Info->Instance, 350 Table, Address); 351 } 352 353 if (ACPI_SUCCESS (Status)) 354 { 355 *Instance = Info->Instance; 356 } 357 return (Status); 358 } 359 360 361 /****************************************************************************** 362 * 363 * FUNCTION: OslTableInitialize 364 * 365 * PARAMETERS: None 366 * 367 * RETURN: Status 368 * 369 * DESCRIPTION: Initialize ACPI table data. Get and store main ACPI tables to 370 * local variables. Main ACPI tables include RSDP, FADT, RSDT, 371 * and/or XSDT. 372 * 373 *****************************************************************************/ 374 375 static ACPI_STATUS 376 OslTableInitialize ( 377 void) 378 { 379 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) 380 char Buffer[32]; 381 #endif 382 ACPI_TABLE_HEADER *MappedTable; 383 UINT8 *TableAddress; 384 UINT8 *RsdpAddress; 385 ACPI_PHYSICAL_ADDRESS RsdpBase; 386 ACPI_SIZE RsdpSize; 387 ACPI_STATUS Status; 388 u_long Address = 0; 389 #if defined(SYSTEM_SYSCTL) 390 size_t Length = sizeof (Address); 391 #endif 392 393 394 /* Get main ACPI tables from memory on first invocation of this function */ 395 396 if (Gbl_MainTableObtained) 397 { 398 return (AE_OK); 399 } 400 401 /* Attempt to use kenv or sysctl to find RSD PTR record. */ 402 403 if (Gbl_RsdpBase) 404 { 405 Address = Gbl_RsdpBase; 406 } 407 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined (__DragonFly__) 408 else if (kenv (KENV_GET, SYSTEM_KENV, Buffer, sizeof (Buffer)) > 0) 409 { 410 Address = strtoul (Buffer, NULL, 0); 411 } 412 #endif 413 #if defined(SYSTEM_SYSCTL) 414 if (!Address) 415 { 416 if (sysctlbyname (SYSTEM_SYSCTL, &Address, &Length, NULL, 0) != 0) 417 { 418 Address = 0; 419 } 420 } 421 #endif 422 if (Address) 423 { 424 RsdpBase = Address; 425 RsdpSize = sizeof (Gbl_Rsdp); 426 } 427 else 428 { 429 RsdpBase = ACPI_HI_RSDP_WINDOW_BASE; 430 RsdpSize = ACPI_HI_RSDP_WINDOW_SIZE; 431 } 432 433 /* Get RSDP from memory */ 434 435 RsdpAddress = AcpiOsMapMemory (RsdpBase, RsdpSize); 436 if (!RsdpAddress) 437 { 438 return (AE_BAD_ADDRESS); 439 } 440 441 /* Search low memory for the RSDP */ 442 443 TableAddress = AcpiTbScanMemoryForRsdp (RsdpAddress, RsdpSize); 444 if (!TableAddress) 445 { 446 AcpiOsUnmapMemory (RsdpAddress, RsdpSize); 447 return (AE_ERROR); 448 } 449 450 memcpy (&Gbl_Rsdp, TableAddress, sizeof (Gbl_Rsdp)); 451 AcpiOsUnmapMemory (RsdpAddress, RsdpSize); 452 453 /* Get XSDT from memory */ 454 455 if (Gbl_Rsdp.Revision) 456 { 457 Status = OslMapTable (Gbl_Rsdp.XsdtPhysicalAddress, 458 ACPI_SIG_XSDT, &MappedTable); 459 if (ACPI_FAILURE (Status)) 460 { 461 return (Status); 462 } 463 464 Gbl_Revision = 2; 465 Gbl_Xsdt = calloc (1, MappedTable->Length); 466 if (!Gbl_Xsdt) 467 { 468 fprintf (stderr, 469 "XSDT: Could not allocate buffer for table of length %X\n", 470 MappedTable->Length); 471 AcpiOsUnmapMemory (MappedTable, MappedTable->Length); 472 return (AE_NO_MEMORY); 473 } 474 475 memcpy (Gbl_Xsdt, MappedTable, MappedTable->Length); 476 AcpiOsUnmapMemory (MappedTable, MappedTable->Length); 477 } 478 479 /* Get RSDT from memory */ 480 481 if (Gbl_Rsdp.RsdtPhysicalAddress) 482 { 483 Status = OslMapTable (Gbl_Rsdp.RsdtPhysicalAddress, 484 ACPI_SIG_RSDT, &MappedTable); 485 if (ACPI_FAILURE (Status)) 486 { 487 return (Status); 488 } 489 490 Gbl_Rsdt = calloc (1, MappedTable->Length); 491 if (!Gbl_Rsdt) 492 { 493 fprintf (stderr, 494 "RSDT: Could not allocate buffer for table of length %X\n", 495 MappedTable->Length); 496 AcpiOsUnmapMemory (MappedTable, MappedTable->Length); 497 return (AE_NO_MEMORY); 498 } 499 500 memcpy (Gbl_Rsdt, MappedTable, MappedTable->Length); 501 AcpiOsUnmapMemory (MappedTable, MappedTable->Length); 502 } 503 504 /* Get FADT from memory */ 505 506 if (Gbl_Revision) 507 { 508 Gbl_FadtAddress = Gbl_Xsdt->TableOffsetEntry[0]; 509 } 510 else 511 { 512 Gbl_FadtAddress = Gbl_Rsdt->TableOffsetEntry[0]; 513 } 514 515 if (!Gbl_FadtAddress) 516 { 517 fprintf(stderr, "FADT: Table could not be found\n"); 518 return (AE_ERROR); 519 } 520 521 Status = OslMapTable (Gbl_FadtAddress, ACPI_SIG_FADT, &MappedTable); 522 if (ACPI_FAILURE (Status)) 523 { 524 return (Status); 525 } 526 527 Gbl_Fadt = calloc (1, MappedTable->Length); 528 if (!Gbl_Fadt) 529 { 530 fprintf (stderr, 531 "FADT: Could not allocate buffer for table of length %X\n", 532 MappedTable->Length); 533 AcpiOsUnmapMemory (MappedTable, MappedTable->Length); 534 return (AE_NO_MEMORY); 535 } 536 537 memcpy (Gbl_Fadt, MappedTable, MappedTable->Length); 538 AcpiOsUnmapMemory (MappedTable, MappedTable->Length); 539 Gbl_MainTableObtained = TRUE; 540 return (AE_OK); 541 } 542 543 544 /****************************************************************************** 545 * 546 * FUNCTION: OslGetTableViaRoot 547 * 548 * PARAMETERS: Signature - ACPI Signature for common table. Must be 549 * a null terminated 4-character string. 550 * Instance - Multiple table support for SSDT/UEFI (0...n) 551 * Must be 0 for other tables. 552 * Table - Where a pointer to the table is returned 553 * Address - Where the table physical address is returned 554 * 555 * RETURN: Status; Table buffer and physical address returned if AE_OK. 556 * AE_LIMIT: Instance is beyond valid limit 557 * AE_NOT_FOUND: A table with the signature was not found 558 * 559 * DESCRIPTION: Get an ACPI table via the root table (RSDT/XSDT) 560 * 561 * NOTE: Assumes the input signature is uppercase. 562 * 563 *****************************************************************************/ 564 565 static ACPI_STATUS 566 OslGetTableViaRoot ( 567 char *Signature, 568 UINT32 Instance, 569 ACPI_TABLE_HEADER **Table, 570 ACPI_PHYSICAL_ADDRESS *Address) 571 { 572 ACPI_TABLE_HEADER *LocalTable = NULL; 573 ACPI_TABLE_HEADER *MappedTable = NULL; 574 UINT8 NumberOfTables; 575 UINT32 CurrentInstance = 0; 576 ACPI_PHYSICAL_ADDRESS TableAddress = 0; 577 ACPI_STATUS Status; 578 UINT32 i; 579 580 581 /* DSDT and FACS address must be extracted from the FADT */ 582 583 if (ACPI_COMPARE_NAME (Signature, ACPI_SIG_DSDT) || 584 ACPI_COMPARE_NAME (Signature, ACPI_SIG_FACS)) 585 { 586 /* 587 * Get the appropriate address, either 32-bit or 64-bit. Be very 588 * careful about the FADT length and validate table addresses. 589 * Note: The 64-bit addresses have priority. 590 */ 591 if (ACPI_COMPARE_NAME (Signature, ACPI_SIG_DSDT)) 592 { 593 if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_XDSDT) && 594 Gbl_Fadt->XDsdt) 595 { 596 TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->XDsdt; 597 } 598 else if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_DSDT) && 599 Gbl_Fadt->Dsdt) 600 { 601 TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->Dsdt; 602 } 603 } 604 else /* FACS */ 605 { 606 if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_XFACS) && 607 Gbl_Fadt->XFacs) 608 { 609 TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->XFacs; 610 } 611 else if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_FACS) && 612 Gbl_Fadt->Facs) 613 { 614 TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->Facs; 615 } 616 } 617 } 618 else /* Case for a normal ACPI table */ 619 { 620 if (Gbl_Revision) 621 { 622 NumberOfTables = 623 (Gbl_Xsdt->Header.Length - sizeof (Gbl_Xsdt->Header)) 624 / sizeof (Gbl_Xsdt->TableOffsetEntry[0]); 625 } 626 else /* Use RSDT if XSDT is not available */ 627 { 628 NumberOfTables = 629 (Gbl_Rsdt->Header.Length - sizeof (Gbl_Rsdt->Header)) 630 / sizeof (Gbl_Rsdt->TableOffsetEntry[0]); 631 } 632 633 /* Search RSDT/XSDT for the requested table */ 634 635 for (i = 0; i < NumberOfTables; i++) 636 { 637 if (Gbl_Revision) 638 { 639 TableAddress = Gbl_Xsdt->TableOffsetEntry[i]; 640 } 641 else 642 { 643 TableAddress = Gbl_Rsdt->TableOffsetEntry[i]; 644 } 645 646 MappedTable = AcpiOsMapMemory (TableAddress, sizeof (*MappedTable)); 647 if (!MappedTable) 648 { 649 return (AE_BAD_ADDRESS); 650 } 651 652 /* Does this table match the requested signature? */ 653 654 if (ACPI_COMPARE_NAME (MappedTable->Signature, Signature)) 655 { 656 657 /* Match table instance (for SSDT/UEFI tables) */ 658 659 if (CurrentInstance == Instance) 660 { 661 AcpiOsUnmapMemory (MappedTable, sizeof (*MappedTable)); 662 break; 663 } 664 665 CurrentInstance++; 666 } 667 668 AcpiOsUnmapMemory (MappedTable, MappedTable->Length); 669 TableAddress = 0; 670 } 671 } 672 673 if (!TableAddress) 674 { 675 if (CurrentInstance) 676 { 677 return (AE_LIMIT); 678 } 679 return (AE_NOT_FOUND); 680 } 681 682 /* Now we can get the requested table */ 683 684 Status = OslMapTable (TableAddress, Signature, &MappedTable); 685 if (ACPI_FAILURE (Status)) 686 { 687 return (Status); 688 } 689 690 /* Copy table to local buffer and return it */ 691 692 LocalTable = calloc (1, MappedTable->Length); 693 if (!LocalTable) 694 { 695 AcpiOsUnmapMemory (MappedTable, MappedTable->Length); 696 return (AE_NO_MEMORY); 697 } 698 699 memcpy (LocalTable, MappedTable, MappedTable->Length); 700 AcpiOsUnmapMemory (MappedTable, MappedTable->Length); 701 *Table = LocalTable; 702 *Address = TableAddress; 703 return (AE_OK); 704 } 705 706 707 /****************************************************************************** 708 * 709 * FUNCTION: OslAddTablesToList 710 * 711 * PARAMETERS: None 712 * 713 * RETURN: Status; Table list is initialized if AE_OK. 714 * 715 * DESCRIPTION: Add ACPI tables to the table list. 716 * 717 *****************************************************************************/ 718 719 static ACPI_STATUS 720 OslAddTablesToList( 721 void) 722 { 723 ACPI_PHYSICAL_ADDRESS TableAddress; 724 OSL_TABLE_INFO *Info = NULL; 725 OSL_TABLE_INFO *NewInfo; 726 ACPI_TABLE_HEADER *Table; 727 UINT8 Instance; 728 UINT8 NumberOfTables; 729 int i; 730 731 732 /* Initialize the table list on first invocation */ 733 734 if (Gbl_TableListInitialized) 735 { 736 return (AE_OK); 737 } 738 739 /* Add mandatory tables to global table list first */ 740 741 for (i = 0; i < 4; i++) 742 { 743 NewInfo = calloc (1, sizeof (*NewInfo)); 744 if (!NewInfo) 745 { 746 return (AE_NO_MEMORY); 747 } 748 749 switch (i) { 750 case 0: 751 752 Gbl_TableListHead = Info = NewInfo; 753 continue; 754 755 case 1: 756 757 ACPI_MOVE_NAME (NewInfo->Signature, 758 Gbl_Revision ? ACPI_SIG_XSDT : ACPI_SIG_RSDT); 759 break; 760 761 case 2: 762 763 ACPI_MOVE_NAME (NewInfo->Signature, ACPI_SIG_FACS); 764 break; 765 766 default: 767 768 ACPI_MOVE_NAME (NewInfo->Signature, ACPI_SIG_DSDT); 769 770 } 771 772 Info->Next = NewInfo; 773 Info = NewInfo; 774 Gbl_TableListHead->Instance++; 775 } 776 777 /* Add normal tables from RSDT/XSDT to global list */ 778 779 if (Gbl_Revision) 780 { 781 NumberOfTables = 782 (Gbl_Xsdt->Header.Length - sizeof (Gbl_Xsdt->Header)) 783 / sizeof (Gbl_Xsdt->TableOffsetEntry[0]); 784 } 785 else 786 { 787 NumberOfTables = 788 (Gbl_Rsdt->Header.Length - sizeof (Gbl_Rsdt->Header)) 789 / sizeof (Gbl_Rsdt->TableOffsetEntry[0]); 790 } 791 792 for (i = 0; i < NumberOfTables; i++) 793 { 794 if (Gbl_Revision) 795 { 796 TableAddress = Gbl_Xsdt->TableOffsetEntry[i]; 797 } 798 else 799 { 800 TableAddress = Gbl_Rsdt->TableOffsetEntry[i]; 801 } 802 803 Table = AcpiOsMapMemory (TableAddress, sizeof (*Table)); 804 if (!Table) 805 { 806 return (AE_BAD_ADDRESS); 807 } 808 809 Instance = 0; 810 NewInfo = Gbl_TableListHead; 811 while (NewInfo->Next != NULL) 812 { 813 NewInfo = NewInfo->Next; 814 if (ACPI_COMPARE_NAME (Table->Signature, NewInfo->Signature)) 815 { 816 Instance++; 817 } 818 } 819 820 NewInfo = calloc (1, sizeof (*NewInfo)); 821 if (!NewInfo) 822 { 823 AcpiOsUnmapMemory (Table, sizeof (*Table)); 824 return (AE_NO_MEMORY); 825 } 826 827 ACPI_MOVE_NAME (NewInfo->Signature, Table->Signature); 828 829 AcpiOsUnmapMemory (Table, sizeof (*Table)); 830 831 NewInfo->Instance = Instance; 832 NewInfo->Address = TableAddress; 833 Info->Next = NewInfo; 834 Info = NewInfo; 835 Gbl_TableListHead->Instance++; 836 } 837 838 Gbl_TableListInitialized = TRUE; 839 return (AE_OK); 840 } 841 842 843 /****************************************************************************** 844 * 845 * FUNCTION: OslMapTable 846 * 847 * PARAMETERS: Address - Address of the table in memory 848 * Signature - Optional ACPI Signature for desired table. 849 * Null terminated 4-character string. 850 * Table - Where a pointer to the mapped table is 851 * returned 852 * 853 * RETURN: Status; Mapped table is returned if AE_OK. 854 * 855 * DESCRIPTION: Map entire ACPI table into caller's address space. Also 856 * validates the table and checksum. 857 * 858 *****************************************************************************/ 859 860 static ACPI_STATUS 861 OslMapTable ( 862 ACPI_SIZE Address, 863 char *Signature, 864 ACPI_TABLE_HEADER **Table) 865 { 866 ACPI_TABLE_HEADER *MappedTable; 867 UINT32 Length; 868 869 870 /* Map the header so we can get the table length */ 871 872 MappedTable = AcpiOsMapMemory (Address, sizeof (*MappedTable)); 873 if (!MappedTable) 874 { 875 return (AE_BAD_ADDRESS); 876 } 877 878 /* Check if table is valid */ 879 880 if (!ApIsValidHeader (MappedTable)) 881 { 882 AcpiOsUnmapMemory (MappedTable, sizeof (*MappedTable)); 883 return (AE_BAD_HEADER); 884 } 885 886 /* If specified, signature must match */ 887 888 if (Signature && 889 !ACPI_COMPARE_NAME (Signature, MappedTable->Signature)) 890 { 891 AcpiOsUnmapMemory (MappedTable, sizeof (*MappedTable)); 892 return (AE_NOT_EXIST); 893 } 894 895 /* Map the entire table */ 896 897 Length = MappedTable->Length; 898 AcpiOsUnmapMemory (MappedTable, sizeof (*MappedTable)); 899 900 MappedTable = AcpiOsMapMemory (Address, Length); 901 if (!MappedTable) 902 { 903 return (AE_BAD_ADDRESS); 904 } 905 906 (void) ApIsValidChecksum (MappedTable); 907 908 *Table = MappedTable; 909 910 return (AE_OK); 911 } 912