dtutils.c revision 228110
1251516Ssbruno/******************************************************************************
2251516Ssbruno *
3251516Ssbruno * Module Name: dtutils.c - Utility routines for the data table compiler
4251516Ssbruno *
5251516Ssbruno *****************************************************************************/
6251516Ssbruno
7251516Ssbruno/*
8251516Ssbruno * Copyright (C) 2000 - 2011, Intel Corp.
9251516Ssbruno * All rights reserved.
10251516Ssbruno *
11251516Ssbruno * Redistribution and use in source and binary forms, with or without
12251516Ssbruno * modification, are permitted provided that the following conditions
13251516Ssbruno * are met:
14251516Ssbruno * 1. Redistributions of source code must retain the above copyright
15251516Ssbruno *    notice, this list of conditions, and the following disclaimer,
16251516Ssbruno *    without modification.
17251516Ssbruno * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18251516Ssbruno *    substantially similar to the "NO WARRANTY" disclaimer below
19251516Ssbruno *    ("Disclaimer") and any redistribution must be conditioned upon
20251516Ssbruno *    including a substantially similar Disclaimer requirement for further
21251516Ssbruno *    binary redistribution.
22251516Ssbruno * 3. Neither the names of the above-listed copyright holders nor the names
23251516Ssbruno *    of any contributors may be used to endorse or promote products derived
24251516Ssbruno *    from this software without specific prior written permission.
25251516Ssbruno *
26251516Ssbruno * Alternatively, this software may be distributed under the terms of the
27251516Ssbruno * GNU General Public License ("GPL") version 2 as published by the Free
28251516Ssbruno * Software Foundation.
29251516Ssbruno *
30251516Ssbruno * NO WARRANTY
31251516Ssbruno * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32251516Ssbruno * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33251516Ssbruno * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34251516Ssbruno * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35251516Ssbruno * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36251516Ssbruno * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37251516Ssbruno * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38251516Ssbruno * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39251516Ssbruno * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40251516Ssbruno * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41251516Ssbruno * POSSIBILITY OF SUCH DAMAGES.
42251516Ssbruno */
43251516Ssbruno
44251516Ssbruno#define __DTUTILS_C__
45251516Ssbruno
46251516Ssbruno#include <contrib/dev/acpica/compiler/aslcompiler.h>
47251516Ssbruno#include <contrib/dev/acpica/compiler/dtcompiler.h>
48251516Ssbruno#include <contrib/dev/acpica/include/actables.h>
49251516Ssbruno
50251516Ssbruno#define _COMPONENT          DT_COMPILER
51251516Ssbruno        ACPI_MODULE_NAME    ("dtutils")
52251516Ssbruno
53251516Ssbruno/* Local prototypes */
54251516Ssbruno
55251516Ssbrunostatic void
56251516SsbrunoDtSum (
57251516Ssbruno    DT_SUBTABLE             *Subtable,
58251516Ssbruno    void                    *Context,
59251516Ssbruno    void                    *ReturnValue);
60251516Ssbruno
61251516Ssbruno
62251516Ssbruno/******************************************************************************
63251516Ssbruno *
64251516Ssbruno * FUNCTION:    DtError
65251516Ssbruno *
66251516Ssbruno * PARAMETERS:  Level               - Seriousness (Warning/error, etc.)
67251516Ssbruno *              MessageId           - Index into global message buffer
68251516Ssbruno *              Op                  - Parse node where error happened
69251516Ssbruno *              ExtraMessage        - additional error message
70251516Ssbruno *
71251516Ssbruno * RETURN:      None
72251516Ssbruno *
73251516Ssbruno * DESCRIPTION: Common error interface for data table compiler
74251516Ssbruno *
75251516Ssbruno *****************************************************************************/
76251516Ssbruno
77251516Ssbrunovoid
78251516SsbrunoDtError (
79251516Ssbruno    UINT8                   Level,
80251516Ssbruno    UINT8                   MessageId,
81251516Ssbruno    DT_FIELD                *FieldObject,
82251516Ssbruno    char                    *ExtraMessage)
83251516Ssbruno{
84251516Ssbruno
85251516Ssbruno    switch (Level)
86251516Ssbruno    {
87251516Ssbruno    case ASL_WARNING2:
88251516Ssbruno    case ASL_WARNING3:
89251516Ssbruno        if (Gbl_WarningLevel < Level)
90251516Ssbruno        {
91251516Ssbruno            return;
92251516Ssbruno        }
93251516Ssbruno        break;
94251516Ssbruno
95251516Ssbruno    default:
96251516Ssbruno        break;
97251516Ssbruno    }
98251516Ssbruno
99251516Ssbruno    if (FieldObject)
100251516Ssbruno    {
101251516Ssbruno        AslCommonError (Level, MessageId,
102251516Ssbruno            FieldObject->Line,
103251516Ssbruno            FieldObject->Line,
104251516Ssbruno            FieldObject->ByteOffset,
105251516Ssbruno            FieldObject->Column,
106251516Ssbruno            Gbl_Files[ASL_FILE_INPUT].Filename, ExtraMessage);
107251516Ssbruno    }
108251516Ssbruno    else
109251516Ssbruno    {
110251516Ssbruno        AslCommonError (Level, MessageId, 0,
111251516Ssbruno            0, 0, 0, 0, ExtraMessage);
112251516Ssbruno    }
113285067Semaste}
114251516Ssbruno
115251516Ssbruno
116251516Ssbruno/******************************************************************************
117251516Ssbruno *
118251516Ssbruno * FUNCTION:    DtNameError
119251516Ssbruno *
120251516Ssbruno * PARAMETERS:  Level               - Seriousness (Warning/error, etc.)
121251516Ssbruno *              MessageId           - Index into global message buffer
122251516Ssbruno *              Op                  - Parse node where error happened
123251516Ssbruno *              ExtraMessage        - additional error message
124251516Ssbruno *
125251516Ssbruno * RETURN:      None
126251516Ssbruno *
127251516Ssbruno * DESCRIPTION: Error interface for named objects
128251516Ssbruno *
129251516Ssbruno *****************************************************************************/
130251516Ssbruno
131251516Ssbrunovoid
132251516SsbrunoDtNameError (
133251516Ssbruno    UINT8                   Level,
134251516Ssbruno    UINT8                   MessageId,
135251516Ssbruno    DT_FIELD                *FieldObject,
136251516Ssbruno    char                    *ExtraMessage)
137251516Ssbruno{
138251516Ssbruno
139251516Ssbruno    switch (Level)
140251516Ssbruno    {
141251516Ssbruno    case ASL_WARNING2:
142251516Ssbruno    case ASL_WARNING3:
143251516Ssbruno        if (Gbl_WarningLevel < Level)
144251516Ssbruno        {
145251516Ssbruno            return;
146251516Ssbruno        }
147251516Ssbruno        break;
148251516Ssbruno
149251516Ssbruno    default:
150251516Ssbruno        break;
151251516Ssbruno    }
152251516Ssbruno
153251516Ssbruno    if (FieldObject)
154251516Ssbruno    {
155251516Ssbruno        AslCommonError (Level, MessageId,
156251516Ssbruno            FieldObject->Line,
157251516Ssbruno            FieldObject->Line,
158251516Ssbruno            FieldObject->ByteOffset,
159251516Ssbruno            FieldObject->NameColumn,
160251516Ssbruno            Gbl_Files[ASL_FILE_INPUT].Filename, ExtraMessage);
161251516Ssbruno    }
162251516Ssbruno    else
163251516Ssbruno    {
164251516Ssbruno        AslCommonError (Level, MessageId, 0,
165251516Ssbruno            0, 0, 0, 0, ExtraMessage);
166251516Ssbruno    }
167251516Ssbruno}
168251516Ssbruno
169251516Ssbruno
170251516Ssbruno/*******************************************************************************
171251516Ssbruno *
172251516Ssbruno * FUNCTION:    DtFatal
173251516Ssbruno *
174251516Ssbruno * PARAMETERS:  None
175251516Ssbruno *
176251516Ssbruno * RETURN:      None
177251516Ssbruno *
178251516Ssbruno * DESCRIPTION: Dump the error log and abort the compiler. Used for serious
179251516Ssbruno *              compile or I/O errors
180251516Ssbruno *
181251516Ssbruno ******************************************************************************/
182251516Ssbruno
183251516Ssbrunovoid
184251516SsbrunoDtFatal (
185251516Ssbruno    UINT8                   MessageId,
186251516Ssbruno    DT_FIELD                *FieldObject,
187251516Ssbruno    char                    *ExtraMessage)
188251516Ssbruno{
189251516Ssbruno
190251516Ssbruno    DtError (ASL_ERROR, MessageId, FieldObject, ExtraMessage);
191251516Ssbruno
192251516Ssbruno/*
193251516Ssbruno * TBD: remove this entire function, DtFatal
194251516Ssbruno *
195251516Ssbruno * We cannot abort the compiler on error, because we may be compiling a
196251516Ssbruno * list of files. We must move on to the next file.
197251516Ssbruno */
198251516Ssbruno#ifdef __OBSOLETE
199251516Ssbruno    CmCleanupAndExit ();
200251516Ssbruno    exit (1);
201251516Ssbruno#endif
202251516Ssbruno}
203251516Ssbruno
204251516Ssbruno
205251516Ssbruno/******************************************************************************
206251516Ssbruno *
207251516Ssbruno * FUNCTION:    DtStrtoul64
208251516Ssbruno *
209251516Ssbruno * PARAMETERS:  String              - Null terminated string
210251516Ssbruno *              ReturnInteger       - Where the converted integer is returned
211251516Ssbruno *
212251516Ssbruno * RETURN:      Status
213251516Ssbruno *
214251516Ssbruno * DESCRIPTION: Simple conversion of a string hex integer constant to unsigned
215251516Ssbruno *              value. Assumes no leading "0x" for the constant.
216251516Ssbruno *
217251516Ssbruno * Portability note: The reason this function exists is because a 64-bit
218251516Ssbruno * sscanf is not available in all environments.
219251516Ssbruno *
220251516Ssbruno *****************************************************************************/
221251516Ssbruno
222251516SsbrunoACPI_STATUS
223251516SsbrunoDtStrtoul64 (
224251516Ssbruno    char                    *String,
225251516Ssbruno    UINT64                  *ReturnInteger)
226251516Ssbruno{
227251516Ssbruno    char                    *ThisChar = String;
228251516Ssbruno    UINT32                  ThisDigit;
229251516Ssbruno    UINT64                  ReturnValue = 0;
230251516Ssbruno    int                     DigitCount = 0;
231251516Ssbruno
232251516Ssbruno
233251516Ssbruno    /* Skip over any white space in the buffer */
234251516Ssbruno
235251516Ssbruno    while ((*ThisChar == ' ') || (*ThisChar == '\t'))
236251516Ssbruno    {
237251516Ssbruno        ThisChar++;
238251516Ssbruno    }
239251516Ssbruno
240251516Ssbruno    /* Skip leading zeros */
241251516Ssbruno
242251516Ssbruno    while ((*ThisChar) == '0')
243251516Ssbruno    {
244251516Ssbruno        ThisChar++;
245251516Ssbruno    }
246251516Ssbruno
247251516Ssbruno    /* Convert character-by-character */
248251516Ssbruno
249251516Ssbruno    while (*ThisChar)
250251516Ssbruno    {
251251516Ssbruno        if (ACPI_IS_DIGIT (*ThisChar))
252251516Ssbruno        {
253251516Ssbruno            /* Convert ASCII 0-9 to Decimal value */
254251516Ssbruno
255251516Ssbruno            ThisDigit = ((UINT8) *ThisChar) - '0';
256251516Ssbruno        }
257251516Ssbruno        else /* Letter */
258251516Ssbruno        {
259251516Ssbruno            ThisDigit = (UINT32) ACPI_TOUPPER (*ThisChar);
260251516Ssbruno            if (!ACPI_IS_XDIGIT ((char) ThisDigit))
261251516Ssbruno            {
262251516Ssbruno                /* Not A-F */
263251516Ssbruno
264251516Ssbruno                return (AE_BAD_CHARACTER);
265251516Ssbruno            }
266251516Ssbruno
267251516Ssbruno            /* Convert ASCII Hex char (A-F) to value */
268251516Ssbruno
269251516Ssbruno            ThisDigit = (ThisDigit - 'A') + 10;
270251516Ssbruno        }
271251516Ssbruno
272251516Ssbruno        /* Insert the 4-bit hex digit */
273251516Ssbruno
274251516Ssbruno        ReturnValue <<= 4;
275251516Ssbruno        ReturnValue += ThisDigit;
276251516Ssbruno
277251516Ssbruno        ThisChar++;
278251516Ssbruno        DigitCount++;
279251516Ssbruno        if (DigitCount > 16)
280251516Ssbruno        {
281251516Ssbruno            /* Value is too large (> 64 bits/8 bytes/16 hex digits) */
282251516Ssbruno
283251516Ssbruno            return (AE_LIMIT);
284251516Ssbruno        }
285251516Ssbruno    }
286251516Ssbruno
287251516Ssbruno    *ReturnInteger = ReturnValue;
288251516Ssbruno    return (AE_OK);
289251516Ssbruno}
290251516Ssbruno
291251516Ssbruno
292251516Ssbruno/******************************************************************************
293251516Ssbruno *
294251516Ssbruno * FUNCTION:    DtGetFileSize
295251516Ssbruno *
296251516Ssbruno * PARAMETERS:  Handle              - Open file handler
297251516Ssbruno *
298251516Ssbruno * RETURN:      Current file size
299251516Ssbruno *
300251516Ssbruno * DESCRIPTION: Get the current size of a file. Seek to the EOF and get the
301251516Ssbruno *              offset. Seek back to the original location.
302251516Ssbruno *
303251516Ssbruno *****************************************************************************/
304251516Ssbruno
305251516SsbrunoUINT32
306251516SsbrunoDtGetFileSize (
307251516Ssbruno    FILE                    *Handle)
308251516Ssbruno{
309251516Ssbruno    int                     CurrentOffset;
310251516Ssbruno    int                     LastOffset;
311251516Ssbruno
312251516Ssbruno
313251516Ssbruno    CurrentOffset = ftell (Handle);
314251516Ssbruno    fseek (Handle, 0, SEEK_END);
315251516Ssbruno    LastOffset = ftell (Handle);
316251516Ssbruno    fseek (Handle, CurrentOffset, SEEK_SET);
317251516Ssbruno
318251516Ssbruno    return ((UINT32) LastOffset);
319251516Ssbruno}
320251516Ssbruno
321251516Ssbruno
322251516Ssbruno/******************************************************************************
323251516Ssbruno *
324251516Ssbruno * FUNCTION:    DtGetFieldValue
325251516Ssbruno *
326251516Ssbruno * PARAMETERS:  Field               - Current field list pointer
327251516Ssbruno *
328251516Ssbruno * RETURN:      Field value
329251516Ssbruno *
330251516Ssbruno * DESCRIPTION: Get field value
331251516Ssbruno *
332251516Ssbruno *****************************************************************************/
333251516Ssbruno
334251516Ssbrunochar *
335251516SsbrunoDtGetFieldValue (
336251516Ssbruno    DT_FIELD                *Field)
337251516Ssbruno{
338251516Ssbruno    if (!Field)
339251516Ssbruno    {
340251516Ssbruno        return (NULL);
341251516Ssbruno    }
342251516Ssbruno
343251516Ssbruno    return (Field->Value);
344251516Ssbruno}
345251516Ssbruno
346251516Ssbruno
347251516Ssbruno/******************************************************************************
348251516Ssbruno *
349251516Ssbruno * FUNCTION:    DtGetFieldType
350251516Ssbruno *
351251516Ssbruno * PARAMETERS:  Info                - Data table info
352251516Ssbruno *
353251516Ssbruno * RETURN:      Field type
354251516Ssbruno *
355251516Ssbruno * DESCRIPTION: Get field type
356251516Ssbruno *
357251516Ssbruno *****************************************************************************/
358251516Ssbruno
359251516SsbrunoUINT8
360251516SsbrunoDtGetFieldType (
361251516Ssbruno    ACPI_DMTABLE_INFO       *Info)
362251516Ssbruno{
363251516Ssbruno    UINT8                   Type;
364251516Ssbruno
365
366    /* DT_FLAG means that this is the start of a block of flag bits */
367    /* TBD - we can make these a separate opcode later */
368
369    if (Info->Flags & DT_FLAG)
370    {
371        return (DT_FIELD_TYPE_FLAGS_INTEGER);
372    }
373
374    /* Type is based upon the opcode for this field in the info table */
375
376    switch (Info->Opcode)
377    {
378    case ACPI_DMT_FLAG0:
379    case ACPI_DMT_FLAG1:
380    case ACPI_DMT_FLAG2:
381    case ACPI_DMT_FLAG3:
382    case ACPI_DMT_FLAG4:
383    case ACPI_DMT_FLAG5:
384    case ACPI_DMT_FLAG6:
385    case ACPI_DMT_FLAG7:
386    case ACPI_DMT_FLAGS0:
387    case ACPI_DMT_FLAGS1:
388    case ACPI_DMT_FLAGS2:
389    case ACPI_DMT_FLAGS4:
390        Type = DT_FIELD_TYPE_FLAG;
391        break;
392
393    case ACPI_DMT_NAME4:
394    case ACPI_DMT_SIG:
395    case ACPI_DMT_NAME6:
396    case ACPI_DMT_NAME8:
397    case ACPI_DMT_STRING:
398        Type = DT_FIELD_TYPE_STRING;
399        break;
400
401    case ACPI_DMT_BUFFER:
402    case ACPI_DMT_BUF7:
403    case ACPI_DMT_BUF16:
404    case ACPI_DMT_BUF128:
405    case ACPI_DMT_PCI_PATH:
406        Type = DT_FIELD_TYPE_BUFFER;
407        break;
408
409    case ACPI_DMT_GAS:
410    case ACPI_DMT_HESTNTFY:
411        Type = DT_FIELD_TYPE_INLINE_SUBTABLE;
412        break;
413
414    case ACPI_DMT_UNICODE:
415        Type = DT_FIELD_TYPE_UNICODE;
416        break;
417
418    case ACPI_DMT_UUID:
419        Type = DT_FIELD_TYPE_UUID;
420        break;
421
422    case ACPI_DMT_DEVICE_PATH:
423        Type = DT_FIELD_TYPE_DEVICE_PATH;
424        break;
425
426    case ACPI_DMT_LABEL:
427        Type = DT_FIELD_TYPE_LABEL;
428        break;
429
430    default:
431        Type = DT_FIELD_TYPE_INTEGER;
432        break;
433    }
434
435    return (Type);
436}
437
438
439/******************************************************************************
440 *
441 * FUNCTION:    DtGetBufferLength
442 *
443 * PARAMETERS:  Buffer              - List of integers,
444 *                                    for example "10 3A 4F 2E"
445 *
446 * RETURN:      Count of integer
447 *
448 * DESCRIPTION: Get length of bytes needed to store the integers
449 *
450 *****************************************************************************/
451
452UINT32
453DtGetBufferLength (
454    char                    *Buffer)
455{
456    UINT32                  ByteLength = 0;
457
458
459    while (*Buffer)
460    {
461        if (*Buffer == ' ')
462        {
463            ByteLength++;
464
465            while (*Buffer == ' ')
466            {
467                Buffer++;
468            }
469        }
470
471        Buffer++;
472    }
473
474    return (++ByteLength);
475}
476
477
478/******************************************************************************
479 *
480 * FUNCTION:    DtGetFieldLength
481 *
482 * PARAMETERS:  Field               - Current field
483 *              Info                - Data table info
484 *
485 * RETURN:      Field length
486 *
487 * DESCRIPTION: Get length of bytes needed to compile the field
488 *
489 * Note: This function must remain in sync with AcpiDmDumpTable.
490 *
491 *****************************************************************************/
492
493UINT32
494DtGetFieldLength (
495    DT_FIELD                *Field,
496    ACPI_DMTABLE_INFO       *Info)
497{
498    UINT32                  ByteLength = 0;
499    char                    *Value;
500
501
502    /* Length is based upon the opcode for this field in the info table */
503
504    switch (Info->Opcode)
505    {
506    case ACPI_DMT_FLAG0:
507    case ACPI_DMT_FLAG1:
508    case ACPI_DMT_FLAG2:
509    case ACPI_DMT_FLAG3:
510    case ACPI_DMT_FLAG4:
511    case ACPI_DMT_FLAG5:
512    case ACPI_DMT_FLAG6:
513    case ACPI_DMT_FLAG7:
514    case ACPI_DMT_FLAGS0:
515    case ACPI_DMT_FLAGS1:
516    case ACPI_DMT_FLAGS2:
517    case ACPI_DMT_FLAGS4:
518    case ACPI_DMT_LABEL:
519    case ACPI_DMT_EXTRA_TEXT:
520        ByteLength = 0;
521        break;
522
523    case ACPI_DMT_UINT8:
524    case ACPI_DMT_CHKSUM:
525    case ACPI_DMT_SPACEID:
526    case ACPI_DMT_ACCWIDTH:
527    case ACPI_DMT_IVRS:
528    case ACPI_DMT_MADT:
529    case ACPI_DMT_PMTT:
530    case ACPI_DMT_SRAT:
531    case ACPI_DMT_ASF:
532    case ACPI_DMT_HESTNTYP:
533    case ACPI_DMT_FADTPM:
534    case ACPI_DMT_EINJACT:
535    case ACPI_DMT_EINJINST:
536    case ACPI_DMT_ERSTACT:
537    case ACPI_DMT_ERSTINST:
538        ByteLength = 1;
539        break;
540
541    case ACPI_DMT_UINT16:
542    case ACPI_DMT_DMAR:
543    case ACPI_DMT_HEST:
544    case ACPI_DMT_PCI_PATH:
545        ByteLength = 2;
546        break;
547
548    case ACPI_DMT_UINT24:
549        ByteLength = 3;
550        break;
551
552    case ACPI_DMT_UINT32:
553    case ACPI_DMT_NAME4:
554    case ACPI_DMT_SLIC:
555    case ACPI_DMT_SIG:
556        ByteLength = 4;
557        break;
558
559    case ACPI_DMT_UINT40:
560        ByteLength = 5;
561        break;
562
563    case ACPI_DMT_UINT48:
564    case ACPI_DMT_NAME6:
565        ByteLength = 6;
566        break;
567
568    case ACPI_DMT_UINT56:
569    case ACPI_DMT_BUF7:
570        ByteLength = 7;
571        break;
572
573    case ACPI_DMT_UINT64:
574    case ACPI_DMT_NAME8:
575        ByteLength = 8;
576        break;
577
578    case ACPI_DMT_STRING:
579        Value = DtGetFieldValue (Field);
580        if (Value)
581        {
582            ByteLength = ACPI_STRLEN (Value) + 1;
583        }
584        else
585        {   /* At this point, this is a fatal error */
586
587            sprintf (MsgBuffer, "Expected \"%s\"", Info->Name);
588            DtFatal (ASL_MSG_COMPILER_INTERNAL, NULL, MsgBuffer);
589            return (0);
590        }
591        break;
592
593    case ACPI_DMT_GAS:
594        ByteLength = sizeof (ACPI_GENERIC_ADDRESS);
595        break;
596
597    case ACPI_DMT_HESTNTFY:
598        ByteLength = sizeof (ACPI_HEST_NOTIFY);
599        break;
600
601    case ACPI_DMT_BUFFER:
602        Value = DtGetFieldValue (Field);
603        if (Value)
604        {
605            ByteLength = DtGetBufferLength (Value);
606        }
607        else
608        {   /* At this point, this is a fatal error */
609
610            sprintf (MsgBuffer, "Expected \"%s\"", Info->Name);
611            DtFatal (ASL_MSG_COMPILER_INTERNAL, NULL, MsgBuffer);
612            return (0);
613        }
614        break;
615
616    case ACPI_DMT_BUF16:
617    case ACPI_DMT_UUID:
618        ByteLength = 16;
619        break;
620
621    case ACPI_DMT_BUF128:
622        ByteLength = 128;
623        break;
624
625    case ACPI_DMT_UNICODE:
626        Value = DtGetFieldValue (Field);
627
628        /* TBD: error if Value is NULL? (as below?) */
629
630        ByteLength = (ACPI_STRLEN (Value) + 1) * sizeof(UINT16);
631        break;
632
633    default:
634        DtFatal (ASL_MSG_COMPILER_INTERNAL, Field, "Invalid table opcode");
635        return (0);
636    }
637
638    return (ByteLength);
639}
640
641
642/******************************************************************************
643 *
644 * FUNCTION:    DtSum
645 *
646 * PARAMETERS:  DT_WALK_CALLBACK:
647 *              Subtable            - Subtable
648 *              Context             - Unused
649 *              ReturnValue         - Store the checksum of subtable
650 *
651 * RETURN:      Status
652 *
653 * DESCRIPTION: Get the checksum of subtable
654 *
655 *****************************************************************************/
656
657static void
658DtSum (
659    DT_SUBTABLE             *Subtable,
660    void                    *Context,
661    void                    *ReturnValue)
662{
663    UINT8                   Checksum;
664    UINT8                   *Sum = ReturnValue;
665
666
667    Checksum = AcpiTbChecksum (Subtable->Buffer, Subtable->Length);
668    *Sum = (UINT8) (*Sum + Checksum);
669}
670
671
672/******************************************************************************
673 *
674 * FUNCTION:    DtSetTableChecksum
675 *
676 * PARAMETERS:  ChecksumPointer     - Where to return the checksum
677 *
678 * RETURN:      None
679 *
680 * DESCRIPTION: Set checksum of the whole data table into the checksum field
681 *
682 *****************************************************************************/
683
684void
685DtSetTableChecksum (
686    UINT8                   *ChecksumPointer)
687{
688    UINT8                   Checksum = 0;
689    UINT8                   OldSum;
690
691
692    DtWalkTableTree (Gbl_RootTable, DtSum, NULL, &Checksum);
693
694    OldSum = *ChecksumPointer;
695    Checksum = (UINT8) (Checksum - OldSum);
696
697    /* Compute the final checksum */
698
699    Checksum = (UINT8) (0 - Checksum);
700    *ChecksumPointer = Checksum;
701}
702
703
704/******************************************************************************
705 *
706 * FUNCTION:    DtSetTableLength
707 *
708 * PARAMETERS:  None
709 *
710 * RETURN:      None
711 *
712 * DESCRIPTION: Walk the subtables and set all the length fields
713 *
714 *****************************************************************************/
715
716void
717DtSetTableLength (
718    void)
719{
720    DT_SUBTABLE             *ParentTable;
721    DT_SUBTABLE             *ChildTable;
722
723
724    ParentTable = Gbl_RootTable;
725    ChildTable = NULL;
726
727    if (!ParentTable)
728    {
729        return;
730    }
731
732    DtSetSubtableLength (ParentTable);
733
734    while (1)
735    {
736        ChildTable = DtGetNextSubtable (ParentTable, ChildTable);
737        if (ChildTable)
738        {
739            if (ChildTable->LengthField)
740            {
741                DtSetSubtableLength (ChildTable);
742            }
743
744            if (ChildTable->Child)
745            {
746                ParentTable = ChildTable;
747                ChildTable = NULL;
748            }
749            else
750            {
751                ParentTable->TotalLength += ChildTable->TotalLength;
752                if (ParentTable->LengthField)
753                {
754                    DtSetSubtableLength (ParentTable);
755                }
756            }
757        }
758        else
759        {
760            ChildTable = ParentTable;
761
762            if (ChildTable == Gbl_RootTable)
763            {
764                break;
765            }
766
767            ParentTable = DtGetParentSubtable (ParentTable);
768
769            ParentTable->TotalLength += ChildTable->TotalLength;
770            if (ParentTable->LengthField)
771            {
772                DtSetSubtableLength (ParentTable);
773            }
774        }
775    }
776}
777
778
779/******************************************************************************
780 *
781 * FUNCTION:    DtWalkTableTree
782 *
783 * PARAMETERS:  StartTable          - Subtable in the tree where walking begins
784 *              UserFunction        - Called during the walk
785 *              Context             - Passed to user function
786 *              ReturnValue         - The return value of UserFunction
787 *
788 * RETURN:      None
789 *
790 * DESCRIPTION: Performs a depth-first walk of the subtable tree
791 *
792 *****************************************************************************/
793
794void
795DtWalkTableTree (
796    DT_SUBTABLE             *StartTable,
797    DT_WALK_CALLBACK        UserFunction,
798    void                    *Context,
799    void                    *ReturnValue)
800{
801    DT_SUBTABLE             *ParentTable;
802    DT_SUBTABLE             *ChildTable;
803
804
805    ParentTable = StartTable;
806    ChildTable = NULL;
807
808    if (!ParentTable)
809    {
810        return;
811    }
812
813    UserFunction (ParentTable, Context, ReturnValue);
814
815    while (1)
816    {
817        ChildTable = DtGetNextSubtable (ParentTable, ChildTable);
818        if (ChildTable)
819        {
820            UserFunction (ChildTable, Context, ReturnValue);
821
822            if (ChildTable->Child)
823            {
824                ParentTable = ChildTable;
825                ChildTable = NULL;
826            }
827        }
828        else
829        {
830            ChildTable = ParentTable;
831            if (ChildTable == Gbl_RootTable)
832            {
833                break;
834            }
835
836            ParentTable = DtGetParentSubtable (ParentTable);
837
838            if (ChildTable->Peer == StartTable)
839            {
840                break;
841            }
842        }
843    }
844}
845
846
847/******************************************************************************
848 *
849 * FUNCTION:    DtFreeFieldList
850 *
851 * PARAMETERS:  None
852 *
853 * RETURN:      None
854 *
855 * DESCRIPTION: Free the field list
856 *
857 *****************************************************************************/
858
859void
860DtFreeFieldList (
861    void)
862{
863    DT_FIELD                *Field = Gbl_FieldList;
864    DT_FIELD                *NextField;
865
866
867    /* Walk and free entire field list */
868
869    while (Field)
870    {
871        NextField = Field->Next; /* Save link */
872
873        if (!(Field->Flags & DT_FIELD_NOT_ALLOCATED))
874        {
875            ACPI_FREE (Field->Name);
876            ACPI_FREE (Field->Value);
877        }
878
879        ACPI_FREE (Field);
880        Field = NextField;
881    }
882}
883