1/****************************************************************************** 2 * 3 * Module Name: dtsubtable.c - handling of subtables within ACPI tables 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#include "aslcompiler.h" 45 46#define _COMPONENT DT_COMPILER 47 ACPI_MODULE_NAME ("dtsubtable") 48 49 50/****************************************************************************** 51 * 52 * FUNCTION: DtCreateSubtable 53 * 54 * PARAMETERS: Buffer - Input buffer 55 * Length - Buffer length 56 * RetSubtable - Returned newly created subtable 57 * 58 * RETURN: None 59 * 60 * DESCRIPTION: Create a subtable that is not listed with ACPI_DMTABLE_INFO 61 * For example, FACS has 24 bytes reserved at the end 62 * and it's not listed at AcpiDmTableInfoFacs 63 * 64 *****************************************************************************/ 65 66void 67DtCreateSubtable ( 68 UINT8 *Buffer, 69 UINT32 Length, 70 DT_SUBTABLE **RetSubtable) 71{ 72 DT_SUBTABLE *Subtable; 73 char *String; 74 75 76 Subtable = UtSubtableCacheCalloc (); 77 78 /* Create a new buffer for the subtable data */ 79 80 String = UtLocalCacheCalloc (Length); 81 Subtable->Buffer = ACPI_CAST_PTR (UINT8, String); 82 memcpy (Subtable->Buffer, Buffer, Length); 83 84 Subtable->Length = Length; 85 Subtable->TotalLength = Length; 86 87 *RetSubtable = Subtable; 88} 89 90 91/****************************************************************************** 92 * 93 * FUNCTION: DtInsertSubtable 94 * 95 * PARAMETERS: ParentTable - The Parent of the new subtable 96 * Subtable - The new subtable to insert 97 * 98 * RETURN: None 99 * 100 * DESCRIPTION: Insert the new subtable to the parent table 101 * 102 *****************************************************************************/ 103 104void 105DtInsertSubtable ( 106 DT_SUBTABLE *ParentTable, 107 DT_SUBTABLE *Subtable) 108{ 109 DT_SUBTABLE *ChildTable; 110 111 112 Subtable->Peer = NULL; 113 Subtable->Parent = ParentTable; 114 Subtable->Depth = ParentTable->Depth + 1; 115 116 /* Link the new entry into the child list */ 117 118 if (!ParentTable->Child) 119 { 120 ParentTable->Child = Subtable; 121 } 122 else 123 { 124 /* Walk to the end of the child list */ 125 126 ChildTable = ParentTable->Child; 127 while (ChildTable->Peer) 128 { 129 ChildTable = ChildTable->Peer; 130 } 131 132 /* Add new subtable at the end of the child list */ 133 134 ChildTable->Peer = Subtable; 135 } 136} 137 138 139/****************************************************************************** 140 * 141 * FUNCTION: DtPushSubtable 142 * 143 * PARAMETERS: Subtable - Subtable to push 144 * 145 * RETURN: None 146 * 147 * DESCRIPTION: Push a subtable onto a subtable stack 148 * 149 *****************************************************************************/ 150 151void 152DtPushSubtable ( 153 DT_SUBTABLE *Subtable) 154{ 155 156 Subtable->StackTop = AslGbl_SubtableStack; 157 AslGbl_SubtableStack = Subtable; 158} 159 160 161/****************************************************************************** 162 * 163 * FUNCTION: DtPopSubtable 164 * 165 * PARAMETERS: None 166 * 167 * RETURN: None 168 * 169 * DESCRIPTION: Pop a subtable from a subtable stack. Uses global SubtableStack 170 * 171 *****************************************************************************/ 172 173void 174DtPopSubtable ( 175 void) 176{ 177 DT_SUBTABLE *Subtable; 178 179 180 Subtable = AslGbl_SubtableStack; 181 182 if (Subtable) 183 { 184 AslGbl_SubtableStack = Subtable->StackTop; 185 } 186} 187 188 189/****************************************************************************** 190 * 191 * FUNCTION: DtPeekSubtable 192 * 193 * PARAMETERS: None 194 * 195 * RETURN: The subtable on top of stack 196 * 197 * DESCRIPTION: Get the subtable on top of stack 198 * 199 *****************************************************************************/ 200 201DT_SUBTABLE * 202DtPeekSubtable ( 203 void) 204{ 205 206 return (AslGbl_SubtableStack); 207} 208 209 210/****************************************************************************** 211 * 212 * FUNCTION: DtGetNextSubtable 213 * 214 * PARAMETERS: ParentTable - Parent table whose children we are 215 * getting 216 * ChildTable - Previous child that was found. 217 * The NEXT child will be returned 218 * 219 * RETURN: Pointer to the NEXT child or NULL if none is found. 220 * 221 * DESCRIPTION: Return the next peer subtable within the tree. 222 * 223 *****************************************************************************/ 224 225DT_SUBTABLE * 226DtGetNextSubtable ( 227 DT_SUBTABLE *ParentTable, 228 DT_SUBTABLE *ChildTable) 229{ 230 ACPI_FUNCTION_ENTRY (); 231 232 233 if (!ChildTable) 234 { 235 /* It's really the parent's _scope_ that we want */ 236 237 return (ParentTable->Child); 238 } 239 240 /* Otherwise just return the next peer (NULL if at end-of-list) */ 241 242 return (ChildTable->Peer); 243} 244 245 246/****************************************************************************** 247 * 248 * FUNCTION: DtGetParentSubtable 249 * 250 * PARAMETERS: Subtable - Current subtable 251 * 252 * RETURN: Parent of the given subtable 253 * 254 * DESCRIPTION: Get the parent of the given subtable in the tree 255 * 256 *****************************************************************************/ 257 258DT_SUBTABLE * 259DtGetParentSubtable ( 260 DT_SUBTABLE *Subtable) 261{ 262 263 if (!Subtable) 264 { 265 return (NULL); 266 } 267 268 return (Subtable->Parent); 269} 270 271 272/****************************************************************************** 273 * 274 * FUNCTION: DtGetSubtableLength 275 * 276 * PARAMETERS: Field - Current field list pointer 277 * Info - Data table info 278 * 279 * RETURN: Subtable length 280 * 281 * DESCRIPTION: Get length of bytes needed to compile the subtable 282 * 283 *****************************************************************************/ 284 285UINT32 286DtGetSubtableLength ( 287 DT_FIELD *Field, 288 ACPI_DMTABLE_INFO *Info) 289{ 290 UINT32 ByteLength = 0; 291 UINT8 Step; 292 UINT8 i; 293 294 295 /* Walk entire Info table; Null name terminates */ 296 297 for (; Info->Name; Info++) 298 { 299 if (Info->Opcode == ACPI_DMT_EXTRA_TEXT) 300 { 301 continue; 302 } 303 304 if (!Field) 305 { 306 goto Error; 307 } 308 309 ByteLength += DtGetFieldLength (Field, Info); 310 311 switch (Info->Opcode) 312 { 313 case ACPI_DMT_GAS: 314 315 Step = 5; 316 break; 317 318 case ACPI_DMT_HESTNTFY: 319 320 Step = 9; 321 break; 322 323 case ACPI_DMT_IORTMEM: 324 325 Step = 10; 326 break; 327 328 default: 329 330 Step = 1; 331 break; 332 } 333 334 for (i = 0; i < Step; i++) 335 { 336 if (!Field) 337 { 338 goto Error; 339 } 340 341 Field = Field->Next; 342 } 343 } 344 345 return (ByteLength); 346 347Error: 348 if (!Field) 349 { 350 snprintf (AslGbl_MsgBuffer, sizeof(AslGbl_MsgBuffer), "Found NULL field - Field name \"%s\" needed", 351 Info->Name); 352 DtFatal (ASL_MSG_COMPILER_INTERNAL, NULL, AslGbl_MsgBuffer); 353 } 354 355 return (ASL_EOF); 356} 357 358 359/****************************************************************************** 360 * 361 * FUNCTION: DtSetSubtableLength 362 * 363 * PARAMETERS: Subtable - Subtable 364 * 365 * RETURN: None 366 * 367 * DESCRIPTION: Set length of the subtable into its length field 368 * 369 *****************************************************************************/ 370 371void 372DtSetSubtableLength ( 373 DT_SUBTABLE *Subtable) 374{ 375 376 if (!Subtable->LengthField) 377 { 378 return; 379 } 380 381 memcpy (Subtable->LengthField, &Subtable->TotalLength, 382 Subtable->SizeOfLengthField); 383} 384