VirtualBox

source: vbox/trunk/src/VBox/Main/src-server/FirmwareSettingsImpl.cpp@ 101505

Last change on this file since 101505 was 101418, checked in by vboxsync, 14 months ago

Main: Added VM setting (AutoSerialNumGen) for enabling automatic VM serial number generation jiraref:VBP-238

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 17.4 KB
Line 
1/* $Id: FirmwareSettingsImpl.cpp 101418 2023-10-12 01:07:17Z vboxsync $ */
2/** @file
3 * VirtualBox COM class implementation - Machine firmware settings.
4 */
5
6/*
7 * Copyright (C) 2006-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#define LOG_GROUP LOG_GROUP_MAIN_FIRMWARESETTINGS
29#include "FirmwareSettingsImpl.h"
30#include "MachineImpl.h"
31#include "GuestOSTypeImpl.h"
32
33#include <iprt/cpp/utils.h>
34#include <VBox/settings.h>
35
36#include "AutoStateDep.h"
37#include "AutoCaller.h"
38#include "LoggingNew.h"
39
40
41////////////////////////////////////////////////////////////////////////////////
42//
43// FirmwareSettings private data definition
44//
45////////////////////////////////////////////////////////////////////////////////
46
47struct FirmwareSettings::Data
48{
49 Data()
50 : pMachine(NULL)
51 { }
52
53 Machine * const pMachine;
54 ComObjPtr<FirmwareSettings> pPeer;
55
56 // use the XML settings structure in the members for simplicity
57 Backupable<settings::FirmwareSettings> bd;
58};
59
60// constructor / destructor
61/////////////////////////////////////////////////////////////////////////////
62
63DEFINE_EMPTY_CTOR_DTOR(FirmwareSettings)
64
65HRESULT FirmwareSettings::FinalConstruct()
66{
67 return BaseFinalConstruct();
68}
69
70void FirmwareSettings::FinalRelease()
71{
72 uninit();
73 BaseFinalRelease();
74}
75
76// public initializer/uninitializer for internal purposes only
77/////////////////////////////////////////////////////////////////////////////
78
79/**
80 * Initializes the BIOS settings object.
81 *
82 * @returns COM result indicator
83 */
84HRESULT FirmwareSettings::init(Machine *aParent)
85{
86 LogFlowThisFuncEnter();
87 LogFlowThisFunc(("aParent: %p\n", aParent));
88
89 ComAssertRet(aParent, E_INVALIDARG);
90
91 /* Enclose the state transition NotReady->InInit->Ready */
92 AutoInitSpan autoInitSpan(this);
93 AssertReturn(autoInitSpan.isOk(), E_FAIL);
94
95 m = new Data();
96
97 /* share the parent weakly */
98 unconst(m->pMachine) = aParent;
99
100 m->bd.allocate();
101
102 autoInitSpan.setSucceeded();
103
104 LogFlowThisFuncLeave();
105 return S_OK;
106}
107
108/**
109 * Initializes the firmware settings object given another firmware settings object
110 * (a kind of copy constructor). This object shares data with
111 * the object passed as an argument.
112 *
113 * @note This object must be destroyed before the original object
114 * it shares data with is destroyed.
115 */
116HRESULT FirmwareSettings::init(Machine *aParent, FirmwareSettings *that)
117{
118 LogFlowThisFuncEnter();
119 LogFlowThisFunc(("aParent: %p, that: %p\n", aParent, that));
120
121 ComAssertRet(aParent && that, E_INVALIDARG);
122
123 /* Enclose the state transition NotReady->InInit->Ready */
124 AutoInitSpan autoInitSpan(this);
125 AssertReturn(autoInitSpan.isOk(), E_FAIL);
126
127 m = new Data();
128
129 unconst(m->pMachine) = aParent;
130 m->pPeer = that;
131
132 AutoWriteLock thatlock(that COMMA_LOCKVAL_SRC_POS);
133 m->bd.share(that->m->bd);
134
135 autoInitSpan.setSucceeded();
136
137 LogFlowThisFuncLeave();
138 return S_OK;
139}
140
141/**
142 * Initializes the guest object given another guest object
143 * (a kind of copy constructor). This object makes a private copy of data
144 * of the original object passed as an argument.
145 */
146HRESULT FirmwareSettings::initCopy(Machine *aParent, FirmwareSettings *that)
147{
148 LogFlowThisFuncEnter();
149 LogFlowThisFunc(("aParent: %p, that: %p\n", aParent, that));
150
151 ComAssertRet(aParent && that, E_INVALIDARG);
152
153 /* Enclose the state transition NotReady->InInit->Ready */
154 AutoInitSpan autoInitSpan(this);
155 AssertReturn(autoInitSpan.isOk(), E_FAIL);
156
157 m = new Data();
158
159 unconst(m->pMachine) = aParent;
160 // mPeer is left null
161
162 AutoWriteLock thatlock(that COMMA_LOCKVAL_SRC_POS); /** @todo r=andy Shouldn't a read lock be sufficient here? */
163 m->bd.attachCopy(that->m->bd);
164
165 autoInitSpan.setSucceeded();
166
167 LogFlowThisFuncLeave();
168 return S_OK;
169}
170
171/**
172 * Uninitializes the instance and sets the ready flag to FALSE.
173 * Called either from FinalRelease() or by the parent when it gets destroyed.
174 */
175void FirmwareSettings::uninit()
176{
177 LogFlowThisFuncEnter();
178
179 /* Enclose the state transition Ready->InUninit->NotReady */
180 AutoUninitSpan autoUninitSpan(this);
181 if (autoUninitSpan.uninitDone())
182 return;
183
184 m->bd.free();
185
186 unconst(m->pPeer) = NULL;
187 unconst(m->pMachine) = NULL;
188
189 delete m;
190 m = NULL;
191
192 LogFlowThisFuncLeave();
193}
194
195// IFirmwareSettings properties
196/////////////////////////////////////////////////////////////////////////////
197
198
199HRESULT FirmwareSettings::getLogoFadeIn(BOOL *enabled)
200{
201 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
202
203 *enabled = m->bd->fLogoFadeIn;
204
205 return S_OK;
206}
207
208HRESULT FirmwareSettings::setLogoFadeIn(BOOL enable)
209{
210 /* the machine needs to be mutable */
211 AutoMutableStateDependency adep(m->pMachine);
212 if (FAILED(adep.hrc())) return adep.hrc();
213
214 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
215
216 m->bd.backup();
217 m->bd->fLogoFadeIn = RT_BOOL(enable);
218
219 alock.release();
220 AutoWriteLock mlock(m->pMachine COMMA_LOCKVAL_SRC_POS); // mParent is const, needs no locking
221 m->pMachine->i_setModified(Machine::IsModified_Firmware);
222
223 return S_OK;
224}
225
226
227HRESULT FirmwareSettings::getLogoFadeOut(BOOL *enabled)
228{
229 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
230
231 *enabled = m->bd->fLogoFadeOut;
232
233 return S_OK;
234}
235
236HRESULT FirmwareSettings::setLogoFadeOut(BOOL enable)
237{
238 /* the machine needs to be mutable */
239 AutoMutableStateDependency adep(m->pMachine);
240 if (FAILED(adep.hrc())) return adep.hrc();
241
242 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
243
244 m->bd.backup();
245 m->bd->fLogoFadeOut = RT_BOOL(enable);
246
247 alock.release();
248 AutoWriteLock mlock(m->pMachine COMMA_LOCKVAL_SRC_POS); // mParent is const, needs no locking
249 m->pMachine->i_setModified(Machine::IsModified_Firmware);
250
251 return S_OK;
252}
253
254
255HRESULT FirmwareSettings::getLogoDisplayTime(ULONG *displayTime)
256{
257 if (!displayTime)
258 return E_POINTER;
259
260 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
261
262 *displayTime = m->bd->ulLogoDisplayTime;
263
264 return S_OK;
265}
266
267HRESULT FirmwareSettings::setLogoDisplayTime(ULONG displayTime)
268{
269 /* the machine needs to be mutable */
270 AutoMutableStateDependency adep(m->pMachine);
271 if (FAILED(adep.hrc())) return adep.hrc();
272
273 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
274
275 m->bd.backup();
276 m->bd->ulLogoDisplayTime = displayTime;
277
278 alock.release();
279 AutoWriteLock mlock(m->pMachine COMMA_LOCKVAL_SRC_POS); // mParent is const, needs no locking
280 m->pMachine->i_setModified(Machine::IsModified_Firmware);
281
282 return S_OK;
283}
284
285
286HRESULT FirmwareSettings::getLogoImagePath(com::Utf8Str &imagePath)
287{
288 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
289
290 imagePath = m->bd->strLogoImagePath;
291 return S_OK;
292}
293
294HRESULT FirmwareSettings::setLogoImagePath(const com::Utf8Str &imagePath)
295{
296 /* the machine needs to be mutable */
297 AutoMutableStateDependency adep(m->pMachine);
298 if (FAILED(adep.hrc())) return adep.hrc();
299
300 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
301
302 m->bd.backup();
303 m->bd->strLogoImagePath = imagePath;
304
305 alock.release();
306 AutoWriteLock mlock(m->pMachine COMMA_LOCKVAL_SRC_POS); // mParent is const, needs no locking
307 m->pMachine->i_setModified(Machine::IsModified_Firmware);
308
309 return S_OK;
310}
311
312HRESULT FirmwareSettings::getBootMenuMode(FirmwareBootMenuMode_T *bootMenuMode)
313{
314 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
315
316 *bootMenuMode = m->bd->enmBootMenuMode;
317 return S_OK;
318}
319
320HRESULT FirmwareSettings::setBootMenuMode(FirmwareBootMenuMode_T bootMenuMode)
321{
322 /* the machine needs to be mutable */
323 AutoMutableStateDependency adep(m->pMachine);
324 if (FAILED(adep.hrc())) return adep.hrc();
325
326 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
327
328 m->bd.backup();
329 m->bd->enmBootMenuMode = bootMenuMode;
330
331 alock.release();
332 AutoWriteLock mlock(m->pMachine COMMA_LOCKVAL_SRC_POS); // mParent is const, needs no locking
333 m->pMachine->i_setModified(Machine::IsModified_Firmware);
334
335 return S_OK;
336}
337
338
339HRESULT FirmwareSettings::getACPIEnabled(BOOL *enabled)
340{
341 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
342
343 *enabled = m->bd->fACPIEnabled;
344
345 return S_OK;
346}
347
348HRESULT FirmwareSettings::setACPIEnabled(BOOL enable)
349{
350 /* the machine needs to be mutable */
351 AutoMutableStateDependency adep(m->pMachine);
352 if (FAILED(adep.hrc())) return adep.hrc();
353
354 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
355
356 m->bd.backup();
357 m->bd->fACPIEnabled = RT_BOOL(enable);
358
359 alock.release();
360 AutoWriteLock mlock(m->pMachine COMMA_LOCKVAL_SRC_POS); // mParent is const, needs no locking
361 m->pMachine->i_setModified(Machine::IsModified_Firmware);
362
363 return S_OK;
364}
365
366
367HRESULT FirmwareSettings::getIOAPICEnabled(BOOL *aIOAPICEnabled)
368{
369 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
370
371 *aIOAPICEnabled = m->bd->fIOAPICEnabled;
372
373 return S_OK;
374}
375
376HRESULT FirmwareSettings::getFirmwareType(FirmwareType_T *aType)
377{
378 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
379
380 *aType = m->bd->firmwareType;
381
382 return S_OK;
383}
384
385HRESULT FirmwareSettings::setFirmwareType(FirmwareType_T aType)
386{
387 /* the machine needs to be mutable */
388 AutoMutableStateDependency adep(m->pMachine);
389 if (FAILED(adep.hrc())) return adep.hrc();
390
391 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
392
393 m->bd.backup();
394 m->bd->firmwareType = aType;
395
396 alock.release();
397
398 AutoWriteLock mlock(m->pMachine COMMA_LOCKVAL_SRC_POS); // pMachine is const, needs no locking
399 m->pMachine->i_setModified(Machine::IsModified_Firmware);
400 Utf8Str strNVRAM = m->pMachine->i_getDefaultNVRAMFilename();
401 mlock.release();
402
403 m->pMachine->i_getNVRAMStore()->i_updateNonVolatileStorageFile(strNVRAM);
404
405 return S_OK;
406}
407
408HRESULT FirmwareSettings::setIOAPICEnabled(BOOL aIOAPICEnabled)
409{
410 /* the machine needs to be mutable */
411 AutoMutableStateDependency adep(m->pMachine);
412 if (FAILED(adep.hrc())) return adep.hrc();
413
414 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
415
416 m->bd.backup();
417 m->bd->fIOAPICEnabled = RT_BOOL(aIOAPICEnabled);
418
419 alock.release();
420 AutoWriteLock mlock(m->pMachine COMMA_LOCKVAL_SRC_POS); // mParent is const, needs no locking
421 m->pMachine->i_setModified(Machine::IsModified_Firmware);
422
423 return S_OK;
424}
425
426
427HRESULT FirmwareSettings::getAPICMode(APICMode_T *aAPICMode)
428{
429 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
430
431 *aAPICMode = m->bd->apicMode;
432
433 return S_OK;
434}
435
436HRESULT FirmwareSettings::setAPICMode(APICMode_T aAPICMode)
437{
438 /* the machine needs to be mutable */
439 AutoMutableStateDependency adep(m->pMachine);
440 if (FAILED(adep.hrc())) return adep.hrc();
441
442 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
443
444 m->bd.backup();
445 m->bd->apicMode = aAPICMode;
446
447 alock.release();
448 AutoWriteLock mlock(m->pMachine COMMA_LOCKVAL_SRC_POS); // mParent is const, needs no locking
449 m->pMachine->i_setModified(Machine::IsModified_Firmware);
450
451 return S_OK;
452}
453
454
455HRESULT FirmwareSettings::getPXEDebugEnabled(BOOL *enabled)
456{
457 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
458
459 *enabled = m->bd->fPXEDebugEnabled;
460
461 return S_OK;
462}
463
464HRESULT FirmwareSettings::setPXEDebugEnabled(BOOL enable)
465{
466 /* the machine needs to be mutable */
467 AutoMutableStateDependency adep(m->pMachine);
468 if (FAILED(adep.hrc())) return adep.hrc();
469
470 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
471
472 m->bd.backup();
473 m->bd->fPXEDebugEnabled = RT_BOOL(enable);
474
475 alock.release();
476 AutoWriteLock mlock(m->pMachine COMMA_LOCKVAL_SRC_POS); // mParent is const, needs no locking
477 m->pMachine->i_setModified(Machine::IsModified_Firmware);
478
479 return S_OK;
480}
481
482
483HRESULT FirmwareSettings::getTimeOffset(LONG64 *offset)
484{
485 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
486
487 *offset = m->bd->llTimeOffset;
488
489 return S_OK;
490}
491
492HRESULT FirmwareSettings::setTimeOffset(LONG64 offset)
493{
494 /* the machine needs to be mutable */
495 AutoMutableStateDependency adep(m->pMachine);
496 if (FAILED(adep.hrc())) return adep.hrc();
497
498 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
499
500 m->bd.backup();
501 m->bd->llTimeOffset = offset;
502
503 alock.release();
504 AutoWriteLock mlock(m->pMachine COMMA_LOCKVAL_SRC_POS); // mParent is const, needs no locking
505 m->pMachine->i_setModified(Machine::IsModified_Firmware);
506
507 return S_OK;
508}
509
510
511HRESULT FirmwareSettings::getSMBIOSUuidLittleEndian(BOOL *enabled)
512{
513 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
514
515 *enabled = m->bd->fSmbiosUuidLittleEndian;
516
517 return S_OK;
518}
519
520HRESULT FirmwareSettings::setSMBIOSUuidLittleEndian(BOOL enable)
521{
522 /* the machine needs to be mutable */
523 AutoMutableStateDependency adep(m->pMachine);
524 if (FAILED(adep.hrc())) return adep.hrc();
525
526 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
527
528 m->bd.backup();
529 m->bd->fSmbiosUuidLittleEndian = RT_BOOL(enable);
530
531 alock.release();
532 AutoWriteLock mlock(m->pMachine COMMA_LOCKVAL_SRC_POS); // mParent is const, needs no locking
533 m->pMachine->i_setModified(Machine::IsModified_Firmware);
534
535 return S_OK;
536}
537
538HRESULT FirmwareSettings::getAutoSerialNumGen(BOOL *enabled)
539{
540 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
541
542 *enabled = m->bd->fAutoSerialNumGen;
543
544 return S_OK;
545}
546
547HRESULT FirmwareSettings::setAutoSerialNumGen(BOOL enable)
548{
549 /* the machine needs to be mutable */
550 AutoMutableStateDependency adep(m->pMachine);
551 if (FAILED(adep.hrc())) return adep.hrc();
552
553 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
554
555 m->bd.backup();
556 m->bd->fAutoSerialNumGen = RT_BOOL(enable);
557
558 alock.release();
559 AutoWriteLock mlock(m->pMachine COMMA_LOCKVAL_SRC_POS); // mParent is const, needs no locking
560 m->pMachine->i_setModified(Machine::IsModified_Firmware);
561
562 return S_OK;
563}
564
565// IFirmwareSettings methods
566/////////////////////////////////////////////////////////////////////////////
567
568// public methods only for internal purposes
569/////////////////////////////////////////////////////////////////////////////
570
571/**
572 * Loads settings from the given machine node.
573 * May be called once right after this object creation.
574 *
575 * @param data Configuration settings.
576 *
577 * @note Locks this object for writing.
578 */
579HRESULT FirmwareSettings::i_loadSettings(const settings::FirmwareSettings &data)
580{
581 AutoCaller autoCaller(this);
582 AssertComRCReturnRC(autoCaller.hrc());
583
584 AutoReadLock mlock(m->pMachine COMMA_LOCKVAL_SRC_POS);
585 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
586
587 // simply copy
588 m->bd.assignCopy(&data);
589 return S_OK;
590}
591
592/**
593 * Saves settings to the given machine node.
594 *
595 * @param data Configuration settings.
596 *
597 * @note Locks this object for reading.
598 */
599HRESULT FirmwareSettings::i_saveSettings(settings::FirmwareSettings &data)
600{
601 AutoCaller autoCaller(this);
602 AssertComRCReturnRC(autoCaller.hrc());
603
604 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
605
606 data = *m->bd.data();
607
608 return S_OK;
609}
610
611FirmwareType_T FirmwareSettings::i_getFirmwareType() const
612{
613 return m->bd->firmwareType;
614}
615
616void FirmwareSettings::i_rollback()
617{
618 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
619 m->bd.rollback();
620}
621
622void FirmwareSettings::i_commit()
623{
624 /* sanity */
625 AutoCaller autoCaller(this);
626 AssertComRCReturnVoid(autoCaller.hrc());
627
628 /* sanity too */
629 AutoCaller peerCaller(m->pPeer);
630 AssertComRCReturnVoid(peerCaller.hrc());
631
632 /* lock both for writing since we modify both (mPeer is "master" so locked
633 * first) */
634 AutoMultiWriteLock2 alock(m->pPeer, this COMMA_LOCKVAL_SRC_POS);
635
636 if (m->bd.isBackedUp())
637 {
638 m->bd.commit();
639 if (m->pPeer)
640 {
641 /* attach new data to the peer and reshare it */
642 AutoWriteLock peerlock(m->pPeer COMMA_LOCKVAL_SRC_POS);
643 m->pPeer->m->bd.attach(m->bd);
644 }
645 }
646}
647
648void FirmwareSettings::i_copyFrom(FirmwareSettings *aThat)
649{
650 AssertReturnVoid(aThat != NULL);
651
652 /* sanity */
653 AutoCaller autoCaller(this);
654 AssertComRCReturnVoid(autoCaller.hrc());
655
656 /* sanity too */
657 AutoCaller thatCaller(aThat);
658 AssertComRCReturnVoid(thatCaller.hrc());
659
660 /* peer is not modified, lock it for reading (aThat is "master" so locked
661 * first) */
662 AutoReadLock rl(aThat COMMA_LOCKVAL_SRC_POS);
663 AutoWriteLock wl(this COMMA_LOCKVAL_SRC_POS);
664
665 /* this will back up current data */
666 m->bd.assignCopy(aThat->m->bd);
667}
668
669void FirmwareSettings::i_applyDefaults(GuestOSType *aOsType)
670{
671 /* sanity */
672 AutoCaller autoCaller(this);
673 AssertComRCReturnVoid(autoCaller.hrc());
674
675 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
676
677 /* Initialize default firmware settings here */
678 if (aOsType)
679 {
680 HRESULT hrc = aOsType->COMGETTER(RecommendedFirmware)(&m->bd->firmwareType);
681 AssertComRC(hrc);
682
683 m->bd->fIOAPICEnabled = aOsType->i_recommendedIOAPIC();
684 }
685 else
686 {
687 m->bd->firmwareType = FirmwareType_BIOS; /** @todo BUGBUG Handle ARM? */
688 m->bd->fIOAPICEnabled = true;
689 }
690
691 /// @todo r=andy BUGBUG Is this really enough here? What about the other stuff?
692}
693
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