1 /****************************************************************************** 2 * 3 * Module Name: dtsubtable.c - handling of subtables within ACPI tables 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2011, 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 77 78 Subtable = UtLocalCalloc (sizeof (DT_SUBTABLE)); 79 80 /* Create a new buffer for the subtable data */ 81 82 Subtable->Buffer = UtLocalCalloc (Length); 83 ACPI_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 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 151 void 152 DtPushSubtable ( 153 DT_SUBTABLE *Subtable) 154 { 155 156 Subtable->StackTop = Gbl_SubtableStack; 157 Gbl_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 173 void 174 DtPopSubtable ( 175 void) 176 { 177 DT_SUBTABLE *Subtable; 178 179 180 Subtable = Gbl_SubtableStack; 181 182 if (Subtable) 183 { 184 Gbl_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 201 DT_SUBTABLE * 202 DtPeekSubtable ( 203 void) 204 { 205 206 return (Gbl_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 225 DT_SUBTABLE * 226 DtGetNextSubtable ( 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 258 DT_SUBTABLE * 259 DtGetParentSubtable ( 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 285 UINT32 286 DtGetSubtableLength ( 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 (!Field) 300 { 301 goto Error; 302 } 303 304 ByteLength += DtGetFieldLength (Field, Info); 305 306 switch (Info->Opcode) 307 { 308 case ACPI_DMT_GAS: 309 Step = 5; 310 break; 311 312 case ACPI_DMT_HESTNTFY: 313 Step = 9; 314 break; 315 316 default: 317 Step = 1; 318 break; 319 } 320 321 for (i = 0; i < Step; i++) 322 { 323 if (!Field) 324 { 325 goto Error; 326 } 327 328 Field = Field->Next; 329 } 330 } 331 332 return (ByteLength); 333 334 Error: 335 if (!Field) 336 { 337 sprintf (MsgBuffer, "Found NULL field - Field name \"%s\" needed", 338 Info->Name); 339 DtFatal (ASL_MSG_COMPILER_INTERNAL, NULL, MsgBuffer); 340 } 341 342 return (ASL_EOF); 343 } 344 345 346 /****************************************************************************** 347 * 348 * FUNCTION: DtSetSubtableLength 349 * 350 * PARAMETERS: Subtable - Subtable 351 * 352 * RETURN: None 353 * 354 * DESCRIPTION: Set length of the subtable into its length field 355 * 356 *****************************************************************************/ 357 358 void 359 DtSetSubtableLength ( 360 DT_SUBTABLE *Subtable) 361 { 362 363 if (!Subtable->LengthField) 364 { 365 return; 366 } 367 368 ACPI_MEMCPY (Subtable->LengthField, &Subtable->TotalLength, 369 Subtable->SizeOfLengthField); 370 } 371