exconfig.c revision 207344
1219019Sgabor/****************************************************************************** 2219019Sgabor * 3219019Sgabor * Module Name: exconfig - Namespace reconfiguration (Load/Unload opcodes) 4219019Sgabor * 5219019Sgabor *****************************************************************************/ 6219019Sgabor 7219019Sgabor/****************************************************************************** 8219019Sgabor * 9219019Sgabor * 1. Copyright Notice 10219019Sgabor * 11219019Sgabor * Some or all of this work - Copyright (c) 1999 - 2010, Intel Corp. 12219019Sgabor * All rights reserved. 13219019Sgabor * 14219019Sgabor * 2. License 15219019Sgabor * 16219019Sgabor * 2.1. This is your license from Intel Corp. under its intellectual property 17219019Sgabor * rights. You may have additional license terms from the party that provided 18219019Sgabor * you this software, covering your right to use that party's intellectual 19219019Sgabor * property rights. 20219019Sgabor * 21219019Sgabor * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a 22219019Sgabor * copy of the source code appearing in this file ("Covered Code") an 23219019Sgabor * irrevocable, perpetual, worldwide license under Intel's copyrights in the 24219019Sgabor * base code distributed originally by Intel ("Original Intel Code") to copy, 25219019Sgabor * make derivatives, distribute, use and display any portion of the Covered 26219019Sgabor * Code in any form, with the right to sublicense such rights; and 27219019Sgabor * 28219019Sgabor * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent 29219019Sgabor * license (with the right to sublicense), under only those claims of Intel 30219019Sgabor * patents that are infringed by the Original Intel Code, to make, use, sell, 31219019Sgabor * offer to sell, and import the Covered Code and derivative works thereof 32219019Sgabor * solely to the minimum extent necessary to exercise the above copyright 33219019Sgabor * license, and in no event shall the patent license extend to any additions 34219019Sgabor * to or modifications of the Original Intel Code. No other license or right 35219019Sgabor * is granted directly or by implication, estoppel or otherwise; 36219019Sgabor * 37219019Sgabor * The above copyright and patent license is granted only if the following 38219019Sgabor * conditions are met: 39219019Sgabor * 40219019Sgabor * 3. Conditions 41219019Sgabor * 42219019Sgabor * 3.1. Redistribution of Source with Rights to Further Distribute Source. 43255297Stheraven * Redistribution of source code of any substantial portion of the Covered 44255297Stheraven * Code or modification with rights to further distribute source must include 45255297Stheraven * the above Copyright Notice, the above License, this list of Conditions, 46255297Stheraven * and the following Disclaimer and Export Compliance provision. In addition, 47255297Stheraven * Licensee must cause all Covered Code to which Licensee contributes to 48255297Stheraven * contain a file documenting the changes Licensee made to create that Covered 49255297Stheraven * Code and the date of any change. Licensee must include in that file the 50219019Sgabor * documentation of any changes made by any predecessor Licensee. Licensee 51219019Sgabor * must include a prominent statement that the modification is derived, 52219019Sgabor * directly or indirectly, from Original Intel Code. 53219019Sgabor * 54219019Sgabor * 3.2. Redistribution of Source with no Rights to Further Distribute Source. 55254273Speter * Redistribution of source code of any substantial portion of the Covered 56254273Speter * Code or modification without rights to further distribute source must 57254273Speter * include the following Disclaimer and Export Compliance provision in the 58254273Speter * documentation and/or other materials provided with distribution. In 59254273Speter * addition, Licensee may not authorize further sublicense of source of any 60219019Sgabor * portion of the Covered Code, and must include terms to the effect that the 61219019Sgabor * license from Licensee to its licensee is limited to the intellectual 62219019Sgabor * property embodied in the software Licensee provides to its licensee, and 63255297Stheraven * not to intellectual property embodied in modifications its licensee may 64219019Sgabor * make. 65252547Speter * 66219019Sgabor * 3.3. Redistribution of Executable. Redistribution in executable form of any 67219019Sgabor * substantial portion of the Covered Code or modification must reproduce the 68219019Sgabor * above Copyright Notice, and the following Disclaimer and Export Compliance 69219019Sgabor * provision in the documentation and/or other materials provided with the 70219019Sgabor * distribution. 71219019Sgabor * 72219019Sgabor * 3.4. Intel retains all right, title, and interest in and to the Original 73219019Sgabor * Intel Code. 74219019Sgabor * 75219019Sgabor * 3.5. Neither the name Intel nor any other trademark owned or controlled by 76219019Sgabor * Intel shall be used in advertising or otherwise to promote the sale, use or 77258283Speter * other dealings in products derived from or relating to the Covered Code 78219019Sgabor * without prior written authorization from Intel. 79219019Sgabor * 80219019Sgabor * 4. Disclaimer and Export Compliance 81219019Sgabor * 82219019Sgabor * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED 83219019Sgabor * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE 84219019Sgabor * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, 85219019Sgabor * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY 86219019Sgabor 87219019Sgabor * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY 88219019Sgabor * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A 89258537Shrs * PARTICULAR PURPOSE. 90258537Shrs * 91219019Sgabor * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES 92219019Sgabor * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR 93219019Sgabor * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT, 94219019Sgabor * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY 95219019Sgabor * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL 96219019Sgabor * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS 97219019Sgabor * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY 98219019Sgabor * LIMITED REMEDY. 99219019Sgabor * 100219019Sgabor * 4.3. Licensee shall not export, either directly or indirectly, any of this 101219019Sgabor * software or system incorporating such software without first obtaining any 102219019Sgabor * required license or other approval from the U. S. Department of Commerce or 103219019Sgabor * any other agency or department of the United States Government. In the 104219019Sgabor * event Licensee exports any such software from the United States or 105219019Sgabor * re-exports any such software from a foreign destination, Licensee shall 106219019Sgabor * ensure that the distribution and export/re-export of the software is in 107219019Sgabor * compliance with all laws, regulations, orders, or other restrictions of the 108219019Sgabor * U.S. Export Administration Regulations. Licensee agrees that neither it nor 109219019Sgabor * any of its subsidiaries will export/re-export any technical data, process, 110219019Sgabor * software, or service, directly or indirectly, to any country for which the 111219019Sgabor * United States government or any agency thereof requires an export license, 112219019Sgabor * other governmental approval, or letter of assurance, without first obtaining 113219019Sgabor * such license, approval or letter. 114219019Sgabor * 115219019Sgabor *****************************************************************************/ 116219019Sgabor 117219019Sgabor#define __EXCONFIG_C__ 118219019Sgabor 119219019Sgabor#include <contrib/dev/acpica/include/acpi.h> 120219019Sgabor#include <contrib/dev/acpica/include/accommon.h> 121219019Sgabor#include <contrib/dev/acpica/include/acinterp.h> 122219019Sgabor#include <contrib/dev/acpica/include/acnamesp.h> 123219019Sgabor#include <contrib/dev/acpica/include/actables.h> 124219019Sgabor#include <contrib/dev/acpica/include/acdispat.h> 125219019Sgabor#include <contrib/dev/acpica/include/acevents.h> 126219019Sgabor 127219019Sgabor 128219019Sgabor#define _COMPONENT ACPI_EXECUTER 129219019Sgabor ACPI_MODULE_NAME ("exconfig") 130219019Sgabor 131219019Sgabor/* Local prototypes */ 132219019Sgabor 133219019Sgaborstatic ACPI_STATUS 134AcpiExAddTable ( 135 UINT32 TableIndex, 136 ACPI_NAMESPACE_NODE *ParentNode, 137 ACPI_OPERAND_OBJECT **DdbHandle); 138 139static ACPI_STATUS 140AcpiExRegionRead ( 141 ACPI_OPERAND_OBJECT *ObjDesc, 142 UINT32 Length, 143 UINT8 *Buffer); 144 145 146/******************************************************************************* 147 * 148 * FUNCTION: AcpiExAddTable 149 * 150 * PARAMETERS: Table - Pointer to raw table 151 * ParentNode - Where to load the table (scope) 152 * DdbHandle - Where to return the table handle. 153 * 154 * RETURN: Status 155 * 156 * DESCRIPTION: Common function to Install and Load an ACPI table with a 157 * returned table handle. 158 * 159 ******************************************************************************/ 160 161static ACPI_STATUS 162AcpiExAddTable ( 163 UINT32 TableIndex, 164 ACPI_NAMESPACE_NODE *ParentNode, 165 ACPI_OPERAND_OBJECT **DdbHandle) 166{ 167 ACPI_OPERAND_OBJECT *ObjDesc; 168 ACPI_STATUS Status; 169 ACPI_OWNER_ID OwnerId; 170 171 172 ACPI_FUNCTION_TRACE (ExAddTable); 173 174 175 /* Create an object to be the table handle */ 176 177 ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_REFERENCE); 178 if (!ObjDesc) 179 { 180 return_ACPI_STATUS (AE_NO_MEMORY); 181 } 182 183 /* Init the table handle */ 184 185 ObjDesc->Common.Flags |= AOPOBJ_DATA_VALID; 186 ObjDesc->Reference.Class = ACPI_REFCLASS_TABLE; 187 *DdbHandle = ObjDesc; 188 189 /* Install the new table into the local data structures */ 190 191 ObjDesc->Reference.Value = TableIndex; 192 193 /* Add the table to the namespace */ 194 195 Status = AcpiNsLoadTable (TableIndex, ParentNode); 196 if (ACPI_FAILURE (Status)) 197 { 198 AcpiUtRemoveReference (ObjDesc); 199 *DdbHandle = NULL; 200 return_ACPI_STATUS (Status); 201 } 202 203 /* Execute any module-level code that was found in the table */ 204 205 AcpiExExitInterpreter (); 206 AcpiNsExecModuleCodeList (); 207 AcpiExEnterInterpreter (); 208 209 /* Update GPEs for any new _PRW or _Lxx/_Exx methods. Ignore errors */ 210 211 Status = AcpiTbGetOwnerId (TableIndex, &OwnerId); 212 if (ACPI_SUCCESS (Status)) 213 { 214 AcpiEvUpdateGpes (OwnerId); 215 } 216 217 return_ACPI_STATUS (AE_OK); 218} 219 220 221/******************************************************************************* 222 * 223 * FUNCTION: AcpiExLoadTableOp 224 * 225 * PARAMETERS: WalkState - Current state with operands 226 * ReturnDesc - Where to store the return object 227 * 228 * RETURN: Status 229 * 230 * DESCRIPTION: Load an ACPI table from the RSDT/XSDT 231 * 232 ******************************************************************************/ 233 234ACPI_STATUS 235AcpiExLoadTableOp ( 236 ACPI_WALK_STATE *WalkState, 237 ACPI_OPERAND_OBJECT **ReturnDesc) 238{ 239 ACPI_STATUS Status; 240 ACPI_OPERAND_OBJECT **Operand = &WalkState->Operands[0]; 241 ACPI_NAMESPACE_NODE *ParentNode; 242 ACPI_NAMESPACE_NODE *StartNode; 243 ACPI_NAMESPACE_NODE *ParameterNode = NULL; 244 ACPI_OPERAND_OBJECT *DdbHandle; 245 ACPI_TABLE_HEADER *Table; 246 UINT32 TableIndex; 247 248 249 ACPI_FUNCTION_TRACE (ExLoadTableOp); 250 251 252 /* Validate lengths for the SignatureString, OEMIDString, OEMTableID */ 253 254 if ((Operand[0]->String.Length > ACPI_NAME_SIZE) || 255 (Operand[1]->String.Length > ACPI_OEM_ID_SIZE) || 256 (Operand[2]->String.Length > ACPI_OEM_TABLE_ID_SIZE)) 257 { 258 return_ACPI_STATUS (AE_BAD_PARAMETER); 259 } 260 261 /* Find the ACPI table in the RSDT/XSDT */ 262 263 Status = AcpiTbFindTable (Operand[0]->String.Pointer, 264 Operand[1]->String.Pointer, 265 Operand[2]->String.Pointer, &TableIndex); 266 if (ACPI_FAILURE (Status)) 267 { 268 if (Status != AE_NOT_FOUND) 269 { 270 return_ACPI_STATUS (Status); 271 } 272 273 /* Table not found, return an Integer=0 and AE_OK */ 274 275 DdbHandle = AcpiUtCreateIntegerObject ((UINT64) 0); 276 if (!DdbHandle) 277 { 278 return_ACPI_STATUS (AE_NO_MEMORY); 279 } 280 281 *ReturnDesc = DdbHandle; 282 return_ACPI_STATUS (AE_OK); 283 } 284 285 /* Default nodes */ 286 287 StartNode = WalkState->ScopeInfo->Scope.Node; 288 ParentNode = AcpiGbl_RootNode; 289 290 /* RootPath (optional parameter) */ 291 292 if (Operand[3]->String.Length > 0) 293 { 294 /* 295 * Find the node referenced by the RootPathString. This is the 296 * location within the namespace where the table will be loaded. 297 */ 298 Status = AcpiNsGetNode (StartNode, Operand[3]->String.Pointer, 299 ACPI_NS_SEARCH_PARENT, &ParentNode); 300 if (ACPI_FAILURE (Status)) 301 { 302 return_ACPI_STATUS (Status); 303 } 304 } 305 306 /* ParameterPath (optional parameter) */ 307 308 if (Operand[4]->String.Length > 0) 309 { 310 if ((Operand[4]->String.Pointer[0] != '\\') && 311 (Operand[4]->String.Pointer[0] != '^')) 312 { 313 /* 314 * Path is not absolute, so it will be relative to the node 315 * referenced by the RootPathString (or the NS root if omitted) 316 */ 317 StartNode = ParentNode; 318 } 319 320 /* Find the node referenced by the ParameterPathString */ 321 322 Status = AcpiNsGetNode (StartNode, Operand[4]->String.Pointer, 323 ACPI_NS_SEARCH_PARENT, &ParameterNode); 324 if (ACPI_FAILURE (Status)) 325 { 326 return_ACPI_STATUS (Status); 327 } 328 } 329 330 /* Load the table into the namespace */ 331 332 Status = AcpiExAddTable (TableIndex, ParentNode, &DdbHandle); 333 if (ACPI_FAILURE (Status)) 334 { 335 return_ACPI_STATUS (Status); 336 } 337 338 /* Parameter Data (optional) */ 339 340 if (ParameterNode) 341 { 342 /* Store the parameter data into the optional parameter object */ 343 344 Status = AcpiExStore (Operand[5], 345 ACPI_CAST_PTR (ACPI_OPERAND_OBJECT, ParameterNode), 346 WalkState); 347 if (ACPI_FAILURE (Status)) 348 { 349 (void) AcpiExUnloadTable (DdbHandle); 350 351 AcpiUtRemoveReference (DdbHandle); 352 return_ACPI_STATUS (Status); 353 } 354 } 355 356 Status = AcpiGetTableByIndex (TableIndex, &Table); 357 if (ACPI_SUCCESS (Status)) 358 { 359 ACPI_INFO ((AE_INFO, "Dynamic OEM Table Load:")); 360 AcpiTbPrintTableHeader (0, Table); 361 } 362 363 /* Invoke table handler if present */ 364 365 if (AcpiGbl_TableHandler) 366 { 367 (void) AcpiGbl_TableHandler (ACPI_TABLE_EVENT_LOAD, Table, 368 AcpiGbl_TableHandlerContext); 369 } 370 371 *ReturnDesc = DdbHandle; 372 return_ACPI_STATUS (Status); 373} 374 375 376/******************************************************************************* 377 * 378 * FUNCTION: AcpiExRegionRead 379 * 380 * PARAMETERS: ObjDesc - Region descriptor 381 * Length - Number of bytes to read 382 * Buffer - Pointer to where to put the data 383 * 384 * RETURN: Status 385 * 386 * DESCRIPTION: Read data from an operation region. The read starts from the 387 * beginning of the region. 388 * 389 ******************************************************************************/ 390 391static ACPI_STATUS 392AcpiExRegionRead ( 393 ACPI_OPERAND_OBJECT *ObjDesc, 394 UINT32 Length, 395 UINT8 *Buffer) 396{ 397 ACPI_STATUS Status; 398 UINT64 Value; 399 UINT32 RegionOffset = 0; 400 UINT32 i; 401 402 403 /* Bytewise reads */ 404 405 for (i = 0; i < Length; i++) 406 { 407 Status = AcpiEvAddressSpaceDispatch (ObjDesc, ACPI_READ, 408 RegionOffset, 8, &Value); 409 if (ACPI_FAILURE (Status)) 410 { 411 return (Status); 412 } 413 414 *Buffer = (UINT8) Value; 415 Buffer++; 416 RegionOffset++; 417 } 418 419 return (AE_OK); 420} 421 422 423/******************************************************************************* 424 * 425 * FUNCTION: AcpiExLoadOp 426 * 427 * PARAMETERS: ObjDesc - Region or Buffer/Field where the table will be 428 * obtained 429 * Target - Where a handle to the table will be stored 430 * WalkState - Current state 431 * 432 * RETURN: Status 433 * 434 * DESCRIPTION: Load an ACPI table from a field or operation region 435 * 436 * NOTE: Region Fields (Field, BankField, IndexFields) are resolved to buffer 437 * objects before this code is reached. 438 * 439 * If source is an operation region, it must refer to SystemMemory, as 440 * per the ACPI specification. 441 * 442 ******************************************************************************/ 443 444ACPI_STATUS 445AcpiExLoadOp ( 446 ACPI_OPERAND_OBJECT *ObjDesc, 447 ACPI_OPERAND_OBJECT *Target, 448 ACPI_WALK_STATE *WalkState) 449{ 450 ACPI_OPERAND_OBJECT *DdbHandle; 451 ACPI_TABLE_HEADER *Table; 452 ACPI_TABLE_DESC TableDesc; 453 UINT32 TableIndex; 454 ACPI_STATUS Status; 455 UINT32 Length; 456 457 458 ACPI_FUNCTION_TRACE (ExLoadOp); 459 460 461 ACPI_MEMSET (&TableDesc, 0, sizeof (ACPI_TABLE_DESC)); 462 463 /* Source Object can be either an OpRegion or a Buffer/Field */ 464 465 switch (ObjDesc->Common.Type) 466 { 467 case ACPI_TYPE_REGION: 468 469 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, 470 "Load table from Region %p\n", ObjDesc)); 471 472 /* Region must be SystemMemory (from ACPI spec) */ 473 474 if (ObjDesc->Region.SpaceId != ACPI_ADR_SPACE_SYSTEM_MEMORY) 475 { 476 return_ACPI_STATUS (AE_AML_OPERAND_TYPE); 477 } 478 479 /* 480 * If the Region Address and Length have not been previously evaluated, 481 * evaluate them now and save the results. 482 */ 483 if (!(ObjDesc->Common.Flags & AOPOBJ_DATA_VALID)) 484 { 485 Status = AcpiDsGetRegionArguments (ObjDesc); 486 if (ACPI_FAILURE (Status)) 487 { 488 return_ACPI_STATUS (Status); 489 } 490 } 491 492 /* Get the table header first so we can get the table length */ 493 494 Table = ACPI_ALLOCATE (sizeof (ACPI_TABLE_HEADER)); 495 if (!Table) 496 { 497 return_ACPI_STATUS (AE_NO_MEMORY); 498 } 499 500 Status = AcpiExRegionRead (ObjDesc, sizeof (ACPI_TABLE_HEADER), 501 ACPI_CAST_PTR (UINT8, Table)); 502 Length = Table->Length; 503 ACPI_FREE (Table); 504 505 if (ACPI_FAILURE (Status)) 506 { 507 return_ACPI_STATUS (Status); 508 } 509 510 /* Must have at least an ACPI table header */ 511 512 if (Length < sizeof (ACPI_TABLE_HEADER)) 513 { 514 return_ACPI_STATUS (AE_INVALID_TABLE_LENGTH); 515 } 516 517 /* 518 * The original implementation simply mapped the table, with no copy. 519 * However, the memory region is not guaranteed to remain stable and 520 * we must copy the table to a local buffer. For example, the memory 521 * region is corrupted after suspend on some machines. Dynamically 522 * loaded tables are usually small, so this overhead is minimal. 523 * 524 * The latest implementation (5/2009) does not use a mapping at all. 525 * We use the low-level operation region interface to read the table 526 * instead of the obvious optimization of using a direct mapping. 527 * This maintains a consistent use of operation regions across the 528 * entire subsystem. This is important if additional processing must 529 * be performed in the (possibly user-installed) operation region 530 * handler. For example, AcpiExec and ASLTS depend on this. 531 */ 532 533 /* Allocate a buffer for the table */ 534 535 TableDesc.Pointer = ACPI_ALLOCATE (Length); 536 if (!TableDesc.Pointer) 537 { 538 return_ACPI_STATUS (AE_NO_MEMORY); 539 } 540 541 /* Read the entire table */ 542 543 Status = AcpiExRegionRead (ObjDesc, Length, 544 ACPI_CAST_PTR (UINT8, TableDesc.Pointer)); 545 if (ACPI_FAILURE (Status)) 546 { 547 ACPI_FREE (TableDesc.Pointer); 548 return_ACPI_STATUS (Status); 549 } 550 551 TableDesc.Address = ObjDesc->Region.Address; 552 break; 553 554 555 case ACPI_TYPE_BUFFER: /* Buffer or resolved RegionField */ 556 557 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, 558 "Load table from Buffer or Field %p\n", ObjDesc)); 559 560 /* Must have at least an ACPI table header */ 561 562 if (ObjDesc->Buffer.Length < sizeof (ACPI_TABLE_HEADER)) 563 { 564 return_ACPI_STATUS (AE_INVALID_TABLE_LENGTH); 565 } 566 567 /* Get the actual table length from the table header */ 568 569 Table = ACPI_CAST_PTR (ACPI_TABLE_HEADER, ObjDesc->Buffer.Pointer); 570 Length = Table->Length; 571 572 /* Table cannot extend beyond the buffer */ 573 574 if (Length > ObjDesc->Buffer.Length) 575 { 576 return_ACPI_STATUS (AE_AML_BUFFER_LIMIT); 577 } 578 if (Length < sizeof (ACPI_TABLE_HEADER)) 579 { 580 return_ACPI_STATUS (AE_INVALID_TABLE_LENGTH); 581 } 582 583 /* 584 * Copy the table from the buffer because the buffer could be modified 585 * or even deleted in the future 586 */ 587 TableDesc.Pointer = ACPI_ALLOCATE (Length); 588 if (!TableDesc.Pointer) 589 { 590 return_ACPI_STATUS (AE_NO_MEMORY); 591 } 592 593 ACPI_MEMCPY (TableDesc.Pointer, Table, Length); 594 TableDesc.Address = ACPI_TO_INTEGER (TableDesc.Pointer); 595 break; 596 597 598 default: 599 return_ACPI_STATUS (AE_AML_OPERAND_TYPE); 600 } 601 602 /* Validate table checksum (will not get validated in TbAddTable) */ 603 604 Status = AcpiTbVerifyChecksum (TableDesc.Pointer, Length); 605 if (ACPI_FAILURE (Status)) 606 { 607 ACPI_FREE (TableDesc.Pointer); 608 return_ACPI_STATUS (Status); 609 } 610 611 /* Complete the table descriptor */ 612 613 TableDesc.Length = Length; 614 TableDesc.Flags = ACPI_TABLE_ORIGIN_ALLOCATED; 615 616 /* Install the new table into the local data structures */ 617 618 Status = AcpiTbAddTable (&TableDesc, &TableIndex); 619 if (ACPI_FAILURE (Status)) 620 { 621 /* Delete allocated table buffer */ 622 623 AcpiTbDeleteTable (&TableDesc); 624 return_ACPI_STATUS (Status); 625 } 626 627 /* 628 * Add the table to the namespace. 629 * 630 * Note: Load the table objects relative to the root of the namespace. 631 * This appears to go against the ACPI specification, but we do it for 632 * compatibility with other ACPI implementations. 633 */ 634 Status = AcpiExAddTable (TableIndex, AcpiGbl_RootNode, &DdbHandle); 635 if (ACPI_FAILURE (Status)) 636 { 637 /* On error, TablePtr was deallocated above */ 638 639 return_ACPI_STATUS (Status); 640 } 641 642 /* Store the DdbHandle into the Target operand */ 643 644 Status = AcpiExStore (DdbHandle, Target, WalkState); 645 if (ACPI_FAILURE (Status)) 646 { 647 (void) AcpiExUnloadTable (DdbHandle); 648 649 /* TablePtr was deallocated above */ 650 651 AcpiUtRemoveReference (DdbHandle); 652 return_ACPI_STATUS (Status); 653 } 654 655 ACPI_INFO ((AE_INFO, "Dynamic OEM Table Load:")); 656 AcpiTbPrintTableHeader (0, TableDesc.Pointer); 657 658 /* Remove the reference by added by AcpiExStore above */ 659 660 AcpiUtRemoveReference (DdbHandle); 661 662 /* Invoke table handler if present */ 663 664 if (AcpiGbl_TableHandler) 665 { 666 (void) AcpiGbl_TableHandler (ACPI_TABLE_EVENT_LOAD, TableDesc.Pointer, 667 AcpiGbl_TableHandlerContext); 668 } 669 670 return_ACPI_STATUS (Status); 671} 672 673 674/******************************************************************************* 675 * 676 * FUNCTION: AcpiExUnloadTable 677 * 678 * PARAMETERS: DdbHandle - Handle to a previously loaded table 679 * 680 * RETURN: Status 681 * 682 * DESCRIPTION: Unload an ACPI table 683 * 684 ******************************************************************************/ 685 686ACPI_STATUS 687AcpiExUnloadTable ( 688 ACPI_OPERAND_OBJECT *DdbHandle) 689{ 690 ACPI_STATUS Status = AE_OK; 691 ACPI_OPERAND_OBJECT *TableDesc = DdbHandle; 692 UINT32 TableIndex; 693 ACPI_TABLE_HEADER *Table; 694 695 696 ACPI_FUNCTION_TRACE (ExUnloadTable); 697 698 699 /* 700 * Validate the handle 701 * Although the handle is partially validated in AcpiExReconfiguration() 702 * when it calls AcpiExResolveOperands(), the handle is more completely 703 * validated here. 704 * 705 * Handle must be a valid operand object of type reference. Also, the 706 * DdbHandle must still be marked valid (table has not been previously 707 * unloaded) 708 */ 709 if ((!DdbHandle) || 710 (ACPI_GET_DESCRIPTOR_TYPE (DdbHandle) != ACPI_DESC_TYPE_OPERAND) || 711 (DdbHandle->Common.Type != ACPI_TYPE_LOCAL_REFERENCE) || 712 (!(DdbHandle->Common.Flags & AOPOBJ_DATA_VALID))) 713 { 714 return_ACPI_STATUS (AE_BAD_PARAMETER); 715 } 716 717 /* Get the table index from the DdbHandle */ 718 719 TableIndex = TableDesc->Reference.Value; 720 721 /* Ensure the table is still loaded */ 722 723 if (!AcpiTbIsTableLoaded (TableIndex)) 724 { 725 return_ACPI_STATUS (AE_NOT_EXIST); 726 } 727 728 /* Invoke table handler if present */ 729 730 if (AcpiGbl_TableHandler) 731 { 732 Status = AcpiGetTableByIndex (TableIndex, &Table); 733 if (ACPI_SUCCESS (Status)) 734 { 735 (void) AcpiGbl_TableHandler (ACPI_TABLE_EVENT_UNLOAD, Table, 736 AcpiGbl_TableHandlerContext); 737 } 738 } 739 740 /* Delete the portion of the namespace owned by this table */ 741 742 Status = AcpiTbDeleteNamespaceByOwner (TableIndex); 743 if (ACPI_FAILURE (Status)) 744 { 745 return_ACPI_STATUS (Status); 746 } 747 748 (void) AcpiTbReleaseOwnerId (TableIndex); 749 AcpiTbSetTableLoadedFlag (TableIndex, FALSE); 750 751 /* 752 * Invalidate the handle. We do this because the handle may be stored 753 * in a named object and may not be actually deleted until much later. 754 */ 755 DdbHandle->Common.Flags &= ~AOPOBJ_DATA_VALID; 756 return_ACPI_STATUS (AE_OK); 757} 758 759