xref: /netbsd-src/sys/external/bsd/acpica/dist/compiler/dtcompile.c (revision 2c7d7e3ca2e4f0b675c6c58e614f6aede66c678e)
1 /******************************************************************************
2  *
3  * Module Name: dtcompile.c - Front-end for data table compiler
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2023, 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 MERCHANTABILITY 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 _DECLARE_DT_GLOBALS
45 
46 #include "aslcompiler.h"
47 
48 #define _COMPONENT          DT_COMPILER
49         ACPI_MODULE_NAME    ("dtcompile")
50 
51 static char                 VersionString[9];
52 
53 
54 /* Local prototypes */
55 
56 void
57 DtInitialize (
58     void);
59 
60 static ACPI_STATUS
61 DtCompileDataTable (
62     DT_FIELD                **Field);
63 
64 static void
65 DtInsertCompilerIds (
66     DT_FIELD                *FieldList);
67 
68 
69 /******************************************************************************
70  *
71  * FUNCTION:    DtDoCompile
72  *
73  * PARAMETERS:  None
74  *
75  * RETURN:      Status
76  *
77  * DESCRIPTION: Main entry point for the data table compiler.
78  *
79  * Note: Assumes AslGbl_Files[ASL_FILE_INPUT] is initialized and the file is
80  *          open at seek offset zero.
81  *
82  *****************************************************************************/
83 
84 ACPI_STATUS
DtDoCompile(void)85 DtDoCompile (
86     void)
87 {
88     ACPI_STATUS             Status;
89     UINT8                   Event;
90     DT_FIELD                *FieldList;
91     ASL_GLOBAL_FILE_NODE    *FileNode;
92 
93 
94     /* Initialize globals */
95 
96     DtInitialize ();
97 
98     /* Preprocessor */
99 
100     if (AslGbl_PreprocessFlag)
101     {
102         /* Preprocessor */
103 
104         Event = UtBeginEvent ("Preprocess input file");
105         PrDoPreprocess ();
106         UtEndEvent (Event);
107 
108         if (AslGbl_PreprocessOnly)
109         {
110             return (AE_OK);
111         }
112     }
113 
114     /* Compile the parse tree */
115 
116     if (AslGbl_DtLexBisonPrototype)
117     {
118         Event = UtBeginEvent ("Parse data table in prototype mode");
119 
120         DtCompilerInitLexer (AslGbl_Files[ASL_FILE_INPUT].Handle);
121         DtCompilerParserparse ();
122         FieldList = AslGbl_FieldList;
123         DtCompilerTerminateLexer ();
124 
125         UtEndEvent (Event);
126     }
127     else
128     {
129         /*
130          * Scan the input file (file is already open) and
131          * build the parse tree
132          */
133         Event = UtBeginEvent ("Scan and parse input file");
134         FieldList = DtScanFile (AslGbl_Files[ASL_FILE_INPUT].Handle);
135         UtEndEvent (Event);
136     }
137 
138     /* Did the parse tree get successfully constructed? */
139 
140     if (!FieldList)
141     {
142         /* TBD: temporary error message. Msgs should come from function above */
143 
144         DtError (ASL_ERROR, ASL_MSG_SYNTAX, NULL,
145             "Input file does not appear to be an ASL or data table source file");
146 
147         return (AE_ERROR);
148     }
149 
150     Event = UtBeginEvent ("Compile parse tree");
151 
152     Status = DtCompileDataTable (&FieldList);
153     UtEndEvent (Event);
154 
155     FileNode = FlGetCurrentFileNode ();
156 
157     FileNode->TotalLineCount = AslGbl_CurrentLineNumber;
158     FileNode->OriginalInputFileSize = AslGbl_InputByteCount;
159     DbgPrint (ASL_PARSE_OUTPUT, "Line count: %u input file size: %u\n",
160             FileNode->TotalLineCount, FileNode->OriginalInputFileSize);
161 
162     if (ACPI_FAILURE (Status))
163     {
164         FileNode->ParserErrorDetected = TRUE;
165 
166         /* TBD: temporary error message. Msgs should come from function above */
167 
168         DtError (ASL_ERROR, ASL_MSG_SYNTAX, NULL,
169             "Could not compile input file");
170 
171         return (Status);
172     }
173 
174     /* Create/open the binary output file */
175 
176     AslGbl_Files[ASL_FILE_AML_OUTPUT].Filename = NULL;
177     Status = FlOpenAmlOutputFile (AslGbl_OutputFilenamePrefix);
178     if (ACPI_FAILURE (Status))
179     {
180         return (Status);
181     }
182 
183     /* Write the binary, then the optional hex file */
184 
185     DtOutputBinary (AslGbl_RootTable);
186     HxDoHexOutput ();
187     DtWriteTableToListing ();
188 
189     /* Save the compile time statistics to the current file node */
190 
191     FileNode->TotalFields = AslGbl_InputFieldCount;
192     FileNode->OutputByteLength = AslGbl_TableLength;
193 
194     return (Status);
195 }
196 
197 
198 /******************************************************************************
199  *
200  * FUNCTION:    DtInitialize
201  *
202  * PARAMETERS:  None
203  *
204  * RETURN:      Status
205  *
206  * DESCRIPTION: Initialize data table compiler globals. Enables multiple
207  *              compiles per invocation.
208  *
209  *****************************************************************************/
210 
211 void
DtInitialize(void)212 DtInitialize (
213     void)
214 {
215 
216 
217     AcpiUtSetIntegerWidth (2); /* Set width to 64 bits */
218 
219     AslGbl_FieldList = NULL;
220     AslGbl_RootTable = NULL;
221     AslGbl_SubtableStack = NULL;
222 
223     snprintf (VersionString, sizeof(VersionString), "%X",
224 	(UINT32) ACPI_CA_VERSION);
225     return;
226 }
227 
228 
229 /******************************************************************************
230  *
231  * FUNCTION:    DtInsertCompilerIds
232  *
233  * PARAMETERS:  FieldList           - Current field list pointer
234  *
235  * RETURN:      None
236  *
237  * DESCRIPTION: Insert the IDs (Name, Version) of the current compiler into
238  *              the original ACPI table header.
239  *
240  *****************************************************************************/
241 
242 static void
DtInsertCompilerIds(DT_FIELD * FieldList)243 DtInsertCompilerIds (
244     DT_FIELD                *FieldList)
245 {
246     DT_FIELD                *Next;
247     UINT32                  i;
248 
249 
250     /*
251      * Don't insert current compiler ID if requested. Used for compiler
252      * debug/validation only.
253      */
254     if (AslGbl_UseOriginalCompilerId)
255     {
256         return;
257     }
258 
259     /* Walk to the Compiler fields at the end of the header */
260 
261     Next = FieldList;
262     for (i = 0; i < 7; i++)
263     {
264         Next = Next->Next;
265     }
266 
267     Next->Value = ASL_CREATOR_ID;
268     Next->Flags = DT_FIELD_NOT_ALLOCATED;
269 
270     Next = Next->Next;
271     Next->Value = VersionString;
272     Next->Flags = DT_FIELD_NOT_ALLOCATED;
273 }
274 
275 
276 /******************************************************************************
277  *
278  * FUNCTION:    DtCompileDataTable
279  *
280  * PARAMETERS:  FieldList           - Current field list pointer
281  *
282  * RETURN:      Status
283  *
284  * DESCRIPTION: Entry point to compile one data table
285  *
286  *****************************************************************************/
287 
288 static ACPI_STATUS
DtCompileDataTable(DT_FIELD ** FieldList)289 DtCompileDataTable (
290     DT_FIELD                **FieldList)
291 {
292     const ACPI_DMTABLE_DATA *TableData;
293     DT_SUBTABLE             *Subtable;
294     char                    *Signature;
295     ACPI_TABLE_HEADER       *AcpiTableHeader;
296     ACPI_STATUS             Status;
297     DT_FIELD                *RootField = *FieldList;
298 
299 
300     /* Verify that we at least have a table signature and save it */
301 
302     Signature = DtGetFieldValue (*FieldList);
303     if (!Signature)
304     {
305         snprintf (AslGbl_MsgBuffer, sizeof(AslGbl_MsgBuffer), "Expected \"%s\"", "Signature");
306         DtNameError (ASL_ERROR, ASL_MSG_INVALID_FIELD_NAME,
307             *FieldList, AslGbl_MsgBuffer);
308         return (AE_ERROR);
309     }
310 
311     AslGbl_Signature = UtLocalCacheCalloc (strlen (Signature) + 1);
312     strcpy (AslGbl_Signature, Signature);
313 
314     /*
315      * Handle tables that don't use the common ACPI table header structure.
316      * Currently, these are the FACS and RSDP. Also check for an OEMx table,
317      * these tables have user-defined contents.
318      */
319     if (ACPI_COMPARE_NAMESEG (Signature, ACPI_SIG_FACS))
320     {
321         Status = DtCompileFacs (FieldList);
322         if (ACPI_FAILURE (Status))
323         {
324             return (Status);
325         }
326 
327         DtSetTableLength ();
328         return (Status);
329     }
330     else if (ACPI_VALIDATE_RSDP_SIG (Signature))
331     {
332         Status = DtCompileRsdp (FieldList);
333         return (Status);
334     }
335     else if (ACPI_COMPARE_NAMESEG (Signature, ACPI_SIG_S3PT))
336     {
337         Status = DtCompileS3pt (FieldList);
338         if (ACPI_FAILURE (Status))
339         {
340             return (Status);
341         }
342 
343         DtSetTableLength ();
344         return (Status);
345     }
346 
347     /*
348      * If the first field is named "CDAT Table Length" (not "Signature"),
349      * assume that we have a CDAT table (whose table header does not have
350      * a signature). Instead, the TableLength field is where the
351      * signature would (normally) be.
352      */
353     else if (!strcmp ((*FieldList)->Name, "CDAT Table Length"))
354     {
355         /* No longer true: (However, use this technique in the disassembler)
356          * We are assuming that there
357          * should be at least one non-ASCII byte in the 4-character
358          * Signature field, (At least the high-order byte should be zero).
359          */
360         Status = DtCompileTable (FieldList, AcpiDmTableInfoCdatTableHdr,
361             &AslGbl_RootTable);
362         if (ACPI_FAILURE (Status))
363         {
364             return (Status);
365         }
366 
367         /* Compile the CDAT */
368 
369         DtPushSubtable (AslGbl_RootTable);
370         Status = DtCompileCdat ((void **) FieldList);
371         if (ACPI_FAILURE (Status))
372         {
373             return (Status);
374         }
375 
376         /*
377          * Set the overall table length and the table checksum.
378          * The entire compiled table (including the CDAT table header with
379          * the table length and checksum) is in AslGbl_RootTable->Buffer.
380          */
381         DtSetTableLength ();
382         DtSetTableChecksum (&ACPI_CAST_PTR (ACPI_TABLE_CDAT, AslGbl_RootTable->Buffer)->Checksum);
383 
384         DtDumpFieldList (RootField);
385         DtDumpSubtableList ();
386         return (AE_OK);
387     }
388 
389     /*
390      * All other tables must use the common ACPI table header. Insert the
391      * current iASL IDs (name, version), and compile the header now.
392      */
393     DtInsertCompilerIds (*FieldList);
394 
395     Status = DtCompileTable (FieldList, AcpiDmTableInfoHeader,
396         &AslGbl_RootTable);
397     if (ACPI_FAILURE (Status))
398     {
399         return (Status);
400     }
401 
402     DtPushSubtable (AslGbl_RootTable);
403 
404     /* Validate the signature via the ACPI table list */
405 
406     TableData = AcpiDmGetTableData (Signature);
407     if (!TableData || AslGbl_CompileGeneric)
408     {
409         /* Unknown table signature and/or force generic compile */
410 
411         DtCompileGeneric ((void **) FieldList, NULL, NULL);
412         goto FinishHeader;
413     }
414 
415     /* Dispatch to per-table compile */
416 
417     if (TableData->CmTableHandler)
418     {
419         /* Complex table, has a handler */
420 
421         Status = TableData->CmTableHandler ((void **) FieldList);
422         if (ACPI_FAILURE (Status))
423         {
424             return (Status);
425         }
426     }
427     else if (TableData->TableInfo)
428     {
429         /* Simple table, just walk the info table, unless its empty */
430 
431         if (FieldList && *FieldList)
432         {
433             Subtable = NULL;
434             Status = DtCompileTable (FieldList, TableData->TableInfo,
435                 &Subtable);
436             if (ACPI_FAILURE (Status))
437             {
438                 return (Status);
439             }
440 
441             DtInsertSubtable (AslGbl_RootTable, Subtable);
442             DtPopSubtable ();
443         }
444     }
445     else
446     {
447         DtFatal (ASL_MSG_COMPILER_INTERNAL, *FieldList,
448             "Missing table dispatch info");
449         return (AE_ERROR);
450     }
451 
452 FinishHeader:
453 
454     /* Set the final table length and then the checksum */
455 
456     DtSetTableLength ();
457     AcpiTableHeader = ACPI_CAST_PTR (
458         ACPI_TABLE_HEADER, AslGbl_RootTable->Buffer);
459     DtSetTableChecksum (&AcpiTableHeader->Checksum);
460 
461     DtDumpFieldList (RootField);
462     DtDumpSubtableList ();
463     return (AE_OK);
464 }
465 
466 
467 /******************************************************************************
468  *
469  * FUNCTION:    DtCompileTable
470  *
471  * PARAMETERS:  Field               - Current field list pointer
472  *              Info                - Info table for this ACPI table
473  *              RetSubtable         - Compile result of table
474  *
475  * RETURN:      Status
476  *
477  * DESCRIPTION: Compile a subtable
478  *
479  *****************************************************************************/
480 
481 ACPI_STATUS
DtCompileTable(DT_FIELD ** Field,ACPI_DMTABLE_INFO * Info,DT_SUBTABLE ** RetSubtable)482 DtCompileTable (
483     DT_FIELD                **Field,
484     ACPI_DMTABLE_INFO       *Info,
485     DT_SUBTABLE             **RetSubtable)
486 {
487     DT_FIELD                *LocalField;
488     UINT32                  Length;
489     DT_SUBTABLE             *Subtable;
490     DT_SUBTABLE             *InlineSubtable = NULL;
491     UINT32                  FieldLength = 0;
492     UINT8                   FieldType;
493     UINT8                   *Buffer;
494     UINT8                   *FlagBuffer = NULL;
495     char                    *String;
496     UINT32                  CurrentFlagByteOffset = 0;
497     ACPI_STATUS             Status = AE_OK;
498 
499 
500     if (!Field || !Info)
501     {
502         return (AE_BAD_PARAMETER);
503     }
504     if (!*Field)
505     {
506         /*
507          * The field list is empty, this means that we are out of fields to
508          * parse. In other words, we are at the end of the table.
509          */
510         return (AE_END_OF_TABLE);
511     }
512 
513     /* Ignore optional subtable if name does not match */
514 
515     if ((Info->Flags & DT_OPTIONAL) &&
516         strcmp ((*Field)->Name, Info->Name))
517     {
518         *RetSubtable = NULL;
519         return (AE_OK);
520     }
521 
522     Length = DtGetSubtableLength (*Field, Info);
523     if (Length == ASL_EOF)
524     {
525         return (AE_ERROR);
526     }
527 
528     Subtable = UtSubtableCacheCalloc ();
529 
530     if (Length > 0)
531     {
532         String = UtLocalCacheCalloc (Length);
533         Subtable->Buffer = ACPI_CAST_PTR (UINT8, String);
534     }
535 
536     Subtable->Length = Length;
537     Subtable->TotalLength = Length;
538     Buffer = Subtable->Buffer;
539 
540     LocalField = *Field;
541     Subtable->Name = LocalField->Name;
542 
543     /*
544      * Main loop walks the info table for this ACPI table or subtable
545      */
546     for (; Info->Name; Info++)
547     {
548         if (Info->Opcode == ACPI_DMT_EXTRA_TEXT)
549         {
550             continue;
551         }
552 
553         if (!LocalField)
554         {
555             snprintf (AslGbl_MsgBuffer, sizeof(AslGbl_MsgBuffer), "Found NULL field - Field name \"%s\" needed",
556                 Info->Name);
557             DtFatal (ASL_MSG_COMPILER_INTERNAL, NULL, AslGbl_MsgBuffer);
558             Status = AE_BAD_DATA;
559             goto Error;
560         }
561 
562         /* Maintain table offsets */
563 
564         LocalField->TableOffset = AslGbl_CurrentTableOffset;
565         FieldLength = DtGetFieldLength (LocalField, Info);
566         AslGbl_CurrentTableOffset += FieldLength;
567 
568         FieldType = DtGetFieldType (Info);
569         AslGbl_InputFieldCount++;
570 
571         if (FieldType != DT_FIELD_TYPE_INLINE_SUBTABLE &&
572             strcmp (Info->Name, LocalField->Name))
573         {
574             sprintf (AslGbl_MsgBuffer, "found \"%s\" expected \"%s\"",
575                 LocalField->Name, Info->Name);
576             DtError (ASL_ERROR, ASL_MSG_INVALID_LABEL, LocalField, AslGbl_MsgBuffer);
577         }
578 
579         switch (FieldType)
580         {
581         case DT_FIELD_TYPE_FLAGS_INTEGER:
582             /*
583              * Start of the definition of a flags field.
584              * This master flags integer starts at value zero, in preparation
585              * to compile and insert the flag fields from the individual bits
586              */
587             LocalField = LocalField->Next;
588             *Field = LocalField;
589 
590             FlagBuffer = Buffer;
591             CurrentFlagByteOffset = Info->Offset;
592             break;
593 
594         case DT_FIELD_TYPE_FLAG:
595 
596             /* Individual Flag field, can be multiple bits */
597 
598             if (FlagBuffer)
599             {
600                 /*
601                  * We must increment the FlagBuffer when we have crossed
602                  * into the next flags byte within the flags field
603                  * of type DT_FIELD_TYPE_FLAGS_INTEGER.
604                  */
605                 FlagBuffer += (Info->Offset - CurrentFlagByteOffset);
606                 CurrentFlagByteOffset = Info->Offset;
607 
608                 DtCompileFlag (FlagBuffer, LocalField, Info);
609             }
610             else
611             {
612                 /* TBD - this is an internal error */
613             }
614 
615             LocalField = LocalField->Next;
616             *Field = LocalField;
617             break;
618 
619         case DT_FIELD_TYPE_INLINE_SUBTABLE:
620             /*
621              * Recursion (one level max): compile GAS (Generic Address)
622              * or Notify in-line subtable
623              */
624             *Field = LocalField;
625 
626             switch (Info->Opcode)
627             {
628             case ACPI_DMT_GAS:
629 
630                 Status = DtCompileTable (Field, AcpiDmTableInfoGas,
631                     &InlineSubtable);
632                 break;
633 
634             case ACPI_DMT_HESTNTFY:
635 
636                 Status = DtCompileTable (Field, AcpiDmTableInfoHestNotify,
637                     &InlineSubtable);
638                 break;
639 
640             case ACPI_DMT_IORTMEM:
641 
642                 Status = DtCompileTable (Field, AcpiDmTableInfoIortAcc,
643                     &InlineSubtable);
644                 break;
645 
646             default:
647                 sprintf (AslGbl_MsgBuffer, "Invalid DMT opcode: 0x%.2X",
648                     Info->Opcode);
649                 DtFatal (ASL_MSG_COMPILER_INTERNAL, NULL, AslGbl_MsgBuffer);
650                 Status = AE_BAD_DATA;
651                 break;
652             }
653 
654             if (ACPI_FAILURE (Status))
655             {
656                 goto Error;
657             }
658 
659             DtSetSubtableLength (InlineSubtable);
660 
661             memcpy (Buffer, InlineSubtable->Buffer, FieldLength);
662             LocalField = *Field;
663             break;
664 
665         case DT_FIELD_TYPE_LABEL:
666 
667             DtWriteFieldToListing (Buffer, LocalField, 0);
668             LocalField = LocalField->Next;
669             break;
670 
671         default:
672 
673             /* Normal case for most field types (Integer, String, etc.) */
674 
675             DtCompileOneField (Buffer, LocalField,
676                 FieldLength, FieldType, Info->Flags);
677 
678             DtWriteFieldToListing (Buffer, LocalField, FieldLength);
679             LocalField = LocalField->Next;
680 
681             if (Info->Flags & DT_LENGTH)
682             {
683                 /* Field is an Integer that will contain a subtable length */
684 
685                 Subtable->LengthField = Buffer;
686                 Subtable->SizeOfLengthField = FieldLength;
687             }
688             break;
689         }
690 
691         Buffer += FieldLength;
692     }
693 
694     *Field = LocalField;
695     *RetSubtable = Subtable;
696     return (AE_OK);
697 
698 Error:
699     ACPI_FREE (Subtable->Buffer);
700     ACPI_FREE (Subtable);
701     return (Status);
702 }
703 
704 
705 /******************************************************************************
706  *
707  * FUNCTION:    DtCompileTwoSubtables
708  *
709  * PARAMETERS:  List                - Current field list pointer
710  *              TableInfo1          - Info table 1
711  *              TableInfo1          - Info table 2
712  *
713  * RETURN:      Status
714  *
715  * DESCRIPTION: Compile tables with a header and one or more same subtables.
716  *              Include CPEP, EINJ, ERST, MCFG, MSCT, WDAT
717  *
718  *****************************************************************************/
719 
720 ACPI_STATUS
DtCompileTwoSubtables(void ** List,ACPI_DMTABLE_INFO * TableInfo1,ACPI_DMTABLE_INFO * TableInfo2)721 DtCompileTwoSubtables (
722     void                    **List,
723     ACPI_DMTABLE_INFO       *TableInfo1,
724     ACPI_DMTABLE_INFO       *TableInfo2)
725 {
726     ACPI_STATUS             Status;
727     DT_SUBTABLE             *Subtable;
728     DT_SUBTABLE             *ParentTable;
729     DT_FIELD                **PFieldList = (DT_FIELD **) List;
730 
731 
732     Status = DtCompileTable (PFieldList, TableInfo1, &Subtable);
733     if (ACPI_FAILURE (Status))
734     {
735         return (Status);
736     }
737 
738     ParentTable = DtPeekSubtable ();
739     DtInsertSubtable (ParentTable, Subtable);
740 
741     while (*PFieldList)
742     {
743         Status = DtCompileTable (PFieldList, TableInfo2, &Subtable);
744         if (ACPI_FAILURE (Status))
745         {
746             return (Status);
747         }
748 
749         DtInsertSubtable (ParentTable, Subtable);
750     }
751 
752     return (AE_OK);
753 }
754 
755 
756 /******************************************************************************
757  *
758  * FUNCTION:    DtCompilePadding
759  *
760  * PARAMETERS:  Length              - Padding field size
761  *              RetSubtable         - Compile result of table
762  *
763  * RETURN:      Status
764  *
765  * DESCRIPTION: Compile a subtable for padding purpose
766  *
767  *****************************************************************************/
768 
769 ACPI_STATUS
DtCompilePadding(UINT32 Length,DT_SUBTABLE ** RetSubtable)770 DtCompilePadding (
771     UINT32                  Length,
772     DT_SUBTABLE             **RetSubtable)
773 {
774     DT_SUBTABLE             *Subtable;
775     /* UINT8                   *Buffer; */
776     char                    *String;
777 
778 
779     Subtable = UtSubtableCacheCalloc ();
780 
781     if (Length > 0)
782     {
783         String = UtLocalCacheCalloc (Length);
784         Subtable->Buffer = ACPI_CAST_PTR (UINT8, String);
785     }
786 
787     Subtable->Length = Length;
788     Subtable->TotalLength = Length;
789     /* Buffer = Subtable->Buffer; */
790 
791     *RetSubtable = Subtable;
792     return (AE_OK);
793 }
794