1 /****************************************************************************** 2 * 3 * Module Name: exdump - Interpreter debug output routines 4 * 5 *****************************************************************************/ 6 7 /****************************************************************************** 8 * 9 * 1. Copyright Notice 10 * 11 * Some or all of this work - Copyright (c) 1999 - 2013, Intel Corp. 12 * All rights reserved. 13 * 14 * 2. License 15 * 16 * 2.1. This is your license from Intel Corp. under its intellectual property 17 * rights. You may have additional license terms from the party that provided 18 * you this software, covering your right to use that party's intellectual 19 * property rights. 20 * 21 * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a 22 * copy of the source code appearing in this file ("Covered Code") an 23 * irrevocable, perpetual, worldwide license under Intel's copyrights in the 24 * base code distributed originally by Intel ("Original Intel Code") to copy, 25 * make derivatives, distribute, use and display any portion of the Covered 26 * Code in any form, with the right to sublicense such rights; and 27 * 28 * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent 29 * license (with the right to sublicense), under only those claims of Intel 30 * patents that are infringed by the Original Intel Code, to make, use, sell, 31 * offer to sell, and import the Covered Code and derivative works thereof 32 * solely to the minimum extent necessary to exercise the above copyright 33 * license, and in no event shall the patent license extend to any additions 34 * to or modifications of the Original Intel Code. No other license or right 35 * is granted directly or by implication, estoppel or otherwise; 36 * 37 * The above copyright and patent license is granted only if the following 38 * conditions are met: 39 * 40 * 3. Conditions 41 * 42 * 3.1. Redistribution of Source with Rights to Further Distribute Source. 43 * Redistribution of source code of any substantial portion of the Covered 44 * Code or modification with rights to further distribute source must include 45 * the above Copyright Notice, the above License, this list of Conditions, 46 * and the following Disclaimer and Export Compliance provision. In addition, 47 * Licensee must cause all Covered Code to which Licensee contributes to 48 * contain a file documenting the changes Licensee made to create that Covered 49 * Code and the date of any change. Licensee must include in that file the 50 * documentation of any changes made by any predecessor Licensee. Licensee 51 * must include a prominent statement that the modification is derived, 52 * directly or indirectly, from Original Intel Code. 53 * 54 * 3.2. Redistribution of Source with no Rights to Further Distribute Source. 55 * Redistribution of source code of any substantial portion of the Covered 56 * Code or modification without rights to further distribute source must 57 * include the following Disclaimer and Export Compliance provision in the 58 * documentation and/or other materials provided with distribution. In 59 * addition, Licensee may not authorize further sublicense of source of any 60 * portion of the Covered Code, and must include terms to the effect that the 61 * license from Licensee to its licensee is limited to the intellectual 62 * property embodied in the software Licensee provides to its licensee, and 63 * not to intellectual property embodied in modifications its licensee may 64 * make. 65 * 66 * 3.3. Redistribution of Executable. Redistribution in executable form of any 67 * substantial portion of the Covered Code or modification must reproduce the 68 * above Copyright Notice, and the following Disclaimer and Export Compliance 69 * provision in the documentation and/or other materials provided with the 70 * distribution. 71 * 72 * 3.4. Intel retains all right, title, and interest in and to the Original 73 * Intel Code. 74 * 75 * 3.5. Neither the name Intel nor any other trademark owned or controlled by 76 * Intel shall be used in advertising or otherwise to promote the sale, use or 77 * other dealings in products derived from or relating to the Covered Code 78 * without prior written authorization from Intel. 79 * 80 * 4. Disclaimer and Export Compliance 81 * 82 * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED 83 * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE 84 * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, 85 * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY 86 * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY 87 * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A 88 * PARTICULAR PURPOSE. 89 * 90 * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES 91 * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR 92 * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT, 93 * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY 94 * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL 95 * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS 96 * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY 97 * LIMITED REMEDY. 98 * 99 * 4.3. Licensee shall not export, either directly or indirectly, any of this 100 * software or system incorporating such software without first obtaining any 101 * required license or other approval from the U. S. Department of Commerce or 102 * any other agency or department of the United States Government. In the 103 * event Licensee exports any such software from the United States or 104 * re-exports any such software from a foreign destination, Licensee shall 105 * ensure that the distribution and export/re-export of the software is in 106 * compliance with all laws, regulations, orders, or other restrictions of the 107 * U.S. Export Administration Regulations. Licensee agrees that neither it nor 108 * any of its subsidiaries will export/re-export any technical data, process, 109 * software, or service, directly or indirectly, to any country for which the 110 * United States government or any agency thereof requires an export license, 111 * other governmental approval, or letter of assurance, without first obtaining 112 * such license, approval or letter. 113 * 114 *****************************************************************************/ 115 116 #define __EXDUMP_C__ 117 118 #include "acpi.h" 119 #include "accommon.h" 120 #include "acinterp.h" 121 #include "amlcode.h" 122 #include "acnamesp.h" 123 124 125 #define _COMPONENT ACPI_EXECUTER 126 ACPI_MODULE_NAME ("exdump") 127 128 /* 129 * The following routines are used for debug output only 130 */ 131 #if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER) 132 133 /* Local prototypes */ 134 135 static void 136 AcpiExOutString ( 137 char *Title, 138 char *Value); 139 140 static void 141 AcpiExOutPointer ( 142 char *Title, 143 void *Value); 144 145 static void 146 AcpiExDumpObject ( 147 ACPI_OPERAND_OBJECT *ObjDesc, 148 ACPI_EXDUMP_INFO *Info); 149 150 static void 151 AcpiExDumpReferenceObj ( 152 ACPI_OPERAND_OBJECT *ObjDesc); 153 154 static void 155 AcpiExDumpPackageObj ( 156 ACPI_OPERAND_OBJECT *ObjDesc, 157 UINT32 Level, 158 UINT32 Index); 159 160 161 /******************************************************************************* 162 * 163 * Object Descriptor info tables 164 * 165 * Note: The first table entry must be an INIT opcode and must contain 166 * the table length (number of table entries) 167 * 168 ******************************************************************************/ 169 170 static ACPI_EXDUMP_INFO AcpiExDumpInteger[2] = 171 { 172 {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE (AcpiExDumpInteger), NULL}, 173 {ACPI_EXD_UINT64, ACPI_EXD_OFFSET (Integer.Value), "Value"} 174 }; 175 176 static ACPI_EXDUMP_INFO AcpiExDumpString[4] = 177 { 178 {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE (AcpiExDumpString), NULL}, 179 {ACPI_EXD_UINT32, ACPI_EXD_OFFSET (String.Length), "Length"}, 180 {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (String.Pointer), "Pointer"}, 181 {ACPI_EXD_STRING, 0, NULL} 182 }; 183 184 static ACPI_EXDUMP_INFO AcpiExDumpBuffer[5] = 185 { 186 {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE (AcpiExDumpBuffer), NULL}, 187 {ACPI_EXD_UINT32, ACPI_EXD_OFFSET (Buffer.Length), "Length"}, 188 {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (Buffer.Pointer), "Pointer"}, 189 {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (Buffer.Node), "Parent Node"}, 190 {ACPI_EXD_BUFFER, 0, NULL} 191 }; 192 193 static ACPI_EXDUMP_INFO AcpiExDumpPackage[5] = 194 { 195 {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE (AcpiExDumpPackage), NULL}, 196 {ACPI_EXD_UINT8, ACPI_EXD_OFFSET (Package.Flags), "Flags"}, 197 {ACPI_EXD_UINT32, ACPI_EXD_OFFSET (Package.Count), "Elements"}, 198 {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (Package.Elements), "Element List"}, 199 {ACPI_EXD_PACKAGE, 0, NULL} 200 }; 201 202 static ACPI_EXDUMP_INFO AcpiExDumpDevice[4] = 203 { 204 {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE (AcpiExDumpDevice), NULL}, 205 {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (Device.Handler), "Handler"}, 206 {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (Device.NotifyList[0]), "System Notify"}, 207 {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (Device.NotifyList[1]), "Device Notify"} 208 }; 209 210 static ACPI_EXDUMP_INFO AcpiExDumpEvent[2] = 211 { 212 {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE (AcpiExDumpEvent), NULL}, 213 {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (Event.OsSemaphore), "OsSemaphore"} 214 }; 215 216 static ACPI_EXDUMP_INFO AcpiExDumpMethod[9] = 217 { 218 {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE (AcpiExDumpMethod), NULL}, 219 {ACPI_EXD_UINT8, ACPI_EXD_OFFSET (Method.InfoFlags), "Info Flags"}, 220 {ACPI_EXD_UINT8, ACPI_EXD_OFFSET (Method.ParamCount), "Parameter Count"}, 221 {ACPI_EXD_UINT8, ACPI_EXD_OFFSET (Method.SyncLevel), "Sync Level"}, 222 {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (Method.Mutex), "Mutex"}, 223 {ACPI_EXD_UINT8, ACPI_EXD_OFFSET (Method.OwnerId), "Owner Id"}, 224 {ACPI_EXD_UINT8, ACPI_EXD_OFFSET (Method.ThreadCount), "Thread Count"}, 225 {ACPI_EXD_UINT32, ACPI_EXD_OFFSET (Method.AmlLength), "Aml Length"}, 226 {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (Method.AmlStart), "Aml Start"} 227 }; 228 229 static ACPI_EXDUMP_INFO AcpiExDumpMutex[5] = 230 { 231 {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE (AcpiExDumpMutex), NULL}, 232 {ACPI_EXD_UINT8, ACPI_EXD_OFFSET (Mutex.SyncLevel), "Sync Level"}, 233 {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (Mutex.OwnerThread), "Owner Thread"}, 234 {ACPI_EXD_UINT16, ACPI_EXD_OFFSET (Mutex.AcquisitionDepth), "Acquire Depth"}, 235 {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (Mutex.OsMutex), "OsMutex"} 236 }; 237 238 static ACPI_EXDUMP_INFO AcpiExDumpRegion[7] = 239 { 240 {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE (AcpiExDumpRegion), NULL}, 241 {ACPI_EXD_UINT8, ACPI_EXD_OFFSET (Region.SpaceId), "Space Id"}, 242 {ACPI_EXD_UINT8, ACPI_EXD_OFFSET (Region.Flags), "Flags"}, 243 {ACPI_EXD_ADDRESS, ACPI_EXD_OFFSET (Region.Address), "Address"}, 244 {ACPI_EXD_UINT32, ACPI_EXD_OFFSET (Region.Length), "Length"}, 245 {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (Region.Handler), "Handler"}, 246 {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (Region.Next), "Next"} 247 }; 248 249 static ACPI_EXDUMP_INFO AcpiExDumpPower[5] = 250 { 251 {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE (AcpiExDumpPower), NULL}, 252 {ACPI_EXD_UINT32, ACPI_EXD_OFFSET (PowerResource.SystemLevel), "System Level"}, 253 {ACPI_EXD_UINT32, ACPI_EXD_OFFSET (PowerResource.ResourceOrder), "Resource Order"}, 254 {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (PowerResource.NotifyList[0]), "System Notify"}, 255 {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (PowerResource.NotifyList[1]), "Device Notify"} 256 }; 257 258 static ACPI_EXDUMP_INFO AcpiExDumpProcessor[7] = 259 { 260 {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE (AcpiExDumpProcessor), NULL}, 261 {ACPI_EXD_UINT8, ACPI_EXD_OFFSET (Processor.ProcId), "Processor ID"}, 262 {ACPI_EXD_UINT8 , ACPI_EXD_OFFSET (Processor.Length), "Length"}, 263 {ACPI_EXD_ADDRESS, ACPI_EXD_OFFSET (Processor.Address), "Address"}, 264 {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (Processor.NotifyList[0]), "System Notify"}, 265 {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (Processor.NotifyList[1]), "Device Notify"}, 266 {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (Processor.Handler), "Handler"} 267 }; 268 269 static ACPI_EXDUMP_INFO AcpiExDumpThermal[4] = 270 { 271 {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE (AcpiExDumpThermal), NULL}, 272 {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (ThermalZone.NotifyList[0]), "System Notify"}, 273 {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (ThermalZone.NotifyList[1]), "Device Notify"}, 274 {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (ThermalZone.Handler), "Handler"} 275 }; 276 277 static ACPI_EXDUMP_INFO AcpiExDumpBufferField[3] = 278 { 279 {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE (AcpiExDumpBufferField), NULL}, 280 {ACPI_EXD_FIELD, 0, NULL}, 281 {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (BufferField.BufferObj), "Buffer Object"} 282 }; 283 284 static ACPI_EXDUMP_INFO AcpiExDumpRegionField[5] = 285 { 286 {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE (AcpiExDumpRegionField), NULL}, 287 {ACPI_EXD_FIELD, 0, NULL}, 288 {ACPI_EXD_UINT8, ACPI_EXD_OFFSET (Field.AccessLength), "AccessLength"}, 289 {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (Field.RegionObj), "Region Object"}, 290 {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (Field.ResourceBuffer), "ResourceBuffer"} 291 }; 292 293 static ACPI_EXDUMP_INFO AcpiExDumpBankField[5] = 294 { 295 {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE (AcpiExDumpBankField), NULL}, 296 {ACPI_EXD_FIELD, 0, NULL}, 297 {ACPI_EXD_UINT32, ACPI_EXD_OFFSET (BankField.Value), "Value"}, 298 {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (BankField.RegionObj), "Region Object"}, 299 {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (BankField.BankObj), "Bank Object"} 300 }; 301 302 static ACPI_EXDUMP_INFO AcpiExDumpIndexField[5] = 303 { 304 {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE (AcpiExDumpBankField), NULL}, 305 {ACPI_EXD_FIELD, 0, NULL}, 306 {ACPI_EXD_UINT32, ACPI_EXD_OFFSET (IndexField.Value), "Value"}, 307 {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (IndexField.IndexObj), "Index Object"}, 308 {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (IndexField.DataObj), "Data Object"} 309 }; 310 311 static ACPI_EXDUMP_INFO AcpiExDumpReference[8] = 312 { 313 {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE (AcpiExDumpReference), NULL}, 314 {ACPI_EXD_UINT8, ACPI_EXD_OFFSET (Reference.Class), "Class"}, 315 {ACPI_EXD_UINT8, ACPI_EXD_OFFSET (Reference.TargetType), "Target Type"}, 316 {ACPI_EXD_UINT32, ACPI_EXD_OFFSET (Reference.Value), "Value"}, 317 {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (Reference.Object), "Object Desc"}, 318 {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (Reference.Node), "Node"}, 319 {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (Reference.Where), "Where"}, 320 {ACPI_EXD_REFERENCE,0, NULL} 321 }; 322 323 static ACPI_EXDUMP_INFO AcpiExDumpAddressHandler[6] = 324 { 325 {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE (AcpiExDumpAddressHandler), NULL}, 326 {ACPI_EXD_UINT8, ACPI_EXD_OFFSET (AddressSpace.SpaceId), "Space Id"}, 327 {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (AddressSpace.Next), "Next"}, 328 {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (AddressSpace.RegionList), "Region List"}, 329 {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (AddressSpace.Node), "Node"}, 330 {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (AddressSpace.Context), "Context"} 331 }; 332 333 static ACPI_EXDUMP_INFO AcpiExDumpNotify[7] = 334 { 335 {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE (AcpiExDumpNotify), NULL}, 336 {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (Notify.Node), "Node"}, 337 {ACPI_EXD_UINT32, ACPI_EXD_OFFSET (Notify.HandlerType), "Handler Type"}, 338 {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (Notify.Handler), "Handler"}, 339 {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (Notify.Context), "Context"}, 340 {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (Notify.Next[0]), "Next System Notify"}, 341 {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (Notify.Next[1]), "Next Device Notify"} 342 }; 343 344 345 /* Miscellaneous tables */ 346 347 static ACPI_EXDUMP_INFO AcpiExDumpCommon[4] = 348 { 349 {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE (AcpiExDumpCommon), NULL}, 350 {ACPI_EXD_TYPE , 0, NULL}, 351 {ACPI_EXD_UINT16, ACPI_EXD_OFFSET (Common.ReferenceCount), "Reference Count"}, 352 {ACPI_EXD_UINT8, ACPI_EXD_OFFSET (Common.Flags), "Flags"} 353 }; 354 355 static ACPI_EXDUMP_INFO AcpiExDumpFieldCommon[7] = 356 { 357 {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE (AcpiExDumpFieldCommon), NULL}, 358 {ACPI_EXD_UINT8, ACPI_EXD_OFFSET (CommonField.FieldFlags), "Field Flags"}, 359 {ACPI_EXD_UINT8, ACPI_EXD_OFFSET (CommonField.AccessByteWidth), "Access Byte Width"}, 360 {ACPI_EXD_UINT32, ACPI_EXD_OFFSET (CommonField.BitLength), "Bit Length"}, 361 {ACPI_EXD_UINT8, ACPI_EXD_OFFSET (CommonField.StartFieldBitOffset),"Field Bit Offset"}, 362 {ACPI_EXD_UINT32, ACPI_EXD_OFFSET (CommonField.BaseByteOffset), "Base Byte Offset"}, 363 {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (CommonField.Node), "Parent Node"} 364 }; 365 366 static ACPI_EXDUMP_INFO AcpiExDumpNode[5] = 367 { 368 {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE (AcpiExDumpNode), NULL}, 369 {ACPI_EXD_UINT8, ACPI_EXD_NSOFFSET (Flags), "Flags"}, 370 {ACPI_EXD_UINT8, ACPI_EXD_NSOFFSET (OwnerId), "Owner Id"}, 371 {ACPI_EXD_POINTER, ACPI_EXD_NSOFFSET (Child), "Child List"}, 372 {ACPI_EXD_POINTER, ACPI_EXD_NSOFFSET (Peer), "Next Peer"} 373 }; 374 375 376 /* Dispatch table, indexed by object type */ 377 378 static ACPI_EXDUMP_INFO *AcpiExDumpInfo[] = 379 { 380 NULL, 381 AcpiExDumpInteger, 382 AcpiExDumpString, 383 AcpiExDumpBuffer, 384 AcpiExDumpPackage, 385 NULL, 386 AcpiExDumpDevice, 387 AcpiExDumpEvent, 388 AcpiExDumpMethod, 389 AcpiExDumpMutex, 390 AcpiExDumpRegion, 391 AcpiExDumpPower, 392 AcpiExDumpProcessor, 393 AcpiExDumpThermal, 394 AcpiExDumpBufferField, 395 NULL, 396 NULL, 397 AcpiExDumpRegionField, 398 AcpiExDumpBankField, 399 AcpiExDumpIndexField, 400 AcpiExDumpReference, 401 NULL, 402 NULL, 403 AcpiExDumpNotify, 404 AcpiExDumpAddressHandler, 405 NULL, 406 NULL, 407 NULL 408 }; 409 410 411 /******************************************************************************* 412 * 413 * FUNCTION: AcpiExDumpObject 414 * 415 * PARAMETERS: ObjDesc - Descriptor to dump 416 * Info - Info table corresponding to this object 417 * type 418 * 419 * RETURN: None 420 * 421 * DESCRIPTION: Walk the info table for this object 422 * 423 ******************************************************************************/ 424 425 static void 426 AcpiExDumpObject ( 427 ACPI_OPERAND_OBJECT *ObjDesc, 428 ACPI_EXDUMP_INFO *Info) 429 { 430 UINT8 *Target; 431 char *Name; 432 const char *ReferenceName; 433 UINT8 Count; 434 435 436 if (!Info) 437 { 438 AcpiOsPrintf ( 439 "ExDumpObject: Display not implemented for object type %s\n", 440 AcpiUtGetObjectTypeName (ObjDesc)); 441 return; 442 } 443 444 /* First table entry must contain the table length (# of table entries) */ 445 446 Count = Info->Offset; 447 448 while (Count) 449 { 450 Target = ACPI_ADD_PTR (UINT8, ObjDesc, Info->Offset); 451 Name = Info->Name; 452 453 switch (Info->Opcode) 454 { 455 case ACPI_EXD_INIT: 456 457 break; 458 459 case ACPI_EXD_TYPE: 460 461 AcpiExOutString ("Type", AcpiUtGetObjectTypeName (ObjDesc)); 462 break; 463 464 case ACPI_EXD_UINT8: 465 466 AcpiOsPrintf ("%20s : %2.2X\n", Name, *Target); 467 break; 468 469 case ACPI_EXD_UINT16: 470 471 AcpiOsPrintf ("%20s : %4.4X\n", Name, ACPI_GET16 (Target)); 472 break; 473 474 case ACPI_EXD_UINT32: 475 476 AcpiOsPrintf ("%20s : %8.8X\n", Name, ACPI_GET32 (Target)); 477 break; 478 479 case ACPI_EXD_UINT64: 480 481 AcpiOsPrintf ("%20s : %8.8X%8.8X\n", "Value", 482 ACPI_FORMAT_UINT64 (ACPI_GET64 (Target))); 483 break; 484 485 case ACPI_EXD_POINTER: 486 case ACPI_EXD_ADDRESS: 487 488 AcpiExOutPointer (Name, *ACPI_CAST_PTR (void *, Target)); 489 break; 490 491 case ACPI_EXD_STRING: 492 493 AcpiUtPrintString (ObjDesc->String.Pointer, ACPI_UINT8_MAX); 494 AcpiOsPrintf ("\n"); 495 break; 496 497 case ACPI_EXD_BUFFER: 498 499 ACPI_DUMP_BUFFER (ObjDesc->Buffer.Pointer, ObjDesc->Buffer.Length); 500 break; 501 502 case ACPI_EXD_PACKAGE: 503 504 /* Dump the package contents */ 505 506 AcpiOsPrintf ("\nPackage Contents:\n"); 507 AcpiExDumpPackageObj (ObjDesc, 0, 0); 508 break; 509 510 case ACPI_EXD_FIELD: 511 512 AcpiExDumpObject (ObjDesc, AcpiExDumpFieldCommon); 513 break; 514 515 case ACPI_EXD_REFERENCE: 516 517 ReferenceName = AcpiUtGetReferenceName (ObjDesc); 518 AcpiExOutString ("Class Name", ACPI_CAST_PTR (char, ReferenceName)); 519 AcpiExDumpReferenceObj (ObjDesc); 520 break; 521 522 default: 523 524 AcpiOsPrintf ("**** Invalid table opcode [%X] ****\n", 525 Info->Opcode); 526 return; 527 } 528 529 Info++; 530 Count--; 531 } 532 } 533 534 535 /******************************************************************************* 536 * 537 * FUNCTION: AcpiExDumpOperand 538 * 539 * PARAMETERS: *ObjDesc - Pointer to entry to be dumped 540 * Depth - Current nesting depth 541 * 542 * RETURN: None 543 * 544 * DESCRIPTION: Dump an operand object 545 * 546 ******************************************************************************/ 547 548 void 549 AcpiExDumpOperand ( 550 ACPI_OPERAND_OBJECT *ObjDesc, 551 UINT32 Depth) 552 { 553 UINT32 Length; 554 UINT32 Index; 555 556 557 ACPI_FUNCTION_NAME (ExDumpOperand) 558 559 560 /* Check if debug output enabled */ 561 562 if (!ACPI_IS_DEBUG_ENABLED (ACPI_LV_EXEC, _COMPONENT)) 563 { 564 return; 565 } 566 567 if (!ObjDesc) 568 { 569 /* This could be a null element of a package */ 570 571 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Null Object Descriptor\n")); 572 return; 573 } 574 575 if (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc) == ACPI_DESC_TYPE_NAMED) 576 { 577 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "%p Namespace Node: ", ObjDesc)); 578 ACPI_DUMP_ENTRY (ObjDesc, ACPI_LV_EXEC); 579 return; 580 } 581 582 if (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc) != ACPI_DESC_TYPE_OPERAND) 583 { 584 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, 585 "%p is not a node or operand object: [%s]\n", 586 ObjDesc, AcpiUtGetDescriptorName (ObjDesc))); 587 ACPI_DUMP_BUFFER (ObjDesc, sizeof (ACPI_OPERAND_OBJECT)); 588 return; 589 } 590 591 /* ObjDesc is a valid object */ 592 593 if (Depth > 0) 594 { 595 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "%*s[%u] %p ", 596 Depth, " ", Depth, ObjDesc)); 597 } 598 else 599 { 600 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "%p ", ObjDesc)); 601 } 602 603 /* Decode object type */ 604 605 switch (ObjDesc->Common.Type) 606 { 607 case ACPI_TYPE_LOCAL_REFERENCE: 608 609 AcpiOsPrintf ("Reference: [%s] ", AcpiUtGetReferenceName (ObjDesc)); 610 611 switch (ObjDesc->Reference.Class) 612 { 613 case ACPI_REFCLASS_DEBUG: 614 615 AcpiOsPrintf ("\n"); 616 break; 617 618 case ACPI_REFCLASS_INDEX: 619 620 AcpiOsPrintf ("%p\n", ObjDesc->Reference.Object); 621 break; 622 623 case ACPI_REFCLASS_TABLE: 624 625 AcpiOsPrintf ("Table Index %X\n", ObjDesc->Reference.Value); 626 break; 627 628 case ACPI_REFCLASS_REFOF: 629 630 AcpiOsPrintf ("%p [%s]\n", ObjDesc->Reference.Object, 631 AcpiUtGetTypeName (((ACPI_OPERAND_OBJECT *) 632 ObjDesc->Reference.Object)->Common.Type)); 633 break; 634 635 case ACPI_REFCLASS_NAME: 636 637 AcpiOsPrintf ("- [%4.4s]\n", ObjDesc->Reference.Node->Name.Ascii); 638 break; 639 640 case ACPI_REFCLASS_ARG: 641 case ACPI_REFCLASS_LOCAL: 642 643 AcpiOsPrintf ("%X\n", ObjDesc->Reference.Value); 644 break; 645 646 default: /* Unknown reference class */ 647 648 AcpiOsPrintf ("%2.2X\n", ObjDesc->Reference.Class); 649 break; 650 } 651 break; 652 653 case ACPI_TYPE_BUFFER: 654 655 AcpiOsPrintf ("Buffer length %.2X @ %p\n", 656 ObjDesc->Buffer.Length, ObjDesc->Buffer.Pointer); 657 658 /* Debug only -- dump the buffer contents */ 659 660 if (ObjDesc->Buffer.Pointer) 661 { 662 Length = ObjDesc->Buffer.Length; 663 if (Length > 128) 664 { 665 Length = 128; 666 } 667 668 AcpiOsPrintf ("Buffer Contents: (displaying length 0x%.2X)\n", 669 Length); 670 ACPI_DUMP_BUFFER (ObjDesc->Buffer.Pointer, Length); 671 } 672 break; 673 674 case ACPI_TYPE_INTEGER: 675 676 AcpiOsPrintf ("Integer %8.8X%8.8X\n", 677 ACPI_FORMAT_UINT64 (ObjDesc->Integer.Value)); 678 break; 679 680 case ACPI_TYPE_PACKAGE: 681 682 AcpiOsPrintf ("Package [Len %X] ElementArray %p\n", 683 ObjDesc->Package.Count, ObjDesc->Package.Elements); 684 685 /* 686 * If elements exist, package element pointer is valid, 687 * and debug_level exceeds 1, dump package's elements. 688 */ 689 if (ObjDesc->Package.Count && 690 ObjDesc->Package.Elements && 691 AcpiDbgLevel > 1) 692 { 693 for (Index = 0; Index < ObjDesc->Package.Count; Index++) 694 { 695 AcpiExDumpOperand (ObjDesc->Package.Elements[Index], Depth+1); 696 } 697 } 698 break; 699 700 case ACPI_TYPE_REGION: 701 702 AcpiOsPrintf ("Region %s (%X)", 703 AcpiUtGetRegionName (ObjDesc->Region.SpaceId), 704 ObjDesc->Region.SpaceId); 705 706 /* 707 * If the address and length have not been evaluated, 708 * don't print them. 709 */ 710 if (!(ObjDesc->Region.Flags & AOPOBJ_DATA_VALID)) 711 { 712 AcpiOsPrintf ("\n"); 713 } 714 else 715 { 716 AcpiOsPrintf (" base %8.8X%8.8X Length %X\n", 717 ACPI_FORMAT_NATIVE_UINT (ObjDesc->Region.Address), 718 ObjDesc->Region.Length); 719 } 720 break; 721 722 case ACPI_TYPE_STRING: 723 724 AcpiOsPrintf ("String length %X @ %p ", 725 ObjDesc->String.Length, 726 ObjDesc->String.Pointer); 727 728 AcpiUtPrintString (ObjDesc->String.Pointer, ACPI_UINT8_MAX); 729 AcpiOsPrintf ("\n"); 730 break; 731 732 case ACPI_TYPE_LOCAL_BANK_FIELD: 733 734 AcpiOsPrintf ("BankField\n"); 735 break; 736 737 case ACPI_TYPE_LOCAL_REGION_FIELD: 738 739 AcpiOsPrintf ("RegionField: Bits=%X AccWidth=%X Lock=%X Update=%X at " 740 "byte=%X bit=%X of below:\n", 741 ObjDesc->Field.BitLength, 742 ObjDesc->Field.AccessByteWidth, 743 ObjDesc->Field.FieldFlags & AML_FIELD_LOCK_RULE_MASK, 744 ObjDesc->Field.FieldFlags & AML_FIELD_UPDATE_RULE_MASK, 745 ObjDesc->Field.BaseByteOffset, 746 ObjDesc->Field.StartFieldBitOffset); 747 748 AcpiExDumpOperand (ObjDesc->Field.RegionObj, Depth+1); 749 break; 750 751 case ACPI_TYPE_LOCAL_INDEX_FIELD: 752 753 AcpiOsPrintf ("IndexField\n"); 754 break; 755 756 case ACPI_TYPE_BUFFER_FIELD: 757 758 AcpiOsPrintf ("BufferField: %X bits at byte %X bit %X of\n", 759 ObjDesc->BufferField.BitLength, 760 ObjDesc->BufferField.BaseByteOffset, 761 ObjDesc->BufferField.StartFieldBitOffset); 762 763 if (!ObjDesc->BufferField.BufferObj) 764 { 765 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "*NULL*\n")); 766 } 767 else if ((ObjDesc->BufferField.BufferObj)->Common.Type != 768 ACPI_TYPE_BUFFER) 769 { 770 AcpiOsPrintf ("*not a Buffer*\n"); 771 } 772 else 773 { 774 AcpiExDumpOperand (ObjDesc->BufferField.BufferObj, Depth+1); 775 } 776 break; 777 778 case ACPI_TYPE_EVENT: 779 780 AcpiOsPrintf ("Event\n"); 781 break; 782 783 case ACPI_TYPE_METHOD: 784 785 AcpiOsPrintf ("Method(%X) @ %p:%X\n", 786 ObjDesc->Method.ParamCount, 787 ObjDesc->Method.AmlStart, 788 ObjDesc->Method.AmlLength); 789 break; 790 791 case ACPI_TYPE_MUTEX: 792 793 AcpiOsPrintf ("Mutex\n"); 794 break; 795 796 case ACPI_TYPE_DEVICE: 797 798 AcpiOsPrintf ("Device\n"); 799 break; 800 801 case ACPI_TYPE_POWER: 802 803 AcpiOsPrintf ("Power\n"); 804 break; 805 806 case ACPI_TYPE_PROCESSOR: 807 808 AcpiOsPrintf ("Processor\n"); 809 break; 810 811 case ACPI_TYPE_THERMAL: 812 813 AcpiOsPrintf ("Thermal\n"); 814 break; 815 816 default: 817 818 /* Unknown Type */ 819 820 AcpiOsPrintf ("Unknown Type %X\n", ObjDesc->Common.Type); 821 break; 822 } 823 824 return; 825 } 826 827 828 /******************************************************************************* 829 * 830 * FUNCTION: AcpiExDumpOperands 831 * 832 * PARAMETERS: Operands - A list of Operand objects 833 * OpcodeName - AML opcode name 834 * NumOperands - Operand count for this opcode 835 * 836 * DESCRIPTION: Dump the operands associated with the opcode 837 * 838 ******************************************************************************/ 839 840 void 841 AcpiExDumpOperands ( 842 ACPI_OPERAND_OBJECT **Operands, 843 const char *OpcodeName, 844 UINT32 NumOperands) 845 { 846 ACPI_FUNCTION_NAME (ExDumpOperands); 847 848 849 if (!OpcodeName) 850 { 851 OpcodeName = "UNKNOWN"; 852 } 853 854 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, 855 "**** Start operand dump for opcode [%s], %u operands\n", 856 OpcodeName, NumOperands)); 857 858 if (NumOperands == 0) 859 { 860 NumOperands = 1; 861 } 862 863 /* Dump the individual operands */ 864 865 while (NumOperands) 866 { 867 AcpiExDumpOperand (*Operands, 0); 868 Operands++; 869 NumOperands--; 870 } 871 872 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, 873 "**** End operand dump for [%s]\n", OpcodeName)); 874 return; 875 } 876 877 878 /******************************************************************************* 879 * 880 * FUNCTION: AcpiExOut* functions 881 * 882 * PARAMETERS: Title - Descriptive text 883 * Value - Value to be displayed 884 * 885 * DESCRIPTION: Object dump output formatting functions. These functions 886 * reduce the number of format strings required and keeps them 887 * all in one place for easy modification. 888 * 889 ******************************************************************************/ 890 891 static void 892 AcpiExOutString ( 893 char *Title, 894 char *Value) 895 { 896 AcpiOsPrintf ("%20s : %s\n", Title, Value); 897 } 898 899 static void 900 AcpiExOutPointer ( 901 char *Title, 902 void *Value) 903 { 904 AcpiOsPrintf ("%20s : %p\n", Title, Value); 905 } 906 907 908 /******************************************************************************* 909 * 910 * FUNCTION: AcpiExDumpNamespaceNode 911 * 912 * PARAMETERS: Node - Descriptor to dump 913 * Flags - Force display if TRUE 914 * 915 * DESCRIPTION: Dumps the members of the given.Node 916 * 917 ******************************************************************************/ 918 919 void 920 AcpiExDumpNamespaceNode ( 921 ACPI_NAMESPACE_NODE *Node, 922 UINT32 Flags) 923 { 924 925 ACPI_FUNCTION_ENTRY (); 926 927 928 if (!Flags) 929 { 930 /* Check if debug output enabled */ 931 932 if (!ACPI_IS_DEBUG_ENABLED (ACPI_LV_OBJECTS, _COMPONENT)) 933 { 934 return; 935 } 936 } 937 938 AcpiOsPrintf ("%20s : %4.4s\n", "Name", AcpiUtGetNodeName (Node)); 939 AcpiExOutString ("Type", AcpiUtGetTypeName (Node->Type)); 940 AcpiExOutPointer ("Attached Object", AcpiNsGetAttachedObject (Node)); 941 AcpiExOutPointer ("Parent", Node->Parent); 942 943 AcpiExDumpObject (ACPI_CAST_PTR (ACPI_OPERAND_OBJECT, Node), 944 AcpiExDumpNode); 945 } 946 947 948 /******************************************************************************* 949 * 950 * FUNCTION: AcpiExDumpReferenceObj 951 * 952 * PARAMETERS: Object - Descriptor to dump 953 * 954 * DESCRIPTION: Dumps a reference object 955 * 956 ******************************************************************************/ 957 958 static void 959 AcpiExDumpReferenceObj ( 960 ACPI_OPERAND_OBJECT *ObjDesc) 961 { 962 ACPI_BUFFER RetBuf; 963 ACPI_STATUS Status; 964 965 966 RetBuf.Length = ACPI_ALLOCATE_LOCAL_BUFFER; 967 968 if (ObjDesc->Reference.Class == ACPI_REFCLASS_NAME) 969 { 970 AcpiOsPrintf (" %p ", ObjDesc->Reference.Node); 971 972 Status = AcpiNsHandleToPathname (ObjDesc->Reference.Node, &RetBuf); 973 if (ACPI_FAILURE (Status)) 974 { 975 AcpiOsPrintf (" Could not convert name to pathname\n"); 976 } 977 else 978 { 979 AcpiOsPrintf ("%s\n", (char *) RetBuf.Pointer); 980 ACPI_FREE (RetBuf.Pointer); 981 } 982 } 983 else if (ObjDesc->Reference.Object) 984 { 985 if (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc) == ACPI_DESC_TYPE_OPERAND) 986 { 987 AcpiOsPrintf (" Target: %p", ObjDesc->Reference.Object); 988 if (ObjDesc->Reference.Class == ACPI_REFCLASS_TABLE) 989 { 990 AcpiOsPrintf (" Table Index: %X\n", ObjDesc->Reference.Value); 991 } 992 else 993 { 994 AcpiOsPrintf (" Target: %p [%s]\n", ObjDesc->Reference.Object, 995 AcpiUtGetTypeName (((ACPI_OPERAND_OBJECT *) 996 ObjDesc->Reference.Object)->Common.Type)); 997 } 998 } 999 else 1000 { 1001 AcpiOsPrintf (" Target: %p\n", ObjDesc->Reference.Object); 1002 } 1003 } 1004 } 1005 1006 1007 /******************************************************************************* 1008 * 1009 * FUNCTION: AcpiExDumpPackageObj 1010 * 1011 * PARAMETERS: ObjDesc - Descriptor to dump 1012 * Level - Indentation Level 1013 * Index - Package index for this object 1014 * 1015 * DESCRIPTION: Dumps the elements of the package 1016 * 1017 ******************************************************************************/ 1018 1019 static void 1020 AcpiExDumpPackageObj ( 1021 ACPI_OPERAND_OBJECT *ObjDesc, 1022 UINT32 Level, 1023 UINT32 Index) 1024 { 1025 UINT32 i; 1026 1027 1028 /* Indentation and index output */ 1029 1030 if (Level > 0) 1031 { 1032 for (i = 0; i < Level; i++) 1033 { 1034 AcpiOsPrintf (" "); 1035 } 1036 1037 AcpiOsPrintf ("[%.2d] ", Index); 1038 } 1039 1040 AcpiOsPrintf ("%p ", ObjDesc); 1041 1042 /* Null package elements are allowed */ 1043 1044 if (!ObjDesc) 1045 { 1046 AcpiOsPrintf ("[Null Object]\n"); 1047 return; 1048 } 1049 1050 /* Packages may only contain a few object types */ 1051 1052 switch (ObjDesc->Common.Type) 1053 { 1054 case ACPI_TYPE_INTEGER: 1055 1056 AcpiOsPrintf ("[Integer] = %8.8X%8.8X\n", 1057 ACPI_FORMAT_UINT64 (ObjDesc->Integer.Value)); 1058 break; 1059 1060 case ACPI_TYPE_STRING: 1061 1062 AcpiOsPrintf ("[String] Value: "); 1063 AcpiUtPrintString (ObjDesc->String.Pointer, ACPI_UINT8_MAX); 1064 AcpiOsPrintf ("\n"); 1065 break; 1066 1067 case ACPI_TYPE_BUFFER: 1068 1069 AcpiOsPrintf ("[Buffer] Length %.2X = ", ObjDesc->Buffer.Length); 1070 if (ObjDesc->Buffer.Length) 1071 { 1072 AcpiUtDebugDumpBuffer (ACPI_CAST_PTR (UINT8, ObjDesc->Buffer.Pointer), 1073 ObjDesc->Buffer.Length, DB_DWORD_DISPLAY, _COMPONENT); 1074 } 1075 else 1076 { 1077 AcpiOsPrintf ("\n"); 1078 } 1079 break; 1080 1081 case ACPI_TYPE_PACKAGE: 1082 1083 AcpiOsPrintf ("[Package] Contains %u Elements:\n", 1084 ObjDesc->Package.Count); 1085 1086 for (i = 0; i < ObjDesc->Package.Count; i++) 1087 { 1088 AcpiExDumpPackageObj (ObjDesc->Package.Elements[i], Level+1, i); 1089 } 1090 break; 1091 1092 case ACPI_TYPE_LOCAL_REFERENCE: 1093 1094 AcpiOsPrintf ("[Object Reference] Type [%s] %2.2X", 1095 AcpiUtGetReferenceName (ObjDesc), 1096 ObjDesc->Reference.Class); 1097 AcpiExDumpReferenceObj (ObjDesc); 1098 break; 1099 1100 default: 1101 1102 AcpiOsPrintf ("[Unknown Type] %X\n", ObjDesc->Common.Type); 1103 break; 1104 } 1105 } 1106 1107 1108 /******************************************************************************* 1109 * 1110 * FUNCTION: AcpiExDumpObjectDescriptor 1111 * 1112 * PARAMETERS: ObjDesc - Descriptor to dump 1113 * Flags - Force display if TRUE 1114 * 1115 * DESCRIPTION: Dumps the members of the object descriptor given. 1116 * 1117 ******************************************************************************/ 1118 1119 void 1120 AcpiExDumpObjectDescriptor ( 1121 ACPI_OPERAND_OBJECT *ObjDesc, 1122 UINT32 Flags) 1123 { 1124 ACPI_FUNCTION_TRACE (ExDumpObjectDescriptor); 1125 1126 1127 if (!ObjDesc) 1128 { 1129 return_VOID; 1130 } 1131 1132 if (!Flags) 1133 { 1134 /* Check if debug output enabled */ 1135 1136 if (!ACPI_IS_DEBUG_ENABLED (ACPI_LV_OBJECTS, _COMPONENT)) 1137 { 1138 return_VOID; 1139 } 1140 } 1141 1142 if (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc) == ACPI_DESC_TYPE_NAMED) 1143 { 1144 AcpiExDumpNamespaceNode ((ACPI_NAMESPACE_NODE *) ObjDesc, Flags); 1145 1146 AcpiOsPrintf ("\nAttached Object (%p):\n", 1147 ((ACPI_NAMESPACE_NODE *) ObjDesc)->Object); 1148 1149 AcpiExDumpObjectDescriptor ( 1150 ((ACPI_NAMESPACE_NODE *) ObjDesc)->Object, Flags); 1151 return_VOID; 1152 } 1153 1154 if (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc) != ACPI_DESC_TYPE_OPERAND) 1155 { 1156 AcpiOsPrintf ( 1157 "ExDumpObjectDescriptor: %p is not an ACPI operand object: [%s]\n", 1158 ObjDesc, AcpiUtGetDescriptorName (ObjDesc)); 1159 return_VOID; 1160 } 1161 1162 if (ObjDesc->Common.Type > ACPI_TYPE_NS_NODE_MAX) 1163 { 1164 return_VOID; 1165 } 1166 1167 /* Common Fields */ 1168 1169 AcpiExDumpObject (ObjDesc, AcpiExDumpCommon); 1170 1171 /* Object-specific fields */ 1172 1173 AcpiExDumpObject (ObjDesc, AcpiExDumpInfo[ObjDesc->Common.Type]); 1174 return_VOID; 1175 } 1176 1177 #endif 1178