VirtualBox

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

Last change on this file since 91483 was 91457, checked in by vboxsync, 3 years ago

Main,FE/VBoxManage: Implement functionality to list and query UEFI variables, bugref:9580

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 10.8 KB
Line 
1/* $Id: VBoxManageModifyNvram.cpp 91457 2021-09-29 14:08:32Z vboxsync $ */
2/** @file
3 * VBoxManage - The nvram control related commands.
4 */
5
6/*
7 * Copyright (C) 2021 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#ifndef VBOX_ONLY_DOCS
19
20
21/*********************************************************************************************************************************
22* Header Files *
23*********************************************************************************************************************************/
24#include <VBox/com/com.h>
25#include <VBox/com/array.h>
26#include <VBox/com/ErrorInfo.h>
27#include <VBox/com/errorprint.h>
28#include <VBox/com/VirtualBox.h>
29
30#include <iprt/errcore.h>
31#include <iprt/path.h>
32#include <iprt/param.h>
33#include <iprt/string.h>
34#include <iprt/ctype.h>
35#include <iprt/stream.h>
36#include <iprt/file.h>
37#include <iprt/getopt.h>
38#include <iprt/uuid.h>
39#include <VBox/log.h>
40
41#include "VBoxManage.h"
42using namespace com;
43
44
45// funcs
46///////////////////////////////////////////////////////////////////////////////
47
48
49/**
50 * Handles the 'modifynvram myvm inituefivarstore' sub-command.
51 * @returns Exit code.
52 * @param a The handler argument package.
53 * @param nvram Reference to the NVRAM store interface.
54 */
55static RTEXITCODE handleModifyNvramInitUefiVarStore(HandlerArg *a, ComPtr<INvramStore> &nvramStore)
56{
57 RT_NOREF(a);
58
59 CHECK_ERROR2I_RET(nvramStore, InitUefiVariableStore(0 /*aSize*/), RTEXITCODE_FAILURE);
60 return RTEXITCODE_SUCCESS;
61}
62
63
64/**
65 * Handles the 'modifynvram myvm enrollmssignatures' sub-command.
66 * @returns Exit code.
67 * @param a The handler argument package.
68 * @param nvram Reference to the NVRAM store interface.
69 */
70static RTEXITCODE handleModifyNvramEnrollMsSignatures(HandlerArg *a, ComPtr<INvramStore> &nvramStore)
71{
72 RT_NOREF(a);
73
74 ComPtr<IUefiVariableStore> uefiVarStore;
75 CHECK_ERROR2I_RET(nvramStore, COMGETTER(UefiVariableStore)(uefiVarStore.asOutParam()), RTEXITCODE_FAILURE);
76
77 CHECK_ERROR2I_RET(uefiVarStore, EnrollDefaultMsSignatures(), RTEXITCODE_FAILURE);
78 return RTEXITCODE_SUCCESS;
79}
80
81
82/**
83 * Handles the 'modifynvram myvm enrollpk' sub-command.
84 * @returns Exit code.
85 * @param a The handler argument package.
86 * @param nvram Reference to the NVRAM store interface.
87 */
88static RTEXITCODE handleModifyNvramEnrollPlatformKey(HandlerArg *a, ComPtr<INvramStore> &nvramStore)
89{
90 static const RTGETOPTDEF s_aOptions[] =
91 {
92 /* common options */
93 { "--platform-key", 'p', RTGETOPT_REQ_STRING },
94 { "--owner-uuid", 'f', RTGETOPT_REQ_STRING }
95 };
96
97 const char *pszPlatformKey = NULL;
98 const char *pszOwnerUuid = NULL;
99
100 RTGETOPTSTATE GetState;
101 int vrc = RTGetOptInit(&GetState, a->argc - 2, &a->argv[2], s_aOptions, RT_ELEMENTS(s_aOptions), 0, 0);
102 AssertRCReturn(vrc, RTEXITCODE_FAILURE);
103
104 int c;
105 RTGETOPTUNION ValueUnion;
106 while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
107 {
108 switch (c)
109 {
110 case 'p':
111 pszPlatformKey = ValueUnion.psz;
112 break;
113 case 'f':
114 pszOwnerUuid = ValueUnion.psz;
115 break;
116 default:
117 return errorGetOpt(c, &ValueUnion);
118 }
119 }
120
121 if (!pszPlatformKey)
122 return errorSyntax("No platform key file path was given to \"enrollpk\"");
123 if (!pszOwnerUuid)
124 return errorSyntax("No owner UUID was given to \"enrollpk\"");
125
126 RTFILE hPkFile;
127 vrc = RTFileOpen(&hPkFile, pszPlatformKey, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE);
128 if (RT_SUCCESS(vrc))
129 {
130 uint64_t cbSize;
131 vrc = RTFileQuerySize(hPkFile, &cbSize);
132 if (RT_SUCCESS(vrc))
133 {
134 if (cbSize <= _32K)
135 {
136 SafeArray<BYTE> aPk((size_t)cbSize);
137 vrc = RTFileRead(hPkFile, aPk.raw(), (size_t)cbSize, NULL);
138 if (RT_SUCCESS(vrc))
139 {
140 RTFileClose(hPkFile);
141
142 ComPtr<IUefiVariableStore> uefiVarStore;
143 CHECK_ERROR2I_RET(nvramStore, COMGETTER(UefiVariableStore)(uefiVarStore.asOutParam()), RTEXITCODE_FAILURE);
144 CHECK_ERROR2I_RET(uefiVarStore, EnrollPlatformKey(ComSafeArrayAsInParam(aPk), Bstr(pszOwnerUuid).raw()), RTEXITCODE_FAILURE);
145 return RTEXITCODE_SUCCESS;
146 }
147 else
148 RTMsgError("Cannot read contents of file \"%s\": %Rrc", pszPlatformKey, vrc);
149 }
150 else
151 RTMsgError("File \"%s\" is bigger than 32KByte", pszPlatformKey);
152 }
153 else
154 RTMsgError("Cannot get size of file \"%s\": %Rrc", pszPlatformKey, vrc);
155
156 RTFileClose(hPkFile);
157 }
158 else
159 RTMsgError("Cannot open file \"%s\": %Rrc", pszPlatformKey, vrc);
160
161 return RTEXITCODE_FAILURE;
162}
163
164
165/**
166 * Handles the 'modifynvram myvm listvars' sub-command.
167 * @returns Exit code.
168 * @param a The handler argument package.
169 * @param nvram Reference to the NVRAM store interface.
170 */
171static RTEXITCODE handleModifyNvramListUefiVars(HandlerArg *a, ComPtr<INvramStore> &nvramStore)
172{
173 RT_NOREF(a);
174
175 ComPtr<IUefiVariableStore> uefiVarStore;
176 CHECK_ERROR2I_RET(nvramStore, COMGETTER(UefiVariableStore)(uefiVarStore.asOutParam()), RTEXITCODE_FAILURE);
177
178 com::SafeArray<BSTR> aNames;
179 com::SafeArray<BSTR> aOwnerGuids;
180 CHECK_ERROR2I_RET(uefiVarStore, QueryVariables(ComSafeArrayAsOutParam(aNames), ComSafeArrayAsOutParam(aOwnerGuids)), RTEXITCODE_FAILURE);
181 for (size_t i = 0; i < aNames.size(); i++)
182 {
183 Bstr strName = aNames[i];
184 Bstr strOwnerGuid = aOwnerGuids[i];
185
186 RTPrintf("%-32ls {%ls}\n", strName.raw(), strOwnerGuid.raw());
187 }
188
189 return RTEXITCODE_SUCCESS;
190}
191
192
193/**
194 * Handles the 'modifynvram myvm queryvar' sub-command.
195 * @returns Exit code.
196 * @param a The handler argument package.
197 * @param nvram Reference to the NVRAM store interface.
198 */
199static RTEXITCODE handleModifyNvramQueryUefiVar(HandlerArg *a, ComPtr<INvramStore> &nvramStore)
200{
201 static const RTGETOPTDEF s_aOptions[] =
202 {
203 /* common options */
204 { "--name", 'n', RTGETOPT_REQ_STRING },
205 { "--filename", 'f', RTGETOPT_REQ_STRING }
206 };
207
208 const char *pszVarName = NULL;
209 const char *pszVarDataFilename = NULL;
210
211 RTGETOPTSTATE GetState;
212 int vrc = RTGetOptInit(&GetState, a->argc - 2, &a->argv[2], s_aOptions, RT_ELEMENTS(s_aOptions), 0, 0);
213 AssertRCReturn(vrc, RTEXITCODE_FAILURE);
214
215 int c;
216 RTGETOPTUNION ValueUnion;
217 while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
218 {
219 switch (c)
220 {
221 case 'n':
222 pszVarName = ValueUnion.psz;
223 break;
224 case 'f':
225 pszVarDataFilename = ValueUnion.psz;
226 break;
227 default:
228 return errorGetOpt(c, &ValueUnion);
229 }
230 }
231
232 if (!pszVarName)
233 return errorSyntax("No variable name was given to \"queryvar\"");
234
235 ComPtr<IUefiVariableStore> uefiVarStore;
236 CHECK_ERROR2I_RET(nvramStore, COMGETTER(UefiVariableStore)(uefiVarStore.asOutParam()), RTEXITCODE_FAILURE);
237
238 Bstr strOwnerGuid;
239 com::SafeArray<UefiVariableAttributes_T> aVarAttrs;
240 com::SafeArray<BYTE> aData;
241 CHECK_ERROR2I_RET(uefiVarStore, QueryVariableByName(Bstr(pszVarName).raw(), strOwnerGuid.asOutParam(),
242 ComSafeArrayAsOutParam(aVarAttrs), ComSafeArrayAsOutParam(aData)),
243 RTEXITCODE_FAILURE);
244
245 RTEXITCODE rcExit = RTEXITCODE_SUCCESS;
246 if (!pszVarDataFilename)
247 {
248 RTPrintf("%s {%ls}:\n"
249 "%.*Rhxd\n", pszVarName, strOwnerGuid.raw(), aData.size(), aData.raw());
250 }
251 else
252 {
253 /* Just write the data to the file. */
254 RTFILE hFile = NIL_RTFILE;
255 vrc = RTFileOpen(&hFile, pszVarDataFilename, RTFILE_O_CREATE_REPLACE | RTFILE_O_WRITE | RTFILE_O_DENY_NONE);
256 if (RT_SUCCESS(vrc))
257 {
258 vrc = RTFileWrite(hFile, aData.raw(), aData.size(), NULL /*pcbWritten*/);
259 if (RT_FAILURE(vrc))
260 rcExit = RTMsgErrorExitFailure("Error writing to '%s': %Rrc", pszVarDataFilename, vrc);
261
262 RTFileClose(hFile);
263 }
264 else
265 rcExit = RTMsgErrorExitFailure("Error opening '%s': %Rrc", pszVarDataFilename, vrc);
266 }
267
268 return rcExit;
269}
270
271
272/**
273 * Handles the 'modifynvram' command.
274 * @returns Exit code.
275 * @param a The handler argument package.
276 */
277RTEXITCODE handleModifyNvram(HandlerArg *a)
278{
279 HRESULT rc = S_OK;
280 ComPtr<IMachine> machine;
281 ComPtr<INvramStore> nvramStore;
282
283 if (a->argc < 2)
284 return errorNoSubcommand();
285
286 /* try to find the given machine */
287 CHECK_ERROR_RET(a->virtualBox, FindMachine(Bstr(a->argv[0]).raw(),
288 machine.asOutParam()), RTEXITCODE_FAILURE);
289
290 /* open a session for the VM (new or shared) */
291 CHECK_ERROR_RET(machine, LockMachine(a->session, LockType_Write), RTEXITCODE_FAILURE);
292
293 /* get the mutable session machine */
294 a->session->COMGETTER(Machine)(machine.asOutParam());
295 rc = machine->COMGETTER(NonVolatileStore)(nvramStore.asOutParam());
296 if (FAILED(rc)) goto leave;
297
298 if (!strcmp(a->argv[1], "inituefivarstore"))
299 rc = handleModifyNvramInitUefiVarStore(a, nvramStore) == RTEXITCODE_SUCCESS ? S_OK : E_FAIL;
300 else if (!strcmp(a->argv[1], "enrollmssignatures"))
301 rc = handleModifyNvramEnrollMsSignatures(a, nvramStore) == RTEXITCODE_SUCCESS ? S_OK : E_FAIL;
302 else if (!strcmp(a->argv[1], "enrollpk"))
303 rc = handleModifyNvramEnrollPlatformKey(a, nvramStore) == RTEXITCODE_SUCCESS ? S_OK : E_FAIL;
304 else if (!strcmp(a->argv[1], "listvars"))
305 rc = handleModifyNvramListUefiVars(a, nvramStore) == RTEXITCODE_SUCCESS ? S_OK : E_FAIL;
306 else if (!strcmp(a->argv[1], "queryvar"))
307 rc = handleModifyNvramQueryUefiVar(a, nvramStore) == RTEXITCODE_SUCCESS ? S_OK : E_FAIL;
308 else
309 return errorUnknownSubcommand(a->argv[0]);
310
311 /* commit changes */
312 if (SUCCEEDED(rc))
313 CHECK_ERROR(machine, SaveSettings());
314
315leave:
316 /* it's important to always close sessions */
317 a->session->UnlockMachine();
318
319 return SUCCEEDED(rc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
320}
321
322#endif /* !VBOX_ONLY_DOCS */
323
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