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 - 2012, 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 UINT8 Count; 433 434 435 if (!Info) 436 { 437 AcpiOsPrintf ( 438 "ExDumpObject: Display not implemented for object type %s\n", 439 AcpiUtGetObjectTypeName (ObjDesc)); 440 return; 441 } 442 443 /* First table entry must contain the table length (# of table entries) */ 444 445 Count = Info->Offset; 446 447 while (Count) 448 { 449 Target = ACPI_ADD_PTR (UINT8, ObjDesc, Info->Offset); 450 Name = Info->Name; 451 452 switch (Info->Opcode) 453 { 454 case ACPI_EXD_INIT: 455 break; 456 457 case ACPI_EXD_TYPE: 458 459 AcpiExOutString ("Type", AcpiUtGetObjectTypeName (ObjDesc)); 460 break; 461 462 case ACPI_EXD_UINT8: 463 464 AcpiOsPrintf ("%20s : %2.2X\n", Name, *Target); 465 break; 466 467 case ACPI_EXD_UINT16: 468 469 AcpiOsPrintf ("%20s : %4.4X\n", Name, ACPI_GET16 (Target)); 470 break; 471 472 case ACPI_EXD_UINT32: 473 474 AcpiOsPrintf ("%20s : %8.8X\n", Name, ACPI_GET32 (Target)); 475 break; 476 477 case ACPI_EXD_UINT64: 478 479 AcpiOsPrintf ("%20s : %8.8X%8.8X\n", "Value", 480 ACPI_FORMAT_UINT64 (ACPI_GET64 (Target))); 481 break; 482 483 case ACPI_EXD_POINTER: 484 case ACPI_EXD_ADDRESS: 485 486 AcpiExOutPointer (Name, *ACPI_CAST_PTR (void *, Target)); 487 break; 488 489 case ACPI_EXD_STRING: 490 491 AcpiUtPrintString (ObjDesc->String.Pointer, ACPI_UINT8_MAX); 492 AcpiOsPrintf ("\n"); 493 break; 494 495 case ACPI_EXD_BUFFER: 496 497 ACPI_DUMP_BUFFER (ObjDesc->Buffer.Pointer, ObjDesc->Buffer.Length); 498 break; 499 500 case ACPI_EXD_PACKAGE: 501 502 /* Dump the package contents */ 503 504 AcpiOsPrintf ("\nPackage Contents:\n"); 505 AcpiExDumpPackageObj (ObjDesc, 0, 0); 506 break; 507 508 case ACPI_EXD_FIELD: 509 510 AcpiExDumpObject (ObjDesc, AcpiExDumpFieldCommon); 511 break; 512 513 case ACPI_EXD_REFERENCE: 514 515 AcpiExOutString ("Class Name", 516 ACPI_CAST_PTR (char, AcpiUtGetReferenceName (ObjDesc))); 517 AcpiExDumpReferenceObj (ObjDesc); 518 break; 519 520 default: 521 522 AcpiOsPrintf ("**** Invalid table opcode [%X] ****\n", 523 Info->Opcode); 524 return; 525 } 526 527 Info++; 528 Count--; 529 } 530 } 531 532 533 /******************************************************************************* 534 * 535 * FUNCTION: AcpiExDumpOperand 536 * 537 * PARAMETERS: *ObjDesc - Pointer to entry to be dumped 538 * Depth - Current nesting depth 539 * 540 * RETURN: None 541 * 542 * DESCRIPTION: Dump an operand object 543 * 544 ******************************************************************************/ 545 546 void 547 AcpiExDumpOperand ( 548 ACPI_OPERAND_OBJECT *ObjDesc, 549 UINT32 Depth) 550 { 551 UINT32 Length; 552 UINT32 Index; 553 554 555 ACPI_FUNCTION_NAME (ExDumpOperand) 556 557 558 if (!((ACPI_LV_EXEC & AcpiDbgLevel) && (_COMPONENT & AcpiDbgLayer))) 559 { 560 return; 561 } 562 563 if (!ObjDesc) 564 { 565 /* This could be a null element of a package */ 566 567 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Null Object Descriptor\n")); 568 return; 569 } 570 571 if (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc) == ACPI_DESC_TYPE_NAMED) 572 { 573 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "%p Namespace Node: ", ObjDesc)); 574 ACPI_DUMP_ENTRY (ObjDesc, ACPI_LV_EXEC); 575 return; 576 } 577 578 if (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc) != ACPI_DESC_TYPE_OPERAND) 579 { 580 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, 581 "%p is not a node or operand object: [%s]\n", 582 ObjDesc, AcpiUtGetDescriptorName (ObjDesc))); 583 ACPI_DUMP_BUFFER (ObjDesc, sizeof (ACPI_OPERAND_OBJECT)); 584 return; 585 } 586 587 /* ObjDesc is a valid object */ 588 589 if (Depth > 0) 590 { 591 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "%*s[%u] %p ", 592 Depth, " ", Depth, ObjDesc)); 593 } 594 else 595 { 596 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "%p ", ObjDesc)); 597 } 598 599 /* Decode object type */ 600 601 switch (ObjDesc->Common.Type) 602 { 603 case ACPI_TYPE_LOCAL_REFERENCE: 604 605 AcpiOsPrintf ("Reference: [%s] ", AcpiUtGetReferenceName (ObjDesc)); 606 607 switch (ObjDesc->Reference.Class) 608 { 609 case ACPI_REFCLASS_DEBUG: 610 611 AcpiOsPrintf ("\n"); 612 break; 613 614 615 case ACPI_REFCLASS_INDEX: 616 617 AcpiOsPrintf ("%p\n", ObjDesc->Reference.Object); 618 break; 619 620 621 case ACPI_REFCLASS_TABLE: 622 623 AcpiOsPrintf ("Table Index %X\n", ObjDesc->Reference.Value); 624 break; 625 626 627 case ACPI_REFCLASS_REFOF: 628 629 AcpiOsPrintf ("%p [%s]\n", ObjDesc->Reference.Object, 630 AcpiUtGetTypeName (((ACPI_OPERAND_OBJECT *) 631 ObjDesc->Reference.Object)->Common.Type)); 632 break; 633 634 635 case ACPI_REFCLASS_NAME: 636 637 AcpiOsPrintf ("- [%4.4s]\n", ObjDesc->Reference.Node->Name.Ascii); 638 break; 639 640 641 case ACPI_REFCLASS_ARG: 642 case ACPI_REFCLASS_LOCAL: 643 644 AcpiOsPrintf ("%X\n", ObjDesc->Reference.Value); 645 break; 646 647 648 default: /* Unknown reference class */ 649 650 AcpiOsPrintf ("%2.2X\n", ObjDesc->Reference.Class); 651 break; 652 } 653 break; 654 655 656 case ACPI_TYPE_BUFFER: 657 658 AcpiOsPrintf ("Buffer length %.2X @ %p\n", 659 ObjDesc->Buffer.Length, ObjDesc->Buffer.Pointer); 660 661 /* Debug only -- dump the buffer contents */ 662 663 if (ObjDesc->Buffer.Pointer) 664 { 665 Length = ObjDesc->Buffer.Length; 666 if (Length > 128) 667 { 668 Length = 128; 669 } 670 671 AcpiOsPrintf ("Buffer Contents: (displaying length 0x%.2X)\n", 672 Length); 673 ACPI_DUMP_BUFFER (ObjDesc->Buffer.Pointer, Length); 674 } 675 break; 676 677 678 case ACPI_TYPE_INTEGER: 679 680 AcpiOsPrintf ("Integer %8.8X%8.8X\n", 681 ACPI_FORMAT_UINT64 (ObjDesc->Integer.Value)); 682 break; 683 684 685 case ACPI_TYPE_PACKAGE: 686 687 AcpiOsPrintf ("Package [Len %X] ElementArray %p\n", 688 ObjDesc->Package.Count, ObjDesc->Package.Elements); 689 690 /* 691 * If elements exist, package element pointer is valid, 692 * and debug_level exceeds 1, dump package's elements. 693 */ 694 if (ObjDesc->Package.Count && 695 ObjDesc->Package.Elements && 696 AcpiDbgLevel > 1) 697 { 698 for (Index = 0; Index < ObjDesc->Package.Count; Index++) 699 { 700 AcpiExDumpOperand (ObjDesc->Package.Elements[Index], Depth+1); 701 } 702 } 703 break; 704 705 706 case ACPI_TYPE_REGION: 707 708 AcpiOsPrintf ("Region %s (%X)", 709 AcpiUtGetRegionName (ObjDesc->Region.SpaceId), 710 ObjDesc->Region.SpaceId); 711 712 /* 713 * If the address and length have not been evaluated, 714 * don't print them. 715 */ 716 if (!(ObjDesc->Region.Flags & AOPOBJ_DATA_VALID)) 717 { 718 AcpiOsPrintf ("\n"); 719 } 720 else 721 { 722 AcpiOsPrintf (" base %8.8X%8.8X Length %X\n", 723 ACPI_FORMAT_NATIVE_UINT (ObjDesc->Region.Address), 724 ObjDesc->Region.Length); 725 } 726 break; 727 728 729 case ACPI_TYPE_STRING: 730 731 AcpiOsPrintf ("String length %X @ %p ", 732 ObjDesc->String.Length, 733 ObjDesc->String.Pointer); 734 735 AcpiUtPrintString (ObjDesc->String.Pointer, ACPI_UINT8_MAX); 736 AcpiOsPrintf ("\n"); 737 break; 738 739 740 case ACPI_TYPE_LOCAL_BANK_FIELD: 741 742 AcpiOsPrintf ("BankField\n"); 743 break; 744 745 746 case ACPI_TYPE_LOCAL_REGION_FIELD: 747 748 AcpiOsPrintf ("RegionField: Bits=%X AccWidth=%X Lock=%X Update=%X at " 749 "byte=%X bit=%X of below:\n", 750 ObjDesc->Field.BitLength, 751 ObjDesc->Field.AccessByteWidth, 752 ObjDesc->Field.FieldFlags & AML_FIELD_LOCK_RULE_MASK, 753 ObjDesc->Field.FieldFlags & AML_FIELD_UPDATE_RULE_MASK, 754 ObjDesc->Field.BaseByteOffset, 755 ObjDesc->Field.StartFieldBitOffset); 756 757 AcpiExDumpOperand (ObjDesc->Field.RegionObj, Depth+1); 758 break; 759 760 761 case ACPI_TYPE_LOCAL_INDEX_FIELD: 762 763 AcpiOsPrintf ("IndexField\n"); 764 break; 765 766 767 case ACPI_TYPE_BUFFER_FIELD: 768 769 AcpiOsPrintf ("BufferField: %X bits at byte %X bit %X of\n", 770 ObjDesc->BufferField.BitLength, 771 ObjDesc->BufferField.BaseByteOffset, 772 ObjDesc->BufferField.StartFieldBitOffset); 773 774 if (!ObjDesc->BufferField.BufferObj) 775 { 776 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "*NULL*\n")); 777 } 778 else if ((ObjDesc->BufferField.BufferObj)->Common.Type != 779 ACPI_TYPE_BUFFER) 780 { 781 AcpiOsPrintf ("*not a Buffer*\n"); 782 } 783 else 784 { 785 AcpiExDumpOperand (ObjDesc->BufferField.BufferObj, Depth+1); 786 } 787 break; 788 789 790 case ACPI_TYPE_EVENT: 791 792 AcpiOsPrintf ("Event\n"); 793 break; 794 795 796 case ACPI_TYPE_METHOD: 797 798 AcpiOsPrintf ("Method(%X) @ %p:%X\n", 799 ObjDesc->Method.ParamCount, 800 ObjDesc->Method.AmlStart, 801 ObjDesc->Method.AmlLength); 802 break; 803 804 805 case ACPI_TYPE_MUTEX: 806 807 AcpiOsPrintf ("Mutex\n"); 808 break; 809 810 811 case ACPI_TYPE_DEVICE: 812 813 AcpiOsPrintf ("Device\n"); 814 break; 815 816 817 case ACPI_TYPE_POWER: 818 819 AcpiOsPrintf ("Power\n"); 820 break; 821 822 823 case ACPI_TYPE_PROCESSOR: 824 825 AcpiOsPrintf ("Processor\n"); 826 break; 827 828 829 case ACPI_TYPE_THERMAL: 830 831 AcpiOsPrintf ("Thermal\n"); 832 break; 833 834 835 default: 836 /* Unknown Type */ 837 838 AcpiOsPrintf ("Unknown Type %X\n", ObjDesc->Common.Type); 839 break; 840 } 841 842 return; 843 } 844 845 846 /******************************************************************************* 847 * 848 * FUNCTION: AcpiExDumpOperands 849 * 850 * PARAMETERS: Operands - A list of Operand objects 851 * OpcodeName - AML opcode name 852 * NumOperands - Operand count for this opcode 853 * 854 * DESCRIPTION: Dump the operands associated with the opcode 855 * 856 ******************************************************************************/ 857 858 void 859 AcpiExDumpOperands ( 860 ACPI_OPERAND_OBJECT **Operands, 861 const char *OpcodeName, 862 UINT32 NumOperands) 863 { 864 ACPI_FUNCTION_NAME (ExDumpOperands); 865 866 867 if (!OpcodeName) 868 { 869 OpcodeName = "UNKNOWN"; 870 } 871 872 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, 873 "**** Start operand dump for opcode [%s], %u operands\n", 874 OpcodeName, NumOperands)); 875 876 if (NumOperands == 0) 877 { 878 NumOperands = 1; 879 } 880 881 /* Dump the individual operands */ 882 883 while (NumOperands) 884 { 885 AcpiExDumpOperand (*Operands, 0); 886 Operands++; 887 NumOperands--; 888 } 889 890 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, 891 "**** End operand dump for [%s]\n", OpcodeName)); 892 return; 893 } 894 895 896 /******************************************************************************* 897 * 898 * FUNCTION: AcpiExOut* functions 899 * 900 * PARAMETERS: Title - Descriptive text 901 * Value - Value to be displayed 902 * 903 * DESCRIPTION: Object dump output formatting functions. These functions 904 * reduce the number of format strings required and keeps them 905 * all in one place for easy modification. 906 * 907 ******************************************************************************/ 908 909 static void 910 AcpiExOutString ( 911 char *Title, 912 char *Value) 913 { 914 AcpiOsPrintf ("%20s : %s\n", Title, Value); 915 } 916 917 static void 918 AcpiExOutPointer ( 919 char *Title, 920 void *Value) 921 { 922 AcpiOsPrintf ("%20s : %p\n", Title, Value); 923 } 924 925 926 /******************************************************************************* 927 * 928 * FUNCTION: AcpiExDumpNamespaceNode 929 * 930 * PARAMETERS: Node - Descriptor to dump 931 * Flags - Force display if TRUE 932 * 933 * DESCRIPTION: Dumps the members of the given.Node 934 * 935 ******************************************************************************/ 936 937 void 938 AcpiExDumpNamespaceNode ( 939 ACPI_NAMESPACE_NODE *Node, 940 UINT32 Flags) 941 { 942 943 ACPI_FUNCTION_ENTRY (); 944 945 946 if (!Flags) 947 { 948 if (!((ACPI_LV_OBJECTS & AcpiDbgLevel) && (_COMPONENT & AcpiDbgLayer))) 949 { 950 return; 951 } 952 } 953 954 AcpiOsPrintf ("%20s : %4.4s\n", "Name", AcpiUtGetNodeName (Node)); 955 AcpiExOutString ("Type", AcpiUtGetTypeName (Node->Type)); 956 AcpiExOutPointer ("Attached Object", AcpiNsGetAttachedObject (Node)); 957 AcpiExOutPointer ("Parent", Node->Parent); 958 959 AcpiExDumpObject (ACPI_CAST_PTR (ACPI_OPERAND_OBJECT, Node), 960 AcpiExDumpNode); 961 } 962 963 964 /******************************************************************************* 965 * 966 * FUNCTION: AcpiExDumpReferenceObj 967 * 968 * PARAMETERS: Object - Descriptor to dump 969 * 970 * DESCRIPTION: Dumps a reference object 971 * 972 ******************************************************************************/ 973 974 static void 975 AcpiExDumpReferenceObj ( 976 ACPI_OPERAND_OBJECT *ObjDesc) 977 { 978 ACPI_BUFFER RetBuf; 979 ACPI_STATUS Status; 980 981 982 RetBuf.Length = ACPI_ALLOCATE_LOCAL_BUFFER; 983 984 if (ObjDesc->Reference.Class == ACPI_REFCLASS_NAME) 985 { 986 AcpiOsPrintf (" %p ", ObjDesc->Reference.Node); 987 988 Status = AcpiNsHandleToPathname (ObjDesc->Reference.Node, &RetBuf); 989 if (ACPI_FAILURE (Status)) 990 { 991 AcpiOsPrintf (" Could not convert name to pathname\n"); 992 } 993 else 994 { 995 AcpiOsPrintf ("%s\n", (char *) RetBuf.Pointer); 996 ACPI_FREE (RetBuf.Pointer); 997 } 998 } 999 else if (ObjDesc->Reference.Object) 1000 { 1001 if (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc) == ACPI_DESC_TYPE_OPERAND) 1002 { 1003 AcpiOsPrintf (" Target: %p", ObjDesc->Reference.Object); 1004 if (ObjDesc->Reference.Class == ACPI_REFCLASS_TABLE) 1005 { 1006 AcpiOsPrintf (" Table Index: %X\n", ObjDesc->Reference.Value); 1007 } 1008 else 1009 { 1010 AcpiOsPrintf (" Target: %p [%s]\n", ObjDesc->Reference.Object, 1011 AcpiUtGetTypeName (((ACPI_OPERAND_OBJECT *) 1012 ObjDesc->Reference.Object)->Common.Type)); 1013 } 1014 } 1015 else 1016 { 1017 AcpiOsPrintf (" Target: %p\n", ObjDesc->Reference.Object); 1018 } 1019 } 1020 } 1021 1022 1023 /******************************************************************************* 1024 * 1025 * FUNCTION: AcpiExDumpPackageObj 1026 * 1027 * PARAMETERS: ObjDesc - Descriptor to dump 1028 * Level - Indentation Level 1029 * Index - Package index for this object 1030 * 1031 * DESCRIPTION: Dumps the elements of the package 1032 * 1033 ******************************************************************************/ 1034 1035 static void 1036 AcpiExDumpPackageObj ( 1037 ACPI_OPERAND_OBJECT *ObjDesc, 1038 UINT32 Level, 1039 UINT32 Index) 1040 { 1041 UINT32 i; 1042 1043 1044 /* Indentation and index output */ 1045 1046 if (Level > 0) 1047 { 1048 for (i = 0; i < Level; i++) 1049 { 1050 AcpiOsPrintf (" "); 1051 } 1052 1053 AcpiOsPrintf ("[%.2d] ", Index); 1054 } 1055 1056 AcpiOsPrintf ("%p ", ObjDesc); 1057 1058 /* Null package elements are allowed */ 1059 1060 if (!ObjDesc) 1061 { 1062 AcpiOsPrintf ("[Null Object]\n"); 1063 return; 1064 } 1065 1066 /* Packages may only contain a few object types */ 1067 1068 switch (ObjDesc->Common.Type) 1069 { 1070 case ACPI_TYPE_INTEGER: 1071 1072 AcpiOsPrintf ("[Integer] = %8.8X%8.8X\n", 1073 ACPI_FORMAT_UINT64 (ObjDesc->Integer.Value)); 1074 break; 1075 1076 1077 case ACPI_TYPE_STRING: 1078 1079 AcpiOsPrintf ("[String] Value: "); 1080 AcpiUtPrintString (ObjDesc->String.Pointer, ACPI_UINT8_MAX); 1081 AcpiOsPrintf ("\n"); 1082 break; 1083 1084 1085 case ACPI_TYPE_BUFFER: 1086 1087 AcpiOsPrintf ("[Buffer] Length %.2X = ", ObjDesc->Buffer.Length); 1088 if (ObjDesc->Buffer.Length) 1089 { 1090 AcpiUtDumpBuffer (ACPI_CAST_PTR (UINT8, ObjDesc->Buffer.Pointer), 1091 ObjDesc->Buffer.Length, DB_DWORD_DISPLAY, _COMPONENT); 1092 } 1093 else 1094 { 1095 AcpiOsPrintf ("\n"); 1096 } 1097 break; 1098 1099 1100 case ACPI_TYPE_PACKAGE: 1101 1102 AcpiOsPrintf ("[Package] Contains %u Elements:\n", 1103 ObjDesc->Package.Count); 1104 1105 for (i = 0; i < ObjDesc->Package.Count; i++) 1106 { 1107 AcpiExDumpPackageObj (ObjDesc->Package.Elements[i], Level+1, i); 1108 } 1109 break; 1110 1111 1112 case ACPI_TYPE_LOCAL_REFERENCE: 1113 1114 AcpiOsPrintf ("[Object Reference] Type [%s] %2.2X", 1115 AcpiUtGetReferenceName (ObjDesc), 1116 ObjDesc->Reference.Class); 1117 AcpiExDumpReferenceObj (ObjDesc); 1118 break; 1119 1120 1121 default: 1122 1123 AcpiOsPrintf ("[Unknown Type] %X\n", ObjDesc->Common.Type); 1124 break; 1125 } 1126 } 1127 1128 1129 /******************************************************************************* 1130 * 1131 * FUNCTION: AcpiExDumpObjectDescriptor 1132 * 1133 * PARAMETERS: ObjDesc - Descriptor to dump 1134 * Flags - Force display if TRUE 1135 * 1136 * DESCRIPTION: Dumps the members of the object descriptor given. 1137 * 1138 ******************************************************************************/ 1139 1140 void 1141 AcpiExDumpObjectDescriptor ( 1142 ACPI_OPERAND_OBJECT *ObjDesc, 1143 UINT32 Flags) 1144 { 1145 ACPI_FUNCTION_TRACE (ExDumpObjectDescriptor); 1146 1147 1148 if (!ObjDesc) 1149 { 1150 return_VOID; 1151 } 1152 1153 if (!Flags) 1154 { 1155 if (!((ACPI_LV_OBJECTS & AcpiDbgLevel) && (_COMPONENT & AcpiDbgLayer))) 1156 { 1157 return_VOID; 1158 } 1159 } 1160 1161 if (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc) == ACPI_DESC_TYPE_NAMED) 1162 { 1163 AcpiExDumpNamespaceNode ((ACPI_NAMESPACE_NODE *) ObjDesc, Flags); 1164 1165 AcpiOsPrintf ("\nAttached Object (%p):\n", 1166 ((ACPI_NAMESPACE_NODE *) ObjDesc)->Object); 1167 1168 AcpiExDumpObjectDescriptor ( 1169 ((ACPI_NAMESPACE_NODE *) ObjDesc)->Object, Flags); 1170 return_VOID; 1171 } 1172 1173 if (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc) != ACPI_DESC_TYPE_OPERAND) 1174 { 1175 AcpiOsPrintf ( 1176 "ExDumpObjectDescriptor: %p is not an ACPI operand object: [%s]\n", 1177 ObjDesc, AcpiUtGetDescriptorName (ObjDesc)); 1178 return_VOID; 1179 } 1180 1181 if (ObjDesc->Common.Type > ACPI_TYPE_NS_NODE_MAX) 1182 { 1183 return_VOID; 1184 } 1185 1186 /* Common Fields */ 1187 1188 AcpiExDumpObject (ObjDesc, AcpiExDumpCommon); 1189 1190 /* Object-specific fields */ 1191 1192 AcpiExDumpObject (ObjDesc, AcpiExDumpInfo[ObjDesc->Common.Type]); 1193 return_VOID; 1194 } 1195 1196 #endif 1197 1198