- Timestamp:
- May 29, 2012 11:25:30 PM (13 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/PC/BIOS-new/MakeDebianBiosAssembly.cpp
r41488 r41489 22 22 #include <iprt/buildconfig.h> 23 23 #include <iprt/ctype.h> 24 #include <iprt/dbg.h> 24 25 #include <iprt/file.h> 25 26 #include <iprt/getopt.h> … … 83 84 static size_t g_cbImg; 84 85 86 /** Debug module for the map file. */ 87 static RTDBGMOD g_hMapMod = NIL_RTDBGMOD; 85 88 /** The number of BIOS segments found in the map file. */ 86 89 static uint32_t g_cSegs = 0; … … 88 91 static BIOSSEG g_aSegs[32]; 89 92 90 93 /** The output stream. */ 94 static PRTSTREAM g_hStrmOutput = NULL; 95 96 97 static bool outputPrintfV(const char *pszFormat, va_list va) 98 { 99 int rc = RTStrmPrintfV(g_hStrmOutput, pszFormat, va); 100 if (RT_FAILURE(rc)) 101 { 102 RTMsgError("Output error: %Rrc\n", rc); 103 return false; 104 } 105 return true; 106 } 107 108 109 static bool outputPrintf(const char *pszFormat, ...) 110 { 111 va_list va; 112 va_start(va, pszFormat); 113 bool fRc = outputPrintfV(pszFormat, va); 114 va_end(va); 115 return fRc; 116 } 117 118 119 /** 120 * Opens the output file for writing. 121 * 122 * @returns RTEXITCODE_SUCCESS or RTEXITCODE_FAILURE+msg. 123 * @param pszOutput Path to the output file. 124 */ 125 static RTEXITCODE OpenOutputFile(const char *pszOutput) 126 { 127 if (!pszOutput) 128 g_hStrmOutput = g_pStdOut; 129 else 130 { 131 int rc = RTStrmOpen(pszOutput, "w", &g_hStrmOutput); 132 if (RT_FAILURE(rc)) 133 return RTMsgErrorExit(RTEXITCODE_FAILURE, "Failed to open output file '%s': %Rrc", pszOutput, rc); 134 } 135 return RTEXITCODE_SUCCESS; 136 } 137 138 139 /** 140 * Output the disassembly file header. 141 * 142 * @returns @c true on success, 143 */ 144 static bool disFileHeader(void) 145 { 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; 156 } 157 158 159 static bool disByteData(uint32_t uFlatAddr, uint32_t cb) 160 { 161 uint8_t const *pb = &g_pbImg[uFlatAddr - 0xf0000]; 162 size_t cbOnLine = 0; 163 while (cb-- > 0) 164 { 165 bool fRc; 166 if (cbOnLine >= 16) 167 { 168 fRc = outputPrintf("\n" 169 " db 0%02xh", *pb); 170 cbOnLine = 1; 171 } 172 else if (!cbOnLine) 173 { 174 fRc = outputPrintf(" db 0%02xh", *pb); 175 cbOnLine = 1; 176 } 177 else 178 { 179 fRc = outputPrintf(", 0%02xh", *pb); 180 cbOnLine++; 181 } 182 if (!fRc) 183 return false; 184 pb++; 185 } 186 return outputPrintf("\n"); 187 } 188 189 190 191 static bool disCopySegmentGap(uint32_t uFlatAddr, uint32_t cbPadding) 192 { 193 if (g_cVerbose > 0) 194 RTStrmPrintf(g_pStdErr, "Padding %#x bytes at %#x\n", cbPadding, uFlatAddr); 195 return disByteData(uFlatAddr, cbPadding); 196 } 197 198 199 static bool disDataSegment(uint32_t iSeg) 200 { 201 return disByteData(g_aSegs[iSeg].uFlatAddr, g_aSegs[iSeg].cb); 202 } 203 204 205 static bool disCodeSegment(uint32_t iSeg) 206 { 207 return disDataSegment(iSeg); 208 } 91 209 92 210 … … 94 212 static RTEXITCODE DisassembleBiosImage(void) 95 213 { 96 return RTMsgErrorExit(RTEXITCODE_FAILURE, "DisassembleBiosImage is not implemented"); 97 } 98 99 static RTEXITCODE OpenOutputFile(const char *pszOutput) 100 { 101 return RTMsgErrorExit(RTEXITCODE_FAILURE, "OpenOutputFile is not implemented"); 102 } 214 if (!outputPrintf("")) 215 return RTEXITCODE_FAILURE; 216 217 /* 218 * Work the image segment by segment. 219 */ 220 bool fRc = true; 221 uint32_t uFlatAddr = 0xf0000; 222 for (uint32_t iSeg = 0; iSeg < g_cSegs && fRc; iSeg++) 223 { 224 /* Is there a gap between the segments? */ 225 if (uFlatAddr < g_aSegs[iSeg].uFlatAddr) 226 { 227 fRc = disCopySegmentGap(uFlatAddr, g_aSegs[iSeg].uFlatAddr - uFlatAddr); 228 if (!fRc) 229 break; 230 uFlatAddr = g_aSegs[iSeg].uFlatAddr; 231 } 232 else if (uFlatAddr > g_aSegs[iSeg].uFlatAddr) 233 return RTMsgErrorExit(RTEXITCODE_FAILURE, "Overlapping segments: %u and %u; uFlatAddr=%#x\n", iSeg - 1, iSeg, uFlatAddr); 234 235 /* Disassemble the segment. */ 236 fRc = outputPrintf("\n" 237 "section %s progbits vstart=%#x align=1\n", 238 g_aSegs[iSeg].szName, g_aSegs[iSeg].uFlatAddr); 239 if (!fRc) 240 return RTEXITCODE_FAILURE; 241 if (!strcmp(g_aSegs[iSeg].szClass, "DATA")) 242 fRc = disDataSegment(iSeg); 243 else 244 fRc = disCodeSegment(iSeg); 245 246 /* Advance. */ 247 uFlatAddr += g_aSegs[iSeg].cb; 248 } 249 250 /* Final gap. */ 251 if (uFlatAddr < 0x100000) 252 fRc = disCopySegmentGap(uFlatAddr, 0x100000 - uFlatAddr); 253 else if (uFlatAddr > 0x100000) 254 return RTMsgErrorExit(RTEXITCODE_FAILURE, "Last segment spills beyond 1MB; uFlatAddr=%#x\n", uFlatAddr); 255 256 if (!fRc) 257 return RTEXITCODE_FAILURE; 258 return RTEXITCODE_SUCCESS; 259 } 260 103 261 104 262 … … 257 415 258 416 259 260 static char *ReadMapLineR(const char *pszBiosMap, PRTSTREAM hStrm, uint32_t *piLine,261 char *pszLine, size_t cbLine, size_t *pcchLine)262 {263 int rc = RTStrmGetLine(hStrm, pszLine, cbLine);264 if (RT_FAILURE(rc))265 {266 RTMsgError("%s:%d: Read error: %Rrc", pszBiosMap, *piLine, rc);267 return NULL;268 }269 *piLine += 1;270 271 char *psz = RTStrStripR(pszLine);272 *pcchLine = strlen(psz);273 return psz;274 }275 276 277 417 /** 278 418 * mapReadLine() + mapStripCurrentLine(). … … 342 482 size_t cchWord = strlen(szWord); 343 483 344 /* Check the first 4+1+4 chars. */ 345 if (cchWord < 4 + 1 + 4) 484 /* An address is at least 16:16 format. It may be 16:32. It may also be flagged. */ 485 size_t cchAddr = 4 + 1 + 4; 486 if (cchWord < cchAddr) 346 487 return false; 347 488 if ( !RT_C_IS_XDIGIT(szWord[0]) … … 356 497 ) 357 498 return false; 358 359 /* Drop annotation. */ 360 if (cchWord > 4+1+4) 499 if ( cchWord > cchAddr 500 && RT_C_IS_XDIGIT(szWord[9]) 501 && RT_C_IS_XDIGIT(szWord[10]) 502 && RT_C_IS_XDIGIT(szWord[11]) 503 && RT_C_IS_XDIGIT(szWord[12])) 504 cchAddr += 4; 505 506 /* Drop flag if present. */ 507 if (cchWord > cchAddr) 361 508 { 362 509 if (RT_C_IS_XDIGIT(szWord[4+1+4])) 363 510 return false; 364 szWord[ 4+1+4] = '\0';365 cchWord = 4 + 1 + 4;511 szWord[cchAddr] = '\0'; 512 cchWord = cchAddr; 366 513 } 367 514 368 515 /* Convert it. */ 369 516 szWord[4] = '\0'; 370 int rc1 = RTStrToUInt16Full(szWord, 16, &pAddr->sel); AssertRCSuccess(rc1); 371 int rc2 = RTStrToUInt16Full(szWord + 5, 16, &pAddr->off); AssertRCSuccess(rc2); 517 int rc1 = RTStrToUInt16Full(szWord, 16, &pAddr->sel); 518 if (rc1 != VINF_SUCCESS) 519 return false; 520 521 int rc2 = RTStrToUInt16Full(szWord + 5, 16, &pAddr->off); 522 if (rc2 != VINF_SUCCESS) 523 return false; 372 524 return true; 373 525 } … … 592 744 593 745 /** 594 * Sorts the segment array by flat address. 595 */ 596 static void mapSortSegments(void) 597 { 598 for (uint32_t i = 0; i < g_cSegs - 1; i++) 746 * Sorts the segment array by flat address and adds them to the debug module. 747 * 748 * @returns @c true on success, @c false + msg on failure, @c false on eof. 749 */ 750 static bool mapSortAndAddSegments(void) 751 { 752 for (uint32_t i = 0; i < g_cSegs; i++) 599 753 { 600 754 for (uint32_t j = i + 1; j < g_cSegs; j++) … … 614 768 g_aSegs[i].szClass, 615 769 g_aSegs[i].szGroup); 616 } 617 } 618 770 771 RTDBGSEGIDX idx = i; 772 int rc = RTDbgModSegmentAdd(g_hMapMod, g_aSegs[i].uFlatAddr, g_aSegs[i].cb, g_aSegs[i].szName, 0 /*fFlags*/, &idx); 773 if (RT_FAILURE(rc)) 774 { 775 RTMsgError("RTDbgModSegmentAdd failed on %s: %Rrc", g_aSegs[i].szName); 776 return false; 777 } 778 } 779 return true; 780 } 781 782 783 /** 784 * Parses a segment list. 785 * 786 * @returns @c true on success, @c false + msg on failure, @c false on eof. 787 * @param pMap The map file handle. 788 */ 789 static bool mapParseSymbols(PBIOSMAP pMap) 790 { 791 for (;;) 792 { 793 if (!mapReadLineStripRight(pMap, NULL)) 794 return false; 795 796 /* The end? The line should be empty. Expectes segment name to not 797 start with a space. */ 798 if (!pMap->szLine[0] || RT_C_IS_SPACE(pMap->szLine[0])) 799 { 800 if (!pMap->szLine[0]) 801 return true; 802 RTMsgError("%s:%u: Malformed symbol line", pMap->pszMapFile, pMap->iLine); 803 return false; 804 } 805 806 /* Skip the module name lines for now. */ 807 if (!strncmp(pMap->szLine, RT_STR_TUPLE("Module: "))) 808 continue; 809 810 /* Parse the segment line. */ 811 char szName[4096]; 812 RTFAR16 Addr; 813 char *psz = pMap->szLine; 814 if (!mapParseAddress(&psz, &Addr)) 815 RTMsgError("%s:%u: Symbol address parser error", pMap->pszMapFile, pMap->iLine); 816 else if (!mapParseWord(&psz, szName, sizeof(szName))) 817 RTMsgError("%s:%u: Symbol name parser error", pMap->pszMapFile, pMap->iLine); 818 else 819 { 820 uint32_t uFlatAddr = ((uint32_t)Addr.sel << 4) + Addr.off; 821 if (uFlatAddr == 0) 822 continue; 823 824 int rc = RTDbgModSymbolAdd(g_hMapMod, szName, RTDBGSEGIDX_RVA, uFlatAddr, 0 /*cb*/, 0 /*fFlags*/, NULL); 825 if (RT_SUCCESS(rc) || rc == VERR_DBG_ADDRESS_CONFLICT) 826 { 827 828 if (g_cVerbose > 2) 829 RTStrmPrintf(g_pStdErr, "read symbol - %08x %s\n", uFlatAddr, szName); 830 while (RT_C_IS_SPACE(*psz)) 831 psz++; 832 if (!*psz) 833 continue; 834 RTMsgError("%s:%u: Junk at end of line", pMap->pszMapFile, pMap->iLine); 835 } 836 else 837 RTMsgError("%s:%u: RTDbgModSymbolAdd failed: %Rrc", pMap->pszMapFile, pMap->iLine, rc); 838 } 839 return false; 840 } 841 } 619 842 620 843 … … 628 851 static RTEXITCODE mapParseFile(PBIOSMAP pMap) 629 852 { 630 const char *psz; 853 int rc = RTDbgModCreate(&g_hMapMod, "VBoxBios", 0 /*cbSeg*/, 0 /*fFlags*/); 854 if (RT_FAILURE(rc)) 855 return RTMsgErrorExit(RTEXITCODE_FAILURE, "RTDbgModCreate failed: %Rrc", rc); 631 856 632 857 /* … … 656 881 if (!mapParseSegments(pMap)) 657 882 return RTEXITCODE_FAILURE; 658 mapSortSegments(); 659 660 661 return RTMsgErrorExit(RTEXITCODE_FAILURE, "mapParseFile is not fully implemented"); 883 if (!mapSortAndAddSegments()) 884 return RTEXITCODE_FAILURE; 885 886 /* 887 * Parse symbols. 888 */ 889 if (!mapSkipThruColumnHeadings(pMap, "Memory Map", 2, "Address", "Symbol")) 890 return RTEXITCODE_FAILURE; 891 if (!mapParseSymbols(pMap)) 892 return RTEXITCODE_FAILURE; 893 894 /* Ignore the rest of the file. */ 895 return RTEXITCODE_SUCCESS; 662 896 } 663 897
Note:
See TracChangeset
for help on using the changeset viewer.