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