VirtualBox

Changeset 48452 in vbox for trunk/src/VBox/Devices


Ignore:
Timestamp:
Sep 12, 2013 3:13:26 PM (12 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
88908
Message:

DevEFI.cpp: Get the TSC frequency from the VMM. Sort the variables (easier to read). Display variable values that looks like strings as strings in 'info nvram'.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/EFI/DevEFI.cpp

    r48400 r48452  
    3232#include <iprt/asm.h>
    3333#include <iprt/assert.h>
     34#include <iprt/ctype.h>
    3435#include <iprt/file.h>
    3536#include <iprt/mem.h>
     
    8687/** Pointer to an EFI NVRAM variable. */
    8788typedef EFIVAR *PEFIVAR;
     89/** Pointer to a const EFI NVRAM variable. */
     90typedef EFIVAR const *PCEFIVAR;
    8891/** Pointer to an EFI NVRAM variable pointer. */
    8992typedef PEFIVAR *PPEFIVAR;
     
    330333}
    331334
     335
     336/**
     337 * Inserts the EFI variable into the list.
     338 *
     339 * This enforces the desired list ordering and/or insertion policy.
     340 *
     341 * @param   pThis           The EFI state.
     342 * @param   pEfiVar         The variable to insert.
     343 */
     344static void nvramInsertVariable(PDEVEFI pThis, PEFIVAR pEfiVar)
     345{
     346#if 1
     347    /*
     348     * Sorted by UUID and name.
     349     */
     350    PEFIVAR pCurVar;
     351    RTListForEach(&pThis->NVRAM.VarList, pCurVar, EFIVAR, ListNode)
     352    {
     353        int iDiff = RTUuidCompare(&pEfiVar->uuid, &pCurVar->uuid);
     354        if (!iDiff)
     355            iDiff = strcmp(pEfiVar->szName, pCurVar->szName);
     356        if (iDiff < 0)
     357        {
     358            RTListNodeInsertBefore(&pCurVar->ListNode, &pEfiVar->ListNode);
     359            return;
     360        }
     361    }
     362#endif
     363
     364    /*
     365     * Add it at the end.
     366     */
     367    RTListAppend(&pThis->NVRAM.VarList, &pEfiVar->ListNode);
     368}
     369
     370
    332371/**
    333372 * Creates an device internal list of variables.
     
    372411
    373412        /* Append it. */
    374         RTListAppend((PRTLISTNODE)&pThis->NVRAM.VarList, &pEfiVar->ListNode);
     413        nvramInsertVariable(pThis, pEfiVar);
    375414        pThis->NVRAM.cVariables++;
    376415    }
     
    602641            memcpy(pEfiVar->abValue, pThis->NVRAM.VarOpBuf.abValue, pEfiVar->cbValue);
    603642
    604             RTListAppend(&pThis->NVRAM.VarList, &pEfiVar->ListNode);
     643            nvramInsertVariable(pThis, pEfiVar);
     644            pThis->NVRAM.cVariables++;
    605645            pThis->NVRAM.u32Status = EFI_VARIABLE_OP_STATUS_OK;
    606             pThis->NVRAM.cVariables++;
    607646        }
    608647        else
     
    867906}
    868907
     908
     909/**
     910 * Checks if the EFI variable value looks like a printable UTF-8 string.
     911 *
     912 * @returns true if it is, false if not.
     913 * @param   pEfiVar             The variable.
     914 * @param   pfZeroTerm          Where to return whether the string is zero
     915 *                              terminated.
     916 */
     917static bool efiInfoNvramIsUtf8(PCEFIVAR pEfiVar, bool *pfZeroTerm)
     918{
     919    if (pEfiVar->cbValue < 2)
     920        return false;
     921    const char *pachValue = (const char *)&pEfiVar->abValue[0];
     922    *pfZeroTerm = pachValue[pEfiVar->cbValue - 1] == 0;
     923
     924    /* Check the length. */
     925    size_t cchValue = RTStrNLen((const char *)pEfiVar->abValue, pEfiVar->cbValue);
     926    if (cchValue != pEfiVar->cbValue - *pfZeroTerm)
     927        return false; /* stray zeros in the value, forget it. */
     928
     929    /* Check that the string is valid UTF-8 and printable. */
     930    const char *pchCur = pachValue;
     931    while ((uintptr_t)(pchCur - pachValue) < cchValue)
     932    {
     933        RTUNICP uc;
     934        int rc = RTStrGetCpEx(&pachValue, &uc);
     935        if (RT_FAILURE(rc))
     936            return false;
     937        /** @todo Missing RTUniCpIsPrintable. */
     938        if (uc < 128 && !RT_C_IS_PRINT(uc))
     939            return false;
     940    }
     941
     942    return true;
     943}
     944
     945
     946/**
     947 * Checks if the EFI variable value looks like a printable UTF-16 string.
     948 *
     949 * @returns true if it is, false if not.
     950 * @param   pEfiVar             The variable.
     951 * @param   pfZeroTerm          Where to return whether the string is zero
     952 *                              terminated.
     953 */
     954static bool efiInfoNvramIsUtf16(PCEFIVAR pEfiVar, bool *pfZeroTerm)
     955{
     956    if (pEfiVar->cbValue < 4 || (pEfiVar->cbValue & 1))
     957        return false;
     958
     959    PCRTUTF16 pwcValue = (PCRTUTF16)&pEfiVar->abValue[0];
     960    size_t    cwcValue = pEfiVar->cbValue /  sizeof(RTUTF16);
     961    *pfZeroTerm = pwcValue[cwcValue - 1] == 0;
     962    if (!*pfZeroTerm && RTUtf16IsHighSurrogate(pwcValue[cwcValue - 1]))
     963        return false; /* Catch bad string early, before reading a char too many. */
     964    cwcValue -= *pfZeroTerm;
     965    if (cwcValue < 2)
     966        return false;
     967
     968    /* Check that the string is valid UTF-16, printable and spans the whole
     969       value length. */
     970    size_t    cAscii = 0;
     971    PCRTUTF16 pwcCur = pwcValue;
     972    while ((uintptr_t)(pwcCur - pwcValue) < cwcValue)
     973    {
     974        RTUNICP uc;
     975        int rc = RTUtf16GetCpEx(&pwcCur, &uc);
     976        if (RT_FAILURE(rc))
     977            return false;
     978        /** @todo Missing RTUniCpIsPrintable. */
     979        if (uc < 128 && !RT_C_IS_PRINT(uc))
     980            return false;
     981        cAscii += uc < 128;
     982    }
     983    if (cAscii < 2)
     984        return false;
     985
     986    return true;
     987}
     988
     989
    869990/**
    870991 * @implement_callback_method{FNDBGFHANDLERDEV}
     
    876997
    877998    pHlp->pfnPrintf(pHlp, "NVRAM variables: %u\n", pThis->NVRAM.cVariables);
    878     PEFIVAR pEfiVar;
     999    PCEFIVAR pEfiVar;
    8791000    RTListForEach(&pThis->NVRAM.VarList, pEfiVar, EFIVAR, ListNode)
    8801001    {
    881         pHlp->pfnPrintf(pHlp,
    882                         "Variable - fAttr=%#04x - '%RTuuid:%s' - cb=%#04x\n"
    883                         "%.*Rhxd\n",
    884                         pEfiVar->fAttributes, &pEfiVar->uuid, pEfiVar->szName, pEfiVar->cbValue,
    885                         pEfiVar->cbValue, pEfiVar->abValue);
     1002        /* Detect UTF-8 and UTF-16 strings. */
     1003        bool fZeroTerm = false;
     1004        if (efiInfoNvramIsUtf8(pEfiVar, &fZeroTerm))
     1005            pHlp->pfnPrintf(pHlp,
     1006                            "Variable - fAttr=%#04x - '%RTuuid:%s' - cb=%#04x\n"
     1007                            "String value (UTF-8%s): \"%.*s\"\n",
     1008                            pEfiVar->fAttributes, &pEfiVar->uuid, pEfiVar->szName, pEfiVar->cbValue,
     1009                            fZeroTerm ? "" : ",nz", pEfiVar->cbValue, pEfiVar->abValue);
     1010        else if (efiInfoNvramIsUtf16(pEfiVar, &fZeroTerm))
     1011            pHlp->pfnPrintf(pHlp,
     1012                            "Variable - fAttr=%#04x - '%RTuuid:%s' - cb=%#04x\n"
     1013                            "String value (UTF-16%s): \"%.*ls\"\n",
     1014                            pEfiVar->fAttributes, &pEfiVar->uuid, pEfiVar->szName, pEfiVar->cbValue,
     1015                            fZeroTerm ? "" : ",nz", pEfiVar->cbValue, pEfiVar->abValue);
     1016        else
     1017            pHlp->pfnPrintf(pHlp,
     1018                            "Variable - fAttr=%#04x - '%RTuuid:%s' - cb=%#04x\n"
     1019                            "%.*Rhxd\n",
     1020                            pEfiVar->fAttributes, &pEfiVar->uuid, pEfiVar->szName, pEfiVar->cbValue,
     1021                            pEfiVar->cbValue, pEfiVar->abValue);
     1022
    8861023    }
    8871024
     
    13171454        AssertRCReturnStmt(rc, RTMemFree(pEfiVar), rc);
    13181455
    1319         /* Add it, updating the current variable pointer while we're here. */
     1456        /* Add it (not using nvramInsertVariable to preserve saved order),
     1457           updating the current variable pointer while we're here. */
     1458#if 1
    13201459        RTListAppend(&pThis->NVRAM.VarList, &pEfiVar->ListNode);
     1460#else
     1461        nvramInsertVariable(pThis, pEfiVar);
     1462#endif
    13211463        if (pThis->NVRAM.idUniqueCurVar == pEfiVar->idUniqueSavedState)
    13221464            pThis->NVRAM.pCurVar = pEfiVar;
     
    18571999                                   N_("Configuration error: Querying \"BootArgs\" as a string failed"));
    18582000
     2001    //strcpy(pThis->szBootArgs, "-v keepsyms=1 io=0xf");
    18592002    LogRel(("EFI boot args: %s\n", pThis->szBootArgs));
    18602003
     
    18832026
    18842027    /*
    1885      * CPU frequencies
    1886      */
    1887     /// @todo we need to have VMM API to access TSC increase speed, for now provide reasonable default
    1888     pThis->u64TscFrequency = RTMpGetMaxFrequency(0) * 1000 * 1000;// TMCpuTicksPerSecond(PDMDevHlpGetVM(pDevIns));
    1889     if (pThis->u64TscFrequency == 0)
    1890         pThis->u64TscFrequency = UINT64_C(2500000000);
    1891     /* Multiplier is read from MSR_IA32_PERF_STATUS, and now is hardcoded as 4 */
     2028     * CPU frequencies.
     2029     */
     2030    pThis->u64TscFrequency = TMCpuTicksPerSecond(PDMDevHlpGetVM(pDevIns));
     2031    /* Multiplier is read from MSR_IA32_PERF_STATUS, and now is hardcoded as 4. */
    18922032    pThis->u64FsbFrequency = pThis->u64TscFrequency / 4;
    18932033    pThis->u64CpuFrequency = pThis->u64TscFrequency;
    18942034
    18952035    /*
    1896      * GOP graphics
     2036     * GOP graphics.
    18972037     */
    18982038    rc = CFGMR3QueryU32Def(pCfg, "GopMode", &pThis->u32GopMode, 2 /* 1024x768 */);
     
    19042044
    19052045    /*
    1906      * Uga graphics.
    1907      */
    1908     rc = CFGMR3QueryU32Def(pCfg, "UgaHorizontalResolution", &pThis->cxUgaResolution, 0); AssertRC(rc);
    1909     if (pThis->cxUgaResolution == 0)
    1910         pThis->cxUgaResolution = 1024;  /* 1024x768 */
    1911     rc = CFGMR3QueryU32Def(pCfg, "UgaVerticalResolution", &pThis->cyUgaResolution, 0); AssertRC(rc);
    1912     if (pThis->cyUgaResolution == 0)
    1913         pThis->cyUgaResolution = 768;    /* 1024x768 */
     2046     * Uga graphics, default to 1024x768.
     2047     */
     2048    rc = CFGMR3QueryU32Def(pCfg, "UgaHorizontalResolution", &pThis->cxUgaResolution, 0);
     2049    AssertRCReturn(rc, rc);
     2050    rc = CFGMR3QueryU32Def(pCfg, "UgaVerticalResolution", &pThis->cyUgaResolution, 0);
     2051    AssertRCReturn(rc, rc);
     2052    if (pThis->cxUgaResolution == 0 || pThis->cyUgaResolution == 0)
     2053    {
     2054        pThis->cxUgaResolution = 1024;
     2055        pThis->cyUgaResolution = 768;
     2056    }
    19142057
    19152058#ifdef DEVEFI_WITH_VBOXDBG_SCRIPT
Note: See TracChangeset for help on using the changeset viewer.

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