1 /******************************************************************************* 2 * 3 * Module Name: dmbuffer - AML disassembler, buffer and string support 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 45 #include "acpi.h" 46 #include "accommon.h" 47 #include "acdisasm.h" 48 #include "acparser.h" 49 #include "amlcode.h" 50 51 52 #ifdef ACPI_DISASSEMBLER 53 54 #define _COMPONENT ACPI_CA_DEBUGGER 55 ACPI_MODULE_NAME ("dmbuffer") 56 57 /* Local prototypes */ 58 59 static void 60 AcpiDmUnicode ( 61 ACPI_PARSE_OBJECT *Op); 62 63 static void 64 AcpiDmIsEisaIdElement ( 65 ACPI_PARSE_OBJECT *Op); 66 67 68 /******************************************************************************* 69 * 70 * FUNCTION: AcpiDmDisasmByteList 71 * 72 * PARAMETERS: Level - Current source code indentation level 73 * ByteData - Pointer to the byte list 74 * ByteCount - Length of the byte list 75 * 76 * RETURN: None 77 * 78 * DESCRIPTION: Dump an AML "ByteList" in Hex format. 8 bytes per line, prefixed 79 * with the hex buffer offset. 80 * 81 ******************************************************************************/ 82 83 void 84 AcpiDmDisasmByteList ( 85 UINT32 Level, 86 UINT8 *ByteData, 87 UINT32 ByteCount) 88 { 89 UINT32 i; 90 91 92 if (!ByteCount) 93 { 94 return; 95 } 96 97 /* Dump the byte list */ 98 99 for (i = 0; i < ByteCount; i++) 100 { 101 /* New line every 8 bytes */ 102 103 if (((i % 8) == 0) && (i < ByteCount)) 104 { 105 if (i > 0) 106 { 107 AcpiOsPrintf ("\n"); 108 } 109 110 AcpiDmIndent (Level); 111 if (ByteCount > 7) 112 { 113 AcpiOsPrintf ("/* %04X */ ", i); 114 } 115 } 116 117 AcpiOsPrintf ("0x%2.2X", (UINT32) ByteData[i]); 118 119 /* Add comma if there are more bytes to display */ 120 121 if (i < (ByteCount -1)) 122 { 123 AcpiOsPrintf (", "); 124 } 125 } 126 127 if (Level) 128 { 129 AcpiOsPrintf ("\n"); 130 } 131 } 132 133 134 /******************************************************************************* 135 * 136 * FUNCTION: AcpiDmByteList 137 * 138 * PARAMETERS: Info - Parse tree walk info 139 * Op - Byte list op 140 * 141 * RETURN: None 142 * 143 * DESCRIPTION: Dump a buffer byte list, handling the various types of buffers. 144 * Buffer type must be already set in the Op DisasmOpcode. 145 * 146 ******************************************************************************/ 147 148 void 149 AcpiDmByteList ( 150 ACPI_OP_WALK_INFO *Info, 151 ACPI_PARSE_OBJECT *Op) 152 { 153 UINT8 *ByteData; 154 UINT32 ByteCount; 155 156 157 ByteData = Op->Named.Data; 158 ByteCount = (UINT32) Op->Common.Value.Integer; 159 160 /* 161 * The byte list belongs to a buffer, and can be produced by either 162 * a ResourceTemplate, Unicode, quoted string, or a plain byte list. 163 */ 164 switch (Op->Common.Parent->Common.DisasmOpcode) 165 { 166 case ACPI_DASM_RESOURCE: 167 168 AcpiDmResourceTemplate (Info, Op->Common.Parent, ByteData, ByteCount); 169 break; 170 171 case ACPI_DASM_STRING: 172 173 AcpiDmIndent (Info->Level); 174 AcpiUtPrintString ((char *) ByteData, ACPI_UINT8_MAX); 175 AcpiOsPrintf ("\n"); 176 break; 177 178 case ACPI_DASM_UNICODE: 179 180 AcpiDmUnicode (Op); 181 break; 182 183 case ACPI_DASM_BUFFER: 184 default: 185 186 /* 187 * Not a resource, string, or unicode string. 188 * Just dump the buffer 189 */ 190 AcpiDmDisasmByteList (Info->Level, ByteData, ByteCount); 191 break; 192 } 193 } 194 195 196 /******************************************************************************* 197 * 198 * FUNCTION: AcpiDmIsUnicodeBuffer 199 * 200 * PARAMETERS: Op - Buffer Object to be examined 201 * 202 * RETURN: TRUE if buffer contains a UNICODE string 203 * 204 * DESCRIPTION: Determine if a buffer Op contains a Unicode string 205 * 206 ******************************************************************************/ 207 208 BOOLEAN 209 AcpiDmIsUnicodeBuffer ( 210 ACPI_PARSE_OBJECT *Op) 211 { 212 UINT8 *ByteData; 213 UINT32 ByteCount; 214 UINT32 WordCount; 215 ACPI_PARSE_OBJECT *SizeOp; 216 ACPI_PARSE_OBJECT *NextOp; 217 UINT32 i; 218 219 220 /* Buffer size is the buffer argument */ 221 222 SizeOp = Op->Common.Value.Arg; 223 224 /* Next, the initializer byte list to examine */ 225 226 NextOp = SizeOp->Common.Next; 227 if (!NextOp) 228 { 229 return (FALSE); 230 } 231 232 /* Extract the byte list info */ 233 234 ByteData = NextOp->Named.Data; 235 ByteCount = (UINT32) NextOp->Common.Value.Integer; 236 WordCount = ACPI_DIV_2 (ByteCount); 237 238 /* 239 * Unicode string must have an even number of bytes and last 240 * word must be zero 241 */ 242 if ((!ByteCount) || 243 (ByteCount < 4) || 244 (ByteCount & 1) || 245 ((UINT16 *) (void *) ByteData)[WordCount - 1] != 0) 246 { 247 return (FALSE); 248 } 249 250 /* For each word, 1st byte must be ascii, 2nd byte must be zero */ 251 252 for (i = 0; i < (ByteCount - 2); i += 2) 253 { 254 if ((!ACPI_IS_PRINT (ByteData[i])) || 255 (ByteData[(ACPI_SIZE) i + 1] != 0)) 256 { 257 return (FALSE); 258 } 259 } 260 261 /* Ignore the Size argument in the disassembly of this buffer op */ 262 263 SizeOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE; 264 return (TRUE); 265 } 266 267 268 /******************************************************************************* 269 * 270 * FUNCTION: AcpiDmIsStringBuffer 271 * 272 * PARAMETERS: Op - Buffer Object to be examined 273 * 274 * RETURN: TRUE if buffer contains a ASCII string, FALSE otherwise 275 * 276 * DESCRIPTION: Determine if a buffer Op contains a ASCII string 277 * 278 ******************************************************************************/ 279 280 BOOLEAN 281 AcpiDmIsStringBuffer ( 282 ACPI_PARSE_OBJECT *Op) 283 { 284 UINT8 *ByteData; 285 UINT32 ByteCount; 286 ACPI_PARSE_OBJECT *SizeOp; 287 ACPI_PARSE_OBJECT *NextOp; 288 UINT32 i; 289 290 291 /* Buffer size is the buffer argument */ 292 293 SizeOp = Op->Common.Value.Arg; 294 295 /* Next, the initializer byte list to examine */ 296 297 NextOp = SizeOp->Common.Next; 298 if (!NextOp) 299 { 300 return (FALSE); 301 } 302 303 /* Extract the byte list info */ 304 305 ByteData = NextOp->Named.Data; 306 ByteCount = (UINT32) NextOp->Common.Value.Integer; 307 308 /* Last byte must be the null terminator */ 309 310 if ((!ByteCount) || 311 (ByteCount < 2) || 312 (ByteData[ByteCount-1] != 0)) 313 { 314 return (FALSE); 315 } 316 317 for (i = 0; i < (ByteCount - 1); i++) 318 { 319 /* TBD: allow some escapes (non-ascii chars). 320 * they will be handled in the string output routine 321 */ 322 323 if (!ACPI_IS_PRINT (ByteData[i])) 324 { 325 return (FALSE); 326 } 327 } 328 329 return (TRUE); 330 } 331 332 333 /******************************************************************************* 334 * 335 * FUNCTION: AcpiDmUnicode 336 * 337 * PARAMETERS: Op - Byte List op containing Unicode string 338 * 339 * RETURN: None 340 * 341 * DESCRIPTION: Dump Unicode string as a standard ASCII string. (Remove 342 * the extra zero bytes). 343 * 344 ******************************************************************************/ 345 346 static void 347 AcpiDmUnicode ( 348 ACPI_PARSE_OBJECT *Op) 349 { 350 UINT16 *WordData; 351 UINT32 WordCount; 352 UINT32 i; 353 354 355 /* Extract the buffer info as a WORD buffer */ 356 357 WordData = ACPI_CAST_PTR (UINT16, Op->Named.Data); 358 WordCount = ACPI_DIV_2 (((UINT32) Op->Common.Value.Integer)); 359 360 361 AcpiOsPrintf ("\""); 362 363 /* Write every other byte as an ASCII character */ 364 365 for (i = 0; i < (WordCount - 1); i++) 366 { 367 AcpiOsPrintf ("%c", (int) WordData[i]); 368 } 369 370 AcpiOsPrintf ("\")"); 371 } 372 373 374 /******************************************************************************* 375 * 376 * FUNCTION: AcpiDmIsEisaIdElement 377 * 378 * PARAMETERS: Op - Op to be examined 379 * 380 * RETURN: None 381 * 382 * DESCRIPTION: Determine if an Op (argument to _HID or _CID) can be converted 383 * to an EISA ID. 384 * 385 ******************************************************************************/ 386 387 static void 388 AcpiDmIsEisaIdElement ( 389 ACPI_PARSE_OBJECT *Op) 390 { 391 UINT32 BigEndianId; 392 UINT32 Prefix[3]; 393 UINT32 i; 394 395 396 /* The parameter must be either a word or a dword */ 397 398 if ((Op->Common.AmlOpcode != AML_DWORD_OP) && 399 (Op->Common.AmlOpcode != AML_WORD_OP)) 400 { 401 return; 402 } 403 404 /* Swap from little-endian to big-endian to simplify conversion */ 405 406 BigEndianId = AcpiUtDwordByteSwap ((UINT32) Op->Common.Value.Integer); 407 408 /* Create the 3 leading ASCII letters */ 409 410 Prefix[0] = ((BigEndianId >> 26) & 0x1F) + 0x40; 411 Prefix[1] = ((BigEndianId >> 21) & 0x1F) + 0x40; 412 Prefix[2] = ((BigEndianId >> 16) & 0x1F) + 0x40; 413 414 /* Verify that all 3 are ascii and alpha */ 415 416 for (i = 0; i < 3; i++) 417 { 418 if (!ACPI_IS_ASCII (Prefix[i]) || 419 !ACPI_IS_ALPHA (Prefix[i])) 420 { 421 return; 422 } 423 } 424 425 /* OK - mark this node as convertable to an EISA ID */ 426 427 Op->Common.DisasmOpcode = ACPI_DASM_EISAID; 428 } 429 430 431 /******************************************************************************* 432 * 433 * FUNCTION: AcpiDmIsEisaId 434 * 435 * PARAMETERS: Op - Op to be examined 436 * 437 * RETURN: None 438 * 439 * DESCRIPTION: Determine if a Name() Op can be converted to an EisaId. 440 * 441 ******************************************************************************/ 442 443 void 444 AcpiDmIsEisaId ( 445 ACPI_PARSE_OBJECT *Op) 446 { 447 UINT32 Name; 448 ACPI_PARSE_OBJECT *NextOp; 449 450 451 /* Get the NameSegment */ 452 453 Name = AcpiPsGetName (Op); 454 if (!Name) 455 { 456 return; 457 } 458 459 NextOp = AcpiPsGetDepthNext (NULL, Op); 460 if (!NextOp) 461 { 462 return; 463 } 464 465 /* Check for _HID - has one argument */ 466 467 if (ACPI_COMPARE_NAME (&Name, METHOD_NAME__HID)) 468 { 469 AcpiDmIsEisaIdElement (NextOp); 470 return; 471 } 472 473 /* Exit if not _CID */ 474 475 if (!ACPI_COMPARE_NAME (&Name, METHOD_NAME__CID)) 476 { 477 return; 478 } 479 480 /* _CID can contain a single argument or a package */ 481 482 if (NextOp->Common.AmlOpcode != AML_PACKAGE_OP) 483 { 484 AcpiDmIsEisaIdElement (NextOp); 485 return; 486 } 487 488 /* _CID with Package: get the package length */ 489 490 NextOp = AcpiPsGetDepthNext (NULL, NextOp); 491 492 /* Don't need to use the length, just walk the peer list */ 493 494 NextOp = NextOp->Common.Next; 495 while (NextOp) 496 { 497 AcpiDmIsEisaIdElement (NextOp); 498 NextOp = NextOp->Common.Next; 499 } 500 } 501 502 503 /******************************************************************************* 504 * 505 * FUNCTION: AcpiDmEisaId 506 * 507 * PARAMETERS: EncodedId - Raw encoded EISA ID. 508 * 509 * RETURN: None 510 * 511 * DESCRIPTION: Convert an encoded EISAID back to the original ASCII String. 512 * 513 ******************************************************************************/ 514 515 void 516 AcpiDmEisaId ( 517 UINT32 EncodedId) 518 { 519 UINT32 BigEndianId; 520 521 522 /* Swap from little-endian to big-endian to simplify conversion */ 523 524 BigEndianId = AcpiUtDwordByteSwap (EncodedId); 525 526 527 /* Split to form "AAANNNN" string */ 528 529 AcpiOsPrintf ("EisaId (\"%c%c%c%4.4X\")", 530 531 /* Three Alpha characters (AAA), 5 bits each */ 532 533 (int) ((BigEndianId >> 26) & 0x1F) + 0x40, 534 (int) ((BigEndianId >> 21) & 0x1F) + 0x40, 535 (int) ((BigEndianId >> 16) & 0x1F) + 0x40, 536 537 /* Numeric part (NNNN) is simply the lower 16 bits */ 538 539 (UINT32) (BigEndianId & 0xFFFF)); 540 } 541 542 #endif 543