1 /****************************************************************************** 2 * 3 * Module Name: osbsdtbl - BSD OSL for obtaining ACPI tables 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2015, 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__) 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__) 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 size_t Length = sizeof (Address); 390 391 392 /* Get main ACPI tables from memory on first invocation of this function */ 393 394 if (Gbl_MainTableObtained) 395 { 396 return (AE_OK); 397 } 398 399 /* Attempt to use kenv or sysctl to find RSD PTR record. */ 400 401 if (Gbl_RsdpBase) 402 { 403 Address = Gbl_RsdpBase; 404 } 405 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) 406 else if (kenv (KENV_GET, SYSTEM_KENV, Buffer, sizeof (Buffer)) > 0) 407 { 408 Address = strtoul (Buffer, NULL, 0); 409 } 410 #endif 411 if (!Address) 412 { 413 if (sysctlbyname (SYSTEM_SYSCTL, &Address, &Length, NULL, 0) != 0) 414 { 415 Address = 0; 416 } 417 } 418 if (Address) 419 { 420 RsdpBase = Address; 421 RsdpSize = sizeof (Gbl_Rsdp); 422 } 423 else 424 { 425 RsdpBase = ACPI_HI_RSDP_WINDOW_BASE; 426 RsdpSize = ACPI_HI_RSDP_WINDOW_SIZE; 427 } 428 429 /* Get RSDP from memory */ 430 431 RsdpAddress = AcpiOsMapMemory (RsdpBase, RsdpSize); 432 if (!RsdpAddress) 433 { 434 return (AE_BAD_ADDRESS); 435 } 436 437 /* Search low memory for the RSDP */ 438 439 TableAddress = AcpiTbScanMemoryForRsdp (RsdpAddress, RsdpSize); 440 if (!TableAddress) 441 { 442 AcpiOsUnmapMemory (RsdpAddress, RsdpSize); 443 return (AE_ERROR); 444 } 445 446 memcpy (&Gbl_Rsdp, TableAddress, sizeof (Gbl_Rsdp)); 447 AcpiOsUnmapMemory (RsdpAddress, RsdpSize); 448 449 /* Get XSDT from memory */ 450 451 if (Gbl_Rsdp.Revision) 452 { 453 Status = OslMapTable (Gbl_Rsdp.XsdtPhysicalAddress, 454 ACPI_SIG_XSDT, &MappedTable); 455 if (ACPI_FAILURE (Status)) 456 { 457 return (Status); 458 } 459 460 Gbl_Revision = 2; 461 Gbl_Xsdt = calloc (1, MappedTable->Length); 462 if (!Gbl_Xsdt) 463 { 464 fprintf (stderr, 465 "XSDT: Could not allocate buffer for table of length %X\n", 466 MappedTable->Length); 467 AcpiOsUnmapMemory (MappedTable, MappedTable->Length); 468 return (AE_NO_MEMORY); 469 } 470 471 memcpy (Gbl_Xsdt, MappedTable, MappedTable->Length); 472 AcpiOsUnmapMemory (MappedTable, MappedTable->Length); 473 } 474 475 /* Get RSDT from memory */ 476 477 if (Gbl_Rsdp.RsdtPhysicalAddress) 478 { 479 Status = OslMapTable (Gbl_Rsdp.RsdtPhysicalAddress, 480 ACPI_SIG_RSDT, &MappedTable); 481 if (ACPI_FAILURE (Status)) 482 { 483 return (Status); 484 } 485 486 Gbl_Rsdt = calloc (1, MappedTable->Length); 487 if (!Gbl_Rsdt) 488 { 489 fprintf (stderr, 490 "RSDT: Could not allocate buffer for table of length %X\n", 491 MappedTable->Length); 492 AcpiOsUnmapMemory (MappedTable, MappedTable->Length); 493 return (AE_NO_MEMORY); 494 } 495 496 memcpy (Gbl_Rsdt, MappedTable, MappedTable->Length); 497 AcpiOsUnmapMemory (MappedTable, MappedTable->Length); 498 } 499 500 /* Get FADT from memory */ 501 502 if (Gbl_Revision) 503 { 504 Gbl_FadtAddress = Gbl_Xsdt->TableOffsetEntry[0]; 505 } 506 else 507 { 508 Gbl_FadtAddress = Gbl_Rsdt->TableOffsetEntry[0]; 509 } 510 511 if (!Gbl_FadtAddress) 512 { 513 fprintf(stderr, "FADT: Table could not be found\n"); 514 return (AE_ERROR); 515 } 516 517 Status = OslMapTable (Gbl_FadtAddress, ACPI_SIG_FADT, &MappedTable); 518 if (ACPI_FAILURE (Status)) 519 { 520 return (Status); 521 } 522 523 Gbl_Fadt = calloc (1, MappedTable->Length); 524 if (!Gbl_Fadt) 525 { 526 fprintf (stderr, 527 "FADT: Could not allocate buffer for table of length %X\n", 528 MappedTable->Length); 529 AcpiOsUnmapMemory (MappedTable, MappedTable->Length); 530 return (AE_NO_MEMORY); 531 } 532 533 memcpy (Gbl_Fadt, MappedTable, MappedTable->Length); 534 AcpiOsUnmapMemory (MappedTable, MappedTable->Length); 535 Gbl_MainTableObtained = TRUE; 536 return (AE_OK); 537 } 538 539 540 /****************************************************************************** 541 * 542 * FUNCTION: OslGetTableViaRoot 543 * 544 * PARAMETERS: Signature - ACPI Signature for common table. Must be 545 * a null terminated 4-character string. 546 * Instance - Multiple table support for SSDT/UEFI (0...n) 547 * Must be 0 for other tables. 548 * Table - Where a pointer to the table is returned 549 * Address - Where the table physical address is returned 550 * 551 * RETURN: Status; Table buffer and physical address returned if AE_OK. 552 * AE_LIMIT: Instance is beyond valid limit 553 * AE_NOT_FOUND: A table with the signature was not found 554 * 555 * DESCRIPTION: Get an ACPI table via the root table (RSDT/XSDT) 556 * 557 * NOTE: Assumes the input signature is uppercase. 558 * 559 *****************************************************************************/ 560 561 static ACPI_STATUS 562 OslGetTableViaRoot ( 563 char *Signature, 564 UINT32 Instance, 565 ACPI_TABLE_HEADER **Table, 566 ACPI_PHYSICAL_ADDRESS *Address) 567 { 568 ACPI_TABLE_HEADER *LocalTable = NULL; 569 ACPI_TABLE_HEADER *MappedTable = NULL; 570 UINT8 NumberOfTables; 571 UINT32 CurrentInstance = 0; 572 ACPI_PHYSICAL_ADDRESS TableAddress = 0; 573 ACPI_STATUS Status; 574 UINT32 i; 575 576 577 /* DSDT and FACS address must be extracted from the FADT */ 578 579 if (ACPI_COMPARE_NAME (Signature, ACPI_SIG_DSDT) || 580 ACPI_COMPARE_NAME (Signature, ACPI_SIG_FACS)) 581 { 582 /* 583 * Get the appropriate address, either 32-bit or 64-bit. Be very 584 * careful about the FADT length and validate table addresses. 585 * Note: The 64-bit addresses have priority. 586 */ 587 if (ACPI_COMPARE_NAME (Signature, ACPI_SIG_DSDT)) 588 { 589 if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_XDSDT) && 590 Gbl_Fadt->XDsdt) 591 { 592 TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->XDsdt; 593 } 594 else if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_DSDT) && 595 Gbl_Fadt->Dsdt) 596 { 597 TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->Dsdt; 598 } 599 } 600 else /* FACS */ 601 { 602 if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_XFACS) && 603 Gbl_Fadt->XFacs) 604 { 605 TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->XFacs; 606 } 607 else if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_FACS) && 608 Gbl_Fadt->Facs) 609 { 610 TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->Facs; 611 } 612 } 613 } 614 else /* Case for a normal ACPI table */ 615 { 616 if (Gbl_Revision) 617 { 618 NumberOfTables = 619 (Gbl_Xsdt->Header.Length - sizeof (Gbl_Xsdt->Header)) 620 / sizeof (Gbl_Xsdt->TableOffsetEntry[0]); 621 } 622 else /* Use RSDT if XSDT is not available */ 623 { 624 NumberOfTables = 625 (Gbl_Rsdt->Header.Length - sizeof (Gbl_Rsdt->Header)) 626 / sizeof (Gbl_Rsdt->TableOffsetEntry[0]); 627 } 628 629 /* Search RSDT/XSDT for the requested table */ 630 631 for (i = 0; i < NumberOfTables; i++) 632 { 633 if (Gbl_Revision) 634 { 635 TableAddress = Gbl_Xsdt->TableOffsetEntry[i]; 636 } 637 else 638 { 639 TableAddress = Gbl_Rsdt->TableOffsetEntry[i]; 640 } 641 642 MappedTable = AcpiOsMapMemory (TableAddress, sizeof (*MappedTable)); 643 if (!MappedTable) 644 { 645 return (AE_BAD_ADDRESS); 646 } 647 648 /* Does this table match the requested signature? */ 649 650 if (ACPI_COMPARE_NAME (MappedTable->Signature, Signature)) 651 { 652 653 /* Match table instance (for SSDT/UEFI tables) */ 654 655 if (CurrentInstance == Instance) 656 { 657 AcpiOsUnmapMemory (MappedTable, sizeof (*MappedTable)); 658 break; 659 } 660 661 CurrentInstance++; 662 } 663 664 AcpiOsUnmapMemory (MappedTable, MappedTable->Length); 665 TableAddress = 0; 666 } 667 } 668 669 if (!TableAddress) 670 { 671 if (CurrentInstance) 672 { 673 return (AE_LIMIT); 674 } 675 return (AE_NOT_FOUND); 676 } 677 678 /* Now we can get the requested table */ 679 680 Status = OslMapTable (TableAddress, Signature, &MappedTable); 681 if (ACPI_FAILURE (Status)) 682 { 683 return (Status); 684 } 685 686 /* Copy table to local buffer and return it */ 687 688 LocalTable = calloc (1, MappedTable->Length); 689 if (!LocalTable) 690 { 691 AcpiOsUnmapMemory (MappedTable, MappedTable->Length); 692 return (AE_NO_MEMORY); 693 } 694 695 memcpy (LocalTable, MappedTable, MappedTable->Length); 696 AcpiOsUnmapMemory (MappedTable, MappedTable->Length); 697 *Table = LocalTable; 698 *Address = TableAddress; 699 return (AE_OK); 700 } 701 702 703 /****************************************************************************** 704 * 705 * FUNCTION: OslAddTablesToList 706 * 707 * PARAMETERS: None 708 * 709 * RETURN: Status; Table list is initialized if AE_OK. 710 * 711 * DESCRIPTION: Add ACPI tables to the table list. 712 * 713 *****************************************************************************/ 714 715 static ACPI_STATUS 716 OslAddTablesToList( 717 void) 718 { 719 ACPI_PHYSICAL_ADDRESS TableAddress; 720 OSL_TABLE_INFO *Info = NULL; 721 OSL_TABLE_INFO *NewInfo; 722 ACPI_TABLE_HEADER *Table; 723 UINT8 Instance; 724 UINT8 NumberOfTables; 725 int i; 726 727 728 /* Initialize the table list on first invocation */ 729 730 if (Gbl_TableListInitialized) 731 { 732 return (AE_OK); 733 } 734 735 /* Add mandatory tables to global table list first */ 736 737 for (i = 0; i < 4; i++) 738 { 739 NewInfo = calloc (1, sizeof (*NewInfo)); 740 if (!NewInfo) 741 { 742 return (AE_NO_MEMORY); 743 } 744 745 switch (i) { 746 case 0: 747 748 Gbl_TableListHead = Info = NewInfo; 749 continue; 750 751 case 1: 752 753 ACPI_MOVE_NAME (NewInfo->Signature, 754 Gbl_Revision ? ACPI_SIG_XSDT : ACPI_SIG_RSDT); 755 break; 756 757 case 2: 758 759 ACPI_MOVE_NAME (NewInfo->Signature, ACPI_SIG_FACS); 760 break; 761 762 default: 763 764 ACPI_MOVE_NAME (NewInfo->Signature, ACPI_SIG_DSDT); 765 766 } 767 768 Info->Next = NewInfo; 769 Info = NewInfo; 770 Gbl_TableListHead->Instance++; 771 } 772 773 /* Add normal tables from RSDT/XSDT to global list */ 774 775 if (Gbl_Revision) 776 { 777 NumberOfTables = 778 (Gbl_Xsdt->Header.Length - sizeof (Gbl_Xsdt->Header)) 779 / sizeof (Gbl_Xsdt->TableOffsetEntry[0]); 780 } 781 else 782 { 783 NumberOfTables = 784 (Gbl_Rsdt->Header.Length - sizeof (Gbl_Rsdt->Header)) 785 / sizeof (Gbl_Rsdt->TableOffsetEntry[0]); 786 } 787 788 for (i = 0; i < NumberOfTables; i++) 789 { 790 if (Gbl_Revision) 791 { 792 TableAddress = Gbl_Xsdt->TableOffsetEntry[i]; 793 } 794 else 795 { 796 TableAddress = Gbl_Rsdt->TableOffsetEntry[i]; 797 } 798 799 Table = AcpiOsMapMemory (TableAddress, sizeof (*Table)); 800 if (!Table) 801 { 802 return (AE_BAD_ADDRESS); 803 } 804 805 Instance = 0; 806 NewInfo = Gbl_TableListHead; 807 while (NewInfo->Next != NULL) 808 { 809 NewInfo = NewInfo->Next; 810 if (ACPI_COMPARE_NAME (Table->Signature, NewInfo->Signature)) 811 { 812 Instance++; 813 } 814 } 815 816 NewInfo = calloc (1, sizeof (*NewInfo)); 817 if (!NewInfo) 818 { 819 AcpiOsUnmapMemory (Table, sizeof (*Table)); 820 return (AE_NO_MEMORY); 821 } 822 823 ACPI_MOVE_NAME (NewInfo->Signature, Table->Signature); 824 825 AcpiOsUnmapMemory (Table, sizeof (*Table)); 826 827 NewInfo->Instance = Instance; 828 NewInfo->Address = TableAddress; 829 Info->Next = NewInfo; 830 Info = NewInfo; 831 Gbl_TableListHead->Instance++; 832 } 833 834 Gbl_TableListInitialized = TRUE; 835 return (AE_OK); 836 } 837 838 839 /****************************************************************************** 840 * 841 * FUNCTION: OslMapTable 842 * 843 * PARAMETERS: Address - Address of the table in memory 844 * Signature - Optional ACPI Signature for desired table. 845 * Null terminated 4-character string. 846 * Table - Where a pointer to the mapped table is 847 * returned 848 * 849 * RETURN: Status; Mapped table is returned if AE_OK. 850 * 851 * DESCRIPTION: Map entire ACPI table into caller's address space. Also 852 * validates the table and checksum. 853 * 854 *****************************************************************************/ 855 856 static ACPI_STATUS 857 OslMapTable ( 858 ACPI_SIZE Address, 859 char *Signature, 860 ACPI_TABLE_HEADER **Table) 861 { 862 ACPI_TABLE_HEADER *MappedTable; 863 UINT32 Length; 864 865 866 /* Map the header so we can get the table length */ 867 868 MappedTable = AcpiOsMapMemory (Address, sizeof (*MappedTable)); 869 if (!MappedTable) 870 { 871 return (AE_BAD_ADDRESS); 872 } 873 874 /* Check if table is valid */ 875 876 if (!ApIsValidHeader (MappedTable)) 877 { 878 AcpiOsUnmapMemory (MappedTable, sizeof (*MappedTable)); 879 return (AE_BAD_HEADER); 880 } 881 882 /* If specified, signature must match */ 883 884 if (Signature && 885 !ACPI_COMPARE_NAME (Signature, MappedTable->Signature)) 886 { 887 AcpiOsUnmapMemory (MappedTable, sizeof (*MappedTable)); 888 return (AE_NOT_EXIST); 889 } 890 891 /* Map the entire table */ 892 893 Length = MappedTable->Length; 894 AcpiOsUnmapMemory (MappedTable, sizeof (*MappedTable)); 895 896 MappedTable = AcpiOsMapMemory (Address, Length); 897 if (!MappedTable) 898 { 899 return (AE_BAD_ADDRESS); 900 } 901 902 (void) ApIsValidChecksum (MappedTable); 903 904 *Table = MappedTable; 905 906 return (AE_OK); 907 } 908