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