dtsubtable.c revision 228110
1208625Sjkim/****************************************************************************** 2208625Sjkim * 3208625Sjkim * Module Name: dtsubtable.c - handling of subtables within ACPI tables 4208625Sjkim * 5208625Sjkim *****************************************************************************/ 6208625Sjkim 7217365Sjkim/* 8217365Sjkim * Copyright (C) 2000 - 2011, Intel Corp. 9208625Sjkim * All rights reserved. 10208625Sjkim * 11217365Sjkim * Redistribution and use in source and binary forms, with or without 12217365Sjkim * modification, are permitted provided that the following conditions 13217365Sjkim * are met: 14217365Sjkim * 1. Redistributions of source code must retain the above copyright 15217365Sjkim * notice, this list of conditions, and the following disclaimer, 16217365Sjkim * without modification. 17217365Sjkim * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18217365Sjkim * substantially similar to the "NO WARRANTY" disclaimer below 19217365Sjkim * ("Disclaimer") and any redistribution must be conditioned upon 20217365Sjkim * including a substantially similar Disclaimer requirement for further 21217365Sjkim * binary redistribution. 22217365Sjkim * 3. Neither the names of the above-listed copyright holders nor the names 23217365Sjkim * of any contributors may be used to endorse or promote products derived 24217365Sjkim * from this software without specific prior written permission. 25208625Sjkim * 26217365Sjkim * Alternatively, this software may be distributed under the terms of the 27217365Sjkim * GNU General Public License ("GPL") version 2 as published by the Free 28217365Sjkim * Software Foundation. 29208625Sjkim * 30217365Sjkim * NO WARRANTY 31217365Sjkim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32217365Sjkim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33217365Sjkim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 34217365Sjkim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35217365Sjkim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36217365Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37217365Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38217365Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39217365Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40217365Sjkim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41217365Sjkim * POSSIBILITY OF SUCH DAMAGES. 42217365Sjkim */ 43208625Sjkim 44208625Sjkim#define __DTSUBTABLE_C__ 45208625Sjkim 46209746Sjkim#include <contrib/dev/acpica/compiler/aslcompiler.h> 47209746Sjkim#include <contrib/dev/acpica/compiler/dtcompiler.h> 48208625Sjkim 49208625Sjkim#define _COMPONENT DT_COMPILER 50208625Sjkim ACPI_MODULE_NAME ("dtsubtable") 51208625Sjkim 52208625Sjkim 53208625Sjkim/****************************************************************************** 54208625Sjkim * 55208625Sjkim * FUNCTION: DtCreateSubtable 56208625Sjkim * 57208625Sjkim * PARAMETERS: Buffer - Input buffer 58208625Sjkim * Length - Buffer length 59208625Sjkim * RetSubtable - Returned newly created subtable 60208625Sjkim * 61208625Sjkim * RETURN: None 62208625Sjkim * 63208625Sjkim * DESCRIPTION: Create a subtable that is not listed with ACPI_DMTABLE_INFO 64208625Sjkim * For example, FACS has 24 bytes reserved at the end 65208625Sjkim * and it's not listed at AcpiDmTableInfoFacs 66208625Sjkim * 67208625Sjkim *****************************************************************************/ 68208625Sjkim 69208625Sjkimvoid 70208625SjkimDtCreateSubtable ( 71208625Sjkim UINT8 *Buffer, 72208625Sjkim UINT32 Length, 73208625Sjkim DT_SUBTABLE **RetSubtable) 74208625Sjkim{ 75208625Sjkim DT_SUBTABLE *Subtable; 76208625Sjkim 77208625Sjkim 78208625Sjkim Subtable = UtLocalCalloc (sizeof (DT_SUBTABLE)); 79208625Sjkim 80208625Sjkim /* Create a new buffer for the subtable data */ 81208625Sjkim 82208625Sjkim Subtable->Buffer = UtLocalCalloc (Length); 83208625Sjkim ACPI_MEMCPY (Subtable->Buffer, Buffer, Length); 84208625Sjkim 85208625Sjkim Subtable->Length = Length; 86208625Sjkim Subtable->TotalLength = Length; 87208625Sjkim 88208625Sjkim *RetSubtable = Subtable; 89208625Sjkim} 90208625Sjkim 91208625Sjkim 92208625Sjkim/****************************************************************************** 93208625Sjkim * 94208625Sjkim * FUNCTION: DtInsertSubtable 95208625Sjkim * 96208625Sjkim * PARAMETERS: ParentTable - The Parent of the new subtable 97208625Sjkim * Subtable - The new subtable to insert 98208625Sjkim * 99208625Sjkim * RETURN: None 100208625Sjkim * 101208625Sjkim * DESCRIPTION: Insert the new subtable to the parent table 102208625Sjkim * 103208625Sjkim *****************************************************************************/ 104208625Sjkim 105208625Sjkimvoid 106208625SjkimDtInsertSubtable ( 107208625Sjkim DT_SUBTABLE *ParentTable, 108208625Sjkim DT_SUBTABLE *Subtable) 109208625Sjkim{ 110208625Sjkim DT_SUBTABLE *ChildTable; 111208625Sjkim 112208625Sjkim 113208625Sjkim Subtable->Peer = NULL; 114208625Sjkim Subtable->Parent = ParentTable; 115208625Sjkim 116208625Sjkim /* Link the new entry into the child list */ 117208625Sjkim 118208625Sjkim if (!ParentTable->Child) 119208625Sjkim { 120208625Sjkim ParentTable->Child = Subtable; 121208625Sjkim } 122208625Sjkim else 123208625Sjkim { 124208625Sjkim /* Walk to the end of the child list */ 125208625Sjkim 126208625Sjkim ChildTable = ParentTable->Child; 127208625Sjkim while (ChildTable->Peer) 128208625Sjkim { 129208625Sjkim ChildTable = ChildTable->Peer; 130208625Sjkim } 131208625Sjkim 132208625Sjkim /* Add new subtable at the end of the child list */ 133208625Sjkim 134208625Sjkim ChildTable->Peer = Subtable; 135208625Sjkim } 136208625Sjkim} 137208625Sjkim 138208625Sjkim 139208625Sjkim/****************************************************************************** 140208625Sjkim * 141208625Sjkim * FUNCTION: DtPushSubtable 142208625Sjkim * 143208625Sjkim * PARAMETERS: Subtable - Subtable to push 144208625Sjkim * 145208625Sjkim * RETURN: None 146208625Sjkim * 147208625Sjkim * DESCRIPTION: Push a subtable onto a subtable stack 148208625Sjkim * 149208625Sjkim *****************************************************************************/ 150208625Sjkim 151208625Sjkimvoid 152208625SjkimDtPushSubtable ( 153208625Sjkim DT_SUBTABLE *Subtable) 154208625Sjkim{ 155208625Sjkim 156208625Sjkim Subtable->StackTop = Gbl_SubtableStack; 157208625Sjkim Gbl_SubtableStack = Subtable; 158208625Sjkim} 159208625Sjkim 160208625Sjkim 161208625Sjkim/****************************************************************************** 162208625Sjkim * 163208625Sjkim * FUNCTION: DtPopSubtable 164208625Sjkim * 165208625Sjkim * PARAMETERS: None 166208625Sjkim * 167208625Sjkim * RETURN: None 168208625Sjkim * 169208625Sjkim * DESCRIPTION: Pop a subtable from a subtable stack. Uses global SubtableStack 170208625Sjkim * 171208625Sjkim *****************************************************************************/ 172208625Sjkim 173208625Sjkimvoid 174208625SjkimDtPopSubtable ( 175208625Sjkim void) 176208625Sjkim{ 177208625Sjkim DT_SUBTABLE *Subtable; 178208625Sjkim 179208625Sjkim 180208625Sjkim Subtable = Gbl_SubtableStack; 181208625Sjkim 182208625Sjkim if (Subtable) 183208625Sjkim { 184208625Sjkim Gbl_SubtableStack = Subtable->StackTop; 185208625Sjkim } 186208625Sjkim} 187208625Sjkim 188208625Sjkim 189208625Sjkim/****************************************************************************** 190208625Sjkim * 191208625Sjkim * FUNCTION: DtPeekSubtable 192208625Sjkim * 193208625Sjkim * PARAMETERS: None 194208625Sjkim * 195208625Sjkim * RETURN: The subtable on top of stack 196208625Sjkim * 197208625Sjkim * DESCRIPTION: Get the subtable on top of stack 198208625Sjkim * 199208625Sjkim *****************************************************************************/ 200208625Sjkim 201208625SjkimDT_SUBTABLE * 202208625SjkimDtPeekSubtable ( 203208625Sjkim void) 204208625Sjkim{ 205208625Sjkim 206208625Sjkim return (Gbl_SubtableStack); 207208625Sjkim} 208208625Sjkim 209208625Sjkim 210208625Sjkim/****************************************************************************** 211208625Sjkim * 212208625Sjkim * FUNCTION: DtGetNextSubtable 213208625Sjkim * 214208625Sjkim * PARAMETERS: ParentTable - Parent table whose children we are 215208625Sjkim * getting 216208625Sjkim * ChildTable - Previous child that was found. 217208625Sjkim * The NEXT child will be returned 218208625Sjkim * 219208625Sjkim * RETURN: Pointer to the NEXT child or NULL if none is found. 220208625Sjkim * 221208625Sjkim * DESCRIPTION: Return the next peer subtable within the tree. 222208625Sjkim * 223208625Sjkim *****************************************************************************/ 224208625Sjkim 225208625SjkimDT_SUBTABLE * 226208625SjkimDtGetNextSubtable ( 227208625Sjkim DT_SUBTABLE *ParentTable, 228208625Sjkim DT_SUBTABLE *ChildTable) 229208625Sjkim{ 230208625Sjkim ACPI_FUNCTION_ENTRY (); 231208625Sjkim 232208625Sjkim 233208625Sjkim if (!ChildTable) 234208625Sjkim { 235208625Sjkim /* It's really the parent's _scope_ that we want */ 236208625Sjkim 237208625Sjkim return (ParentTable->Child); 238208625Sjkim } 239208625Sjkim 240208625Sjkim /* Otherwise just return the next peer (NULL if at end-of-list) */ 241208625Sjkim 242208625Sjkim return (ChildTable->Peer); 243208625Sjkim} 244208625Sjkim 245208625Sjkim 246208625Sjkim/****************************************************************************** 247208625Sjkim * 248208625Sjkim * FUNCTION: DtGetParentSubtable 249208625Sjkim * 250208625Sjkim * PARAMETERS: Subtable - Current subtable 251208625Sjkim * 252208625Sjkim * RETURN: Parent of the given subtable 253208625Sjkim * 254208625Sjkim * DESCRIPTION: Get the parent of the given subtable in the tree 255208625Sjkim * 256208625Sjkim *****************************************************************************/ 257208625Sjkim 258208625SjkimDT_SUBTABLE * 259208625SjkimDtGetParentSubtable ( 260208625Sjkim DT_SUBTABLE *Subtable) 261208625Sjkim{ 262208625Sjkim 263208625Sjkim if (!Subtable) 264208625Sjkim { 265208625Sjkim return (NULL); 266208625Sjkim } 267208625Sjkim 268208625Sjkim return (Subtable->Parent); 269208625Sjkim} 270208625Sjkim 271208625Sjkim 272208625Sjkim/****************************************************************************** 273208625Sjkim * 274208625Sjkim * FUNCTION: DtGetSubtableLength 275208625Sjkim * 276208625Sjkim * PARAMETERS: Field - Current field list pointer 277208625Sjkim * Info - Data table info 278208625Sjkim * 279208625Sjkim * RETURN: Subtable length 280208625Sjkim * 281208625Sjkim * DESCRIPTION: Get length of bytes needed to compile the subtable 282208625Sjkim * 283208625Sjkim *****************************************************************************/ 284208625Sjkim 285208625SjkimUINT32 286208625SjkimDtGetSubtableLength ( 287208625Sjkim DT_FIELD *Field, 288208625Sjkim ACPI_DMTABLE_INFO *Info) 289208625Sjkim{ 290208625Sjkim UINT32 ByteLength = 0; 291220663Sjkim UINT8 Step; 292220663Sjkim UINT8 i; 293208625Sjkim 294208625Sjkim 295208625Sjkim /* Walk entire Info table; Null name terminates */ 296208625Sjkim 297208625Sjkim for (; Info->Name; Info++) 298208625Sjkim { 299228110Sjkim if (Info->Opcode == ACPI_DMT_EXTRA_TEXT) 300228110Sjkim { 301228110Sjkim continue; 302228110Sjkim } 303228110Sjkim 304220663Sjkim if (!Field) 305220663Sjkim { 306220663Sjkim goto Error; 307220663Sjkim } 308220663Sjkim 309208625Sjkim ByteLength += DtGetFieldLength (Field, Info); 310220663Sjkim 311220663Sjkim switch (Info->Opcode) 312220663Sjkim { 313220663Sjkim case ACPI_DMT_GAS: 314220663Sjkim Step = 5; 315220663Sjkim break; 316220663Sjkim 317220663Sjkim case ACPI_DMT_HESTNTFY: 318220663Sjkim Step = 9; 319220663Sjkim break; 320220663Sjkim 321220663Sjkim default: 322220663Sjkim Step = 1; 323220663Sjkim break; 324220663Sjkim } 325220663Sjkim 326220663Sjkim for (i = 0; i < Step; i++) 327220663Sjkim { 328220663Sjkim if (!Field) 329220663Sjkim { 330220663Sjkim goto Error; 331220663Sjkim } 332220663Sjkim 333220663Sjkim Field = Field->Next; 334220663Sjkim } 335208625Sjkim } 336208625Sjkim 337208625Sjkim return (ByteLength); 338220663Sjkim 339220663SjkimError: 340220663Sjkim if (!Field) 341220663Sjkim { 342220663Sjkim sprintf (MsgBuffer, "Found NULL field - Field name \"%s\" needed", 343220663Sjkim Info->Name); 344220663Sjkim DtFatal (ASL_MSG_COMPILER_INTERNAL, NULL, MsgBuffer); 345220663Sjkim } 346220663Sjkim 347220663Sjkim return (ASL_EOF); 348208625Sjkim} 349208625Sjkim 350208625Sjkim 351208625Sjkim/****************************************************************************** 352208625Sjkim * 353208625Sjkim * FUNCTION: DtSetSubtableLength 354208625Sjkim * 355208625Sjkim * PARAMETERS: Subtable - Subtable 356208625Sjkim * 357208625Sjkim * RETURN: None 358208625Sjkim * 359208625Sjkim * DESCRIPTION: Set length of the subtable into its length field 360208625Sjkim * 361208625Sjkim *****************************************************************************/ 362208625Sjkim 363208625Sjkimvoid 364208625SjkimDtSetSubtableLength ( 365208625Sjkim DT_SUBTABLE *Subtable) 366208625Sjkim{ 367208625Sjkim 368208625Sjkim if (!Subtable->LengthField) 369208625Sjkim { 370208625Sjkim return; 371208625Sjkim } 372208625Sjkim 373208625Sjkim ACPI_MEMCPY (Subtable->LengthField, &Subtable->TotalLength, 374208625Sjkim Subtable->SizeOfLengthField); 375208625Sjkim} 376