VirtualBox

source: vbox/trunk/src/VBox/Devices/PC/BIOS-new/MakeDebianBiosAssembly.cpp@ 41488

Last change on this file since 41488 was 41488, checked in by vboxsync, 13 years ago

A bit more code.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 23.9 KB
Line 
1/* $Id: MakeDebianBiosAssembly.cpp 41488 2012-05-29 20:18:30Z vboxsync $ */
2/** @file
3 * MakeDebianBiosAssembly - Generate Assembly Source for Debian-minded Distros.
4 */
5
6/*
7 * Copyright (C) 2012 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/*******************************************************************************
20* Header Files *
21*******************************************************************************/
22#include <iprt/buildconfig.h>
23#include <iprt/ctype.h>
24#include <iprt/file.h>
25#include <iprt/getopt.h>
26#include <iprt/initterm.h>
27#include <iprt/mem.h>
28#include <iprt/message.h>
29#include <iprt/string.h>
30#include <iprt/stream.h>
31
32
33/*******************************************************************************
34* Structures and Typedefs *
35*******************************************************************************/
36/**
37 * A BIOS segment.
38 */
39typedef struct BIOSSEG
40{
41 char szName[32];
42 char szClass[32];
43 char szGroup[32];
44 RTFAR16 Address;
45 uint32_t uFlatAddr;
46 uint32_t cb;
47} BIOSSEG;
48/** Pointer to a BIOS segment. */
49typedef BIOSSEG *PBIOSSEG;
50
51
52/**
53 * Pointer to a BIOS map parser handle.
54 */
55typedef struct BIOSMAP
56{
57 /** The stream pointer. */
58 PRTSTREAM hStrm;
59 /** The file name. */
60 const char *pszMapFile;
61 /** Set when EOF has been reached. */
62 bool fEof;
63 /** The current line number (0 based).*/
64 uint32_t iLine;
65 /** The length of the current line. */
66 uint32_t cch;
67 /** The offset of the first non-white character on the line. */
68 uint32_t offNW;
69 /** The line buffer. */
70 char szLine[16384];
71} BIOSMAP;
72/** Pointer to a BIOS map parser handle. */
73typedef BIOSMAP *PBIOSMAP;
74
75
76/*******************************************************************************
77* Global Variables *
78*******************************************************************************/
79static unsigned g_cVerbose = 1 /*0*/;
80/** Pointer to the BIOS image. */
81static uint8_t const *g_pbImg;
82/** The size of the BIOS image. */
83static size_t g_cbImg;
84
85/** The number of BIOS segments found in the map file. */
86static uint32_t g_cSegs = 0;
87/** Array of BIOS segments from the map file. */
88static BIOSSEG g_aSegs[32];
89
90
91
92
93
94static RTEXITCODE DisassembleBiosImage(void)
95{
96 return RTMsgErrorExit(RTEXITCODE_FAILURE, "DisassembleBiosImage is not implemented");
97}
98
99static RTEXITCODE OpenOutputFile(const char *pszOutput)
100{
101 return RTMsgErrorExit(RTEXITCODE_FAILURE, "OpenOutputFile is not implemented");
102}
103
104
105/**
106 * Parses the symbol file for the BIOS.
107 *
108 * This is in ELF/DWARF format.
109 *
110 * @returns RTEXITCODE_SUCCESS or RTEXITCODE_FAILURE+msg.
111 * @param pszBiosSym Path to the sym file.
112 */
113static RTEXITCODE ParseSymFile(const char *pszBiosSym)
114{
115 /** @todo use RTDbg* later. (Just checking for existance currently.) */
116 PRTSTREAM hStrm;
117 int rc = RTStrmOpen(pszBiosSym, "rb", &hStrm);
118 if (RT_FAILURE(rc))
119 return RTMsgErrorExit(RTEXITCODE_FAILURE, "Error opening '%s': %Rrc", pszBiosSym, rc);
120 RTStrmClose(hStrm);
121 return RTEXITCODE_SUCCESS;
122}
123
124
125/**
126 * Reads a line from the file.
127 *
128 * @returns @c true on success, @c false + msg on failure, @c false on eof.
129 * @param pMap The map file handle.
130 */
131static bool mapReadLine(PBIOSMAP pMap)
132{
133 int rc = RTStrmGetLine(pMap->hStrm, pMap->szLine, sizeof(pMap->szLine));
134 if (RT_FAILURE(rc))
135 {
136 if (rc == VERR_EOF)
137 {
138 pMap->fEof = true;
139 pMap->cch = 0;
140 pMap->offNW = 0;
141 pMap->szLine[0] = '\0';
142 }
143 else
144 RTMsgError("%s:%d: Read error %Rrc", pMap->pszMapFile, pMap->iLine + 1, rc);
145 return false;
146 }
147 pMap->iLine++;
148 pMap->cch = strlen(pMap->szLine);
149
150 /* Check out leading white space. */
151 if (!RT_C_IS_SPACE(pMap->szLine[0]))
152 pMap->offNW = 0;
153 else
154 {
155 uint32_t off = 1;
156 while (RT_C_IS_SPACE(pMap->szLine[off]))
157 off++;
158 pMap->offNW = off;
159 }
160
161 return true;
162}
163
164
165/**
166 * Checks if it is an empty line.
167 * @returns @c true if empty, @c false if not.
168 * @param pMap The map file handle.
169 */
170static bool mapIsEmptyLine(PBIOSMAP pMap)
171{
172 Assert(pMap->offNW <= pMap->cch);
173 return pMap->offNW == pMap->cch;
174}
175
176
177/**
178 * Reads ahead in the map file until a non-empty line or EOF is encountered.
179 *
180 * @returns @c true on success, @c false + msg on failure, @c false on eof.
181 * @param pMap The map file handle.
182 */
183static bool mapSkipEmptyLines(PBIOSMAP pMap)
184{
185 for (;;)
186 {
187 if (!mapReadLine(pMap))
188 return false;
189 if (pMap->offNW < pMap->cch)
190 return true;
191 }
192}
193
194
195/**
196 * Reads ahead in the map file until an empty line or EOF is encountered.
197 *
198 * @returns @c true on success, @c false + msg on failure, @c false on eof.
199 * @param pMap The map file handle.
200 */
201static bool mapSkipNonEmptyLines(PBIOSMAP pMap)
202{
203 for (;;)
204 {
205 if (!mapReadLine(pMap))
206 return false;
207 if (pMap->offNW == pMap->cch)
208 return true;
209 }
210}
211
212
213/**
214 * Strips the current line.
215 *
216 * The string length may change.
217 *
218 * @returns Pointer to the first non-space character.
219 * @param pMap The map file handle.
220 * @param pcch Where to return the length of the unstripped
221 * part. Optional.
222 */
223static char *mapStripCurrentLine(PBIOSMAP pMap, size_t *pcch)
224{
225 char *psz = &pMap->szLine[pMap->offNW];
226 char *pszEnd = &pMap->szLine[pMap->cch];
227 while ( (uintptr_t)pszEnd > (uintptr_t)psz
228 && RT_C_IS_SPACE(pszEnd[-1]))
229 {
230 *--pszEnd = '\0';
231 pMap->cch--;
232 }
233 if (pcch)
234 *pcch = pszEnd - psz;
235 return psz;
236}
237
238
239/**
240 * Reads a line from the file and right strips it.
241 *
242 * @returns Pointer to szLine on success, @c NULL + msg on failure, @c NULL on
243 * EOF.
244 * @param pMap The map file handle.
245 * @param pcch Where to return the length of the unstripped
246 * part. Optional.
247 */
248static char *mapReadLineStripRight(PBIOSMAP pMap, size_t *pcch)
249{
250 if (!mapReadLine(pMap))
251 return NULL;
252 mapStripCurrentLine(pMap, NULL);
253 if (pcch)
254 *pcch = pMap->cch;
255 return pMap->szLine;
256}
257
258
259
260static 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/**
278 * mapReadLine() + mapStripCurrentLine().
279 *
280 * @returns Pointer to the first non-space character in the new line. NULL on
281 * read error (bitched already) or end of file.
282 * @param pMap The map file handle.
283 * @param pcch Where to return the length of the unstripped
284 * part. Optional.
285 */
286static char *mapReadLineStrip(PBIOSMAP pMap, size_t *pcch)
287{
288 if (!mapReadLine(pMap))
289 return NULL;
290 return mapStripCurrentLine(pMap, pcch);
291}
292
293
294/**
295 * Parses a word, copying it into the supplied buffer, and skipping any spaces
296 * following it.
297 *
298 * @returns @c true on success, @c false on failure.
299 * @param ppszCursor Pointer to the cursor variable.
300 * @param pszBuf The output buffer.
301 * @param cbBuf The size of the output buffer.
302 */
303static bool mapParseWord(char **ppszCursor, char *pszBuf, size_t cbBuf)
304{
305 /* Check that we start on a non-blank. */
306 char *pszStart = *ppszCursor;
307 if (!*pszStart || RT_C_IS_SPACE(*pszStart))
308 return false;
309
310 /* Find the end of the word. */
311 char *psz = pszStart + 1;
312 while (*psz && !RT_C_IS_SPACE(*psz))
313 psz++;
314
315 /* Copy it. */
316 size_t cchWord = (uintptr_t)psz - (uintptr_t)pszStart;
317 if (cchWord >= cbBuf)
318 return false;
319 memcpy(pszBuf, pszStart, cchWord);
320 pszBuf[cchWord] = '\0';
321
322 /* Skip blanks following it. */
323 while (RT_C_IS_SPACE(*psz))
324 psz++;
325 *ppszCursor = psz;
326 return true;
327}
328
329
330/**
331 * Parses an 16:16 address.
332 *
333 * @returns @c true on success, @c false on failure.
334 * @param ppszCursor Pointer to the cursor variable.
335 * @param pAddr Where to return the address.
336 */
337static bool mapParseAddress(char **ppszCursor, PRTFAR16 pAddr)
338{
339 char szWord[32];
340 if (!mapParseWord(ppszCursor, szWord, sizeof(szWord)))
341 return false;
342 size_t cchWord = strlen(szWord);
343
344 /* Check the first 4+1+4 chars. */
345 if (cchWord < 4 + 1 + 4)
346 return false;
347 if ( !RT_C_IS_XDIGIT(szWord[0])
348 || !RT_C_IS_XDIGIT(szWord[1])
349 || !RT_C_IS_XDIGIT(szWord[2])
350 || !RT_C_IS_XDIGIT(szWord[3])
351 || szWord[4] != ':'
352 || !RT_C_IS_XDIGIT(szWord[5])
353 || !RT_C_IS_XDIGIT(szWord[6])
354 || !RT_C_IS_XDIGIT(szWord[7])
355 || !RT_C_IS_XDIGIT(szWord[8])
356 )
357 return false;
358
359 /* Drop annotation. */
360 if (cchWord > 4+1+4)
361 {
362 if (RT_C_IS_XDIGIT(szWord[4+1+4]))
363 return false;
364 szWord[4+1+4] = '\0';
365 cchWord = 4 + 1 + 4;
366 }
367
368 /* Convert it. */
369 szWord[4] = '\0';
370 int rc1 = RTStrToUInt16Full(szWord, 16, &pAddr->sel); AssertRCSuccess(rc1);
371 int rc2 = RTStrToUInt16Full(szWord + 5, 16, &pAddr->off); AssertRCSuccess(rc2);
372 return true;
373}
374
375
376/**
377 * Parses a size.
378 *
379 * @returns @c true on success, @c false on failure.
380 * @param ppszCursor Pointer to the cursor variable.
381 * @param pcb Where to return the size.
382 */
383static bool mapParseSize(char **ppszCursor, uint32_t *pcb)
384{
385 char szWord[32];
386 if (!mapParseWord(ppszCursor, szWord, sizeof(szWord)))
387 return false;
388 size_t cchWord = strlen(szWord);
389 if (cchWord != 8)
390 return false;
391
392 int rc = RTStrToUInt32Full(szWord, 16, pcb);
393 if (rc != VINF_SUCCESS)
394 return false;
395 return true;
396}
397
398
399/**
400 * Parses a section box and the following column header.
401 *
402 * @returns @c true on success, @c false + msg on failure, @c false on eof.
403 * @param pMap Map file handle.
404 * @param pszSectionNm The expected section name.
405 * @param cColumns The number of columns.
406 * @param ... The column names.
407 */
408static bool mapSkipThruColumnHeadings(PBIOSMAP pMap, const char *pszSectionNm, uint32_t cColumns, ...)
409{
410 if ( mapIsEmptyLine(pMap)
411 && !mapSkipEmptyLines(pMap))
412 return false;
413
414 /* +------------+ */
415 size_t cch;
416 char *psz = mapStripCurrentLine(pMap, &cch);
417 if (!psz)
418 return false;
419
420 if ( psz[0] != '+'
421 || psz[1] != '-'
422 || psz[2] != '-'
423 || psz[3] != '-'
424 || psz[cch - 4] != '-'
425 || psz[cch - 3] != '-'
426 || psz[cch - 2] != '-'
427 || psz[cch - 1] != '+'
428 )
429 {
430 RTMsgError("%s:%d: Expected section box: +-----...", pMap->pszMapFile, pMap->iLine);
431 return false;
432 }
433
434 /* | pszSectionNm | */
435 psz = mapReadLineStrip(pMap, &cch);
436 if (!psz)
437 return false;
438
439 size_t cchSectionNm = strlen(pszSectionNm);
440 if ( psz[0] != '|'
441 || psz[1] != ' '
442 || psz[2] != ' '
443 || psz[3] != ' '
444 || psz[cch - 4] != ' '
445 || psz[cch - 3] != ' '
446 || psz[cch - 2] != ' '
447 || psz[cch - 1] != '|'
448 || cch != 1 + 3 + cchSectionNm + 3 + 1
449 || strncmp(&psz[4], pszSectionNm, cchSectionNm)
450 )
451 {
452 RTMsgError("%s:%d: Expected section box: | %s |", pMap->pszMapFile, pMap->iLine, pszSectionNm);
453 return false;
454 }
455
456 /* +------------+ */
457 psz = mapReadLineStrip(pMap, &cch);
458 if (!psz)
459 return false;
460 if ( psz[0] != '+'
461 || psz[1] != '-'
462 || psz[2] != '-'
463 || psz[3] != '-'
464 || psz[cch - 4] != '-'
465 || psz[cch - 3] != '-'
466 || psz[cch - 2] != '-'
467 || psz[cch - 1] != '+'
468 )
469 return RTMsgErrorExit(RTEXITCODE_FAILURE, "%s:%d: Expected section box: +-----...", pMap->pszMapFile, pMap->iLine);
470
471 /* There may be a few lines describing the table notation now, surrounded by blank lines. */
472 do
473 {
474 psz = mapReadLineStripRight(pMap, &cch);
475 if (!psz)
476 return false;
477 } while ( *psz == '\0'
478 || ( !RT_C_IS_SPACE(psz[0])
479 && RT_C_IS_SPACE(psz[1])
480 && psz[2] == '='
481 && RT_C_IS_SPACE(psz[3]))
482 );
483
484 /* Should have the column heading now. */
485 va_list va;
486 va_start(va, cColumns);
487 for (uint32_t i = 0; i < cColumns; i++)
488 {
489 const char *pszColumn = va_arg(va, const char *);
490 size_t cchColumn = strlen(pszColumn);
491 if ( strncmp(psz, pszColumn, cchColumn)
492 || ( psz[cchColumn] != '\0'
493 && !RT_C_IS_SPACE(psz[cchColumn])))
494 {
495 va_end(va);
496 RTMsgError("%s:%d: Expected column '%s' found '%s'", pMap->pszMapFile, pMap->iLine, pszColumn, psz);
497 return false;
498 }
499 psz += cchColumn;
500 while (RT_C_IS_SPACE(*psz))
501 psz++;
502 }
503 va_end(va);
504
505 /* The next line is the underlining. */
506 psz = mapReadLineStripRight(pMap, &cch);
507 if (!psz)
508 return false;
509 if (*psz != '=' || psz[cch - 1] != '=')
510 {
511 RTMsgError("%s:%d: Expected column header underlining", pMap->pszMapFile, pMap->iLine);
512 return false;
513 }
514
515 /* Skip one blank line. */
516 psz = mapReadLineStripRight(pMap, &cch);
517 if (!psz)
518 return false;
519 if (*psz)
520 {
521 RTMsgError("%s:%d: Expected blank line beneath the column headers", pMap->pszMapFile, pMap->iLine);
522 return false;
523 }
524
525 return true;
526}
527
528
529/**
530 * Parses a segment list.
531 *
532 * @returns @c true on success, @c false + msg on failure, @c false on eof.
533 * @param pMap The map file handle.
534 */
535static bool mapParseSegments(PBIOSMAP pMap)
536{
537 for (;;)
538 {
539 if (!mapReadLineStripRight(pMap, NULL))
540 return false;
541
542 /* The end? The line should be empty. Expectes segment name to not
543 start with a space. */
544 if (!pMap->szLine[0] || RT_C_IS_SPACE(pMap->szLine[0]))
545 {
546 if (!pMap->szLine[0])
547 return true;
548 RTMsgError("%s:%u: Malformed segment line", pMap->pszMapFile, pMap->iLine);
549 return false;
550 }
551
552 /* Parse the segment line. */
553 uint32_t iSeg = g_cSegs;
554 if (iSeg >= RT_ELEMENTS(g_aSegs))
555 return RTMsgErrorExit(RTEXITCODE_FAILURE, "%s:%u: Too many segments", pMap->pszMapFile, pMap->iLine);
556
557 char *psz = pMap->szLine;
558 if (!mapParseWord(&psz, g_aSegs[iSeg].szName, sizeof(g_aSegs[iSeg].szName)))
559 RTMsgError("%s:%u: Segment name parser error", pMap->pszMapFile, pMap->iLine);
560 else if (!mapParseWord(&psz, g_aSegs[iSeg].szClass, sizeof(g_aSegs[iSeg].szClass)))
561 RTMsgError("%s:%u: Segment class parser error", pMap->pszMapFile, pMap->iLine);
562 else if (!mapParseWord(&psz, g_aSegs[iSeg].szGroup, sizeof(g_aSegs[iSeg].szGroup)))
563 RTMsgError("%s:%u: Segment group parser error", pMap->pszMapFile, pMap->iLine);
564 else if (!mapParseAddress(&psz, &g_aSegs[iSeg].Address))
565 RTMsgError("%s:%u: Segment address parser error", pMap->pszMapFile, pMap->iLine);
566 else if (!mapParseSize(&psz, &g_aSegs[iSeg].cb))
567 RTMsgError("%s:%u: Segment size parser error", pMap->pszMapFile, pMap->iLine);
568 else
569 {
570 g_aSegs[iSeg].uFlatAddr = ((uint32_t)g_aSegs[iSeg].Address.sel << 4) + g_aSegs[iSeg].Address.off;
571 g_cSegs++;
572 if (g_cVerbose > 2)
573 RTStrmPrintf(g_pStdErr, "read segment at %08x / %04x:%04x LB %04x %s / %s / %s\n",
574 g_aSegs[iSeg].uFlatAddr,
575 g_aSegs[iSeg].Address.sel,
576 g_aSegs[iSeg].Address.off,
577 g_aSegs[iSeg].cb,
578 g_aSegs[iSeg].szName,
579 g_aSegs[iSeg].szClass,
580 g_aSegs[iSeg].szGroup);
581
582 while (RT_C_IS_SPACE(*psz))
583 psz++;
584 if (!*psz)
585 continue;
586 RTMsgError("%s:%u: Junk at end of line", pMap->pszMapFile, pMap->iLine);
587 }
588 return false;
589 }
590}
591
592
593/**
594 * Sorts the segment array by flat address.
595 */
596static void mapSortSegments(void)
597{
598 for (uint32_t i = 0; i < g_cSegs - 1; i++)
599 {
600 for (uint32_t j = i + 1; j < g_cSegs; j++)
601 if (g_aSegs[j].uFlatAddr < g_aSegs[i].uFlatAddr)
602 {
603 BIOSSEG Tmp = g_aSegs[i];
604 g_aSegs[i] = g_aSegs[j];
605 g_aSegs[j] = Tmp;
606 }
607 if (g_cVerbose > 0)
608 RTStrmPrintf(g_pStdErr, "segment at %08x / %04x:%04x LB %04x %s / %s / %s\n",
609 g_aSegs[i].uFlatAddr,
610 g_aSegs[i].Address.sel,
611 g_aSegs[i].Address.off,
612 g_aSegs[i].cb,
613 g_aSegs[i].szName,
614 g_aSegs[i].szClass,
615 g_aSegs[i].szGroup);
616 }
617}
618
619
620
621/**
622 * Parses the given map file.
623 *
624 * @returns RTEXITCODE_SUCCESS and lots of globals, or RTEXITCODE_FAILURE and a
625 * error message.
626 * @param pMap The map file handle.
627 */
628static RTEXITCODE mapParseFile(PBIOSMAP pMap)
629{
630 const char *psz;
631
632 /*
633 * Read the header.
634 */
635 if (!mapReadLine(pMap))
636 return RTEXITCODE_FAILURE;
637 if (strncmp(pMap->szLine, RT_STR_TUPLE("Open Watcom Linker Version")))
638 return RTMsgErrorExit(RTEXITCODE_FAILURE, "Unexpected map-file header: '%s'", pMap->szLine);
639 if ( !mapSkipNonEmptyLines(pMap)
640 || !mapSkipEmptyLines(pMap))
641 return RTEXITCODE_FAILURE;
642
643 /*
644 * Skip groups.
645 */
646 if (!mapSkipThruColumnHeadings(pMap, "Groups", 3, "Group", "Address", "Size", NULL))
647 return RTEXITCODE_FAILURE;
648 if (!mapSkipNonEmptyLines(pMap))
649 return RTEXITCODE_FAILURE;
650
651 /*
652 * Parse segments.
653 */
654 if (!mapSkipThruColumnHeadings(pMap, "Segments", 5, "Segment", "Class", "Group", "Address", "Size"))
655 return RTEXITCODE_FAILURE;
656 if (!mapParseSegments(pMap))
657 return RTEXITCODE_FAILURE;
658 mapSortSegments();
659
660
661 return RTMsgErrorExit(RTEXITCODE_FAILURE, "mapParseFile is not fully implemented");
662}
663
664
665/**
666 * Parses the linker map file for the BIOS.
667 *
668 * This is generated by the Watcom linker.
669 *
670 * @returns RTEXITCODE_SUCCESS or RTEXITCODE_FAILURE+msg.
671 * @param pszBiosMap Path to the map file.
672 */
673static RTEXITCODE ParseMapFile(const char *pszBiosMap)
674{
675 BIOSMAP Map;
676 Map.pszMapFile = pszBiosMap;
677 Map.hStrm = NULL;
678 Map.iLine = 0;
679 Map.fEof = false;
680 Map.cch = 0;
681 Map.offNW = 0;
682 int rc = RTStrmOpen(pszBiosMap, "r", &Map.hStrm);
683 if (RT_FAILURE(rc))
684 return RTMsgErrorExit(RTEXITCODE_FAILURE, "Error opening '%s': %Rrc", pszBiosMap, rc);
685 RTEXITCODE rcExit = mapParseFile(&Map);
686 RTStrmClose(Map.hStrm);
687 return rcExit;
688}
689
690
691/**
692 * Reads the BIOS image into memory (g_pbImg and g_cbImg).
693 *
694 * @returns RTEXITCODE_SUCCESS or RTEXITCODE_FAILURE+msg.
695 * @param pszBiosImg Path to the image file.
696 */
697static RTEXITCODE ReadBiosImage(const char *pszBiosImg)
698{
699 void *pvImg;
700 size_t cbImg;
701 int rc = RTFileReadAll(pszBiosImg, &pvImg, &cbImg);
702 if (RT_FAILURE(rc))
703 return RTMsgErrorExit(RTEXITCODE_FAILURE, "Error reading '%s': %Rrc", pszBiosImg, rc);
704 if (cbImg != _64K)
705 {
706 RTFileReadAllFree(pvImg, cbImg);
707 return RTMsgErrorExit(RTEXITCODE_FAILURE, "The BIOS image %u bytes intead of 64KB", cbImg);
708 }
709
710 g_pbImg = (uint8_t *)pvImg;
711 g_cbImg = cbImg;
712 return RTEXITCODE_SUCCESS;
713}
714
715
716int main(int argc, char **argv)
717{
718 int rc = RTR3InitExe(argc, &argv, 0);
719 if (RT_FAILURE(rc))
720 return RTMsgInitFailure(rc);
721
722 /*
723 * Option config.
724 */
725 static RTGETOPTDEF const s_aOpts[] =
726 {
727 { "--bios-image", 'i', RTGETOPT_REQ_STRING },
728 { "--bios-map", 'm', RTGETOPT_REQ_STRING },
729 { "--bios-sym", 's', RTGETOPT_REQ_STRING },
730 { "--output", 'o', RTGETOPT_REQ_STRING },
731 { "--verbose", 'v', RTGETOPT_REQ_NOTHING },
732 { "--quiet", 'q', RTGETOPT_REQ_NOTHING },
733 };
734
735 const char *pszBiosMap = NULL;
736 const char *pszBiosSym = NULL;
737 const char *pszBiosImg = NULL;
738 const char *pszOutput = NULL;
739
740 RTGETOPTUNION ValueUnion;
741 RTGETOPTSTATE GetOptState;
742 rc = RTGetOptInit(&GetOptState, argc, argv, &s_aOpts[0], RT_ELEMENTS(s_aOpts), 1, RTGETOPTINIT_FLAGS_OPTS_FIRST);
743 AssertReleaseRCReturn(rc, RTEXITCODE_FAILURE);
744
745 /*
746 * Process the options.
747 */
748 while ((rc = RTGetOpt(&GetOptState, &ValueUnion)) != 0)
749 {
750 switch (rc)
751 {
752 case 'i':
753 if (pszBiosImg)
754 return RTMsgErrorExit(RTEXITCODE_SYNTAX, "--bios-image is given more than once");
755 pszBiosImg = ValueUnion.psz;
756 break;
757
758 case 'm':
759 if (pszBiosMap)
760 return RTMsgErrorExit(RTEXITCODE_SYNTAX, "--bios-map is given more than once");
761 pszBiosMap = ValueUnion.psz;
762 break;
763
764 case 's':
765 if (pszBiosSym)
766 return RTMsgErrorExit(RTEXITCODE_SYNTAX, "--bios-sym is given more than once");
767 pszBiosSym = ValueUnion.psz;
768 break;
769
770 case 'o':
771 if (pszOutput)
772 return RTMsgErrorExit(RTEXITCODE_SYNTAX, "--output is given more than once");
773 pszOutput = ValueUnion.psz;
774 break;
775
776 case 'v':
777 g_cVerbose++;
778 break;
779
780 case 'q':
781 g_cVerbose = 0;
782 break;
783
784 case 'H':
785 RTPrintf("usage: %Rbn --bios-image <file.img> --bios-map <file.map> [--output <file.asm>]\n",
786 argv[0]);
787 return RTEXITCODE_SUCCESS;
788
789 case 'V':
790 {
791 /* The following is assuming that svn does it's job here. */
792 RTPrintf("r%u\n", RTBldCfgRevision());
793 return RTEXITCODE_SUCCESS;
794 }
795
796 default:
797 return RTGetOptPrintError(rc, &ValueUnion);
798 }
799 }
800
801 /*
802 * Got it all?
803 */
804 if (!pszBiosImg)
805 return RTMsgErrorExit(RTEXITCODE_SYNTAX, "--bios-image is required");
806 if (!pszBiosMap)
807 return RTMsgErrorExit(RTEXITCODE_SYNTAX, "--bios-map is required");
808 if (!pszBiosSym)
809 return RTMsgErrorExit(RTEXITCODE_SYNTAX, "--bios-sym is required");
810
811 /*
812 * Do the job.
813 */
814 RTEXITCODE rcExit;
815 rcExit = ReadBiosImage(pszBiosImg);
816 if (rcExit == RTEXITCODE_SUCCESS)
817 rcExit = ParseMapFile(pszBiosMap);
818 if (rcExit == RTEXITCODE_SUCCESS)
819 rcExit = ParseSymFile(pszBiosSym);
820 if (rcExit == RTEXITCODE_SUCCESS)
821 rcExit = OpenOutputFile(pszOutput);
822 if (rcExit == RTEXITCODE_SUCCESS)
823 rcExit = DisassembleBiosImage();
824
825 return rcExit;
826}
827
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette