kernel: Sync ACPICA with Intel's version 20140114.
[dragonfly.git] / sys / contrib / dev / acpica / source / components / tables / tbutils.c
1 /******************************************************************************
2  *
3  * Module Name: tbutils - ACPI Table utilities
4  *
5  *****************************************************************************/
6
7 /*
8  * Copyright (C) 2000 - 2014, 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 #define __TBUTILS_C__
45
46 #include "acpi.h"
47 #include "accommon.h"
48 #include "actables.h"
49
50 #define _COMPONENT          ACPI_TABLES
51         ACPI_MODULE_NAME    ("tbutils")
52
53
54 /* Local prototypes */
55
56 static ACPI_STATUS
57 AcpiTbValidateXsdt (
58     ACPI_PHYSICAL_ADDRESS   Address);
59
60 static ACPI_PHYSICAL_ADDRESS
61 AcpiTbGetRootTableEntry (
62     UINT8                   *TableEntry,
63     UINT32                  TableEntrySize);
64
65
66 #if (!ACPI_REDUCED_HARDWARE)
67 /*******************************************************************************
68  *
69  * FUNCTION:    AcpiTbInitializeFacs
70  *
71  * PARAMETERS:  None
72  *
73  * RETURN:      Status
74  *
75  * DESCRIPTION: Create a permanent mapping for the FADT and save it in a global
76  *              for accessing the Global Lock and Firmware Waking Vector
77  *
78  ******************************************************************************/
79
80 ACPI_STATUS
81 AcpiTbInitializeFacs (
82     void)
83 {
84     ACPI_STATUS             Status;
85
86
87     /* If Hardware Reduced flag is set, there is no FACS */
88
89     if (AcpiGbl_ReducedHardware)
90     {
91         AcpiGbl_FACS = NULL;
92         return (AE_OK);
93     }
94
95     Status = AcpiGetTableByIndex (ACPI_TABLE_INDEX_FACS,
96                 ACPI_CAST_INDIRECT_PTR (ACPI_TABLE_HEADER, &AcpiGbl_FACS));
97     return (Status);
98 }
99 #endif /* !ACPI_REDUCED_HARDWARE */
100
101
102 /*******************************************************************************
103  *
104  * FUNCTION:    AcpiTbTablesLoaded
105  *
106  * PARAMETERS:  None
107  *
108  * RETURN:      TRUE if required ACPI tables are loaded
109  *
110  * DESCRIPTION: Determine if the minimum required ACPI tables are present
111  *              (FADT, FACS, DSDT)
112  *
113  ******************************************************************************/
114
115 BOOLEAN
116 AcpiTbTablesLoaded (
117     void)
118 {
119
120     if (AcpiGbl_RootTableList.CurrentTableCount >= 3)
121     {
122         return (TRUE);
123     }
124
125     return (FALSE);
126 }
127
128
129 /*******************************************************************************
130  *
131  * FUNCTION:    AcpiTbCheckDsdtHeader
132  *
133  * PARAMETERS:  None
134  *
135  * RETURN:      None
136  *
137  * DESCRIPTION: Quick compare to check validity of the DSDT. This will detect
138  *              if the DSDT has been replaced from outside the OS and/or if
139  *              the DSDT header has been corrupted.
140  *
141  ******************************************************************************/
142
143 void
144 AcpiTbCheckDsdtHeader (
145     void)
146 {
147
148     /* Compare original length and checksum to current values */
149
150     if (AcpiGbl_OriginalDsdtHeader.Length != AcpiGbl_DSDT->Length ||
151         AcpiGbl_OriginalDsdtHeader.Checksum != AcpiGbl_DSDT->Checksum)
152     {
153         ACPI_BIOS_ERROR ((AE_INFO,
154             "The DSDT has been corrupted or replaced - "
155             "old, new headers below"));
156         AcpiTbPrintTableHeader (0, &AcpiGbl_OriginalDsdtHeader);
157         AcpiTbPrintTableHeader (0, AcpiGbl_DSDT);
158
159         /* Disable further error messages */
160
161         AcpiGbl_OriginalDsdtHeader.Length = AcpiGbl_DSDT->Length;
162         AcpiGbl_OriginalDsdtHeader.Checksum = AcpiGbl_DSDT->Checksum;
163     }
164 }
165
166
167 /*******************************************************************************
168  *
169  * FUNCTION:    AcpiTbCopyDsdt
170  *
171  * PARAMETERS:  TableDesc           - Installed table to copy
172  *
173  * RETURN:      None
174  *
175  * DESCRIPTION: Implements a subsystem option to copy the DSDT to local memory.
176  *              Some very bad BIOSs are known to either corrupt the DSDT or
177  *              install a new, bad DSDT. This copy works around the problem.
178  *
179  ******************************************************************************/
180
181 ACPI_TABLE_HEADER *
182 AcpiTbCopyDsdt (
183     UINT32                  TableIndex)
184 {
185     ACPI_TABLE_HEADER       *NewTable;
186     ACPI_TABLE_DESC         *TableDesc;
187
188
189     TableDesc = &AcpiGbl_RootTableList.Tables[TableIndex];
190
191     NewTable = ACPI_ALLOCATE (TableDesc->Length);
192     if (!NewTable)
193     {
194         ACPI_ERROR ((AE_INFO, "Could not copy DSDT of length 0x%X",
195             TableDesc->Length));
196         return (NULL);
197     }
198
199     ACPI_MEMCPY (NewTable, TableDesc->Pointer, TableDesc->Length);
200     AcpiTbDeleteTable (TableDesc);
201     TableDesc->Pointer = NewTable;
202     TableDesc->Flags = ACPI_TABLE_ORIGIN_ALLOCATED;
203
204     ACPI_INFO ((AE_INFO,
205         "Forced DSDT copy: length 0x%05X copied locally, original unmapped",
206         NewTable->Length));
207
208     return (NewTable);
209 }
210
211
212 /*******************************************************************************
213  *
214  * FUNCTION:    AcpiTbInstallTable
215  *
216  * PARAMETERS:  Address                 - Physical address of DSDT or FACS
217  *              Signature               - Table signature, NULL if no need to
218  *                                        match
219  *              TableIndex              - Index into root table array
220  *
221  * RETURN:      None
222  *
223  * DESCRIPTION: Install an ACPI table into the global data structure. The
224  *              table override mechanism is called to allow the host
225  *              OS to replace any table before it is installed in the root
226  *              table array.
227  *
228  ******************************************************************************/
229
230 void
231 AcpiTbInstallTable (
232     ACPI_PHYSICAL_ADDRESS   Address,
233     char                    *Signature,
234     UINT32                  TableIndex)
235 {
236     ACPI_TABLE_HEADER       *Table;
237     ACPI_TABLE_HEADER       *FinalTable;
238     ACPI_TABLE_DESC         *TableDesc;
239
240
241     if (!Address)
242     {
243         ACPI_ERROR ((AE_INFO, "Null physical address for ACPI table [%s]",
244             Signature));
245         return;
246     }
247
248     /* Map just the table header */
249
250     Table = AcpiOsMapMemory (Address, sizeof (ACPI_TABLE_HEADER));
251     if (!Table)
252     {
253         ACPI_ERROR ((AE_INFO, "Could not map memory for table [%s] at %p",
254             Signature, ACPI_CAST_PTR (void, Address)));
255         return;
256     }
257
258     /* If a particular signature is expected (DSDT/FACS), it must match */
259
260     if (Signature &&
261         !ACPI_COMPARE_NAME (Table->Signature, Signature))
262     {
263         ACPI_BIOS_ERROR ((AE_INFO,
264             "Invalid signature 0x%X for ACPI table, expected [%s]",
265             *ACPI_CAST_PTR (UINT32, Table->Signature), Signature));
266         goto UnmapAndExit;
267     }
268
269     /*
270      * Initialize the table entry. Set the pointer to NULL, since the
271      * table is not fully mapped at this time.
272      */
273     TableDesc = &AcpiGbl_RootTableList.Tables[TableIndex];
274
275     TableDesc->Address = Address;
276     TableDesc->Pointer = NULL;
277     TableDesc->Length = Table->Length;
278     TableDesc->Flags = ACPI_TABLE_ORIGIN_MAPPED;
279     ACPI_MOVE_32_TO_32 (TableDesc->Signature.Ascii, Table->Signature);
280
281     /*
282      * ACPI Table Override:
283      *
284      * Before we install the table, let the host OS override it with a new
285      * one if desired. Any table within the RSDT/XSDT can be replaced,
286      * including the DSDT which is pointed to by the FADT.
287      *
288      * NOTE: If the table is overridden, then FinalTable will contain a
289      * mapped pointer to the full new table. If the table is not overridden,
290      * or if there has been a physical override, then the table will be
291      * fully mapped later (in verify table). In any case, we must
292      * unmap the header that was mapped above.
293      */
294     FinalTable = AcpiTbTableOverride (Table, TableDesc);
295     if (!FinalTable)
296     {
297         FinalTable = Table; /* There was no override */
298     }
299
300     AcpiTbPrintTableHeader (TableDesc->Address, FinalTable);
301
302     /* Set the global integer width (based upon revision of the DSDT) */
303
304     if (TableIndex == ACPI_TABLE_INDEX_DSDT)
305     {
306         AcpiUtSetIntegerWidth (FinalTable->Revision);
307     }
308
309     /*
310      * If we have a physical override during this early loading of the ACPI
311      * tables, unmap the table for now. It will be mapped again later when
312      * it is actually used. This supports very early loading of ACPI tables,
313      * before virtual memory is fully initialized and running within the
314      * host OS. Note: A logical override has the ACPI_TABLE_ORIGIN_OVERRIDE
315      * flag set and will not be deleted below.
316      */
317     if (FinalTable != Table)
318     {
319         AcpiTbDeleteTable (TableDesc);
320     }
321
322
323 UnmapAndExit:
324
325     /* Always unmap the table header that we mapped above */
326
327     AcpiOsUnmapMemory (Table, sizeof (ACPI_TABLE_HEADER));
328 }
329
330
331 /*******************************************************************************
332  *
333  * FUNCTION:    AcpiTbGetRootTableEntry
334  *
335  * PARAMETERS:  TableEntry          - Pointer to the RSDT/XSDT table entry
336  *              TableEntrySize      - sizeof 32 or 64 (RSDT or XSDT)
337  *
338  * RETURN:      Physical address extracted from the root table
339  *
340  * DESCRIPTION: Get one root table entry. Handles 32-bit and 64-bit cases on
341  *              both 32-bit and 64-bit platforms
342  *
343  * NOTE:        ACPI_PHYSICAL_ADDRESS is 32-bit on 32-bit platforms, 64-bit on
344  *              64-bit platforms.
345  *
346  ******************************************************************************/
347
348 static ACPI_PHYSICAL_ADDRESS
349 AcpiTbGetRootTableEntry (
350     UINT8                   *TableEntry,
351     UINT32                  TableEntrySize)
352 {
353     UINT64                  Address64;
354
355
356     /*
357      * Get the table physical address (32-bit for RSDT, 64-bit for XSDT):
358      * Note: Addresses are 32-bit aligned (not 64) in both RSDT and XSDT
359      */
360     if (TableEntrySize == ACPI_RSDT_ENTRY_SIZE)
361     {
362         /*
363          * 32-bit platform, RSDT: Return 32-bit table entry
364          * 64-bit platform, RSDT: Expand 32-bit to 64-bit and return
365          */
366         return ((ACPI_PHYSICAL_ADDRESS) (*ACPI_CAST_PTR (UINT32, TableEntry)));
367     }
368     else
369     {
370         /*
371          * 32-bit platform, XSDT: Truncate 64-bit to 32-bit and return
372          * 64-bit platform, XSDT: Move (unaligned) 64-bit to local,
373          *  return 64-bit
374          */
375         ACPI_MOVE_64_TO_64 (&Address64, TableEntry);
376
377 #if ACPI_MACHINE_WIDTH == 32
378         if (Address64 > ACPI_UINT32_MAX)
379         {
380             /* Will truncate 64-bit address to 32 bits, issue warning */
381
382             ACPI_BIOS_WARNING ((AE_INFO,
383                 "64-bit Physical Address in XSDT is too large (0x%8.8X%8.8X),"
384                 " truncating",
385                 ACPI_FORMAT_UINT64 (Address64)));
386         }
387 #endif
388         return ((ACPI_PHYSICAL_ADDRESS) (Address64));
389     }
390 }
391
392
393 /*******************************************************************************
394  *
395  * FUNCTION:    AcpiTbValidateXsdt
396  *
397  * PARAMETERS:  Address             - Physical address of the XSDT (from RSDP)
398  *
399  * RETURN:      Status. AE_OK if the table appears to be valid.
400  *
401  * DESCRIPTION: Validate an XSDT to ensure that it is of minimum size and does
402  *              not contain any NULL entries. A problem that is seen in the
403  *              field is that the XSDT exists, but is actually useless because
404  *              of one or more (or all) NULL entries.
405  *
406  ******************************************************************************/
407
408 static ACPI_STATUS
409 AcpiTbValidateXsdt (
410     ACPI_PHYSICAL_ADDRESS   XsdtAddress)
411 {
412     ACPI_TABLE_HEADER       *Table;
413     UINT8                   *NextEntry;
414     ACPI_PHYSICAL_ADDRESS   Address;
415     UINT32                  Length;
416     UINT32                  EntryCount;
417     ACPI_STATUS             Status;
418     UINT32                  i;
419
420
421     /* Get the XSDT length */
422
423     Table = AcpiOsMapMemory (XsdtAddress, sizeof (ACPI_TABLE_HEADER));
424     if (!Table)
425     {
426         return (AE_NO_MEMORY);
427     }
428
429     Length = Table->Length;
430     AcpiOsUnmapMemory (Table, sizeof (ACPI_TABLE_HEADER));
431
432     /*
433      * Minimum XSDT length is the size of the standard ACPI header
434      * plus one physical address entry
435      */
436     if (Length < (sizeof (ACPI_TABLE_HEADER) + ACPI_XSDT_ENTRY_SIZE))
437     {
438         return (AE_INVALID_TABLE_LENGTH);
439     }
440
441     /* Map the entire XSDT */
442
443     Table = AcpiOsMapMemory (XsdtAddress, Length);
444     if (!Table)
445     {
446         return (AE_NO_MEMORY);
447     }
448
449     /* Get the number of entries and pointer to first entry */
450
451     Status = AE_OK;
452     NextEntry = ACPI_ADD_PTR (UINT8, Table, sizeof (ACPI_TABLE_HEADER));
453     EntryCount = (UINT32) ((Table->Length - sizeof (ACPI_TABLE_HEADER)) /
454         ACPI_XSDT_ENTRY_SIZE);
455
456     /* Validate each entry (physical address) within the XSDT */
457
458     for (i = 0; i < EntryCount; i++)
459     {
460         Address = AcpiTbGetRootTableEntry (NextEntry, ACPI_XSDT_ENTRY_SIZE);
461         if (!Address)
462         {
463             /* Detected a NULL entry, XSDT is invalid */
464
465             Status = AE_NULL_ENTRY;
466             break;
467         }
468
469         NextEntry += ACPI_XSDT_ENTRY_SIZE;
470     }
471
472     /* Unmap table */
473
474     AcpiOsUnmapMemory (Table, Length);
475     return (Status);
476 }
477
478
479 /*******************************************************************************
480  *
481  * FUNCTION:    AcpiTbParseRootTable
482  *
483  * PARAMETERS:  Rsdp                    - Pointer to the RSDP
484  *
485  * RETURN:      Status
486  *
487  * DESCRIPTION: This function is called to parse the Root System Description
488  *              Table (RSDT or XSDT)
489  *
490  * NOTE:        Tables are mapped (not copied) for efficiency. The FACS must
491  *              be mapped and cannot be copied because it contains the actual
492  *              memory location of the ACPI Global Lock.
493  *
494  ******************************************************************************/
495
496 ACPI_STATUS
497 AcpiTbParseRootTable (
498     ACPI_PHYSICAL_ADDRESS   RsdpAddress)
499 {
500     ACPI_TABLE_RSDP         *Rsdp;
501     UINT32                  TableEntrySize;
502     UINT32                  i;
503     UINT32                  TableCount;
504     ACPI_TABLE_HEADER       *Table;
505     ACPI_PHYSICAL_ADDRESS   Address;
506     UINT32                  Length;
507     UINT8                   *TableEntry;
508     ACPI_STATUS             Status;
509
510
511     ACPI_FUNCTION_TRACE (TbParseRootTable);
512
513
514     /* Map the entire RSDP and extract the address of the RSDT or XSDT */
515
516     Rsdp = AcpiOsMapMemory (RsdpAddress, sizeof (ACPI_TABLE_RSDP));
517     if (!Rsdp)
518     {
519         return_ACPI_STATUS (AE_NO_MEMORY);
520     }
521
522     AcpiTbPrintTableHeader (RsdpAddress,
523         ACPI_CAST_PTR (ACPI_TABLE_HEADER, Rsdp));
524
525     /* Use XSDT if present and not overridden. Otherwise, use RSDT */
526
527     if ((Rsdp->Revision > 1) &&
528         Rsdp->XsdtPhysicalAddress &&
529         !AcpiGbl_DoNotUseXsdt)
530     {
531         /*
532          * RSDP contains an XSDT (64-bit physical addresses). We must use
533          * the XSDT if the revision is > 1 and the XSDT pointer is present,
534          * as per the ACPI specification.
535          */
536         Address = (ACPI_PHYSICAL_ADDRESS) Rsdp->XsdtPhysicalAddress;
537         TableEntrySize = ACPI_XSDT_ENTRY_SIZE;
538     }
539     else
540     {
541         /* Root table is an RSDT (32-bit physical addresses) */
542
543         Address = (ACPI_PHYSICAL_ADDRESS) Rsdp->RsdtPhysicalAddress;
544         TableEntrySize = ACPI_RSDT_ENTRY_SIZE;
545     }
546
547     /*
548      * It is not possible to map more than one entry in some environments,
549      * so unmap the RSDP here before mapping other tables
550      */
551     AcpiOsUnmapMemory (Rsdp, sizeof (ACPI_TABLE_RSDP));
552
553     /*
554      * If it is present and used, validate the XSDT for access/size
555      * and ensure that all table entries are at least non-NULL
556      */
557     if (TableEntrySize == ACPI_XSDT_ENTRY_SIZE)
558     {
559         Status = AcpiTbValidateXsdt (Address);
560         if (ACPI_FAILURE (Status))
561         {
562             ACPI_BIOS_WARNING ((AE_INFO, "XSDT is invalid (%s), using RSDT",
563                 AcpiFormatException (Status)));
564
565             /* Fall back to the RSDT */
566
567             Address = (ACPI_PHYSICAL_ADDRESS) Rsdp->RsdtPhysicalAddress;
568             TableEntrySize = ACPI_RSDT_ENTRY_SIZE;
569         }
570     }
571
572     /* Map the RSDT/XSDT table header to get the full table length */
573
574     Table = AcpiOsMapMemory (Address, sizeof (ACPI_TABLE_HEADER));
575     if (!Table)
576     {
577         return_ACPI_STATUS (AE_NO_MEMORY);
578     }
579
580     AcpiTbPrintTableHeader (Address, Table);
581
582     /*
583      * Validate length of the table, and map entire table.
584      * Minimum length table must contain at least one entry.
585      */
586     Length = Table->Length;
587     AcpiOsUnmapMemory (Table, sizeof (ACPI_TABLE_HEADER));
588
589     if (Length < (sizeof (ACPI_TABLE_HEADER) + TableEntrySize))
590     {
591         ACPI_BIOS_ERROR ((AE_INFO,
592             "Invalid table length 0x%X in RSDT/XSDT", Length));
593         return_ACPI_STATUS (AE_INVALID_TABLE_LENGTH);
594     }
595
596     Table = AcpiOsMapMemory (Address, Length);
597     if (!Table)
598     {
599         return_ACPI_STATUS (AE_NO_MEMORY);
600     }
601
602     /* Validate the root table checksum */
603
604     Status = AcpiTbVerifyChecksum (Table, Length);
605     if (ACPI_FAILURE (Status))
606     {
607         AcpiOsUnmapMemory (Table, Length);
608         return_ACPI_STATUS (Status);
609     }
610
611     /* Get the number of entries and pointer to first entry */
612
613     TableCount = (UINT32) ((Table->Length - sizeof (ACPI_TABLE_HEADER)) /
614         TableEntrySize);
615     TableEntry = ACPI_ADD_PTR (UINT8, Table, sizeof (ACPI_TABLE_HEADER));
616
617     /*
618      * First two entries in the table array are reserved for the DSDT
619      * and FACS, which are not actually present in the RSDT/XSDT - they
620      * come from the FADT
621      */
622     AcpiGbl_RootTableList.CurrentTableCount = 2;
623
624     /* Initialize the root table array from the RSDT/XSDT */
625
626     for (i = 0; i < TableCount; i++)
627     {
628         if (AcpiGbl_RootTableList.CurrentTableCount >=
629             AcpiGbl_RootTableList.MaxTableCount)
630         {
631             /* There is no more room in the root table array, attempt resize */
632
633             Status = AcpiTbResizeRootTableList ();
634             if (ACPI_FAILURE (Status))
635             {
636                 ACPI_WARNING ((AE_INFO, "Truncating %u table entries!",
637                     (unsigned) (TableCount -
638                     (AcpiGbl_RootTableList.CurrentTableCount - 2))));
639                 break;
640             }
641         }
642
643         /* Get the table physical address (32-bit for RSDT, 64-bit for XSDT) */
644
645         AcpiGbl_RootTableList.Tables[AcpiGbl_RootTableList.CurrentTableCount].Address =
646             AcpiTbGetRootTableEntry (TableEntry, TableEntrySize);
647
648         TableEntry += TableEntrySize;
649         AcpiGbl_RootTableList.CurrentTableCount++;
650     }
651
652     /*
653      * It is not possible to map more than one entry in some environments,
654      * so unmap the root table here before mapping other tables
655      */
656     AcpiOsUnmapMemory (Table, Length);
657
658     /*
659      * Complete the initialization of the root table array by examining
660      * the header of each table
661      */
662     for (i = 2; i < AcpiGbl_RootTableList.CurrentTableCount; i++)
663     {
664         AcpiTbInstallTable (AcpiGbl_RootTableList.Tables[i].Address,
665             NULL, i);
666
667         /* Special case for FADT - validate it then get the DSDT and FACS */
668
669         if (ACPI_COMPARE_NAME (
670                 &AcpiGbl_RootTableList.Tables[i].Signature, ACPI_SIG_FADT))
671         {
672             AcpiTbParseFadt (i);
673         }
674     }
675
676     return_ACPI_STATUS (AE_OK);
677 }