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