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