1208625Sjkim/****************************************************************************** 2208625Sjkim * 3208625Sjkim * Module Name: dtsubtable.c - handling of subtables within ACPI tables 4208625Sjkim * 5208625Sjkim *****************************************************************************/ 6208625Sjkim 7217365Sjkim/* 8306536Sjkim * Copyright (C) 2000 - 2016, 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 44209746Sjkim#include <contrib/dev/acpica/compiler/aslcompiler.h> 45209746Sjkim#include <contrib/dev/acpica/compiler/dtcompiler.h> 46208625Sjkim 47208625Sjkim#define _COMPONENT DT_COMPILER 48208625Sjkim ACPI_MODULE_NAME ("dtsubtable") 49208625Sjkim 50208625Sjkim 51208625Sjkim/****************************************************************************** 52208625Sjkim * 53208625Sjkim * FUNCTION: DtCreateSubtable 54208625Sjkim * 55208625Sjkim * PARAMETERS: Buffer - Input buffer 56208625Sjkim * Length - Buffer length 57208625Sjkim * RetSubtable - Returned newly created subtable 58208625Sjkim * 59208625Sjkim * RETURN: None 60208625Sjkim * 61208625Sjkim * DESCRIPTION: Create a subtable that is not listed with ACPI_DMTABLE_INFO 62208625Sjkim * For example, FACS has 24 bytes reserved at the end 63208625Sjkim * and it's not listed at AcpiDmTableInfoFacs 64208625Sjkim * 65208625Sjkim *****************************************************************************/ 66208625Sjkim 67208625Sjkimvoid 68208625SjkimDtCreateSubtable ( 69208625Sjkim UINT8 *Buffer, 70208625Sjkim UINT32 Length, 71208625Sjkim DT_SUBTABLE **RetSubtable) 72208625Sjkim{ 73208625Sjkim DT_SUBTABLE *Subtable; 74281075Sdim char *String; 75208625Sjkim 76208625Sjkim 77281075Sdim Subtable = UtSubtableCacheCalloc (); 78208625Sjkim 79208625Sjkim /* Create a new buffer for the subtable data */ 80208625Sjkim 81281075Sdim String = UtStringCacheCalloc (Length); 82281075Sdim Subtable->Buffer = ACPI_CAST_PTR (UINT8, String); 83306536Sjkim 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; 115245582Sjkim Subtable->Depth = ParentTable->Depth + 1; 116208625Sjkim 117208625Sjkim /* Link the new entry into the child list */ 118208625Sjkim 119208625Sjkim if (!ParentTable->Child) 120208625Sjkim { 121208625Sjkim ParentTable->Child = Subtable; 122208625Sjkim } 123208625Sjkim else 124208625Sjkim { 125208625Sjkim /* Walk to the end of the child list */ 126208625Sjkim 127208625Sjkim ChildTable = ParentTable->Child; 128208625Sjkim while (ChildTable->Peer) 129208625Sjkim { 130208625Sjkim ChildTable = ChildTable->Peer; 131208625Sjkim } 132208625Sjkim 133208625Sjkim /* Add new subtable at the end of the child list */ 134208625Sjkim 135208625Sjkim ChildTable->Peer = Subtable; 136208625Sjkim } 137208625Sjkim} 138208625Sjkim 139208625Sjkim 140208625Sjkim/****************************************************************************** 141208625Sjkim * 142208625Sjkim * FUNCTION: DtPushSubtable 143208625Sjkim * 144208625Sjkim * PARAMETERS: Subtable - Subtable to push 145208625Sjkim * 146208625Sjkim * RETURN: None 147208625Sjkim * 148208625Sjkim * DESCRIPTION: Push a subtable onto a subtable stack 149208625Sjkim * 150208625Sjkim *****************************************************************************/ 151208625Sjkim 152208625Sjkimvoid 153208625SjkimDtPushSubtable ( 154208625Sjkim DT_SUBTABLE *Subtable) 155208625Sjkim{ 156208625Sjkim 157208625Sjkim Subtable->StackTop = Gbl_SubtableStack; 158208625Sjkim Gbl_SubtableStack = Subtable; 159208625Sjkim} 160208625Sjkim 161208625Sjkim 162208625Sjkim/****************************************************************************** 163208625Sjkim * 164208625Sjkim * FUNCTION: DtPopSubtable 165208625Sjkim * 166208625Sjkim * PARAMETERS: None 167208625Sjkim * 168208625Sjkim * RETURN: None 169208625Sjkim * 170208625Sjkim * DESCRIPTION: Pop a subtable from a subtable stack. Uses global SubtableStack 171208625Sjkim * 172208625Sjkim *****************************************************************************/ 173208625Sjkim 174208625Sjkimvoid 175208625SjkimDtPopSubtable ( 176208625Sjkim void) 177208625Sjkim{ 178208625Sjkim DT_SUBTABLE *Subtable; 179208625Sjkim 180208625Sjkim 181208625Sjkim Subtable = Gbl_SubtableStack; 182208625Sjkim 183208625Sjkim if (Subtable) 184208625Sjkim { 185208625Sjkim Gbl_SubtableStack = Subtable->StackTop; 186208625Sjkim } 187208625Sjkim} 188208625Sjkim 189208625Sjkim 190208625Sjkim/****************************************************************************** 191208625Sjkim * 192208625Sjkim * FUNCTION: DtPeekSubtable 193208625Sjkim * 194208625Sjkim * PARAMETERS: None 195208625Sjkim * 196208625Sjkim * RETURN: The subtable on top of stack 197208625Sjkim * 198208625Sjkim * DESCRIPTION: Get the subtable on top of stack 199208625Sjkim * 200208625Sjkim *****************************************************************************/ 201208625Sjkim 202208625SjkimDT_SUBTABLE * 203208625SjkimDtPeekSubtable ( 204208625Sjkim void) 205208625Sjkim{ 206208625Sjkim 207208625Sjkim return (Gbl_SubtableStack); 208208625Sjkim} 209208625Sjkim 210208625Sjkim 211208625Sjkim/****************************************************************************** 212208625Sjkim * 213208625Sjkim * FUNCTION: DtGetNextSubtable 214208625Sjkim * 215208625Sjkim * PARAMETERS: ParentTable - Parent table whose children we are 216208625Sjkim * getting 217208625Sjkim * ChildTable - Previous child that was found. 218208625Sjkim * The NEXT child will be returned 219208625Sjkim * 220208625Sjkim * RETURN: Pointer to the NEXT child or NULL if none is found. 221208625Sjkim * 222208625Sjkim * DESCRIPTION: Return the next peer subtable within the tree. 223208625Sjkim * 224208625Sjkim *****************************************************************************/ 225208625Sjkim 226208625SjkimDT_SUBTABLE * 227208625SjkimDtGetNextSubtable ( 228208625Sjkim DT_SUBTABLE *ParentTable, 229208625Sjkim DT_SUBTABLE *ChildTable) 230208625Sjkim{ 231208625Sjkim ACPI_FUNCTION_ENTRY (); 232208625Sjkim 233208625Sjkim 234208625Sjkim if (!ChildTable) 235208625Sjkim { 236208625Sjkim /* It's really the parent's _scope_ that we want */ 237208625Sjkim 238208625Sjkim return (ParentTable->Child); 239208625Sjkim } 240208625Sjkim 241208625Sjkim /* Otherwise just return the next peer (NULL if at end-of-list) */ 242208625Sjkim 243208625Sjkim return (ChildTable->Peer); 244208625Sjkim} 245208625Sjkim 246208625Sjkim 247208625Sjkim/****************************************************************************** 248208625Sjkim * 249208625Sjkim * FUNCTION: DtGetParentSubtable 250208625Sjkim * 251208625Sjkim * PARAMETERS: Subtable - Current subtable 252208625Sjkim * 253208625Sjkim * RETURN: Parent of the given subtable 254208625Sjkim * 255208625Sjkim * DESCRIPTION: Get the parent of the given subtable in the tree 256208625Sjkim * 257208625Sjkim *****************************************************************************/ 258208625Sjkim 259208625SjkimDT_SUBTABLE * 260208625SjkimDtGetParentSubtable ( 261208625Sjkim DT_SUBTABLE *Subtable) 262208625Sjkim{ 263208625Sjkim 264208625Sjkim if (!Subtable) 265208625Sjkim { 266208625Sjkim return (NULL); 267208625Sjkim } 268208625Sjkim 269208625Sjkim return (Subtable->Parent); 270208625Sjkim} 271208625Sjkim 272208625Sjkim 273208625Sjkim/****************************************************************************** 274208625Sjkim * 275208625Sjkim * FUNCTION: DtGetSubtableLength 276208625Sjkim * 277208625Sjkim * PARAMETERS: Field - Current field list pointer 278208625Sjkim * Info - Data table info 279208625Sjkim * 280208625Sjkim * RETURN: Subtable length 281208625Sjkim * 282208625Sjkim * DESCRIPTION: Get length of bytes needed to compile the subtable 283208625Sjkim * 284208625Sjkim *****************************************************************************/ 285208625Sjkim 286208625SjkimUINT32 287208625SjkimDtGetSubtableLength ( 288208625Sjkim DT_FIELD *Field, 289208625Sjkim ACPI_DMTABLE_INFO *Info) 290208625Sjkim{ 291208625Sjkim UINT32 ByteLength = 0; 292220663Sjkim UINT8 Step; 293220663Sjkim UINT8 i; 294208625Sjkim 295208625Sjkim 296208625Sjkim /* Walk entire Info table; Null name terminates */ 297208625Sjkim 298208625Sjkim for (; Info->Name; Info++) 299208625Sjkim { 300228110Sjkim if (Info->Opcode == ACPI_DMT_EXTRA_TEXT) 301228110Sjkim { 302228110Sjkim continue; 303228110Sjkim } 304228110Sjkim 305220663Sjkim if (!Field) 306220663Sjkim { 307220663Sjkim goto Error; 308220663Sjkim } 309220663Sjkim 310208625Sjkim ByteLength += DtGetFieldLength (Field, Info); 311220663Sjkim 312220663Sjkim switch (Info->Opcode) 313220663Sjkim { 314220663Sjkim case ACPI_DMT_GAS: 315250838Sjkim 316220663Sjkim Step = 5; 317220663Sjkim break; 318220663Sjkim 319220663Sjkim case ACPI_DMT_HESTNTFY: 320250838Sjkim 321220663Sjkim Step = 9; 322220663Sjkim break; 323220663Sjkim 324284460Sjkim case ACPI_DMT_IORTMEM: 325284460Sjkim 326284460Sjkim Step = 10; 327284460Sjkim break; 328284460Sjkim 329220663Sjkim default: 330250838Sjkim 331220663Sjkim Step = 1; 332220663Sjkim break; 333220663Sjkim } 334220663Sjkim 335220663Sjkim for (i = 0; i < Step; i++) 336220663Sjkim { 337220663Sjkim if (!Field) 338220663Sjkim { 339220663Sjkim goto Error; 340220663Sjkim } 341220663Sjkim 342220663Sjkim Field = Field->Next; 343220663Sjkim } 344208625Sjkim } 345208625Sjkim 346208625Sjkim return (ByteLength); 347220663Sjkim 348220663SjkimError: 349220663Sjkim if (!Field) 350220663Sjkim { 351220663Sjkim sprintf (MsgBuffer, "Found NULL field - Field name \"%s\" needed", 352220663Sjkim Info->Name); 353220663Sjkim DtFatal (ASL_MSG_COMPILER_INTERNAL, NULL, MsgBuffer); 354220663Sjkim } 355220663Sjkim 356220663Sjkim return (ASL_EOF); 357208625Sjkim} 358208625Sjkim 359208625Sjkim 360208625Sjkim/****************************************************************************** 361208625Sjkim * 362208625Sjkim * FUNCTION: DtSetSubtableLength 363208625Sjkim * 364208625Sjkim * PARAMETERS: Subtable - Subtable 365208625Sjkim * 366208625Sjkim * RETURN: None 367208625Sjkim * 368208625Sjkim * DESCRIPTION: Set length of the subtable into its length field 369208625Sjkim * 370208625Sjkim *****************************************************************************/ 371208625Sjkim 372208625Sjkimvoid 373208625SjkimDtSetSubtableLength ( 374208625Sjkim DT_SUBTABLE *Subtable) 375208625Sjkim{ 376208625Sjkim 377208625Sjkim if (!Subtable->LengthField) 378208625Sjkim { 379208625Sjkim return; 380208625Sjkim } 381208625Sjkim 382306536Sjkim memcpy (Subtable->LengthField, &Subtable->TotalLength, 383208625Sjkim Subtable->SizeOfLengthField); 384208625Sjkim} 385