VirtualBox

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

Last change on this file since 94660 was 94236, checked in by vboxsync, 3 years ago

FE/VBoxManage: Remove the now unused VBoxManageHelp build target and the VBOX_ONLY_DOCS #ifdef's in the code, ​bugref:9186 [scm fix]

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