VirtualBox

source: vbox/trunk/src/VBox/Frontends/VBoxManage/VBoxManageModifyNvram.cpp@ 99844

Last change on this file since 99844 was 98988, checked in by vboxsync, 21 months ago

VBoxManage: Introduce modifynvram enrollmok sub-command, bugref:10287.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 19.7 KB
Line 
1/* $Id: VBoxManageModifyNvram.cpp 98988 2023-03-15 15:00:19Z vboxsync $ */
2/** @file
3 * VBoxManage - The nvram control related commands.
4 */
5
6/*
7 * Copyright (C) 2021-2023 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28
29/*********************************************************************************************************************************
30* Header Files *
31*********************************************************************************************************************************/
32#include <VBox/com/com.h>
33#include <VBox/com/array.h>
34#include <VBox/com/ErrorInfo.h>
35#include <VBox/com/errorprint.h>
36#include <VBox/com/VirtualBox.h>
37
38#include <iprt/errcore.h>
39#include <iprt/path.h>
40#include <iprt/param.h>
41#include <iprt/string.h>
42#include <iprt/ctype.h>
43#include <iprt/stream.h>
44#include <iprt/file.h>
45#include <iprt/getopt.h>
46#include <iprt/uuid.h>
47#include <VBox/log.h>
48
49#include "VBoxManage.h"
50using namespace com;
51
52DECLARE_TRANSLATION_CONTEXT(Nvram);
53
54// funcs
55///////////////////////////////////////////////////////////////////////////////
56
57
58/**
59 * Handles the 'modifynvram myvm inituefivarstore' sub-command.
60 * @returns Exit code.
61 * @param a The handler argument package.
62 * @param nvram Reference to the NVRAM store interface.
63 */
64static RTEXITCODE handleModifyNvramInitUefiVarStore(HandlerArg *a, ComPtr<INvramStore> &nvramStore)
65{
66 RT_NOREF(a);
67
68 CHECK_ERROR2I_RET(nvramStore, InitUefiVariableStore(0 /*aSize*/), RTEXITCODE_FAILURE);
69 return RTEXITCODE_SUCCESS;
70}
71
72
73/**
74 * Handles the 'modifynvram myvm enrollmssignatures' sub-command.
75 * @returns Exit code.
76 * @param a The handler argument package.
77 * @param nvram Reference to the NVRAM store interface.
78 */
79static RTEXITCODE handleModifyNvramEnrollMsSignatures(HandlerArg *a, ComPtr<INvramStore> &nvramStore)
80{
81 RT_NOREF(a);
82
83 ComPtr<IUefiVariableStore> uefiVarStore;
84 CHECK_ERROR2I_RET(nvramStore, COMGETTER(UefiVariableStore)(uefiVarStore.asOutParam()), RTEXITCODE_FAILURE);
85
86 CHECK_ERROR2I_RET(uefiVarStore, EnrollDefaultMsSignatures(), RTEXITCODE_FAILURE);
87 return RTEXITCODE_SUCCESS;
88}
89
90
91/**
92 * Helper for handleModifyNvramEnrollPlatformKey() and handleModifyNvramEnrollMok().
93 *
94 * This function reads key from file and enrolls it either as a PK (Platform Key)
95 * or as a MOK (Machine Owner Key).
96 *
97 * @returns Exit code.
98 * @param pszKey Path to a file which contains the key.
99 * @param pszOwnerUuid Owner's UUID.
100 * @param nvramStore Reference to the NVRAM store interface.
101 * @param fPk If True, a key will be enrolled as a PK, otherwise as a MOK.
102 */
103static RTEXITCODE handleModifyNvramEnrollPlatformKeyOrMok(const char *pszKey, const char *pszOwnerUuid,
104 ComPtr<INvramStore> &nvramStore, bool fPk)
105{
106 RTFILE hKeyFile;
107
108 int vrc = RTFileOpen(&hKeyFile, pszKey, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE);
109 if (RT_SUCCESS(vrc))
110 {
111 uint64_t cbSize;
112 vrc = RTFileQuerySize(hKeyFile, &cbSize);
113 if (RT_SUCCESS(vrc))
114 {
115 if (cbSize <= _32K)
116 {
117 SafeArray<BYTE> aKey((size_t)cbSize);
118 vrc = RTFileRead(hKeyFile, aKey.raw(), (size_t)cbSize, NULL);
119 if (RT_SUCCESS(vrc))
120 {
121 RTFileClose(hKeyFile);
122
123 ComPtr<IUefiVariableStore> uefiVarStore;
124 CHECK_ERROR2I_RET(nvramStore, COMGETTER(UefiVariableStore)(uefiVarStore.asOutParam()), RTEXITCODE_FAILURE);
125 if (fPk)
126 CHECK_ERROR2I_RET(uefiVarStore, EnrollPlatformKey(ComSafeArrayAsInParam(aKey), Bstr(pszOwnerUuid).raw()), RTEXITCODE_FAILURE);
127 else
128 CHECK_ERROR2I_RET(uefiVarStore, AddSignatureToMok(ComSafeArrayAsInParam(aKey), Bstr(pszOwnerUuid).raw(), SignatureType_X509), RTEXITCODE_FAILURE);
129
130 return RTEXITCODE_SUCCESS;
131 }
132 else
133 RTMsgError(Nvram::tr("Cannot read contents of file \"%s\": %Rrc"), pszKey, vrc);
134 }
135 else
136 RTMsgError(Nvram::tr("File \"%s\" is bigger than 32KByte"), pszKey);
137 }
138 else
139 RTMsgError(Nvram::tr("Cannot get size of file \"%s\": %Rrc"), pszKey, vrc);
140
141 RTFileClose(hKeyFile);
142 }
143 else
144 RTMsgError(Nvram::tr("Cannot open file \"%s\": %Rrc"), pszKey, vrc);
145
146 return RTEXITCODE_FAILURE;
147}
148
149
150/**
151 * Handles the 'modifynvram myvm enrollpk' sub-command.
152 * @returns Exit code.
153 * @param a The handler argument package.
154 * @param nvramStore Reference to the NVRAM store interface.
155 */
156static RTEXITCODE handleModifyNvramEnrollPlatformKey(HandlerArg *a, ComPtr<INvramStore> &nvramStore)
157{
158 static const RTGETOPTDEF s_aOptions[] =
159 {
160 /* common options */
161 { "--platform-key", 'p', RTGETOPT_REQ_STRING },
162 { "--owner-uuid", 'f', RTGETOPT_REQ_STRING }
163 };
164
165 const char *pszPlatformKey = NULL;
166 const char *pszOwnerUuid = NULL;
167
168 RTGETOPTSTATE GetState;
169 int vrc = RTGetOptInit(&GetState, a->argc - 2, &a->argv[2], s_aOptions, RT_ELEMENTS(s_aOptions), 0, 0);
170 AssertRCReturn(vrc, RTEXITCODE_FAILURE);
171
172 int c;
173 RTGETOPTUNION ValueUnion;
174 while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
175 {
176 switch (c)
177 {
178 case 'p':
179 pszPlatformKey = ValueUnion.psz;
180 break;
181 case 'f':
182 pszOwnerUuid = ValueUnion.psz;
183 break;
184 default:
185 return errorGetOpt(c, &ValueUnion);
186 }
187 }
188
189 if (!pszPlatformKey)
190 return errorSyntax(Nvram::tr("No platform key file path was given to \"enrollpk\""));
191 if (!pszOwnerUuid)
192 return errorSyntax(Nvram::tr("No owner UUID was given to \"enrollpk\""));
193
194 return handleModifyNvramEnrollPlatformKeyOrMok(pszPlatformKey, pszOwnerUuid, nvramStore, true /* fPk */);
195}
196
197
198/**
199 * Handles the 'modifynvram myvm enrollmok' sub-command.
200 * @returns Exit code.
201 * @param a The handler argument package.
202 * @param nvramStore Reference to the NVRAM store interface.
203 */
204static RTEXITCODE handleModifyNvramEnrollMok(HandlerArg *a, ComPtr<INvramStore> &nvramStore)
205{
206 static const RTGETOPTDEF s_aOptions[] =
207 {
208 /* common options */
209 { "--mok", 'p', RTGETOPT_REQ_STRING },
210 { "--owner-uuid", 'f', RTGETOPT_REQ_STRING }
211 };
212
213 const char *pszMok = NULL;
214 const char *pszOwnerUuid = NULL;
215
216 RTGETOPTSTATE GetState;
217 int vrc = RTGetOptInit(&GetState, a->argc - 2, &a->argv[2], s_aOptions, RT_ELEMENTS(s_aOptions), 0, 0);
218 AssertRCReturn(vrc, RTEXITCODE_FAILURE);
219
220 int c;
221 RTGETOPTUNION ValueUnion;
222 while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
223 {
224 switch (c)
225 {
226 case 'p':
227 pszMok = ValueUnion.psz;
228 break;
229 case 'f':
230 pszOwnerUuid = ValueUnion.psz;
231 break;
232 default:
233 return errorGetOpt(c, &ValueUnion);
234 }
235 }
236
237 if (!pszMok)
238 return errorSyntax(Nvram::tr("No machine owner key file path was given to \"enrollpk\""));
239 if (!pszOwnerUuid)
240 return errorSyntax(Nvram::tr("No owner UUID was given to \"enrollpk\""));
241
242 return handleModifyNvramEnrollPlatformKeyOrMok(pszMok, pszOwnerUuid, nvramStore, false /* fPk */);
243}
244
245
246/**
247 * Handles the 'modifynvram myvm enrollorclpk' sub-command.
248 * @returns Exit code.
249 * @param a The handler argument package.
250 * @param nvram Reference to the NVRAM store interface.
251 */
252static RTEXITCODE handleModifyNvramEnrollOraclePlatformKey(HandlerArg *a, ComPtr<INvramStore> &nvramStore)
253{
254 RT_NOREF(a);
255
256 ComPtr<IUefiVariableStore> uefiVarStore;
257 CHECK_ERROR2I_RET(nvramStore, COMGETTER(UefiVariableStore)(uefiVarStore.asOutParam()), RTEXITCODE_FAILURE);
258
259 CHECK_ERROR2I_RET(uefiVarStore, EnrollOraclePlatformKey(), RTEXITCODE_FAILURE);
260 return RTEXITCODE_SUCCESS;
261}
262
263
264/**
265 * Handles the 'modifynvram myvm listvars' sub-command.
266 * @returns Exit code.
267 * @param a The handler argument package.
268 * @param nvram Reference to the NVRAM store interface.
269 */
270static RTEXITCODE handleModifyNvramListUefiVars(HandlerArg *a, ComPtr<INvramStore> &nvramStore)
271{
272 RT_NOREF(a);
273
274 ComPtr<IUefiVariableStore> uefiVarStore;
275 CHECK_ERROR2I_RET(nvramStore, COMGETTER(UefiVariableStore)(uefiVarStore.asOutParam()), RTEXITCODE_FAILURE);
276
277 com::SafeArray<BSTR> aNames;
278 com::SafeArray<BSTR> aOwnerGuids;
279 CHECK_ERROR2I_RET(uefiVarStore, QueryVariables(ComSafeArrayAsOutParam(aNames), ComSafeArrayAsOutParam(aOwnerGuids)), RTEXITCODE_FAILURE);
280 for (size_t i = 0; i < aNames.size(); i++)
281 {
282 Bstr strName = aNames[i];
283 Bstr strOwnerGuid = aOwnerGuids[i];
284
285 RTPrintf("%-32ls {%ls}\n", strName.raw(), strOwnerGuid.raw());
286 }
287
288 return RTEXITCODE_SUCCESS;
289}
290
291
292/**
293 * Handles the 'modifynvram myvm queryvar' sub-command.
294 * @returns Exit code.
295 * @param a The handler argument package.
296 * @param nvram Reference to the NVRAM store interface.
297 */
298static RTEXITCODE handleModifyNvramQueryUefiVar(HandlerArg *a, ComPtr<INvramStore> &nvramStore)
299{
300 static const RTGETOPTDEF s_aOptions[] =
301 {
302 /* common options */
303 { "--name", 'n', RTGETOPT_REQ_STRING },
304 { "--filename", 'f', RTGETOPT_REQ_STRING }
305 };
306
307 const char *pszVarName = NULL;
308 const char *pszVarDataFilename = NULL;
309
310 RTGETOPTSTATE GetState;
311 int vrc = RTGetOptInit(&GetState, a->argc - 2, &a->argv[2], s_aOptions, RT_ELEMENTS(s_aOptions), 0, 0);
312 AssertRCReturn(vrc, RTEXITCODE_FAILURE);
313
314 int c;
315 RTGETOPTUNION ValueUnion;
316 while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
317 {
318 switch (c)
319 {
320 case 'n':
321 pszVarName = ValueUnion.psz;
322 break;
323 case 'f':
324 pszVarDataFilename = ValueUnion.psz;
325 break;
326 default:
327 return errorGetOpt(c, &ValueUnion);
328 }
329 }
330
331 if (!pszVarName)
332 return errorSyntax(Nvram::tr("No variable name was given to \"queryvar\""));
333
334 ComPtr<IUefiVariableStore> uefiVarStore;
335 CHECK_ERROR2I_RET(nvramStore, COMGETTER(UefiVariableStore)(uefiVarStore.asOutParam()), RTEXITCODE_FAILURE);
336
337 Bstr strOwnerGuid;
338 com::SafeArray<UefiVariableAttributes_T> aVarAttrs;
339 com::SafeArray<BYTE> aData;
340 CHECK_ERROR2I_RET(uefiVarStore, QueryVariableByName(Bstr(pszVarName).raw(), strOwnerGuid.asOutParam(),
341 ComSafeArrayAsOutParam(aVarAttrs), ComSafeArrayAsOutParam(aData)),
342 RTEXITCODE_FAILURE);
343
344 RTEXITCODE rcExit = RTEXITCODE_SUCCESS;
345 if (!pszVarDataFilename)
346 {
347 RTPrintf("%s {%ls}:\n"
348 "%.*Rhxd\n", pszVarName, strOwnerGuid.raw(), aData.size(), aData.raw());
349 }
350 else
351 {
352 /* Just write the data to the file. */
353 RTFILE hFile = NIL_RTFILE;
354 vrc = RTFileOpen(&hFile, pszVarDataFilename, RTFILE_O_CREATE_REPLACE | RTFILE_O_WRITE | RTFILE_O_DENY_NONE);
355 if (RT_SUCCESS(vrc))
356 {
357 vrc = RTFileWrite(hFile, aData.raw(), aData.size(), NULL /*pcbWritten*/);
358 if (RT_FAILURE(vrc))
359 rcExit = RTMsgErrorExitFailure(Nvram::tr("Error writing to '%s': %Rrc"), pszVarDataFilename, vrc);
360
361 RTFileClose(hFile);
362 }
363 else
364 rcExit = RTMsgErrorExitFailure(Nvram::tr("Error opening '%s': %Rrc"), pszVarDataFilename, vrc);
365 }
366
367 return rcExit;
368}
369
370
371/**
372 * Handles the 'modifynvram myvm deletevar' sub-command.
373 * @returns Exit code.
374 * @param a The handler argument package.
375 * @param nvram Reference to the NVRAM store interface.
376 */
377static RTEXITCODE handleModifyNvramDeleteUefiVar(HandlerArg *a, ComPtr<INvramStore> &nvramStore)
378{
379 static const RTGETOPTDEF s_aOptions[] =
380 {
381 /* common options */
382 { "--name", 'n', RTGETOPT_REQ_STRING },
383 { "--owner-uuid", 'f', RTGETOPT_REQ_STRING }
384 };
385
386 const char *pszVarName = NULL;
387 const char *pszOwnerUuid = NULL;
388
389 RTGETOPTSTATE GetState;
390 int vrc = RTGetOptInit(&GetState, a->argc - 2, &a->argv[2], s_aOptions, RT_ELEMENTS(s_aOptions), 0, 0);
391 AssertRCReturn(vrc, RTEXITCODE_FAILURE);
392
393 int c;
394 RTGETOPTUNION ValueUnion;
395 while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
396 {
397 switch (c)
398 {
399 case 'n':
400 pszVarName = ValueUnion.psz;
401 break;
402 case 'f':
403 pszOwnerUuid = ValueUnion.psz;
404 break;
405 default:
406 return errorGetOpt(c, &ValueUnion);
407 }
408 }
409
410 if (!pszVarName)
411 return errorSyntax(Nvram::tr("No variable name was given to \"deletevar\""));
412 if (!pszOwnerUuid)
413 return errorSyntax(Nvram::tr("No owner UUID was given to \"deletevar\""));
414
415 ComPtr<IUefiVariableStore> uefiVarStore;
416 CHECK_ERROR2I_RET(nvramStore, COMGETTER(UefiVariableStore)(uefiVarStore.asOutParam()), RTEXITCODE_FAILURE);
417 CHECK_ERROR2I_RET(uefiVarStore, DeleteVariable(Bstr(pszVarName).raw(), Bstr(pszOwnerUuid).raw()), RTEXITCODE_FAILURE);
418
419 return RTEXITCODE_SUCCESS;
420}
421
422
423/**
424 * Handles the 'modifynvram myvm changevar' sub-command.
425 * @returns Exit code.
426 * @param a The handler argument package.
427 * @param nvram Reference to the NVRAM store interface.
428 */
429static RTEXITCODE handleModifyNvramChangeUefiVar(HandlerArg *a, ComPtr<INvramStore> &nvramStore)
430{
431 static const RTGETOPTDEF s_aOptions[] =
432 {
433 /* common options */
434 { "--name", 'n', RTGETOPT_REQ_STRING },
435 { "--filename", 'f', RTGETOPT_REQ_STRING }
436 };
437
438 const char *pszVarName = NULL;
439 const char *pszVarDataFilename = NULL;
440
441 RTGETOPTSTATE GetState;
442 int vrc = RTGetOptInit(&GetState, a->argc - 2, &a->argv[2], s_aOptions, RT_ELEMENTS(s_aOptions), 0, 0);
443 AssertRCReturn(vrc, RTEXITCODE_FAILURE);
444
445 int c;
446 RTGETOPTUNION ValueUnion;
447 while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
448 {
449 switch (c)
450 {
451 case 'n':
452 pszVarName = ValueUnion.psz;
453 break;
454 case 'f':
455 pszVarDataFilename = ValueUnion.psz;
456 break;
457 default:
458 return errorGetOpt(c, &ValueUnion);
459 }
460 }
461
462 if (!pszVarName)
463 return errorSyntax(Nvram::tr("No variable name was given to \"changevar\""));
464 if (!pszVarDataFilename)
465 return errorSyntax(Nvram::tr("No variable data filename was given to \"changevar\""));
466
467 RTFILE hFile = NIL_RTFILE;
468 RTEXITCODE rcExit = RTEXITCODE_SUCCESS;
469 vrc = RTFileOpen(&hFile, pszVarDataFilename, RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_NONE);
470 if (RT_SUCCESS(vrc))
471 {
472 uint64_t cbFile = 0;
473 vrc = RTFileQuerySize(hFile, &cbFile);
474 if (RT_SUCCESS(vrc))
475 {
476 com::SafeArray<BYTE> aData;
477 aData.resize(cbFile);
478
479 vrc = RTFileRead(hFile, aData.raw(), aData.size(), NULL /*pcbRead*/);
480 RTFileClose(hFile);
481
482 if (RT_SUCCESS(vrc))
483 {
484 ComPtr<IUefiVariableStore> uefiVarStore;
485 CHECK_ERROR2I_RET(nvramStore, COMGETTER(UefiVariableStore)(uefiVarStore.asOutParam()), RTEXITCODE_FAILURE);
486 CHECK_ERROR2I_RET(uefiVarStore, ChangeVariable(Bstr(pszVarName).raw(), ComSafeArrayAsInParam(aData)), RTEXITCODE_FAILURE);
487 }
488 else
489 rcExit = RTMsgErrorExitFailure(Nvram::tr("Error reading from '%s': %Rrc"), pszVarDataFilename, vrc);
490 }
491 }
492 else
493 rcExit = RTMsgErrorExitFailure(Nvram::tr("Error opening '%s': %Rrc"), pszVarDataFilename, vrc);
494
495 return rcExit;
496}
497
498
499/**
500 * Handles the 'modifynvram' command.
501 * @returns Exit code.
502 * @param a The handler argument package.
503 */
504RTEXITCODE handleModifyNvram(HandlerArg *a)
505{
506 HRESULT hrc = S_OK;
507 ComPtr<IMachine> machine;
508 ComPtr<INvramStore> nvramStore;
509
510 if (a->argc < 2)
511 return errorNoSubcommand();
512
513 /* try to find the given machine */
514 CHECK_ERROR_RET(a->virtualBox, FindMachine(Bstr(a->argv[0]).raw(),
515 machine.asOutParam()), RTEXITCODE_FAILURE);
516
517 /* open a session for the VM (new or shared) */
518 CHECK_ERROR_RET(machine, LockMachine(a->session, LockType_Write), RTEXITCODE_FAILURE);
519
520 /* get the mutable session machine */
521 a->session->COMGETTER(Machine)(machine.asOutParam());
522 hrc = machine->COMGETTER(NonVolatileStore)(nvramStore.asOutParam());
523 if (FAILED(hrc)) goto leave;
524
525 if (!strcmp(a->argv[1], "inituefivarstore"))
526 {
527 setCurrentSubcommand(HELP_SCOPE_MODIFYNVRAM_INITUEFIVARSTORE);
528 hrc = handleModifyNvramInitUefiVarStore(a, nvramStore) == RTEXITCODE_SUCCESS ? S_OK : E_FAIL;
529 }
530 else if (!strcmp(a->argv[1], "enrollmssignatures"))
531 {
532 setCurrentSubcommand(HELP_SCOPE_MODIFYNVRAM_ENROLLMSSIGNATURES);
533 hrc = handleModifyNvramEnrollMsSignatures(a, nvramStore) == RTEXITCODE_SUCCESS ? S_OK : E_FAIL;
534 }
535 else if (!strcmp(a->argv[1], "enrollpk"))
536 {
537 setCurrentSubcommand(HELP_SCOPE_MODIFYNVRAM_ENROLLPK);
538 hrc = handleModifyNvramEnrollPlatformKey(a, nvramStore) == RTEXITCODE_SUCCESS ? S_OK : E_FAIL;
539 }
540 else if (!strcmp(a->argv[1], "enrollmok"))
541 {
542 setCurrentSubcommand(HELP_SCOPE_MODIFYNVRAM_ENROLLMOK);
543 hrc = handleModifyNvramEnrollMok(a, nvramStore) == RTEXITCODE_SUCCESS ? S_OK : E_FAIL;
544 }
545 else if (!strcmp(a->argv[1], "enrollorclpk"))
546 {
547 setCurrentSubcommand(HELP_SCOPE_MODIFYNVRAM_ENROLLORCLPK);
548 hrc = handleModifyNvramEnrollOraclePlatformKey(a, nvramStore) == RTEXITCODE_SUCCESS ? S_OK : E_FAIL;
549 }
550 else if (!strcmp(a->argv[1], "listvars"))
551 {
552 setCurrentSubcommand(HELP_SCOPE_MODIFYNVRAM_LISTVARS);
553 hrc = handleModifyNvramListUefiVars(a, nvramStore) == RTEXITCODE_SUCCESS ? S_OK : E_FAIL;
554 }
555 else if (!strcmp(a->argv[1], "queryvar"))
556 {
557 setCurrentSubcommand(HELP_SCOPE_MODIFYNVRAM_QUERYVAR);
558 hrc = handleModifyNvramQueryUefiVar(a, nvramStore) == RTEXITCODE_SUCCESS ? S_OK : E_FAIL;
559 }
560 else if (!strcmp(a->argv[1], "deletevar"))
561 {
562 setCurrentSubcommand(HELP_SCOPE_MODIFYNVRAM_DELETEVAR);
563 hrc = handleModifyNvramDeleteUefiVar(a, nvramStore) == RTEXITCODE_SUCCESS ? S_OK : E_FAIL;
564 }
565 else if (!strcmp(a->argv[1], "changevar"))
566 {
567 setCurrentSubcommand(HELP_SCOPE_MODIFYNVRAM_CHANGEVAR);
568 hrc = handleModifyNvramChangeUefiVar(a, nvramStore) == RTEXITCODE_SUCCESS ? S_OK : E_FAIL;
569 }
570 else
571 return errorUnknownSubcommand(a->argv[0]);
572
573 /* commit changes */
574 if (SUCCEEDED(hrc))
575 CHECK_ERROR(machine, SaveSettings());
576
577leave:
578 /* it's important to always close sessions */
579 a->session->UnlockMachine();
580
581 return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
582}
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