VirtualBox

Changeset 91685 in vbox


Ignore:
Timestamp:
Oct 12, 2021 9:26:59 AM (4 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
147413
Message:

Main/UefiVariableStore,FE/VBoxManage: Implement API to delete and change the content of a UEFI variable and hook it up to VBoxManage, bugref:9580

Location:
trunk
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/doc/manual/en_US/man_VBoxManage-modifynvram.xml

    r91617 r91685  
    7070      <arg>--filename=<replaceable>filename</replaceable></arg>
    7171    </cmdsynopsis>
     72    <cmdsynopsis id="synopsis-vboxmanage-modifynvram-deletevar">
     73      <command>VBoxManage modifynvram</command>
     74      <arg choice="req"><replaceable>uuid|vmname</replaceable></arg>
     75      <arg choice="plain">deletevar</arg>
     76      <arg>--name=<replaceable>name</replaceable></arg>
     77      <arg>--owner-uuid=<replaceable>uuid</replaceable></arg>
     78    </cmdsynopsis>
     79    <cmdsynopsis id="synopsis-vboxmanage-modifynvram-changevar">
     80      <command>VBoxManage modifynvram</command>
     81      <arg choice="req"><replaceable>uuid|vmname</replaceable></arg>
     82      <arg choice="plain">changevar</arg>
     83      <arg>--name=<replaceable>name</replaceable></arg>
     84      <arg>--filename=<replaceable>filename</replaceable></arg>
     85    </cmdsynopsis>
    7286  </refsynopsisdiv>
    7387
     
    172186    </refsect2>
    173187
     188    <refsect2 id="vboxmanage-modifynvram-deletevar">
     189      <title>modifynvram deletevar</title>
     190      <remark role="help-copy-synopsis"/>
     191      <para>
     192        Deletes the given variable identified by its name and owner UUID.
     193      </para>
     194      <variablelist>
     195        <varlistentry>
     196          <term><option>--name=<replaceable>name</replaceable></option></term>
     197          <listitem><para>UEFI variable name to delete.</para>
     198          </listitem>
     199        </varlistentry>
     200        <varlistentry>
     201          <term><option>--owner-uuid=<replaceable>uuid</replaceable></option></term>
     202          <listitem><para>The UUID identifying the owner of the variable to delete.</para>
     203          </listitem>
     204        </varlistentry>
     205      </variablelist>
     206    </refsect2>
     207
     208    <refsect2 id="vboxmanage-modifynvram-changevar">
     209      <title>modifynvram changevar</title>
     210      <remark role="help-copy-synopsis"/>
     211      <para>
     212        Changes the UEFI variable content to the one form the given file.
     213      </para>
     214      <variablelist>
     215        <varlistentry>
     216          <term><option>--name=<replaceable>name</replaceable></option></term>
     217          <listitem><para>UEFI variable name to change the data for.</para>
     218          </listitem>
     219        </varlistentry>
     220        <varlistentry>
     221          <term><option>--filename=<replaceable>filename</replaceable></option></term>
     222          <listitem>
     223            <para>The file to read the data from.</para>
     224          </listitem>
     225        </varlistentry>
     226      </variablelist>
     227    </refsect2>
     228
    174229  </refsect1>
    175230</refentry>
  • trunk/src/VBox/Frontends/VBoxManage/VBoxManageModifyNvram.cpp

    r91617 r91685  
    289289
    290290/**
     291 * Handles the 'modifynvram myvm deletevar' sub-command.
     292 * @returns Exit code.
     293 * @param   a               The handler argument package.
     294 * @param   nvram           Reference to the NVRAM store interface.
     295 */
     296static RTEXITCODE handleModifyNvramDeleteUefiVar(HandlerArg *a, ComPtr<INvramStore> &nvramStore)
     297{
     298    static const RTGETOPTDEF s_aOptions[] =
     299    {
     300        /* common options */
     301        { "--name",       'n', RTGETOPT_REQ_STRING },
     302        { "--owner-uuid", 'f', RTGETOPT_REQ_STRING }
     303    };
     304
     305    const char *pszVarName = NULL;
     306    const char *pszOwnerUuid = NULL;
     307
     308    RTGETOPTSTATE GetState;
     309    int vrc = RTGetOptInit(&GetState, a->argc - 2, &a->argv[2], s_aOptions, RT_ELEMENTS(s_aOptions), 0, 0);
     310    AssertRCReturn(vrc, RTEXITCODE_FAILURE);
     311
     312    int c;
     313    RTGETOPTUNION ValueUnion;
     314    while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
     315    {
     316        switch (c)
     317        {
     318            case 'n':
     319                pszVarName = ValueUnion.psz;
     320                break;
     321            case 'f':
     322                pszOwnerUuid = ValueUnion.psz;
     323                break;
     324            default:
     325                return errorGetOpt(c, &ValueUnion);
     326        }
     327    }
     328
     329    if (!pszVarName)
     330        return errorSyntax("No variable name was given to \"deletevar\"");
     331    if (!pszOwnerUuid)
     332        return errorSyntax("No owner UUID was given to \"deletevar\"");
     333
     334    ComPtr<IUefiVariableStore> uefiVarStore;
     335    CHECK_ERROR2I_RET(nvramStore, COMGETTER(UefiVariableStore)(uefiVarStore.asOutParam()), RTEXITCODE_FAILURE);
     336    CHECK_ERROR2I_RET(uefiVarStore, DeleteVariable(Bstr(pszVarName).raw(), Bstr(pszOwnerUuid).raw()), RTEXITCODE_FAILURE);
     337
     338    return RTEXITCODE_SUCCESS;
     339}
     340
     341
     342/**
     343 * Handles the 'modifynvram myvm changevar' sub-command.
     344 * @returns Exit code.
     345 * @param   a               The handler argument package.
     346 * @param   nvram           Reference to the NVRAM store interface.
     347 */
     348static RTEXITCODE handleModifyNvramChangeUefiVar(HandlerArg *a, ComPtr<INvramStore> &nvramStore)
     349{
     350    static const RTGETOPTDEF s_aOptions[] =
     351    {
     352        /* common options */
     353        { "--name",       'n', RTGETOPT_REQ_STRING },
     354        { "--filename",   'f', RTGETOPT_REQ_STRING }
     355    };
     356
     357    const char *pszVarName = NULL;
     358    const char *pszVarDataFilename = NULL;
     359
     360    RTGETOPTSTATE GetState;
     361    int vrc = RTGetOptInit(&GetState, a->argc - 2, &a->argv[2], s_aOptions, RT_ELEMENTS(s_aOptions), 0, 0);
     362    AssertRCReturn(vrc, RTEXITCODE_FAILURE);
     363
     364    int c;
     365    RTGETOPTUNION ValueUnion;
     366    while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
     367    {
     368        switch (c)
     369        {
     370            case 'n':
     371                pszVarName = ValueUnion.psz;
     372                break;
     373            case 'f':
     374                pszVarDataFilename = ValueUnion.psz;
     375                break;
     376            default:
     377                return errorGetOpt(c, &ValueUnion);
     378        }
     379    }
     380
     381    if (!pszVarName)
     382        return errorSyntax("No variable name was given to \"changevar\"");
     383    if (!pszVarDataFilename)
     384        return errorSyntax("No variable data filename was given to \"changevar\"");
     385
     386    RTFILE hFile = NIL_RTFILE;
     387    RTEXITCODE rcExit = RTEXITCODE_SUCCESS;
     388    vrc = RTFileOpen(&hFile, pszVarDataFilename, RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_NONE);
     389    if (RT_SUCCESS(vrc))
     390    {
     391        uint64_t cbFile = 0;
     392        vrc = RTFileQuerySize(hFile, &cbFile);
     393        if (RT_SUCCESS(vrc))
     394        {
     395            com::SafeArray<BYTE> aData;
     396            aData.resize(cbFile);
     397
     398            vrc = RTFileRead(hFile, aData.raw(), aData.size(), NULL /*pcbRead*/);
     399            RTFileClose(hFile);
     400
     401            if (RT_SUCCESS(vrc))
     402            {
     403                ComPtr<IUefiVariableStore> uefiVarStore;
     404                CHECK_ERROR2I_RET(nvramStore, COMGETTER(UefiVariableStore)(uefiVarStore.asOutParam()), RTEXITCODE_FAILURE);
     405                CHECK_ERROR2I_RET(uefiVarStore, ChangeVariable(Bstr(pszVarName).raw(), ComSafeArrayAsInParam(aData)), RTEXITCODE_FAILURE);
     406            }
     407            else
     408                rcExit = RTMsgErrorExitFailure("Error reading from '%s': %Rrc", pszVarDataFilename, vrc);
     409        }
     410    }
     411    else
     412       rcExit = RTMsgErrorExitFailure("Error opening '%s': %Rrc", pszVarDataFilename, vrc);
     413
     414    return rcExit;
     415}
     416
     417
     418/**
    291419 * Handles the 'modifynvram' command.
    292420 * @returns Exit code.
     
    344472        rc = handleModifyNvramQueryUefiVar(a, nvramStore) == RTEXITCODE_SUCCESS ? S_OK : E_FAIL;
    345473    }
     474    else if (!strcmp(a->argv[1], "deletevar"))
     475    {
     476        setCurrentSubcommand(HELP_SCOPE_MODIFYNVRAM_DELETEVAR);
     477        rc = handleModifyNvramDeleteUefiVar(a, nvramStore) == RTEXITCODE_SUCCESS ? S_OK : E_FAIL;
     478    }
     479    else if (!strcmp(a->argv[1], "changevar"))
     480    {
     481        setCurrentSubcommand(HELP_SCOPE_MODIFYNVRAM_CHANGEVAR);
     482        rc = handleModifyNvramChangeUefiVar(a, nvramStore) == RTEXITCODE_SUCCESS ? S_OK : E_FAIL;
     483    }
    346484    else
    347485        return errorUnknownSubcommand(a->argv[0]);
  • trunk/src/VBox/Main/include/UefiVariableStoreImpl.h

    r91535 r91685  
    7878
    7979    HRESULT i_uefiVarStoreAddVar(PCEFI_GUID pGuid, const char *pszVar, uint32_t fAttr, PRTVFSFILE phVfsFile);
     80    HRESULT i_uefiVarStoreOpenVar(const char *pszVar, PRTVFSFILE phVfsFile);
    8081    HRESULT i_uefiVarStoreSetVar(PCEFI_GUID pGuid, const char *pszVar, uint32_t fAttr, const void *pvData, size_t cbData);
    8182    HRESULT i_uefiVarStoreQueryVar(const char *pszVar, void *pvData, size_t cbData);
  • trunk/src/VBox/Main/src-server/UefiVariableStoreImpl.cpp

    r91535 r91685  
    242242HRESULT UefiVariableStore::deleteVariable(const com::Utf8Str &aName, const com::Guid &aOwnerUuid)
    243243{
    244     RT_NOREF(aName, aOwnerUuid);
    245     return E_NOTIMPL;
     244    RT_NOREF(aOwnerUuid);
     245
     246    /* the machine needs to be mutable */
     247    AutoMutableStateDependency adep(m->pMachine);
     248    if (FAILED(adep.rc())) return adep.rc();
     249
     250    HRESULT hrc = i_retainUefiVariableStore(false /*fReadonly*/);
     251    if (FAILED(hrc)) return hrc;
     252
     253    AutoWriteLock wlock(this COMMA_LOCKVAL_SRC_POS);
     254
     255    char szVarPath[_1K];
     256    ssize_t cch = RTStrPrintf2(szVarPath, sizeof(szVarPath), "/raw/%s", aName.c_str());
     257    if (cch > 0)
     258    {
     259        RTVFSDIR hVfsDirRoot = NIL_RTVFSDIR;
     260        int vrc = RTVfsOpenRoot(m->hVfsUefiVarStore, &hVfsDirRoot);
     261        if (RT_SUCCESS(vrc))
     262        {
     263            vrc = RTVfsDirRemoveDir(hVfsDirRoot, szVarPath, 0 /*fFlags*/);
     264            RTVfsDirRelease(hVfsDirRoot);
     265            if (RT_FAILURE(vrc))
     266                hrc = setError(VBOX_E_IPRT_ERROR, tr("Failed to remove variable '%s' (%Rrc)"), aName.c_str(), vrc);
     267        }
     268        else
     269            hrc = setError(VBOX_E_IPRT_ERROR, tr("Failed to open the variable store root (%Rrc)"), vrc);
     270    }
     271    else
     272        hrc = setError(E_FAIL, tr("The variable name is too long"));
     273
     274    i_releaseUefiVariableStore();
     275    return hrc;
    246276}
    247277
     
    249279HRESULT UefiVariableStore::changeVariable(const com::Utf8Str &aName, const std::vector<BYTE> &aData)
    250280{
    251     RT_NOREF(aName, aData);
    252     return E_NOTIMPL;
     281    /* the machine needs to be mutable */
     282    AutoMutableStateDependency adep(m->pMachine);
     283    if (FAILED(adep.rc())) return adep.rc();
     284
     285    HRESULT hrc = i_retainUefiVariableStore(false /*fReadonly*/);
     286    if (FAILED(hrc)) return hrc;
     287
     288    AutoWriteLock wlock(this COMMA_LOCKVAL_SRC_POS);
     289
     290    RTVFSFILE hVfsFile = NIL_RTVFSFILE;
     291    hrc = i_uefiVarStoreOpenVar(aName.c_str(), &hVfsFile);
     292    if (SUCCEEDED(hrc))
     293    {
     294        int vrc = RTVfsFileSetSize(hVfsFile, aData.size(), RTVFSFILE_SIZE_F_NORMAL);
     295        if (RT_SUCCESS(vrc))
     296        {
     297            vrc = RTVfsFileWriteAt(hVfsFile, 0 /*off*/, &aData.front(), aData.size(), NULL /*pcbWritten*/);
     298            if (RT_FAILURE(vrc))
     299                hrc = setError(VBOX_E_IPRT_ERROR, tr("Failed to data for variable '%s' (%Rrc)"), aName.c_str(), vrc);
     300        }
     301        else
     302            hrc = setError(VBOX_E_IPRT_ERROR, tr("Failed to allocate space for the variable '%s' (%Rrc)"), aName.c_str(), vrc);
     303
     304        RTVfsFileRelease(hVfsFile);
     305    }
     306
     307    i_releaseUefiVariableStore();
     308    return hrc;
    253309}
    254310
     
    743799
    744800
     801/**
     802 * Tries to open the given variable from the variable store and returns a file handle.
     803 *
     804 * @returns IPRT status code.
     805 * @param   pszVar              The variable name.
     806 * @param   phVfsFile           Where to return the VFS file handle to the created variable on success.
     807 */
     808HRESULT UefiVariableStore::i_uefiVarStoreOpenVar(const char *pszVar, PRTVFSFILE phVfsFile)
     809{
     810    char szVarPath[_1K];
     811    ssize_t cch = RTStrPrintf2(szVarPath, sizeof(szVarPath), "/by-name/%s", pszVar);
     812    Assert(cch > 0); RT_NOREF(cch);
     813
     814    HRESULT hrc = S_OK;
     815    int vrc = RTVfsFileOpen(m->hVfsUefiVarStore, szVarPath,
     816                            RTFILE_O_READWRITE | RTFILE_O_DENY_NONE | RTFILE_O_OPEN,
     817                            phVfsFile);
     818    if (   vrc == VERR_PATH_NOT_FOUND
     819        || vrc == VERR_FILE_NOT_FOUND)
     820        hrc = setError(VBOX_E_OBJECT_NOT_FOUND, tr("The variable '%s' could not be found"), pszVar);
     821    else if (RT_FAILURE(vrc))
     822        hrc = setError(VBOX_E_IPRT_ERROR, tr("Couldn't open variable '%s' (%Rrc)"), pszVar, vrc);
     823
     824    return hrc;
     825}
     826
     827
    745828HRESULT UefiVariableStore::i_uefiVarStoreSetVar(PCEFI_GUID pGuid, const char *pszVar, uint32_t fAttr, const void *pvData, size_t cbData)
    746829{
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