VirtualBox

Ignore:
Timestamp:
May 29, 2012 2:52:47 PM (13 years ago)
Author:
vboxsync
Message:

a bit more...

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/PC/BIOS-new/MakeDebianBiosAssembly.cpp

    r41316 r41482  
    2121*******************************************************************************/
    2222#include <iprt/buildconfig.h>
     23#include <iprt/ctype.h>
    2324#include <iprt/file.h>
    2425#include <iprt/getopt.h>
     
    3132
    3233/*******************************************************************************
     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    cb;
     46} BIOSSEG;
     47/** Pointer to a BIOS segment. */
     48typedef BIOSSEG *PBIOSSEG;
     49
     50
     51/*******************************************************************************
    3352*   Global Variables                                                           *
    3453*******************************************************************************/
    35 static unsigned g_cVerbose = 1 /*0*/;
     54static unsigned         g_cVerbose = 1 /*0*/;
    3655/** Pointer to the BIOS image. */
    3756static uint8_t const   *g_pbImg;
     
    3958static size_t           g_cbImg;
    4059
     60/** The number of BIOS segments found in the map file. */
     61static uint32_t         g_cSegs = 0;
     62/** Array of BIOS segments from the map file. */
     63static BIOSSEG          g_aSegs[32];
     64
     65
     66
    4167
    4268
     
    5278
    5379
    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 */
     88static 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
     102static bool SkipEmptyLines(PRTSTREAM hStrm, uint32_t *piLine, char *pszLine, size_t cbLine)
    55103{
    56104    for (;;)
    57105    {
     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
     121static 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
     140static 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
     157static 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
     174static 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
     190static 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
     217static 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
     256static 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 */
     283static 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
     394static RTEXITCODE ParseMapFileSegments(const char *pszBiosMap, PRTSTREAM hStrm, uint32_t *piLine)
     395{
     396    for (;;)
     397    {
     398        /* Read the next line and right strip it. */
    58399        char szLine[16384];
    59400        int rc = RTStrmGetLine(hStrm, szLine, sizeof(szLine));
    60401        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]))
    61410        {
    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;
    64414        }
    65415
    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++;
    68437        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
    92443
    93444static RTEXITCODE ParseMapFileInner(const char *pszBiosMap, PRTSTREAM hStrm)
     
    102453    int rc = RTStrmGetLine(hStrm, szLine, sizeof(szLine));
    103454    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);
    105456    if (strncmp(szLine, RT_STR_TUPLE("Open Watcom Linker Version")))
    106457        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
    108481
    109482
     
    111484    return RTMsgErrorExit(RTEXITCODE_FAILURE, "ParseMapFileInner is not fully implemented");
    112485}
    113 
    114486
    115487
     
    172544        { "--bios-image",               'i',                    RTGETOPT_REQ_STRING },
    173545        { "--bios-map",                 'm',                    RTGETOPT_REQ_STRING },
     546        { "--bios-sym",                 's',                    RTGETOPT_REQ_STRING },
    174547        { "--output",                   'o',                    RTGETOPT_REQ_STRING },
    175548        { "--verbose",                  'v',                    RTGETOPT_REQ_NOTHING },
     
    178551
    179552    const char *pszBiosMap = NULL;
     553    const char *pszBiosSym = NULL;
    180554    const char *pszBiosImg = NULL;
    181555    const char *pszOutput  = NULL;
     
    205579                break;
    206580
     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
    207587            case 'o':
    208588                if (pszOutput)
     
    243623    if (!pszBiosMap)
    244624        return RTMsgErrorExit(RTEXITCODE_SYNTAX, "--bios-map is required");
     625    if (!pszBiosSym)
     626        return RTMsgErrorExit(RTEXITCODE_SYNTAX, "--bios-sym is required");
    245627
    246628    /*
     
    252634        rcExit = ParseMapFile(pszBiosMap);
    253635    if (rcExit == RTEXITCODE_SUCCESS)
     636        rcExit = ParseSymFile(pszBiosSym);
     637    if (rcExit == RTEXITCODE_SUCCESS)
    254638        rcExit = OpenOutputFile(pszOutput);
    255639    if (rcExit == RTEXITCODE_SUCCESS)
Note: See TracChangeset for help on using the changeset viewer.

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