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