Changeset 41496 in vbox for trunk/src/VBox/Devices/PC
- Timestamp:
- May 30, 2012 1:49:26 PM (13 years ago)
- Location:
- trunk/src/VBox/Devices/PC/BIOS-new
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/PC/BIOS-new/MakeDebianBiosAssembly.cpp
r41489 r41496 20 20 * Header Files * 21 21 *******************************************************************************/ 22 #include <iprt/asm.h> 22 23 #include <iprt/buildconfig.h> 23 24 #include <iprt/ctype.h> … … 30 31 #include <iprt/string.h> 31 32 #include <iprt/stream.h> 33 34 #include <VBox/dis.h> 35 36 37 /******************************************************************************* 38 * Defined Constants And Macros * 39 *******************************************************************************/ 40 /** The flat ROM base address. */ 41 #define VBOX_BIOS_BASE UINT32_C(0xf0000) 32 42 33 43 … … 138 148 139 149 /** 150 * Displays a disassembly error and returns @c false. 151 * 152 * @returns @c false. 153 * @param pszFormat The error format string. 154 * @param ... Format argument. 155 */ 156 static bool disError(const char *pszFormat, ...) 157 { 158 va_list va; 159 va_start(va, pszFormat); 160 RTMsgErrorV(pszFormat, va); 161 va_end(va); 162 return false; 163 } 164 165 166 /** 140 167 * Output the disassembly file header. 141 168 * … … 144 171 static bool disFileHeader(void) 145 172 { 146 bool fRc = true; 147 fRc = fRc && outputPrintf("; $Id$ \n" 148 ";; @file\n" 149 "; Auto Generated source file. Do not edit.\n" 150 ";\n" 151 "\n" 152 "org 0xf000\n" 153 "\n" 154 ); 155 return fRc; 173 return outputPrintf("; $Id$ \n" 174 ";; @file\n" 175 "; Auto Generated source file. Do not edit.\n" 176 ";\n" 177 "\n" 178 "org 0xf000\n" 179 "\n" 180 ); 181 } 182 183 184 /** 185 * Checks if a byte sequence could be a string litteral. 186 * 187 * @returns @c true if it is, @c false if it isn't. 188 * @param uFlatAddr The address of the byte sequence. 189 * @param cb The length of the sequence. 190 */ 191 static bool disIsString(uint32_t uFlatAddr, uint32_t cb) 192 { 193 if (cb < 6) 194 return false; 195 196 uint8_t const *pb = &g_pbImg[uFlatAddr - VBOX_BIOS_BASE]; 197 while (cb > 0) 198 { 199 if ( !RT_C_IS_PRINT(*pb) 200 && *pb != '\r' 201 && *pb != '\n' 202 && *pb != '\t') 203 { 204 if (*pb == '\0') 205 { 206 do 207 { 208 pb++; 209 cb--; 210 } while (cb > 0 && *pb == '\0'); 211 return cb == 0; 212 } 213 return false; 214 } 215 pb++; 216 cb--; 217 } 218 219 return true; 220 } 221 222 223 /** 224 * Checks if a dword could be a far 16:16 BIOS address. 225 * 226 * @returns @c true if it is, @c false if it isn't. 227 * @param uFlatAddr The address of the dword. 228 */ 229 static bool disIsFarBiosAddr(uint32_t uFlatAddr) 230 { 231 uint16_t const *pu16 = (uint16_t const *)&g_pbImg[uFlatAddr - VBOX_BIOS_BASE]; 232 if (pu16[1] < 0xf000) 233 return false; 234 if (pu16[1] > 0xfff0) 235 return false; 236 uint32_t uFlatAddr2 = (uint32_t)(pu16[1] << 4) | pu16[0]; 237 if (uFlatAddr2 >= VBOX_BIOS_BASE + _64K) 238 return false; 239 return true; 156 240 } 157 241 … … 159 243 static bool disByteData(uint32_t uFlatAddr, uint32_t cb) 160 244 { 161 uint8_t const *pb = &g_pbImg[uFlatAddr - 0xf0000];245 uint8_t const *pb = &g_pbImg[uFlatAddr - VBOX_BIOS_BASE]; 162 246 size_t cbOnLine = 0; 163 247 while (cb-- > 0) … … 167 251 { 168 252 fRc = outputPrintf("\n" 169 " db0%02xh", *pb);253 " db 0%02xh", *pb); 170 254 cbOnLine = 1; 171 255 } 172 256 else if (!cbOnLine) 173 257 { 174 fRc = outputPrintf(" db0%02xh", *pb);258 fRc = outputPrintf(" db 0%02xh", *pb); 175 259 cbOnLine = 1; 176 260 } … … 188 272 189 273 190 274 static bool disWordData(uint32_t uFlatAddr, uint32_t cb) 275 { 276 if (cb & 1) 277 return disError("disWordData expects word aligned size: cb=%#x uFlatAddr=%#x", uFlatAddr, cb); 278 279 uint16_t const *pu16 = (uint16_t const *)&g_pbImg[uFlatAddr - VBOX_BIOS_BASE]; 280 size_t cbOnLine = 0; 281 while (cb > 0) 282 { 283 bool fRc; 284 if (cbOnLine >= 16) 285 { 286 fRc = outputPrintf("\n" 287 " dw 0%04xh", *pu16); 288 cbOnLine = 2; 289 } 290 else if (!cbOnLine) 291 { 292 fRc = outputPrintf(" dw 0%04xh", *pu16); 293 cbOnLine = 2; 294 } 295 else 296 { 297 fRc = outputPrintf(", 0%04xh", *pu16); 298 cbOnLine += 2; 299 } 300 if (!fRc) 301 return false; 302 pu16++; 303 cb -= 2; 304 } 305 return outputPrintf("\n"); 306 } 307 308 309 static bool disDWordData(uint32_t uFlatAddr, uint32_t cb) 310 { 311 if (cb & 3) 312 return disError("disWordData expects dword aligned size: cb=%#x uFlatAddr=%#x", uFlatAddr, cb); 313 314 uint32_t const *pu32 = (uint32_t const *)&g_pbImg[uFlatAddr - VBOX_BIOS_BASE]; 315 size_t cbOnLine = 0; 316 while (cb > 0) 317 { 318 bool fRc; 319 if (cbOnLine >= 16) 320 { 321 fRc = outputPrintf("\n" 322 " dd 0%08xh", *pu32); 323 cbOnLine = 4; 324 } 325 else if (!cbOnLine) 326 { 327 fRc = outputPrintf(" dd 0%08xh", *pu32); 328 cbOnLine = 4; 329 } 330 else 331 { 332 fRc = outputPrintf(", 0%08xh", *pu32); 333 cbOnLine += 4; 334 } 335 if (!fRc) 336 return false; 337 pu32++; 338 cb -= 4; 339 } 340 return outputPrintf("\n"); 341 } 342 343 344 static bool disStringData(uint32_t uFlatAddr, uint32_t cb) 345 { 346 uint8_t const *pb = &g_pbImg[uFlatAddr - VBOX_BIOS_BASE]; 347 size_t cchOnLine = 0; 348 while (cb > 0) 349 { 350 /* Line endings and beginnings. */ 351 if (cchOnLine >= 72) 352 { 353 if (!outputPrintf("\n")) 354 return false; 355 cchOnLine = 0; 356 } 357 if ( !cchOnLine 358 && !outputPrintf(" db ")) 359 return false; 360 361 /* See how many printable character we've got. */ 362 uint32_t cchPrintable = 0; 363 while ( cchPrintable < cb 364 && RT_C_IS_PRINT(pb[cchPrintable]) 365 && pb[cchPrintable] != '\'') 366 cchPrintable++; 367 368 bool fRc = true; 369 if (cchPrintable) 370 { 371 if (cchPrintable + cchOnLine > 72) 372 cchPrintable = 72 - cchOnLine; 373 if (cchOnLine) 374 { 375 fRc = outputPrintf(", '%.*s'", cchPrintable, pb); 376 cchOnLine += 4 + cchPrintable; 377 } 378 else 379 { 380 fRc = outputPrintf("'%.*s'", cchPrintable, pb); 381 cchOnLine += 2 + cchPrintable; 382 } 383 pb += cchPrintable; 384 cb -= cchPrintable; 385 } 386 else 387 { 388 if (cchOnLine) 389 { 390 fRc = outputPrintf(", 0%02xh", *pb); 391 cchOnLine += 6; 392 } 393 else 394 { 395 fRc = outputPrintf("0%02xh", *pb); 396 cchOnLine += 4; 397 } 398 pb++; 399 cb--; 400 } 401 if (!fRc) 402 return false; 403 } 404 return outputPrintf("\n"); 405 } 406 407 408 /** 409 * For dumping a portion of a string table. 410 * 411 * @returns @c true on success, @c false on failure. 412 * @param uFlatAddr The start address. 413 * @param cb The size of the string table. 414 */ 415 static bool disStringsData(uint32_t uFlatAddr, uint32_t cb) 416 { 417 uint8_t const *pb = &g_pbImg[uFlatAddr - VBOX_BIOS_BASE]; 418 size_t cchOnLine = 0; 419 uint8_t bPrev = 255; 420 while (cb > 0) 421 { 422 /* Line endings and beginnings. */ 423 if ( cchOnLine >= 72 424 || (bPrev == '\0' && *pb != '\0')) 425 { 426 if (!outputPrintf("\n")) 427 return false; 428 cchOnLine = 0; 429 } 430 if ( !cchOnLine 431 && !outputPrintf(" db ")) 432 return false; 433 434 /* See how many printable character we've got. */ 435 uint32_t cchPrintable = 0; 436 while ( cchPrintable < cb 437 && RT_C_IS_PRINT(pb[cchPrintable]) 438 && pb[cchPrintable] != '\'') 439 cchPrintable++; 440 441 bool fRc = true; 442 if (cchPrintable) 443 { 444 if (cchPrintable + cchOnLine > 72) 445 cchPrintable = 72 - cchOnLine; 446 if (cchOnLine) 447 { 448 fRc = outputPrintf(", '%.*s'", cchPrintable, pb); 449 cchOnLine += 4 + cchPrintable; 450 } 451 else 452 { 453 fRc = outputPrintf("'%.*s'", cchPrintable, pb); 454 cchOnLine += 2 + cchPrintable; 455 } 456 pb += cchPrintable; 457 cb -= cchPrintable; 458 } 459 else 460 { 461 if (cchOnLine) 462 { 463 fRc = outputPrintf(", 0%02xh", *pb); 464 cchOnLine += 6; 465 } 466 else 467 { 468 fRc = outputPrintf("0%02xh", *pb); 469 cchOnLine += 4; 470 } 471 pb++; 472 cb--; 473 } 474 if (!fRc) 475 return false; 476 bPrev = pb[-1]; 477 } 478 return outputPrintf("\n"); 479 } 480 481 482 /** 483 * Minds the gap between two segments. 484 * 485 * Gaps should generally be zero filled. 486 * 487 * @returns @c true on success, @c false on failure. 488 * @param uFlatAddr The address of the gap. 489 * @param cbPadding The size of the gap. 490 */ 191 491 static bool disCopySegmentGap(uint32_t uFlatAddr, uint32_t cbPadding) 192 492 { 193 493 if (g_cVerbose > 0) 194 RTStrmPrintf(g_pStdErr, "Padding %#x bytes at %#x\n", cbPadding, uFlatAddr); 494 outputPrintf("\n" 495 " ; Padding %#x bytes at %#x\n", cbPadding, uFlatAddr); 496 uint8_t const *pb = &g_pbImg[uFlatAddr - VBOX_BIOS_BASE]; 497 if (!ASMMemIsAll8(pb, cbPadding, 0)) 498 return outputPrintf(" times %u db 0\n", cbPadding); 499 195 500 return disByteData(uFlatAddr, cbPadding); 196 501 } 197 502 198 503 504 /** 505 * Worker for disGetNextSymbol that only does the looking up, no RTDBSYMBOL::cb 506 * calc. 507 * 508 * @param uFlatAddr The address to start searching at. 509 * @param cbMax The size of the search range. 510 * @param poff Where to return the offset between the symbol 511 * and @a uFlatAddr. 512 * @param pSym Where to return the symbol data. 513 */ 514 static void disGetNextSymbolWorker(uint32_t uFlatAddr, uint32_t cbMax, uint32_t *poff, PRTDBGSYMBOL pSym) 515 { 516 RTINTPTR off = 0; 517 int rc = RTDbgModSymbolByAddr(g_hMapMod, RTDBGSEGIDX_RVA, uFlatAddr, RTDBGSYMADDR_FLAGS_GREATER_OR_EQUAL, &off, pSym); 518 if (RT_SUCCESS(rc)) 519 { 520 /* negative offset, indicates beyond. */ 521 if (off <= 0) 522 { 523 *poff = (uint32_t)-off; 524 return; 525 } 526 527 outputPrintf(" ; !! RTDbgModSymbolByAddr(,,%#x,,) -> off=%RTptr cb=%RTptr uValue=%RTptr '%s'\n", 528 uFlatAddr, off, pSym->cb, pSym->Value, pSym->szName); 529 } 530 else if (rc != VERR_SYMBOL_NOT_FOUND) 531 outputPrintf(" ; !! RTDbgModSymbolByAddr(,,%#x,,) -> %Rrc\n", uFlatAddr, rc); 532 533 RTStrPrintf(pSym->szName, sizeof(pSym->szName), "_dummy_addr_%#x", uFlatAddr + cbMax); 534 pSym->Value = uFlatAddr + cbMax; 535 pSym->cb = 0; 536 pSym->offSeg = uFlatAddr + cbMax; 537 pSym->iSeg = RTDBGSEGIDX_RVA; 538 pSym->iOrdinal = 0; 539 pSym->fFlags = 0; 540 *poff = cbMax; 541 } 542 543 544 /** 545 * Gets the symbol at or after the given address. 546 * 547 * If there are no symbols in the specified range, @a pSym and @a poff will be 548 * set up to indicate a symbol at the first byte after the range. 549 * 550 * @param uFlatAddr The address to start searching at. 551 * @param cbMax The size of the search range. 552 * @param poff Where to return the offset between the symbol 553 * and @a uFlatAddr. 554 * @param pSym Where to return the symbol data. 555 */ 556 static void disGetNextSymbol(uint32_t uFlatAddr, uint32_t cbMax, uint32_t *poff, PRTDBGSYMBOL pSym) 557 { 558 disGetNextSymbolWorker(uFlatAddr, cbMax, poff, pSym); 559 if ( *poff < cbMax 560 && pSym->cb == 0) 561 { 562 if (*poff + 1 < cbMax) 563 { 564 uint32_t off2; 565 RTDBGSYMBOL Sym2; 566 disGetNextSymbolWorker(uFlatAddr + *poff + 1, cbMax - *poff - 1, &off2, &Sym2); 567 pSym->cb = off2 + 1; 568 } 569 else 570 pSym->cb = 1; 571 } 572 if (pSym->cb > cbMax - *poff) 573 pSym->cb = cbMax - *poff; 574 575 if (g_cVerbose > 1) 576 outputPrintf(" ; disGetNextSymbol %#x LB %#x -> off=%#x cb=%RTptr uValue=%RTptr '%s'\n", 577 uFlatAddr, cbMax, *poff, pSym->cb, pSym->Value, pSym->szName); 578 579 } 580 581 582 /** 583 * For dealing with the const segment (string constants). 584 * 585 * @returns @c true on success, @c false on failure. 586 * @param iSeg The segment. 587 */ 588 static bool disConstSegment(uint32_t iSeg) 589 { 590 uint32_t uFlatAddr = g_aSegs[iSeg].uFlatAddr; 591 uint32_t cb = g_aSegs[iSeg].cb; 592 593 while (cb > 0) 594 { 595 uint32_t off; 596 RTDBGSYMBOL Sym; 597 disGetNextSymbol(uFlatAddr, cb, &off, &Sym); 598 599 if (off > 0) 600 { 601 if (!disStringsData(uFlatAddr, off)) 602 return false; 603 cb -= off; 604 uFlatAddr += off; 605 off = 0; 606 if (!cb) 607 break; 608 } 609 610 bool fRc; 611 if (off == 0) 612 { 613 size_t cchName = strlen(Sym.szName); 614 fRc = outputPrintf("%s: %*s; %#x LB %#x\n", Sym.szName, cchName < 41 - 2 ? cchName - 41 - 2 : 0, "", uFlatAddr, Sym.cb); 615 if (!fRc) 616 return false; 617 fRc = disStringsData(uFlatAddr, Sym.cb); 618 uFlatAddr += Sym.cb; 619 cb -= Sym.cb; 620 } 621 else 622 { 623 fRc = disStringsData(uFlatAddr, Sym.cb); 624 uFlatAddr += cb; 625 cb = 0; 626 } 627 if (!fRc) 628 return false; 629 } 630 631 return true; 632 } 633 634 635 199 636 static bool disDataSegment(uint32_t iSeg) 200 637 { 201 return disByteData(g_aSegs[iSeg].uFlatAddr, g_aSegs[iSeg].cb); 638 uint32_t uFlatAddr = g_aSegs[iSeg].uFlatAddr; 639 uint32_t cb = g_aSegs[iSeg].cb; 640 641 while (cb > 0) 642 { 643 uint32_t off; 644 RTDBGSYMBOL Sym; 645 disGetNextSymbol(uFlatAddr, cb, &off, &Sym); 646 647 if (off > 0) 648 { 649 if (!disByteData(uFlatAddr, off)) 650 return false; 651 cb -= off; 652 uFlatAddr += off; 653 off = 0; 654 if (!cb) 655 break; 656 } 657 658 bool fRc; 659 if (off == 0) 660 { 661 size_t cchName = strlen(Sym.szName); 662 fRc = outputPrintf("%s: %*s; %#x LB %#x\n", Sym.szName, cchName < 41 - 2 ? cchName - 41 - 2 : 0, "", uFlatAddr, Sym.cb); 663 if (!fRc) 664 return false; 665 666 if (Sym.cb == 2) 667 fRc = disWordData(uFlatAddr, 2); 668 //else if (Sym.cb == 4 && disIsFarBiosAddr(uFlatAddr)) 669 // fRc = disDWordData(uFlatAddr, 4); 670 else if (Sym.cb == 4) 671 fRc = disDWordData(uFlatAddr, 4); 672 else if (disIsString(uFlatAddr, Sym.cb)) 673 fRc = disStringData(uFlatAddr, Sym.cb); 674 else 675 fRc = disByteData(uFlatAddr, Sym.cb); 676 677 uFlatAddr += Sym.cb; 678 cb -= Sym.cb; 679 } 680 else 681 { 682 fRc = disByteData(uFlatAddr, cb); 683 uFlatAddr += cb; 684 cb = 0; 685 } 686 if (!fRc) 687 return false; 688 } 689 690 return true; 691 } 692 693 694 static bool disIsCodeAndAdjustSize(uint32_t uFlatAddr, PRTDBGSYMBOL pSym, PBIOSSEG pSeg) 695 { 696 if (!strcmp(pSeg->szName, "BIOSSEG")) 697 { 698 if ( !strcmp(pSym->szName, "rom_fdpt") 699 || !strcmp(pSym->szName, "pmbios_gdt") 700 || !strcmp(pSym->szName, "pmbios_gdt_desc") 701 || !strcmp(pSym->szName, "_pmode_IDT") 702 || !strcmp(pSym->szName, "_rmode_IDT") 703 || !strncmp(pSym->szName, RT_STR_TUPLE("font")) 704 || !strcmp(pSym->szName, "bios_string") 705 || !strcmp(pSym->szName, "vector_table") 706 || !strcmp(pSym->szName, "pci_routing_table_structure") 707 ) 708 return false; 709 } 710 711 if (!strcmp(pSym->szName, "cpu_reset")) 712 pSym->cb = RT_MIN(pSym->cb, 5); 713 else if (!strcmp(pSym->szName, "pci_init_end")) 714 pSym->cb = RT_MIN(pSym->cb, 3); 715 716 return true; 717 } 718 719 720 static bool disIs16BitCode(const char *pszSymbol) 721 { 722 return true; 723 } 724 725 /* 726 < 00006590 67 aa 67 e7 67 1b 68 56 55 89 e5 83 ec 08 8a 46 |g.g.g.hVU......F| 727 < 000065a0 23 30 e4 3d e8 00 74 3f 3d 86 00 75 49 fb 8b 46 |#0.=..t?=..uI..F| 728 729 > 00006590 67 aa e7 67 1b 68 56 55 89 e5 83 ec 08 8a 46 23 |g..g.hVU......F#| 730 > 000065a0 30 e4 3d e8 00 74 40 3d 86 00 75 4a fb 8b 46 1e |0.=..t@=..uJ..F.| 731 */ 732 733 /** 734 * Deals with instructions that YASM will assemble differently than WASM/WCC. 735 */ 736 static size_t disHandleYasmDifferences(PDISCPUSTATE pCpuState, uint32_t uFlatAddr, uint32_t cbInstr, 737 char *pszBuf, size_t cbBuf, size_t cchUsed) 738 { 739 bool fDifferent = false; 740 uint8_t const *pb = &g_pbImg[uFlatAddr - VBOX_BIOS_BASE]; 741 if ( pb[0] == 0x2a 742 && pb[1] == 0xe4) 743 fDifferent = true; /* sub ah, ah - alternative form 0x28 0x?? */ 744 else if ( pb[0] == 0x2b 745 && pb[1] == 0xc2) 746 fDifferent = true; /* sub ax, dx - alternative form 0x29 0xd0. */ 747 else if ( pb[0] == 0x1b 748 && pb[1] == 0xff) 749 fDifferent = true; /* sbb di, di - alternative form 0x19 0xff. */ 750 else if ( pb[0] == 0x33 751 && ( pb[1] == 0xdb /* xor bx, bx */ 752 || pb[1] == 0xf6 /* xor si, si */ 753 || pb[1] == 0xff /* xor di, di */ 754 || pb[1] == 0xc0 /* xor ax, ax */ 755 )) 756 fDifferent = true; /* xor x, x - alternative form 0x31 xxxx. */ 757 else if ( pb[0] == 0x66 758 && pb[1] == 0x33 759 && pb[2] == 0xc0) 760 fDifferent = true; /* xor eax, eax - alternative form 0x66 0x31 0xc0. */ 761 else if ( pb[0] == 0xf3 762 && pb[1] == 0x66 763 && pb[2] == 0x6d) 764 fDifferent = true; /* rep insd - prefix switched. */ 765 else if ( pb[0] == 0xf3 766 && pb[1] == 0x66 767 && pb[2] == 0x26 768 && pb[3] == 0x6f) 769 fDifferent = true; /* rep es outsd - prefix switched. */ 770 else if ( pb[0] == 0xc6 771 && pb[1] == 0xc5 772 && pb[2] == 0xba) 773 fDifferent = true; /* mov ch, 0bah - yasm uses a short sequence: 0xb5 0xba. */ 774 else if ( pb[0] == 0x8b 775 && pb[1] == 0xe0) 776 fDifferent = true; /* mov sp, ax - alternative form 0x89 c4. */ 777 /* 778 * Switch table fun (.sym may help): 779 */ 780 else if ( pb[0] == 0x64 781 && pb[1] == 0x65 782 && pb[2] == 0x05 783 /*&& pb[3] == 0x61 784 && pb[4] == 0x19*/) 785 fDifferent = true; /* gs add ax, 01961h - both fs and gs prefix. Probably some switch table. */ 786 else if ( pb[0] == 0x65 787 && pb[1] == 0x36 788 && pb[2] == 0x65 789 && pb[3] == 0xae) 790 fDifferent = true; /* gs scasb - switch table or smth. */ 791 else if ( pb[0] == 0x67 792 && pb[1] == 0xe7 793 /*&& pb[2] == 0x67*/) 794 fDifferent = true; /* out 067h, ax - switch table or smth. */ 795 /* 796 * Disassembler / formatter bugs: 797 */ 798 else if (pb[0] == 0x6c && RT_C_IS_SPACE(*pszBuf)) 799 fDifferent = true; 800 801 802 /* 803 * Handle different stuff. 804 */ 805 if (fDifferent) 806 { 807 disByteData(uFlatAddr, cbInstr); /* lazy bird. */ 808 809 if (cchUsed + 2 < cbBuf) 810 { 811 memmove(pszBuf + 2, pszBuf, cchUsed + 2); 812 cchUsed += 2; 813 } 814 815 pszBuf[0] = ';'; 816 pszBuf[1] = ' '; 817 } 818 819 return cchUsed; 820 } 821 822 823 /** 824 * Disassembler callback for reading opcode bytes. 825 * 826 * @returns VINF_SUCCESS. 827 * @param uFlatAddr The address to read at. 828 * @param pbDst Where to store them. 829 * @param cbToRead How many to read. 830 * @param pvUser Unused. 831 */ 832 static DECLCALLBACK(int) disReadOpcodeBytes(RTUINTPTR uFlatAddr, uint8_t *pbDst, unsigned cbToRead, void *pvUser) 833 { 834 if (uFlatAddr + cbToRead >= VBOX_BIOS_BASE + _64K) 835 { 836 RT_BZERO(pbDst, cbToRead); 837 if (uFlatAddr >= VBOX_BIOS_BASE + _64K) 838 cbToRead = 0; 839 else 840 cbToRead = VBOX_BIOS_BASE + _64K - uFlatAddr; 841 } 842 memcpy(pbDst, &g_pbImg[uFlatAddr - VBOX_BIOS_BASE], cbToRead); 843 NOREF(pvUser); 844 return VINF_SUCCESS; 845 } 846 847 848 /** 849 * Disassembles code. 850 * 851 * @returns @c true on success, @c false on failure. 852 * @param uFlatAddr The address where the code starts. 853 * @param cb The amount of code to disassemble. 854 * @param fIs16Bit Is is 16-bit (@c true) or 32-bit (@c false). 855 */ 856 static bool disCode(uint32_t uFlatAddr, uint32_t cb, bool fIs16Bit) 857 { 858 uint8_t const *pb = &g_pbImg[uFlatAddr - VBOX_BIOS_BASE]; 859 860 while (cb > 0) 861 { 862 /* Trailing zero padding detection. */ 863 if ( *pb == '\0' 864 && ASMMemIsAll8(pb, RT_MIN(cb, 8), 0) == NULL) 865 { 866 void *pv = ASMMemIsAll8(pb, cb, 0); 867 size_t cbZeros = pv ? (uint8_t const *)pv - pb : cb; 868 if (!outputPrintf(" times %#x db 0\n", cbZeros)) 869 return false; 870 cb -= cbZeros; 871 pb += cbZeros; 872 uFlatAddr += cbZeros; 873 if ( cb == 2 874 && pb[0] == 'X' 875 && pb[1] == 'M') 876 return disStringData(uFlatAddr, cb); 877 } 878 /* Work arounds for switch tables and such (disas assertions). */ 879 else if ( ( pb[0] == 0x11 /* int13_cdemu switch */ 880 && pb[1] == 0xda 881 && pb[2] == 0x05 882 && pb[3] == 0xff 883 && pb[4] == 0xff 884 ) 885 || 0 886 ) 887 return disByteData(uFlatAddr, cb); 888 else 889 { 890 unsigned cbInstr; 891 DISCPUSTATE CpuState; 892 int rc = DISCoreOneEx(uFlatAddr, fIs16Bit ? CPUMODE_16BIT : CPUMODE_32BIT, 893 disReadOpcodeBytes, NULL, &CpuState, &cbInstr); 894 if ( RT_SUCCESS(rc) 895 && cbInstr <= cb) 896 { 897 char szTmp[4096]; 898 size_t cch = DISFormatYasmEx(&CpuState, szTmp, sizeof(szTmp), 899 DIS_FMT_FLAGS_STRICT 900 | DIS_FMT_FLAGS_BYTES_RIGHT | DIS_FMT_FLAGS_BYTES_COMMENT | DIS_FMT_FLAGS_BYTES_SPACED, 901 NULL, NULL); 902 cch = disHandleYasmDifferences(&CpuState, uFlatAddr, cbInstr, szTmp, sizeof(szTmp), cch); 903 Assert(cch < sizeof(szTmp)); 904 905 if (g_cVerbose > 1) 906 { 907 while (cch < 72) 908 szTmp[cch++] = ' '; 909 RTStrPrintf(&szTmp[cch], sizeof(szTmp) - cch, "; %#x", uFlatAddr); 910 } 911 912 if (!outputPrintf(" %s\n", szTmp)) 913 return false; 914 cb -= cbInstr; 915 pb += cbInstr; 916 uFlatAddr += cbInstr; 917 } 918 else 919 { 920 if (!disByteData(uFlatAddr, 1)) 921 return false; 922 cb--; 923 pb++; 924 uFlatAddr++; 925 } 926 } 927 } 928 return true; 202 929 } 203 930 … … 205 932 static bool disCodeSegment(uint32_t iSeg) 206 933 { 207 return disDataSegment(iSeg); 208 } 209 934 uint32_t uFlatAddr = g_aSegs[iSeg].uFlatAddr; 935 uint32_t cb = g_aSegs[iSeg].cb; 936 937 while (cb > 0) 938 { 939 uint32_t off; 940 RTDBGSYMBOL Sym; 941 disGetNextSymbol(uFlatAddr, cb, &off, &Sym); 942 943 if (off > 0) 944 { 945 if (!disByteData(uFlatAddr, off)) 946 return false; 947 cb -= off; 948 uFlatAddr += off; 949 off = 0; 950 if (!cb) 951 break; 952 } 953 954 bool fRc; 955 if (off == 0) 956 { 957 size_t cchName = strlen(Sym.szName); 958 fRc = outputPrintf("%s: %*s; %#x LB %#x\n", Sym.szName, cchName < 41 - 2 ? cchName - 41 - 2 : 0, "", uFlatAddr, Sym.cb); 959 if (!fRc) 960 return false; 961 962 if (disIsCodeAndAdjustSize(uFlatAddr, &Sym, &g_aSegs[iSeg])) 963 fRc = disCode(uFlatAddr, Sym.cb, disIs16BitCode(Sym.szName)); 964 else 965 fRc = disByteData(uFlatAddr, Sym.cb); 966 967 uFlatAddr += Sym.cb; 968 cb -= Sym.cb; 969 } 970 else 971 { 972 fRc = disByteData(uFlatAddr, cb); 973 uFlatAddr += cb; 974 cb = 0; 975 } 976 if (!fRc) 977 return false; 978 } 979 980 return true; 981 } 210 982 211 983 … … 219 991 */ 220 992 bool fRc = true; 221 uint32_t uFlatAddr = 0xf0000;993 uint32_t uFlatAddr = VBOX_BIOS_BASE; 222 994 for (uint32_t iSeg = 0; iSeg < g_cSegs && fRc; iSeg++) 223 995 { … … 235 1007 /* Disassemble the segment. */ 236 1008 fRc = outputPrintf("\n" 237 "section %s progbits vstart=%#x align=1\n", 238 g_aSegs[iSeg].szName, g_aSegs[iSeg].uFlatAddr); 1009 "section %s progbits vstart=%#x align=1 ; size=%#x class=%s group=%s\n", 1010 g_aSegs[iSeg].szName, g_aSegs[iSeg].uFlatAddr - VBOX_BIOS_BASE, 1011 g_aSegs[iSeg].cb, g_aSegs[iSeg].szClass, g_aSegs[iSeg].szGroup); 239 1012 if (!fRc) 240 1013 return RTEXITCODE_FAILURE; 241 if (!strcmp(g_aSegs[iSeg].szClass, "DATA")) 1014 if (!strcmp(g_aSegs[iSeg].szName, "CONST")) 1015 fRc = disConstSegment(iSeg); 1016 else if (!strcmp(g_aSegs[iSeg].szClass, "DATA")) 242 1017 fRc = disDataSegment(iSeg); 243 1018 else … … 249 1024 250 1025 /* Final gap. */ 251 if (uFlatAddr < 0x100000)252 fRc = disCopySegmentGap(uFlatAddr, 0x100000- uFlatAddr);253 else if (uFlatAddr > 0x100000)1026 if (uFlatAddr < VBOX_BIOS_BASE + _64K) 1027 fRc = disCopySegmentGap(uFlatAddr, VBOX_BIOS_BASE + _64K - uFlatAddr); 1028 else if (uFlatAddr > VBOX_BIOS_BASE + _64K) 254 1029 return RTMsgErrorExit(RTEXITCODE_FAILURE, "Last segment spills beyond 1MB; uFlatAddr=%#x\n", uFlatAddr); 255 1030 -
trunk/src/VBox/Devices/PC/BIOS-new/Makefile.kmk
r41477 r41496 99 99 MakeDebianBiosAssembly_TEMPLATE = VBOXR3EXE 100 100 MakeDebianBiosAssembly_SOURCES = MakeDebianBiosAssembly.cpp 101 MakeDebianBiosAssembly_LIBS = $(LIB_RUNTIME) 101 MakeDebianBiosAssembly_LIBS = \ 102 $(PATH_STAGE_LIB)/DisasmR3$(VBOX_SUFF_LIB) \ 103 $(LIB_RUNTIME) 102 104 103 105 -
trunk/src/VBox/Devices/PC/BIOS-new/pirq.inc
r38699 r41496 40 40 41 41 if BX_PCIBIOS 42 public pci_routing_table_structure ; For disassembly 42 43 43 44 align 16
Note:
See TracChangeset
for help on using the changeset viewer.