/* $Id: MakeDebianBiosAssembly.cpp 41316 2012-05-15 14:44:36Z vboxsync $ */ /** @file * MakeDebianBiosAssembly - Generate Assembly Source for Debian-minded Distros. */ /* * Copyright (C) 2012 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; * you can redistribute it and/or modify it under the terms of the GNU * General Public License (GPL) as published by the Free Software * Foundation, in version 2 as it comes in the "COPYING" file of the * VirtualBox OSE distribution. VirtualBox OSE is distributed in the * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. */ /******************************************************************************* * Header Files * *******************************************************************************/ #include #include #include #include #include #include #include #include /******************************************************************************* * Global Variables * *******************************************************************************/ static unsigned g_cVerbose = 1 /*0*/; /** Pointer to the BIOS image. */ static uint8_t const *g_pbImg; /** The size of the BIOS image. */ static size_t g_cbImg; static RTEXITCODE DisassembleBiosImage(void) { return RTMsgErrorExit(RTEXITCODE_FAILURE, "DisassembleBiosImage is not implemented"); } static RTEXITCODE OpenOutputFile(const char *pszOutput) { return RTMsgErrorExit(RTEXITCODE_FAILURE, "OpenOutputFile is not implemented"); } static int SkipEmptyLines(PRTSTREAM hStrm, uint32_t *piLine) { for (;;) { char szLine[16384]; int rc = RTStrmGetLine(hStrm, szLine, sizeof(szLine)); if (RT_FAILURE(rc)) { RTMsgError("Error read map-file header: %Rrc", rc); return rc; } *piLine += 1; const char *psz = RTStrStrip(szLine); if (*psz) return VINF_SUCCESS; } } static int SkipNonEmptyLines(PRTSTREAM hStrm, uint32_t *piLine) { for (;;) { char szLine[16384]; int rc = RTStrmGetLine(hStrm, szLine, sizeof(szLine)); if (RT_FAILURE(rc)) { RTMsgError("Error read map-file header: %Rrc", rc); return rc; } *piLine += 1; const char *psz = RTStrStrip(szLine); if (!*psz) return VINF_SUCCESS; } } static RTEXITCODE ParseMapFileInner(const char *pszBiosMap, PRTSTREAM hStrm) { uint32_t iLine = 1; char szLine[16384]; const char *psz; /* * Read the header. */ int rc = RTStrmGetLine(hStrm, szLine, sizeof(szLine)); if (RT_FAILURE(rc)) return RTMsgErrorExit(RTEXITCODE_FAILURE, "Error read map-file header: %Rrc", rc); if (strncmp(szLine, RT_STR_TUPLE("Open Watcom Linker Version"))) return RTMsgErrorExit(RTEXITCODE_FAILURE, "Unexpected map-file header: '%s'", szLine); rc = SkipNonEmptyLines(hStrm, &iLine); return RTMsgErrorExit(RTEXITCODE_FAILURE, "ParseMapFileInner is not fully implemented"); } /** * Parses the linker map file for the BIOS. * * This is generated by the Watcom linker. * * @returns RTEXITCODE_SUCCESS or RTEXITCODE_FAILURE+msg. * @param pszBiosMap Path to the map file. */ static RTEXITCODE ParseMapFile(const char *pszBiosMap) { PRTSTREAM hStrm; int rc = RTStrmOpen(pszBiosMap, "rt", &hStrm); if (RT_FAILURE(rc)) return RTMsgErrorExit(RTEXITCODE_FAILURE, "Error opening '%s': %Rrc", pszBiosMap, rc); RTEXITCODE rcExit = ParseMapFileInner(pszBiosMap, hStrm); RTStrmClose(hStrm); return rcExit; } /** * Reads the BIOS image into memory (g_pbImg and g_cbImg). * * @returns RTEXITCODE_SUCCESS or RTEXITCODE_FAILURE+msg. * @param pszBiosImg Path to the image file. */ static RTEXITCODE ReadBiosImage(const char *pszBiosImg) { void *pvImg; size_t cbImg; int rc = RTFileReadAll(pszBiosImg, &pvImg, &cbImg); if (RT_FAILURE(rc)) return RTMsgErrorExit(RTEXITCODE_FAILURE, "Error reading '%s': %Rrc", pszBiosImg, rc); if (cbImg != _64K) { RTFileReadAllFree(pvImg, cbImg); return RTMsgErrorExit(RTEXITCODE_FAILURE, "The BIOS image %u bytes intead of 64KB", cbImg); } g_pbImg = (uint8_t *)pvImg; g_cbImg = cbImg; return RTEXITCODE_SUCCESS; } int main(int argc, char **argv) { int rc = RTR3InitExe(argc, &argv, 0); if (RT_FAILURE(rc)) return RTMsgInitFailure(rc); /* * Option config. */ static RTGETOPTDEF const s_aOpts[] = { { "--bios-image", 'i', RTGETOPT_REQ_STRING }, { "--bios-map", 'm', RTGETOPT_REQ_STRING }, { "--output", 'o', RTGETOPT_REQ_STRING }, { "--verbose", 'v', RTGETOPT_REQ_NOTHING }, { "--quiet", 'q', RTGETOPT_REQ_NOTHING }, }; const char *pszBiosMap = NULL; const char *pszBiosImg = NULL; const char *pszOutput = NULL; RTGETOPTUNION ValueUnion; RTGETOPTSTATE GetOptState; rc = RTGetOptInit(&GetOptState, argc, argv, &s_aOpts[0], RT_ELEMENTS(s_aOpts), 1, RTGETOPTINIT_FLAGS_OPTS_FIRST); AssertReleaseRCReturn(rc, RTEXITCODE_FAILURE); /* * Process the options. */ while ((rc = RTGetOpt(&GetOptState, &ValueUnion)) != 0) { switch (rc) { case 'i': if (pszBiosImg) return RTMsgErrorExit(RTEXITCODE_SYNTAX, "--bios-image is given more than once"); pszBiosImg = ValueUnion.psz; break; case 'm': if (pszBiosMap) return RTMsgErrorExit(RTEXITCODE_SYNTAX, "--bios-map is given more than once"); pszBiosMap = ValueUnion.psz; break; case 'o': if (pszOutput) return RTMsgErrorExit(RTEXITCODE_SYNTAX, "--output is given more than once"); pszOutput = ValueUnion.psz; break; case 'v': g_cVerbose++; break; case 'q': g_cVerbose = 0; break; case 'H': RTPrintf("usage: %Rbn --bios-image --bios-map [--output ]\n", argv[0]); return RTEXITCODE_SUCCESS; case 'V': { /* The following is assuming that svn does it's job here. */ RTPrintf("r%u\n", RTBldCfgRevision()); return RTEXITCODE_SUCCESS; } default: return RTGetOptPrintError(rc, &ValueUnion); } } /* * Got it all? */ if (!pszBiosImg) return RTMsgErrorExit(RTEXITCODE_SYNTAX, "--bios-image is required"); if (!pszBiosMap) return RTMsgErrorExit(RTEXITCODE_SYNTAX, "--bios-map is required"); /* * Do the job. */ RTEXITCODE rcExit; rcExit = ReadBiosImage(pszBiosImg); if (rcExit == RTEXITCODE_SUCCESS) rcExit = ParseMapFile(pszBiosMap); if (rcExit == RTEXITCODE_SUCCESS) rcExit = OpenOutputFile(pszOutput); if (rcExit == RTEXITCODE_SUCCESS) rcExit = DisassembleBiosImage(); return rcExit; }