1 /****************************************************************************** 2 * 3 * Module Name: dtcompile.c - Front-end for data table compiler 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2026, 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 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 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 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, with safety checks */ 260 261 if (!FieldList) 262 { 263 DtError (ASL_WARNING, ASL_MSG_MALFORMED_HEADER, NULL, NULL); 264 return; 265 } 266 267 Next = FieldList; 268 for (i = 0; i < 7; i++) 269 { 270 if (!Next || !Next->Next) 271 { 272 /* Malformed/short header: cannot insert compiler IDs */ 273 DtError (ASL_WARNING, ASL_MSG_MALFORMED_HEADER, FieldList, NULL); 274 return; 275 } 276 Next = Next->Next; 277 } 278 279 /* Ensure both Creator ID and Revision fields exist */ 280 if (!Next || !Next->Next) 281 { 282 DtError (ASL_WARNING, ASL_MSG_MALFORMED_HEADER, FieldList, NULL); 283 return; 284 } 285 286 Next->Value = ASL_CREATOR_ID; 287 Next->Flags = DT_FIELD_NOT_ALLOCATED; 288 289 Next = Next->Next; 290 if (!Next) 291 { 292 DtError (ASL_WARNING, ASL_MSG_MALFORMED_HEADER, FieldList, NULL); 293 return; 294 } 295 Next->Value = VersionString; 296 Next->Flags = DT_FIELD_NOT_ALLOCATED; 297 } 298 299 300 /****************************************************************************** 301 * 302 * FUNCTION: DtCompileDataTable 303 * 304 * PARAMETERS: FieldList - Current field list pointer 305 * 306 * RETURN: Status 307 * 308 * DESCRIPTION: Entry point to compile one data table 309 * 310 *****************************************************************************/ 311 312 static ACPI_STATUS 313 DtCompileDataTable ( 314 DT_FIELD **FieldList) 315 { 316 const ACPI_DMTABLE_DATA *TableData; 317 DT_SUBTABLE *Subtable; 318 char *Signature; 319 ACPI_TABLE_HEADER *AcpiTableHeader; 320 ACPI_STATUS Status; 321 DT_FIELD *RootField = *FieldList; 322 323 324 /* Verify that we at least have a table signature and save it */ 325 326 Signature = DtGetFieldValue (*FieldList); 327 if (!Signature) 328 { 329 snprintf (AslGbl_MsgBuffer, sizeof(AslGbl_MsgBuffer), "Expected \"%s\"", "Signature"); 330 DtNameError (ASL_ERROR, ASL_MSG_INVALID_FIELD_NAME, 331 *FieldList, AslGbl_MsgBuffer); 332 return (AE_ERROR); 333 } 334 335 AslGbl_Signature = UtLocalCacheCalloc (strlen (Signature) + 1); 336 strcpy (AslGbl_Signature, Signature); 337 338 /* 339 * Handle tables that don't use the common ACPI table header structure. 340 * Currently, these are the FACS and RSDP. Also check for an OEMx table, 341 * these tables have user-defined contents. 342 */ 343 if (ACPI_COMPARE_NAMESEG (Signature, ACPI_SIG_FACS)) 344 { 345 Status = DtCompileFacs (FieldList); 346 if (ACPI_FAILURE (Status)) 347 { 348 return (Status); 349 } 350 351 DtSetTableLength (); 352 return (Status); 353 } 354 else if (ACPI_VALIDATE_RSDP_SIG (Signature)) 355 { 356 Status = DtCompileRsdp (FieldList); 357 return (Status); 358 } 359 else if (ACPI_COMPARE_NAMESEG (Signature, ACPI_SIG_S3PT)) 360 { 361 Status = DtCompileS3pt (FieldList); 362 if (ACPI_FAILURE (Status)) 363 { 364 return (Status); 365 } 366 367 DtSetTableLength (); 368 return (Status); 369 } 370 371 /* 372 * If the first field is named "CDAT Table Length" (not "Signature"), 373 * assume that we have a CDAT table (whose table header does not have 374 * a signature). Instead, the TableLength field is where the 375 * signature would (normally) be. 376 */ 377 else if (!strcmp ((*FieldList)->Name, "CDAT Table Length")) 378 { 379 /* No longer true: (However, use this technique in the disassembler) 380 * We are assuming that there 381 * should be at least one non-ASCII byte in the 4-character 382 * Signature field, (At least the high-order byte should be zero). 383 */ 384 Status = DtCompileTable (FieldList, AcpiDmTableInfoCdatTableHdr, 385 &AslGbl_RootTable); 386 if (ACPI_FAILURE (Status)) 387 { 388 return (Status); 389 } 390 391 /* Compile the CDAT */ 392 393 DtPushSubtable (AslGbl_RootTable); 394 Status = DtCompileCdat ((void **) FieldList); 395 if (ACPI_FAILURE (Status)) 396 { 397 return (Status); 398 } 399 400 /* 401 * Set the overall table length and the table checksum. 402 * The entire compiled table (including the CDAT table header with 403 * the table length and checksum) is in AslGbl_RootTable->Buffer. 404 */ 405 DtSetTableLength (); 406 DtSetTableChecksum (&ACPI_CAST_PTR (ACPI_TABLE_CDAT, AslGbl_RootTable->Buffer)->Checksum); 407 408 DtDumpFieldList (RootField); 409 DtDumpSubtableList (); 410 return (AE_OK); 411 } 412 413 /* 414 * All other tables must use the common ACPI table header. Insert the 415 * current iASL IDs (name, version), and compile the header now. 416 */ 417 DtInsertCompilerIds (*FieldList); 418 419 Status = DtCompileTable (FieldList, AcpiDmTableInfoHeader, 420 &AslGbl_RootTable); 421 if (ACPI_FAILURE (Status)) 422 { 423 return (Status); 424 } 425 426 DtPushSubtable (AslGbl_RootTable); 427 428 /* Validate the signature via the ACPI table list */ 429 430 TableData = AcpiDmGetTableData (Signature); 431 if (!TableData || AslGbl_CompileGeneric) 432 { 433 /* Unknown table signature and/or force generic compile */ 434 435 DtCompileGeneric ((void **) FieldList, NULL, NULL); 436 goto FinishHeader; 437 } 438 439 /* Dispatch to per-table compile */ 440 441 if (TableData->CmTableHandler) 442 { 443 /* Complex table, has a handler */ 444 445 Status = TableData->CmTableHandler ((void **) FieldList); 446 if (ACPI_FAILURE (Status)) 447 { 448 return (Status); 449 } 450 } 451 else if (TableData->TableInfo) 452 { 453 /* Simple table, just walk the info table, unless its empty */ 454 455 if (FieldList && *FieldList) 456 { 457 Subtable = NULL; 458 Status = DtCompileTable (FieldList, TableData->TableInfo, 459 &Subtable); 460 if (ACPI_FAILURE (Status)) 461 { 462 return (Status); 463 } 464 465 DtInsertSubtable (AslGbl_RootTable, Subtable); 466 DtPopSubtable (); 467 } 468 } 469 else 470 { 471 DtFatal (ASL_MSG_COMPILER_INTERNAL, *FieldList, 472 "Missing table dispatch info"); 473 return (AE_ERROR); 474 } 475 476 FinishHeader: 477 478 /* Set the final table length and then the checksum */ 479 480 DtSetTableLength (); 481 AcpiTableHeader = ACPI_CAST_PTR ( 482 ACPI_TABLE_HEADER, AslGbl_RootTable->Buffer); 483 DtSetTableChecksum (&AcpiTableHeader->Checksum); 484 485 DtDumpFieldList (RootField); 486 DtDumpSubtableList (); 487 return (AE_OK); 488 } 489 490 491 /****************************************************************************** 492 * 493 * FUNCTION: DtCompileTable 494 * 495 * PARAMETERS: Field - Current field list pointer 496 * Info - Info table for this ACPI table 497 * RetSubtable - Compile result of table 498 * 499 * RETURN: Status 500 * 501 * DESCRIPTION: Compile a subtable 502 * 503 *****************************************************************************/ 504 505 ACPI_STATUS 506 DtCompileTable ( 507 DT_FIELD **Field, 508 ACPI_DMTABLE_INFO *Info, 509 DT_SUBTABLE **RetSubtable) 510 { 511 DT_FIELD *LocalField; 512 UINT32 Length; 513 DT_SUBTABLE *Subtable; 514 DT_SUBTABLE *InlineSubtable = NULL; 515 UINT32 FieldLength = 0; 516 UINT8 FieldType; 517 UINT8 *Buffer; 518 UINT8 *FlagBuffer = NULL; 519 char *String; 520 UINT32 CurrentFlagByteOffset = 0; 521 ACPI_STATUS Status = AE_OK; 522 523 524 if (!Field || !Info) 525 { 526 return (AE_BAD_PARAMETER); 527 } 528 if (!*Field) 529 { 530 /* 531 * The field list is empty, this means that we are out of fields to 532 * parse. In other words, we are at the end of the table. 533 */ 534 return (AE_END_OF_TABLE); 535 } 536 537 /* Ignore optional subtable if name does not match */ 538 539 if ((Info->Flags & DT_OPTIONAL) && 540 strcmp ((*Field)->Name, Info->Name)) 541 { 542 *RetSubtable = NULL; 543 return (AE_OK); 544 } 545 546 Length = DtGetSubtableLength (*Field, Info); 547 if (Length == ASL_EOF) 548 { 549 return (AE_ERROR); 550 } 551 552 Subtable = UtSubtableCacheCalloc (); 553 554 if (Length > 0) 555 { 556 String = UtLocalCacheCalloc (Length); 557 Subtable->Buffer = ACPI_CAST_PTR (UINT8, String); 558 } 559 560 Subtable->Length = Length; 561 Subtable->TotalLength = Length; 562 Buffer = Subtable->Buffer; 563 564 LocalField = *Field; 565 Subtable->Name = LocalField->Name; 566 567 /* 568 * Main loop walks the info table for this ACPI table or subtable 569 */ 570 for (; Info->Name; Info++) 571 { 572 if (Info->Opcode == ACPI_DMT_EXTRA_TEXT) 573 { 574 continue; 575 } 576 577 if (!LocalField) 578 { 579 snprintf (AslGbl_MsgBuffer, sizeof(AslGbl_MsgBuffer), "Found NULL field - Field name \"%s\" needed", 580 Info->Name); 581 DtFatal (ASL_MSG_COMPILER_INTERNAL, NULL, AslGbl_MsgBuffer); 582 Status = AE_BAD_DATA; 583 goto Error; 584 } 585 586 /* Maintain table offsets */ 587 588 LocalField->TableOffset = AslGbl_CurrentTableOffset; 589 FieldLength = DtGetFieldLength (LocalField, Info); 590 AslGbl_CurrentTableOffset += FieldLength; 591 592 FieldType = DtGetFieldType (Info); 593 AslGbl_InputFieldCount++; 594 595 if (FieldType != DT_FIELD_TYPE_INLINE_SUBTABLE && 596 strcmp (Info->Name, LocalField->Name)) 597 { 598 sprintf (AslGbl_MsgBuffer, "found \"%s\" expected \"%s\"", 599 LocalField->Name, Info->Name); 600 DtError (ASL_ERROR, ASL_MSG_INVALID_LABEL, LocalField, AslGbl_MsgBuffer); 601 } 602 603 switch (FieldType) 604 { 605 case DT_FIELD_TYPE_FLAGS_INTEGER: 606 /* 607 * Start of the definition of a flags field. 608 * This master flags integer starts at value zero, in preparation 609 * to compile and insert the flag fields from the individual bits 610 */ 611 LocalField = LocalField->Next; 612 *Field = LocalField; 613 614 FlagBuffer = Buffer; 615 CurrentFlagByteOffset = Info->Offset; 616 break; 617 618 case DT_FIELD_TYPE_FLAG: 619 620 /* Individual Flag field, can be multiple bits */ 621 622 if (FlagBuffer) 623 { 624 /* 625 * We must increment the FlagBuffer when we have crossed 626 * into the next flags byte within the flags field 627 * of type DT_FIELD_TYPE_FLAGS_INTEGER. 628 */ 629 FlagBuffer += (Info->Offset - CurrentFlagByteOffset); 630 CurrentFlagByteOffset = Info->Offset; 631 632 DtCompileFlag (FlagBuffer, LocalField, Info); 633 } 634 else 635 { 636 /* TBD - this is an internal error */ 637 } 638 639 LocalField = LocalField->Next; 640 *Field = LocalField; 641 break; 642 643 case DT_FIELD_TYPE_INLINE_SUBTABLE: 644 /* 645 * Recursion (one level max): compile GAS (Generic Address) 646 * or Notify in-line subtable 647 */ 648 *Field = LocalField; 649 650 switch (Info->Opcode) 651 { 652 case ACPI_DMT_GAS: 653 654 Status = DtCompileTable (Field, AcpiDmTableInfoGas, 655 &InlineSubtable); 656 break; 657 658 case ACPI_DMT_HESTNTFY: 659 660 Status = DtCompileTable (Field, AcpiDmTableInfoHestNotify, 661 &InlineSubtable); 662 break; 663 664 case ACPI_DMT_IORTMEM: 665 666 Status = DtCompileTable (Field, AcpiDmTableInfoIortAcc, 667 &InlineSubtable); 668 break; 669 670 default: 671 sprintf (AslGbl_MsgBuffer, "Invalid DMT opcode: 0x%.2X", 672 Info->Opcode); 673 DtFatal (ASL_MSG_COMPILER_INTERNAL, NULL, AslGbl_MsgBuffer); 674 Status = AE_BAD_DATA; 675 break; 676 } 677 678 if (ACPI_FAILURE (Status)) 679 { 680 goto Error; 681 } 682 683 DtSetSubtableLength (InlineSubtable); 684 685 memcpy (Buffer, InlineSubtable->Buffer, FieldLength); 686 LocalField = *Field; 687 break; 688 689 case DT_FIELD_TYPE_LABEL: 690 691 DtWriteFieldToListing (Buffer, LocalField, 0); 692 LocalField = LocalField->Next; 693 break; 694 695 default: 696 697 /* Normal case for most field types (Integer, String, etc.) */ 698 699 DtCompileOneField (Buffer, LocalField, 700 FieldLength, FieldType, Info->Flags); 701 702 DtWriteFieldToListing (Buffer, LocalField, FieldLength); 703 LocalField = LocalField->Next; 704 705 if (Info->Flags & DT_LENGTH) 706 { 707 /* Field is an Integer that will contain a subtable length */ 708 709 Subtable->LengthField = Buffer; 710 Subtable->SizeOfLengthField = FieldLength; 711 } 712 break; 713 } 714 715 Buffer += FieldLength; 716 } 717 718 *Field = LocalField; 719 *RetSubtable = Subtable; 720 return (AE_OK); 721 722 Error: 723 ACPI_FREE (Subtable->Buffer); 724 ACPI_FREE (Subtable); 725 return (Status); 726 } 727 728 729 /****************************************************************************** 730 * 731 * FUNCTION: DtCompileTwoSubtables 732 * 733 * PARAMETERS: List - Current field list pointer 734 * TableInfo1 - Info table 1 735 * TableInfo1 - Info table 2 736 * 737 * RETURN: Status 738 * 739 * DESCRIPTION: Compile tables with a header and one or more same subtables. 740 * Include CPEP, EINJ, ERST, MCFG, MSCT, WDAT 741 * 742 *****************************************************************************/ 743 744 ACPI_STATUS 745 DtCompileTwoSubtables ( 746 void **List, 747 ACPI_DMTABLE_INFO *TableInfo1, 748 ACPI_DMTABLE_INFO *TableInfo2) 749 { 750 ACPI_STATUS Status; 751 DT_SUBTABLE *Subtable; 752 DT_SUBTABLE *ParentTable; 753 DT_FIELD **PFieldList = (DT_FIELD **) List; 754 755 756 Status = DtCompileTable (PFieldList, TableInfo1, &Subtable); 757 if (ACPI_FAILURE (Status)) 758 { 759 return (Status); 760 } 761 762 ParentTable = DtPeekSubtable (); 763 DtInsertSubtable (ParentTable, Subtable); 764 765 while (*PFieldList) 766 { 767 Status = DtCompileTable (PFieldList, TableInfo2, &Subtable); 768 if (ACPI_FAILURE (Status)) 769 { 770 return (Status); 771 } 772 773 DtInsertSubtable (ParentTable, Subtable); 774 } 775 776 return (AE_OK); 777 } 778 779 780 /****************************************************************************** 781 * 782 * FUNCTION: DtCompilePadding 783 * 784 * PARAMETERS: Length - Padding field size 785 * RetSubtable - Compile result of table 786 * 787 * RETURN: Status 788 * 789 * DESCRIPTION: Compile a subtable for padding purpose 790 * 791 *****************************************************************************/ 792 793 ACPI_STATUS 794 DtCompilePadding ( 795 UINT32 Length, 796 DT_SUBTABLE **RetSubtable) 797 { 798 DT_SUBTABLE *Subtable; 799 /* UINT8 *Buffer; */ 800 char *String; 801 802 803 Subtable = UtSubtableCacheCalloc (); 804 805 if (Length > 0) 806 { 807 String = UtLocalCacheCalloc (Length); 808 Subtable->Buffer = ACPI_CAST_PTR (UINT8, String); 809 } 810 811 Subtable->Length = Length; 812 Subtable->TotalLength = Length; 813 /* Buffer = Subtable->Buffer; */ 814 815 *RetSubtable = Subtable; 816 return (AE_OK); 817 } 818