Changeset 41482 in vbox for trunk/src/VBox/Devices/PC
- Timestamp:
- May 29, 2012 2:52:47 PM (13 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/PC/BIOS-new/MakeDebianBiosAssembly.cpp
r41316 r41482 21 21 *******************************************************************************/ 22 22 #include <iprt/buildconfig.h> 23 #include <iprt/ctype.h> 23 24 #include <iprt/file.h> 24 25 #include <iprt/getopt.h> … … 31 32 32 33 /******************************************************************************* 34 * Structures and Typedefs * 35 *******************************************************************************/ 36 /** 37 * A BIOS segment. 38 */ 39 typedef struct BIOSSEG 40 { 41 char szName[32]; 42 char szClass[32]; 43 char szGroup[32]; 44 RTFAR16 Address; 45 uint32_t cb; 46 } BIOSSEG; 47 /** Pointer to a BIOS segment. */ 48 typedef BIOSSEG *PBIOSSEG; 49 50 51 /******************************************************************************* 33 52 * Global Variables * 34 53 *******************************************************************************/ 35 static unsigned g_cVerbose = 1 /*0*/;54 static unsigned g_cVerbose = 1 /*0*/; 36 55 /** Pointer to the BIOS image. */ 37 56 static uint8_t const *g_pbImg; … … 39 58 static size_t g_cbImg; 40 59 60 /** The number of BIOS segments found in the map file. */ 61 static uint32_t g_cSegs = 0; 62 /** Array of BIOS segments from the map file. */ 63 static BIOSSEG g_aSegs[32]; 64 65 66 41 67 42 68 … … 52 78 53 79 54 static int SkipEmptyLines(PRTSTREAM hStrm, uint32_t *piLine) 80 /** 81 * Parses the symbol file for the BIOS. 82 * 83 * This is in ELF/DWARF format. 84 * 85 * @returns RTEXITCODE_SUCCESS or RTEXITCODE_FAILURE+msg. 86 * @param pszBiosSym Path to the sym file. 87 */ 88 static RTEXITCODE ParseSymFile(const char *pszBiosSym) 89 { 90 /** @todo use RTDbg* later. (Just checking for existance currently.) */ 91 PRTSTREAM hStrm; 92 int rc = RTStrmOpen(pszBiosSym, "rb", &hStrm); 93 if (RT_FAILURE(rc)) 94 return RTMsgErrorExit(RTEXITCODE_FAILURE, "Error opening '%s': %Rrc", pszBiosSym, rc); 95 RTStrmClose(hStrm); 96 return RTEXITCODE_SUCCESS; 97 } 98 99 100 101 102 static bool SkipEmptyLines(PRTSTREAM hStrm, uint32_t *piLine, char *pszLine, size_t cbLine) 55 103 { 56 104 for (;;) 57 105 { 106 int rc = RTStrmGetLine(hStrm, pszLine, cbLine); 107 if (RT_FAILURE(rc)) 108 { 109 RTMsgError("Error reading map-file: %Rrc", rc); 110 return false; 111 } 112 113 *piLine += 1; 114 const char *psz = RTStrStripL(pszLine); 115 if (*psz) 116 return true; 117 } 118 } 119 120 121 static bool SkipNonEmptyLines(PRTSTREAM hStrm, uint32_t *piLine, char *pszLine, size_t cbLine) 122 { 123 for (;;) 124 { 125 int rc = RTStrmGetLine(hStrm, pszLine, cbLine); 126 if (RT_FAILURE(rc)) 127 { 128 RTMsgError("Error reading map-file: %Rrc", rc); 129 return false; 130 } 131 132 *piLine += 1; 133 const char *psz = RTStrStripL(pszLine); 134 if (!*psz) 135 return true; 136 } 137 } 138 139 140 static char *ReadMapLineR(const char *pszBiosMap, PRTSTREAM hStrm, uint32_t *piLine, 141 char *pszLine, size_t cbLine, size_t *pcchLine) 142 { 143 int rc = RTStrmGetLine(hStrm, pszLine, cbLine); 144 if (RT_FAILURE(rc)) 145 { 146 RTMsgError("%s:%d: Read error: %Rrc", pszBiosMap, *piLine, rc); 147 return NULL; 148 } 149 *piLine += 1; 150 151 char *psz = RTStrStripR(pszLine); 152 *pcchLine = strlen(psz); 153 return psz; 154 } 155 156 157 static char *ReadMapLineLR(const char *pszBiosMap, PRTSTREAM hStrm, uint32_t *piLine, 158 char *pszLine, size_t cbLine, size_t *pcchLine) 159 { 160 int rc = RTStrmGetLine(hStrm, pszLine, cbLine); 161 if (RT_FAILURE(rc)) 162 { 163 RTMsgError("%s:%d: Read error: %Rrc", pszBiosMap, *piLine, rc); 164 return NULL; 165 } 166 *piLine += 1; 167 168 char *psz = RTStrStrip(pszLine); 169 *pcchLine = strlen(psz); 170 return psz; 171 } 172 173 174 static char *ReadMapLine(const char *pszBiosMap, PRTSTREAM hStrm, uint32_t *piLine, 175 char *pszLine, size_t cbLine, size_t *pcchLine) 176 { 177 int rc = RTStrmGetLine(hStrm, pszLine, cbLine); 178 if (RT_FAILURE(rc)) 179 { 180 RTMsgError("%s:%d: Read error: %Rrc", pszBiosMap, *piLine, rc); 181 return NULL; 182 } 183 *piLine += 1; 184 185 *pcchLine = strlen(pszLine); 186 return pszLine; 187 } 188 189 190 static bool ParseWord(char **ppszCursor, char *pszBuf, size_t cbBuf) 191 { 192 /* Check that we start on a non-blank. */ 193 char *pszStart = *ppszCursor; 194 if (!*pszStart || RT_C_IS_SPACE(*pszStart)) 195 return false; 196 197 /* Find the end of the word. */ 198 char *psz = pszStart + 1; 199 while (*psz && !RT_C_IS_SPACE(*psz)) 200 psz++; 201 202 /* Copy it. */ 203 size_t cchWord = (uintptr_t)psz - (uintptr_t)pszStart; 204 if (cchWord >= cbBuf) 205 return false; 206 memcpy(pszBuf, pszStart, cchWord); 207 pszBuf[cchWord] = '\0'; 208 209 /* Skip blanks following it. */ 210 while (RT_C_IS_SPACE(*psz)) 211 psz++; 212 *ppszCursor = psz; 213 return true; 214 } 215 216 217 static bool ParseAddress(char **ppszCursor, PRTFAR16 pAddr) 218 { 219 char szWord[32]; 220 if (!ParseWord(ppszCursor, szWord, sizeof(szWord))) 221 return false; 222 size_t cchWord = strlen(szWord); 223 224 /* Check the first 4+1+4 chars. */ 225 if (cchWord < 4 + 1 + 4) 226 return false; 227 if ( !RT_C_IS_XDIGIT(szWord[0]) 228 || !RT_C_IS_XDIGIT(szWord[1]) 229 || !RT_C_IS_XDIGIT(szWord[2]) 230 || !RT_C_IS_XDIGIT(szWord[3]) 231 || szWord[4] != ':' 232 || !RT_C_IS_XDIGIT(szWord[5]) 233 || !RT_C_IS_XDIGIT(szWord[6]) 234 || !RT_C_IS_XDIGIT(szWord[7]) 235 || !RT_C_IS_XDIGIT(szWord[8]) 236 ) 237 return false; 238 239 /* Drop annotation. */ 240 if (cchWord > 4+1+4) 241 { 242 if (RT_C_IS_XDIGIT(szWord[4+1+4])) 243 return false; 244 szWord[4+1+4] = '\0'; 245 cchWord = 4 + 1 + 4; 246 } 247 248 /* Convert it. */ 249 szWord[4] = '\0'; 250 int rc1 = RTStrToUInt16Ex(szWord, NULL, 16, &pAddr->sel); AssertRC(rc1); 251 int rc2 = RTStrToUInt16Ex(szWord + 5, NULL, 16, &pAddr->off); AssertRC(rc2); 252 return true; 253 } 254 255 256 static bool ParseSize(char **ppszCursor, uint32_t *pcb) 257 { 258 char szWord[32]; 259 if (!ParseWord(ppszCursor, szWord, sizeof(szWord))) 260 return false; 261 size_t cchWord = strlen(szWord); 262 if (cchWord != 8) 263 return false; 264 265 int rc = RTStrToUInt32Full(szWord, 16, pcb); 266 if (rc != VINF_SUCCESS) 267 return false; 268 return true; 269 } 270 271 272 /** 273 * Parses a section box and the following column header. 274 * 275 * @returns RTEXITCODE_SUCCESS or RTEXITCODE_FAILURE+msg. 276 * @param pszBiosMap The input file name. 277 * @param hStrm The input stream. 278 * @param piLine Pointer to the current line number variable. 279 * @param pszSectionNm The expected section name. 280 * @param cColumns The number of columns. 281 * @param ... The column names. 282 */ 283 static RTEXITCODE SkipThruColumnHeadings(const char *pszBiosMap, PRTSTREAM hStrm, uint32_t *piLine, 284 const char *pszSectionNm, uint32_t cColumns, ...) 285 { 286 char szLine[16384]; 287 if (!SkipEmptyLines(hStrm, piLine, szLine, sizeof(szLine))) 288 return RTEXITCODE_FAILURE; 289 290 /* +------------+ */ 291 char *psz = RTStrStrip(szLine); 292 size_t cch = strlen(psz); 293 if (!psz) 294 return RTEXITCODE_FAILURE; 295 296 if ( psz[0] != '+' 297 || psz[1] != '-' 298 || psz[2] != '-' 299 || psz[3] != '-' 300 || psz[cch - 4] != '-' 301 || psz[cch - 3] != '-' 302 || psz[cch - 2] != '-' 303 || psz[cch - 1] != '+' 304 ) 305 return RTMsgErrorExit(RTEXITCODE_FAILURE, "%s:%d: Expected section box: +-----...", pszBiosMap, *piLine); 306 307 /* | pszSectionNm | */ 308 psz = ReadMapLineLR(pszBiosMap, hStrm, piLine, szLine, sizeof(szLine), &cch); 309 if (!psz) 310 return RTEXITCODE_FAILURE; 311 312 size_t cchSectionNm = strlen(pszSectionNm); 313 if ( psz[0] != '|' 314 || psz[1] != ' ' 315 || psz[2] != ' ' 316 || psz[3] != ' ' 317 || psz[cch - 4] != ' ' 318 || psz[cch - 3] != ' ' 319 || psz[cch - 2] != ' ' 320 || psz[cch - 1] != '|' 321 || cch != 1 + 3 + cchSectionNm + 3 + 1 322 || strncmp(&psz[4], pszSectionNm, cchSectionNm) 323 ) 324 return RTMsgErrorExit(RTEXITCODE_FAILURE, "%s:%d: Expected section box: | %s |", pszBiosMap, *piLine, pszSectionNm); 325 326 /* +------------+ */ 327 psz = ReadMapLineLR(pszBiosMap, hStrm, piLine, szLine, sizeof(szLine), &cch); 328 if (!psz) 329 return RTEXITCODE_FAILURE; 330 if ( psz[0] != '+' 331 || psz[1] != '-' 332 || psz[2] != '-' 333 || psz[3] != '-' 334 || psz[cch - 4] != '-' 335 || psz[cch - 3] != '-' 336 || psz[cch - 2] != '-' 337 || psz[cch - 1] != '+' 338 ) 339 return RTMsgErrorExit(RTEXITCODE_FAILURE, "%s:%d: Expected section box: +-----...", pszBiosMap, *piLine); 340 341 /* There may be a few lines describing the table notation now, surrounded by blank lines. */ 342 do 343 { 344 psz = ReadMapLineR(pszBiosMap, hStrm, piLine, szLine, sizeof(szLine), &cch); 345 if (!psz) 346 return RTEXITCODE_FAILURE; 347 } while ( *psz == '\0' 348 || ( !RT_C_IS_SPACE(psz[0]) 349 && RT_C_IS_SPACE(psz[1]) 350 && psz[2] == '=' 351 && RT_C_IS_SPACE(psz[3])) 352 ); 353 354 /* Should have the column heading now. */ 355 va_list va; 356 va_start(va, cColumns); 357 for (uint32_t i = 0; i < cColumns; i++) 358 { 359 const char *pszColumn = va_arg(va, const char *); 360 size_t cchColumn = strlen(pszColumn); 361 if ( strncmp(psz, pszColumn, cchColumn) 362 || ( psz[cchColumn] != '\0' 363 && !RT_C_IS_SPACE(psz[cchColumn]))) 364 { 365 va_end(va); 366 return RTMsgErrorExit(RTEXITCODE_FAILURE, "%s:%d: Expected column '%s' found '%s'", 367 pszBiosMap, *piLine, pszColumn, psz); 368 } 369 psz += cchColumn; 370 while (RT_C_IS_SPACE(*psz)) 371 psz++; 372 } 373 va_end(va); 374 375 /* The next line is the underlining. */ 376 psz = ReadMapLineR(pszBiosMap, hStrm, piLine, szLine, sizeof(szLine), &cch); 377 if (!psz) 378 return RTEXITCODE_FAILURE; 379 if (*psz != '=' || psz[cch - 1] != '=') 380 return RTMsgErrorExit(RTEXITCODE_FAILURE, "%s:%d: Expected column header underlining", pszBiosMap, *piLine); 381 382 /* Skip one blank line. */ 383 psz = ReadMapLineR(pszBiosMap, hStrm, piLine, szLine, sizeof(szLine), &cch); 384 if (!psz) 385 return RTEXITCODE_FAILURE; 386 if (*psz) 387 return RTMsgErrorExit(RTEXITCODE_FAILURE, "%s:%d: Expected blank line beneath the column headers", pszBiosMap, *piLine); 388 389 return RTEXITCODE_SUCCESS; 390 } 391 392 393 394 static RTEXITCODE ParseMapFileSegments(const char *pszBiosMap, PRTSTREAM hStrm, uint32_t *piLine) 395 { 396 for (;;) 397 { 398 /* Read the next line and right strip it. */ 58 399 char szLine[16384]; 59 400 int rc = RTStrmGetLine(hStrm, szLine, sizeof(szLine)); 60 401 if (RT_FAILURE(rc)) 402 return RTMsgErrorExit(RTEXITCODE_FAILURE, "%s:%u: Read error: %Rrc", pszBiosMap, *piLine, rc); 403 404 *piLine += 1; 405 RTStrStripR(szLine); 406 407 /* The end? The line should be empty. Expectes segment name to not 408 start with a space. */ 409 if (!szLine[0] || RT_C_IS_SPACE(szLine[0])) 61 410 { 62 RTMsgError("Error read map-file header: %Rrc", rc); 63 return rc; 411 if (szLine[0]) 412 return RTMsgErrorExit(RTEXITCODE_FAILURE, "%s:%u: Malformed segment line", pszBiosMap, *piLine); 413 return RTEXITCODE_SUCCESS; 64 414 } 65 415 66 *piLine += 1; 67 const char *psz = RTStrStrip(szLine); 416 /* Parse the segment line. */ 417 uint32_t iSeg = g_cSegs; 418 if (iSeg >= RT_ELEMENTS(g_aSegs)) 419 return RTMsgErrorExit(RTEXITCODE_FAILURE, "%s:%u: Too many segments", pszBiosMap, *piLine); 420 421 char *psz = szLine; 422 if (ParseWord(&psz, g_aSegs[iSeg].szName, sizeof(g_aSegs[iSeg].szName))) 423 return RTMsgErrorExit(RTEXITCODE_FAILURE, "%s:%u: Segment name parser error", pszBiosMap, *piLine); 424 if (ParseWord(&psz, g_aSegs[iSeg].szClass, sizeof(g_aSegs[iSeg].szClass))) 425 return RTMsgErrorExit(RTEXITCODE_FAILURE, "%s:%u: Segment class parser error", pszBiosMap, *piLine); 426 if (ParseWord(&psz, g_aSegs[iSeg].szGroup, sizeof(g_aSegs[iSeg].szGroup))) 427 return RTMsgErrorExit(RTEXITCODE_FAILURE, "%s:%u: Segment group parser error", pszBiosMap, *piLine); 428 if (ParseAddress(&psz, &g_aSegs[iSeg].Address)) 429 return RTMsgErrorExit(RTEXITCODE_FAILURE, "%s:%u: Segment address parser error", pszBiosMap, *piLine); 430 if (ParseSize(&psz, &g_aSegs[iSeg].cb)) 431 return RTMsgErrorExit(RTEXITCODE_FAILURE, "%s:%u: Segment size parser error", pszBiosMap, *piLine); 432 433 g_cSegs++; 434 435 while (RT_C_IS_SPACE(*psz)) 436 psz++; 68 437 if (*psz) 69 return VINF_SUCCESS; 70 } 71 } 72 73 74 static int SkipNonEmptyLines(PRTSTREAM hStrm, uint32_t *piLine) 75 { 76 for (;;) 77 { 78 char szLine[16384]; 79 int rc = RTStrmGetLine(hStrm, szLine, sizeof(szLine)); 80 if (RT_FAILURE(rc)) 81 { 82 RTMsgError("Error read map-file header: %Rrc", rc); 83 return rc; 84 } 85 86 *piLine += 1; 87 const char *psz = RTStrStrip(szLine); 88 if (!*psz) 89 return VINF_SUCCESS; 90 } 91 } 438 return RTMsgErrorExit(RTEXITCODE_FAILURE, "%s:%u: Junk at end of line", pszBiosMap, *piLine); 439 440 } 441 } 442 92 443 93 444 static RTEXITCODE ParseMapFileInner(const char *pszBiosMap, PRTSTREAM hStrm) … … 102 453 int rc = RTStrmGetLine(hStrm, szLine, sizeof(szLine)); 103 454 if (RT_FAILURE(rc)) 104 return RTMsgErrorExit(RTEXITCODE_FAILURE, "Error read map-file header: %Rrc", rc);455 return RTMsgErrorExit(RTEXITCODE_FAILURE, "Error reading map-file header: %Rrc", rc); 105 456 if (strncmp(szLine, RT_STR_TUPLE("Open Watcom Linker Version"))) 106 457 return RTMsgErrorExit(RTEXITCODE_FAILURE, "Unexpected map-file header: '%s'", szLine); 107 rc = SkipNonEmptyLines(hStrm, &iLine); 458 if ( !SkipNonEmptyLines(hStrm, &iLine, szLine, sizeof(szLine)) 459 || !SkipEmptyLines(hStrm, &iLine, szLine, sizeof(szLine)) ) 460 return RTEXITCODE_FAILURE; 461 462 /* 463 * Skip groups. 464 */ 465 if (SkipThruColumnHeadings(pszBiosMap, hStrm, &iLine, "Groups", 3, "Group", "Address", "Size", NULL) != RTEXITCODE_SUCCESS) 466 return RTEXITCODE_FAILURE; 467 if (!SkipNonEmptyLines(hStrm, &iLine, szLine, sizeof(szLine))) 468 return RTEXITCODE_FAILURE; 469 470 /* 471 * Parse segments. 472 */ 473 if ( SkipThruColumnHeadings(pszBiosMap, hStrm, &iLine, "Segments", 5, "Segment", "Class", "Group", "Address", "Size") 474 != RTEXITCODE_SUCCESS) 475 return RTEXITCODE_FAILURE; 476 477 if (RT_FAILURE(rc)) 478 return RTMsgErrorExit(RTEXITCODE_FAILURE, "Error reading map-file group: %Rrc", rc); 479 480 108 481 109 482 … … 111 484 return RTMsgErrorExit(RTEXITCODE_FAILURE, "ParseMapFileInner is not fully implemented"); 112 485 } 113 114 486 115 487 … … 172 544 { "--bios-image", 'i', RTGETOPT_REQ_STRING }, 173 545 { "--bios-map", 'm', RTGETOPT_REQ_STRING }, 546 { "--bios-sym", 's', RTGETOPT_REQ_STRING }, 174 547 { "--output", 'o', RTGETOPT_REQ_STRING }, 175 548 { "--verbose", 'v', RTGETOPT_REQ_NOTHING }, … … 178 551 179 552 const char *pszBiosMap = NULL; 553 const char *pszBiosSym = NULL; 180 554 const char *pszBiosImg = NULL; 181 555 const char *pszOutput = NULL; … … 205 579 break; 206 580 581 case 's': 582 if (pszBiosMap) 583 return RTMsgErrorExit(RTEXITCODE_SYNTAX, "--bios-sym is given more than once"); 584 pszBiosMap = ValueUnion.psz; 585 break; 586 207 587 case 'o': 208 588 if (pszOutput) … … 243 623 if (!pszBiosMap) 244 624 return RTMsgErrorExit(RTEXITCODE_SYNTAX, "--bios-map is required"); 625 if (!pszBiosSym) 626 return RTMsgErrorExit(RTEXITCODE_SYNTAX, "--bios-sym is required"); 245 627 246 628 /* … … 252 634 rcExit = ParseMapFile(pszBiosMap); 253 635 if (rcExit == RTEXITCODE_SUCCESS) 636 rcExit = ParseSymFile(pszBiosSym); 637 if (rcExit == RTEXITCODE_SUCCESS) 254 638 rcExit = OpenOutputFile(pszOutput); 255 639 if (rcExit == RTEXITCODE_SUCCESS)
Note:
See TracChangeset
for help on using the changeset viewer.