tbutils.c revision 71867
159191Skris/******************************************************************************
2280304Sjkim *
3280304Sjkim * Module Name: tbutils - Table manipulation utilities
4160814Ssimon *              $Revision: 33 $
559191Skris *
659191Skris *****************************************************************************/
7160814Ssimon
859191Skris/******************************************************************************
959191Skris *
1059191Skris * 1. Copyright Notice
1159191Skris *
1259191Skris * Some or all of this work - Copyright (c) 1999, 2000, 2001, Intel Corp.
1359191Skris * All rights reserved.
14280304Sjkim *
1559191Skris * 2. License
1659191Skris *
1759191Skris * 2.1. This is your license from Intel Corp. under its intellectual property
1859191Skris * rights.  You may have additional license terms from the party that provided
1959191Skris * you this software, covering your right to use that party's intellectual
2059191Skris * property rights.
2159191Skris *
2259191Skris * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
2359191Skris * copy of the source code appearing in this file ("Covered Code") an
2459191Skris * irrevocable, perpetual, worldwide license under Intel's copyrights in the
2559191Skris * base code distributed originally by Intel ("Original Intel Code") to copy,
2659191Skris * make derivatives, distribute, use and display any portion of the Covered
2759191Skris * Code in any form, with the right to sublicense such rights; and
2859191Skris *
2959191Skris * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
3059191Skris * license (with the right to sublicense), under only those claims of Intel
3159191Skris * patents that are infringed by the Original Intel Code, to make, use, sell,
3259191Skris * offer to sell, and import the Covered Code and derivative works thereof
3359191Skris * solely to the minimum extent necessary to exercise the above copyright
3459191Skris * license, and in no event shall the patent license extend to any additions
3559191Skris * to or modifications of the Original Intel Code.  No other license or right
3659191Skris * is granted directly or by implication, estoppel or otherwise;
3759191Skris *
3859191Skris * The above copyright and patent license is granted only if the following
3959191Skris * conditions are met:
4059191Skris *
4159191Skris * 3. Conditions
4259191Skris *
4359191Skris * 3.1. Redistribution of Source with Rights to Further Distribute Source.
4459191Skris * Redistribution of source code of any substantial portion of the Covered
4559191Skris * Code or modification with rights to further distribute source must include
4659191Skris * the above Copyright Notice, the above License, this list of Conditions,
4759191Skris * and the following Disclaimer and Export Compliance provision.  In addition,
4859191Skris * Licensee must cause all Covered Code to which Licensee contributes to
4959191Skris * contain a file documenting the changes Licensee made to create that Covered
5059191Skris * Code and the date of any change.  Licensee must include in that file the
5159191Skris * documentation of any changes made by any predecessor Licensee.  Licensee
5259191Skris * must include a prominent statement that the modification is derived,
5359191Skris * directly or indirectly, from Original Intel Code.
5459191Skris *
5559191Skris * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
5659191Skris * Redistribution of source code of any substantial portion of the Covered
5759191Skris * Code or modification without rights to further distribute source must
5859191Skris * include the following Disclaimer and Export Compliance provision in the
5959191Skris * documentation and/or other materials provided with distribution.  In
6059191Skris * addition, Licensee may not authorize further sublicense of source of any
6159191Skris * portion of the Covered Code, and must include terms to the effect that the
6259191Skris * license from Licensee to its licensee is limited to the intellectual
6359191Skris * property embodied in the software Licensee provides to its licensee, and
6459191Skris * not to intellectual property embodied in modifications its licensee may
6559191Skris * make.
6659191Skris *
6759191Skris * 3.3. Redistribution of Executable. Redistribution in executable form of any
68160814Ssimon * substantial portion of the Covered Code or modification must reproduce the
69160814Ssimon * above Copyright Notice, and the following Disclaimer and Export Compliance
7059191Skris * provision in the documentation and/or other materials provided with the
7159191Skris * distribution.
7259191Skris *
7359191Skris * 3.4. Intel retains all right, title, and interest in and to the Original
74160814Ssimon * Intel Code.
7559191Skris *
76280304Sjkim * 3.5. Neither the name Intel nor any other trademark owned or controlled by
77280304Sjkim * Intel shall be used in advertising or otherwise to promote the sale, use or
78280304Sjkim * other dealings in products derived from or relating to the Covered Code
79280304Sjkim * without prior written authorization from Intel.
80280304Sjkim *
81280304Sjkim * 4. Disclaimer and Export Compliance
82280304Sjkim *
83280304Sjkim * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
84280304Sjkim * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
8559191Skris * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
8659191Skris * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
8759191Skris * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
8859191Skris * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
89280304Sjkim * PARTICULAR PURPOSE.
90280304Sjkim *
91280304Sjkim * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
92280304Sjkim * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
93280304Sjkim * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
94280304Sjkim * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
95280304Sjkim * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
96280304Sjkim * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
97280304Sjkim * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
98280304Sjkim * LIMITED REMEDY.
99280304Sjkim *
100280304Sjkim * 4.3. Licensee shall not export, either directly or indirectly, any of this
101280304Sjkim * software or system incorporating such software without first obtaining any
102280304Sjkim * required license or other approval from the U. S. Department of Commerce or
103280304Sjkim * any other agency or department of the United States Government.  In the
104280304Sjkim * event Licensee exports any such software from the United States or
105280304Sjkim * re-exports any such software from a foreign destination, Licensee shall
106280304Sjkim * ensure that the distribution and export/re-export of the software is in
107280304Sjkim * compliance with all laws, regulations, orders, or other restrictions of the
108280304Sjkim * U.S. Export Administration Regulations. Licensee agrees that neither it nor
109280304Sjkim * any of its subsidiaries will export/re-export any technical data, process,
110280304Sjkim * software, or service, directly or indirectly, to any country for which the
111280304Sjkim * United States government or any agency thereof requires an export license,
112280304Sjkim * other governmental approval, or letter of assurance, without first obtaining
113280304Sjkim * such license, approval or letter.
114280304Sjkim *
115280304Sjkim *****************************************************************************/
116280304Sjkim
117111147Snectar#define __TBUTILS_C__
118280304Sjkim
119111147Snectar#include "acpi.h"
120109998Smarkm#include "actables.h"
121280304Sjkim#include "acinterp.h"
122160814Ssimon
123280304Sjkim
124280304Sjkim#define _COMPONENT          TABLE_MANAGER
12559191Skris        MODULE_NAME         ("tbutils")
126280304Sjkim
127109998Smarkm
128280304Sjkim/*******************************************************************************
129280304Sjkim *
130280304Sjkim * FUNCTION:    AcpiTbHandleToObject
131280304Sjkim *
132109998Smarkm * PARAMETERS:  TableId             - Id for which the function is searching
133280304Sjkim *              TableDesc           - Pointer to return the matching table
134280304Sjkim *                                      descriptor.
135109998Smarkm *
136280304Sjkim * RETURN:      Search the tables to find one with a matching TableId and
137280304Sjkim *              return a pointer to that table descriptor.
138280304Sjkim *
139280304Sjkim ******************************************************************************/
140280304Sjkim
141280304SjkimACPI_STATUS
142280304SjkimAcpiTbHandleToObject (
143280304Sjkim    UINT16                  TableId,
144280304Sjkim    ACPI_TABLE_DESC         **TableDesc)
145280304Sjkim{
146280304Sjkim    UINT32                  i;
147280304Sjkim    ACPI_TABLE_DESC         *ListHead;
148280304Sjkim
149109998Smarkm
150280304Sjkim    for (i = 0; i < ACPI_TABLE_MAX; i++)
151280304Sjkim    {
152280304Sjkim        ListHead = &AcpiGbl_AcpiTables[i];
153280304Sjkim        do
15459191Skris        {
155194206Ssimon            if (ListHead->TableId == TableId)
156280304Sjkim            {
157280304Sjkim                *TableDesc = ListHead;
158194206Ssimon                return (AE_OK);
159109998Smarkm            }
160280304Sjkim
161280304Sjkim            ListHead = ListHead->Next;
162280304Sjkim
163280304Sjkim        } while (ListHead != &AcpiGbl_AcpiTables[i]);
164280304Sjkim    }
165280304Sjkim
16659191Skris
167109998Smarkm    DEBUG_PRINT (ACPI_ERROR, ("TableId=%X does not exist\n", TableId));
168280304Sjkim    return (AE_BAD_PARAMETER);
169280304Sjkim}
170280304Sjkim
171280304Sjkim
172280304Sjkim/*******************************************************************************
173280304Sjkim *
174109998Smarkm * FUNCTION:    AcpiTbSystemTablePointer
175162911Ssimon *
176280304Sjkim * PARAMETERS:  *Where              - Pointer to be examined
177280304Sjkim *
178280304Sjkim * RETURN:      TRUE if Where is within the AML stream (in one of the ACPI
179280304Sjkim *              system tables such as the DSDT or an SSDT.)
180280304Sjkim *              FALSE otherwise
181280304Sjkim *
182162911Ssimon ******************************************************************************/
183280304Sjkim
184280304SjkimBOOLEAN
185280304SjkimAcpiTbSystemTablePointer (
186280304Sjkim    void                    *Where)
187280304Sjkim{
188280304Sjkim    UINT32                  i;
189280304Sjkim    ACPI_TABLE_DESC         *TableDesc;
190280304Sjkim    ACPI_TABLE_HEADER       *Table;
191280304Sjkim
192280304Sjkim
193280304Sjkim    /* No function trace, called too often! */
194280304Sjkim
195280304Sjkim
196280304Sjkim    /* Ignore null pointer */
197280304Sjkim
198280304Sjkim    if (!Where)
199280304Sjkim    {
200280304Sjkim        return (FALSE);
201280304Sjkim    }
202280304Sjkim
203280304Sjkim
204280304Sjkim    /* Check for a pointer within the DSDT */
205280304Sjkim
206280304Sjkim    if ((AcpiGbl_DSDT) &&
207280304Sjkim        (IS_IN_ACPI_TABLE (Where, AcpiGbl_DSDT)))
208280304Sjkim    {
209280304Sjkim        return (TRUE);
210280304Sjkim    }
211280304Sjkim
212280304Sjkim
213280304Sjkim    /* Check each of the loaded SSDTs (if any)*/
214280304Sjkim
215280304Sjkim    TableDesc = &AcpiGbl_AcpiTables[ACPI_TABLE_SSDT];
216280304Sjkim
217280304Sjkim    for (i = 0; i < AcpiGbl_AcpiTables[ACPI_TABLE_SSDT].Count; i++)
218280304Sjkim    {
219280304Sjkim        Table = TableDesc->Pointer;
220111147Snectar
221280304Sjkim        if (IS_IN_ACPI_TABLE (Where, Table))
222280304Sjkim        {
223280304Sjkim            return (TRUE);
224280304Sjkim        }
225280304Sjkim
226111147Snectar        TableDesc = TableDesc->Next;
227280304Sjkim    }
228280304Sjkim
229280304Sjkim
230280304Sjkim    /* Check each of the loaded PSDTs (if any)*/
231280304Sjkim
232280304Sjkim    TableDesc = &AcpiGbl_AcpiTables[ACPI_TABLE_PSDT];
233280304Sjkim
234280304Sjkim    for (i = 0; i < AcpiGbl_AcpiTables[ACPI_TABLE_PSDT].Count; i++)
235280304Sjkim    {
236280304Sjkim        Table = TableDesc->Pointer;
237280304Sjkim
238280304Sjkim        if (IS_IN_ACPI_TABLE (Where, Table))
239280304Sjkim        {
240280304Sjkim            return (TRUE);
241280304Sjkim        }
242280304Sjkim
243280304Sjkim        TableDesc = TableDesc->Next;
244280304Sjkim    }
245280304Sjkim
246280304Sjkim
247238405Sjkim    /* Pointer does not point into any system table */
248280304Sjkim
249280304Sjkim    return (FALSE);
250280304Sjkim}
251280304Sjkim
252280304Sjkim
253280304Sjkim/*******************************************************************************
254280304Sjkim *
255280304Sjkim * FUNCTION:    AcpiTbValidateTableHeader
256280304Sjkim *
257280304Sjkim * PARAMETERS:  TableHeader         - Logical pointer to the table
258280304Sjkim *
259280304Sjkim * RETURN:      Status
260280304Sjkim *
261280304Sjkim * DESCRIPTION: Check an ACPI table header for validity
262280304Sjkim *
263280304Sjkim * NOTE:  Table pointers are validated as follows:
264280304Sjkim *          1) Table pointer must point to valid physical memory
265280304Sjkim *          2) Signature must be 4 ASCII chars, even if we don't recognize the
266280304Sjkim *             name
267280304Sjkim *          3) Table must be readable for length specified in the header
268280304Sjkim *          4) Table checksum must be valid (with the exception of the FACS
269280304Sjkim *              which has no checksum for some odd reason)
270280304Sjkim *
271280304Sjkim ******************************************************************************/
272280304Sjkim
273280304SjkimACPI_STATUS
274280304SjkimAcpiTbValidateTableHeader (
275280304Sjkim    ACPI_TABLE_HEADER       *TableHeader)
276280304Sjkim{
277280304Sjkim    ACPI_NAME               Signature;
278280304Sjkim
279280304Sjkim
280280304Sjkim    /* Verify that this is a valid address */
281280304Sjkim
282280304Sjkim    if (!AcpiOsReadable (TableHeader, sizeof (ACPI_TABLE_HEADER)))
283280304Sjkim    {
284280304Sjkim        DEBUG_PRINT (ACPI_ERROR,
285280304Sjkim            ("Cannot read table header at %p\n", TableHeader));
286280304Sjkim        return (AE_BAD_ADDRESS);
287280304Sjkim    }
288280304Sjkim
289280304Sjkim
290280304Sjkim    /* Ensure that the signature is 4 ASCII characters */
291280304Sjkim
292280304Sjkim    MOVE_UNALIGNED32_TO_32 (&Signature, &TableHeader->Signature);
293280304Sjkim    if (!AcpiCmValidAcpiName (Signature))
294280304Sjkim    {
295280304Sjkim        DEBUG_PRINT (ACPI_ERROR,
296280304Sjkim            ("Table signature at %p [%X] has invalid characters\n",
297280304Sjkim            TableHeader, &Signature));
298280304Sjkim
299280304Sjkim        REPORT_WARNING (("Invalid table signature found\n"));
300280304Sjkim        DUMP_BUFFER (TableHeader, sizeof (ACPI_TABLE_HEADER));
301280304Sjkim        return (AE_BAD_SIGNATURE);
302280304Sjkim    }
303280304Sjkim
304280304Sjkim
305280304Sjkim    /* Validate the table length */
306280304Sjkim
307280304Sjkim    if (TableHeader->Length < sizeof (ACPI_TABLE_HEADER))
308280304Sjkim    {
309280304Sjkim        DEBUG_PRINT (ACPI_ERROR,
310280304Sjkim            ("Invalid length in table header %p name %4.4s\n",
311280304Sjkim            TableHeader, &Signature));
312280304Sjkim
313280304Sjkim        REPORT_WARNING (("Invalid table header length found\n"));
314280304Sjkim        DUMP_BUFFER (TableHeader, sizeof (ACPI_TABLE_HEADER));
315280304Sjkim        return (AE_BAD_HEADER);
316280304Sjkim    }
317280304Sjkim
318280304Sjkim    return (AE_OK);
319280304Sjkim}
320280304Sjkim
321280304Sjkim
322280304Sjkim/*******************************************************************************
323280304Sjkim *
324280304Sjkim * FUNCTION:    AcpiTbMapAcpiTable
325280304Sjkim *
326280304Sjkim * PARAMETERS:  PhysicalAddress         - Physical address of table to map
327280304Sjkim *              *Size                   - Size of the table.  If zero, the size
328280304Sjkim *                                        from the table header is used.
329280304Sjkim *                                        Actual size is returned here.
330280304Sjkim *              **LogicalAddress        - Logical address of mapped table
331280304Sjkim *
33259191Skris * RETURN:      Logical address of the mapped table.
333280304Sjkim *
334280304Sjkim * DESCRIPTION: Maps the physical address of table into a logical address
335280304Sjkim *
336280304Sjkim ******************************************************************************/
337160814Ssimon
338280304SjkimACPI_STATUS
339280304SjkimAcpiTbMapAcpiTable (
340280304Sjkim    ACPI_PHYSICAL_ADDRESS   PhysicalAddress,
341280304Sjkim    UINT32                  *Size,
342280304Sjkim    void                    **LogicalAddress)
343280304Sjkim{
344280304Sjkim    ACPI_TABLE_HEADER       *Table;
345280304Sjkim    UINT32                  TableSize = *Size;
346280304Sjkim    ACPI_STATUS             Status = AE_OK;
347280304Sjkim
348280304Sjkim
349280304Sjkim    /* If size is zero, look at the table header to get the actual size */
350280304Sjkim
351280304Sjkim    if ((*Size) == 0)
352280304Sjkim    {
353280304Sjkim        /* Get the table header so we can extract the table length */
354280304Sjkim
355280304Sjkim        Status = AcpiOsMapMemory (PhysicalAddress, sizeof (ACPI_TABLE_HEADER),
356280304Sjkim                                    (void **) &Table);
357280304Sjkim        if (ACPI_FAILURE (Status))
358280304Sjkim        {
359280304Sjkim            return (Status);
360280304Sjkim        }
361280304Sjkim
362280304Sjkim        /* Extract the full table length before we delete the mapping */
363280304Sjkim
364280304Sjkim        TableSize = Table->Length;
365280304Sjkim
366280304Sjkim        /*
367280304Sjkim         * Validate the header and delete the mapping.
368280304Sjkim         * We will create a mapping for the full table below.
369280304Sjkim         */
370280304Sjkim
371280304Sjkim        Status = AcpiTbValidateTableHeader (Table);
372280304Sjkim
373280304Sjkim        /* Always unmap the memory for the header */
374280304Sjkim
37559191Skris        AcpiOsUnmapMemory (Table, sizeof (ACPI_TABLE_HEADER));
376280304Sjkim
377280304Sjkim        /* Exit if header invalid */
378280304Sjkim
379280304Sjkim        if (ACPI_FAILURE (Status))
380280304Sjkim        {
381280304Sjkim            return (Status);
382280304Sjkim        }
383280304Sjkim    }
384280304Sjkim
385109998Smarkm
386280304Sjkim    /* Map the physical memory for the correct length */
387280304Sjkim
38859191Skris    Status = AcpiOsMapMemory (PhysicalAddress, TableSize, (void **) &Table);
389194206Ssimon    if (ACPI_FAILURE (Status))
390280304Sjkim    {
391194206Ssimon        return (Status);
392109998Smarkm    }
393280304Sjkim
394280304Sjkim    DEBUG_PRINT (ACPI_INFO,
395280304Sjkim        ("Mapped memory for ACPI table, length=%d(%X) at %p\n",
39659191Skris        TableSize, TableSize, Table));
397109998Smarkm
398280304Sjkim    *Size = TableSize;
399280304Sjkim    *LogicalAddress = Table;
400280304Sjkim
401109998Smarkm    return (Status);
402162911Ssimon}
403280304Sjkim
404280304Sjkim
405280304Sjkim/*******************************************************************************
406162911Ssimon *
407280304Sjkim * FUNCTION:    AcpiTbVerifyTableChecksum
408280304Sjkim *
409280304Sjkim * PARAMETERS:  *TableHeader            - ACPI table to verify
410280304Sjkim *
411280304Sjkim * RETURN:      8 bit checksum of table
412280304Sjkim *
413280304Sjkim * DESCRIPTION: Does an 8 bit checksum of table and returns status.  A correct
414280304Sjkim *              table should have a checksum of 0.
415280304Sjkim *
416280304Sjkim ******************************************************************************/
417280304Sjkim
418280304SjkimACPI_STATUS
419280304SjkimAcpiTbVerifyTableChecksum (
420280304Sjkim    ACPI_TABLE_HEADER       *TableHeader)
421280304Sjkim{
422280304Sjkim    UINT8                   Checksum;
423280304Sjkim    ACPI_STATUS             Status = AE_OK;
424280304Sjkim
425280304Sjkim
426280304Sjkim    FUNCTION_TRACE ("TbVerifyTableChecksum");
427280304Sjkim
428280304Sjkim
429280304Sjkim    /* Compute the checksum on the table */
430280304Sjkim
431280304Sjkim    Checksum = AcpiTbChecksum (TableHeader, TableHeader->Length);
432280304Sjkim
433280304Sjkim    /* Return the appropriate exception */
434280304Sjkim
435280304Sjkim    if (Checksum)
436280304Sjkim    {
437280304Sjkim        REPORT_WARNING (("Invalid checksum (%X) in table %4.4s\n",
438280304Sjkim            Checksum, &TableHeader->Signature));
439280304Sjkim
440280304Sjkim        Status = AE_BAD_CHECKSUM;
441280304Sjkim    }
442280304Sjkim
443280304Sjkim
444280304Sjkim    return_ACPI_STATUS (Status);
445284285Sjkim}
446284285Sjkim
447280304Sjkim
448280304Sjkim/*******************************************************************************
449280304Sjkim *
450111147Snectar * FUNCTION:    AcpiTbChecksum
451280304Sjkim *
452280304Sjkim * PARAMETERS:  Buffer              - Buffer to checksum
453111147Snectar *              Length              - Size of the buffer
454280304Sjkim *
455280304Sjkim * RETURNS      8 bit checksum of buffer
456280304Sjkim *
457280304Sjkim * DESCRIPTION: Computes an 8 bit checksum of the buffer(length) and returns it.
458280304Sjkim *
459280304Sjkim ******************************************************************************/
460280304Sjkim
461280304SjkimUINT8
462280304SjkimAcpiTbChecksum (
463280304Sjkim    void                    *Buffer,
464111147Snectar    UINT32                  Length)
465280304Sjkim{
466111147Snectar    UINT8                   *limit;
467109998Smarkm    UINT8                   *rover;
468280304Sjkim    UINT8                   sum = 0;
469280304Sjkim
470280304Sjkim
471280304Sjkim    if (Buffer && Length)
47259191Skris    {
473280304Sjkim        /*  Buffer and Length are valid   */
474280304Sjkim
475280304Sjkim        limit = (UINT8 *) Buffer + Length;
476280304Sjkim
477280304Sjkim        for (rover = Buffer; rover < limit; rover++)
478280304Sjkim        {
47959191Skris            sum = (UINT8) (sum + *rover);
480280304Sjkim        }
48159191Skris    }
482280304Sjkim
483280304Sjkim    return (sum);
48459191Skris}
485280304Sjkim
486280304Sjkim
487280304Sjkim