VirtualBox

source: vbox/trunk/src/VBox/Main/BIOSSettingsImpl.cpp@ 14558

Last change on this file since 14558 was 14558, checked in by vboxsync, 16 years ago

#3285: Improve error handling API to include unique error numbers

  • Property svn:eol-style set to native
File size: 18.8 KB
Line 
1/** @file
2 *
3 * VirtualBox COM class implementation
4 */
5
6/*
7 * Copyright (C) 2006-2007 Sun Microsystems, Inc.
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 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
18 * Clara, CA 95054 USA or visit http://www.sun.com if you need
19 * additional information or have any questions.
20 */
21
22#include "BIOSSettingsImpl.h"
23#include "MachineImpl.h"
24#include "Logging.h"
25#include <iprt/cpputils.h>
26
27// constructor / destructor
28/////////////////////////////////////////////////////////////////////////////
29
30HRESULT BIOSSettings::FinalConstruct()
31{
32 return S_OK;
33}
34
35void BIOSSettings::FinalRelease()
36{
37 uninit ();
38}
39
40// public initializer/uninitializer for internal purposes only
41/////////////////////////////////////////////////////////////////////////////
42
43/**
44 * Initializes the audio adapter object.
45 *
46 * @returns COM result indicator
47 */
48HRESULT BIOSSettings::init (Machine *aParent)
49{
50 LogFlowThisFuncEnter();
51 LogFlowThisFunc (("aParent: %p\n", aParent));
52
53 ComAssertRet (aParent, E_INVALIDARG);
54
55 /* Enclose the state transition NotReady->InInit->Ready */
56 AutoInitSpan autoInitSpan (this);
57 AssertReturn (autoInitSpan.isOk(), E_UNEXPECTED);
58
59 /* share the parent weakly */
60 unconst (mParent) = aParent;
61
62 mData.allocate();
63
64 autoInitSpan.setSucceeded();
65
66 LogFlowThisFuncLeave();
67 return S_OK;
68}
69
70/**
71 * Initializes the audio adapter object given another audio adapter object
72 * (a kind of copy constructor). This object shares data with
73 * the object passed as an argument.
74 *
75 * @note This object must be destroyed before the original object
76 * it shares data with is destroyed.
77 */
78HRESULT BIOSSettings::init (Machine *aParent, BIOSSettings *that)
79{
80 LogFlowThisFuncEnter();
81 LogFlowThisFunc (("aParent: %p, that: %p\n", aParent, that));
82
83 ComAssertRet (aParent && that, E_INVALIDARG);
84
85 /* Enclose the state transition NotReady->InInit->Ready */
86 AutoInitSpan autoInitSpan (this);
87 AssertReturn (autoInitSpan.isOk(), E_UNEXPECTED);
88
89 mParent = aParent;
90 mPeer = that;
91
92 AutoWriteLock thatlock (that);
93 mData.share (that->mData);
94
95 autoInitSpan.setSucceeded();
96
97 LogFlowThisFuncLeave();
98 return S_OK;
99}
100
101/**
102 * Initializes the guest object given another guest object
103 * (a kind of copy constructor). This object makes a private copy of data
104 * of the original object passed as an argument.
105 */
106HRESULT BIOSSettings::initCopy (Machine *aParent, BIOSSettings *that)
107{
108 LogFlowThisFuncEnter();
109 LogFlowThisFunc (("aParent: %p, that: %p\n", aParent, that));
110
111 ComAssertRet (aParent && that, E_INVALIDARG);
112
113 /* Enclose the state transition NotReady->InInit->Ready */
114 AutoInitSpan autoInitSpan (this);
115 AssertReturn (autoInitSpan.isOk(), E_UNEXPECTED);
116
117 mParent = aParent;
118 // mPeer is left null
119
120 AutoWriteLock thatlock (that);
121 mData.attachCopy (that->mData);
122
123 autoInitSpan.setSucceeded();
124
125 LogFlowThisFuncLeave();
126 return S_OK;
127}
128
129/**
130 * Uninitializes the instance and sets the ready flag to FALSE.
131 * Called either from FinalRelease() or by the parent when it gets destroyed.
132 */
133void BIOSSettings::uninit()
134{
135 LogFlowThisFuncEnter();
136
137 /* Enclose the state transition Ready->InUninit->NotReady */
138 AutoUninitSpan autoUninitSpan (this);
139 if (autoUninitSpan.uninitDone())
140 return;
141
142 mData.free();
143
144 mPeer.setNull();
145 mParent.setNull();
146
147 LogFlowThisFuncLeave();
148}
149
150// IBIOSSettings properties
151/////////////////////////////////////////////////////////////////////////////
152
153STDMETHODIMP BIOSSettings::COMGETTER(LogoFadeIn)(BOOL *enabled)
154{
155 if (!enabled)
156 return E_POINTER;
157
158 AutoCaller autoCaller (this);
159 CheckComRCReturnRC (autoCaller.rc());
160
161 AutoReadLock alock (this);
162
163 *enabled = mData->mLogoFadeIn;
164
165 return S_OK;
166}
167
168STDMETHODIMP BIOSSettings::COMSETTER(LogoFadeIn)(BOOL enable)
169{
170 AutoCaller autoCaller (this);
171 CheckComRCReturnRC (autoCaller.rc());
172
173 /* the machine needs to be mutable */
174 Machine::AutoMutableStateDependency adep (mParent);
175 CheckComRCReturnRC (adep.rc());
176
177 AutoWriteLock alock (this);
178
179 mData.backup();
180 mData->mLogoFadeIn = enable;
181
182 return S_OK;
183}
184
185STDMETHODIMP BIOSSettings::COMGETTER(LogoFadeOut)(BOOL *enabled)
186{
187 if (!enabled)
188 return E_POINTER;
189
190 AutoCaller autoCaller (this);
191 CheckComRCReturnRC (autoCaller.rc());
192
193 AutoReadLock alock (this);
194
195 *enabled = mData->mLogoFadeOut;
196
197 return S_OK;
198}
199
200STDMETHODIMP BIOSSettings::COMSETTER(LogoFadeOut)(BOOL enable)
201{
202 AutoCaller autoCaller (this);
203 CheckComRCReturnRC (autoCaller.rc());
204
205 /* the machine needs to be mutable */
206 Machine::AutoMutableStateDependency adep (mParent);
207 CheckComRCReturnRC (adep.rc());
208
209 AutoWriteLock alock (this);
210
211 mData.backup();
212 mData->mLogoFadeOut = enable;
213
214 return S_OK;
215}
216
217STDMETHODIMP BIOSSettings::COMGETTER(LogoDisplayTime)(ULONG *displayTime)
218{
219 if (!displayTime)
220 return E_POINTER;
221
222 AutoCaller autoCaller (this);
223 CheckComRCReturnRC (autoCaller.rc());
224
225 AutoReadLock alock (this);
226
227 *displayTime = mData->mLogoDisplayTime;
228
229 return S_OK;
230}
231
232STDMETHODIMP BIOSSettings::COMSETTER(LogoDisplayTime)(ULONG displayTime)
233{
234 AutoCaller autoCaller (this);
235 CheckComRCReturnRC (autoCaller.rc());
236
237 /* the machine needs to be mutable */
238 Machine::AutoMutableStateDependency adep (mParent);
239 CheckComRCReturnRC (adep.rc());
240
241 AutoWriteLock alock (this);
242
243 mData.backup();
244 mData->mLogoDisplayTime = displayTime;
245
246 return S_OK;
247}
248
249STDMETHODIMP BIOSSettings::COMGETTER(LogoImagePath)(BSTR *imagePath)
250{
251 if (!imagePath)
252 return E_POINTER;
253
254 AutoCaller autoCaller (this);
255 CheckComRCReturnRC (autoCaller.rc());
256
257 AutoReadLock alock (this);
258
259 mData->mLogoImagePath.cloneTo(imagePath);
260 return S_OK;
261}
262
263STDMETHODIMP BIOSSettings::COMSETTER(LogoImagePath)(INPTR BSTR imagePath)
264{
265 /* empty strings are not allowed as path names */
266 if (imagePath && !(*imagePath))
267 return E_INVALIDARG;
268
269 AutoCaller autoCaller (this);
270 CheckComRCReturnRC (autoCaller.rc());
271
272 /* the machine needs to be mutable */
273 Machine::AutoMutableStateDependency adep (mParent);
274 CheckComRCReturnRC (adep.rc());
275
276 AutoWriteLock alock (this);
277
278 mData.backup();
279 mData->mLogoImagePath = imagePath;
280
281 return S_OK;
282}
283
284STDMETHODIMP BIOSSettings::COMGETTER(BootMenuMode)(BIOSBootMenuMode_T *bootMenuMode)
285{
286 if (!bootMenuMode)
287 return E_POINTER;
288
289 AutoCaller autoCaller (this);
290 CheckComRCReturnRC (autoCaller.rc());
291
292 AutoReadLock alock (this);
293
294 *bootMenuMode = mData->mBootMenuMode;
295 return S_OK;
296}
297
298STDMETHODIMP BIOSSettings::COMSETTER(BootMenuMode)(BIOSBootMenuMode_T bootMenuMode)
299{
300 AutoCaller autoCaller (this);
301 CheckComRCReturnRC (autoCaller.rc());
302
303 /* the machine needs to be mutable */
304 Machine::AutoMutableStateDependency adep (mParent);
305 CheckComRCReturnRC (adep.rc());
306
307 AutoWriteLock alock (this);
308
309 mData.backup();
310 mData->mBootMenuMode = bootMenuMode;
311
312 return S_OK;
313}
314
315STDMETHODIMP BIOSSettings::COMGETTER(ACPIEnabled)(BOOL *enabled)
316{
317 if (!enabled)
318 return E_POINTER;
319
320 AutoCaller autoCaller (this);
321 CheckComRCReturnRC (autoCaller.rc());
322
323 AutoReadLock alock (this);
324
325 *enabled = mData->mACPIEnabled;
326
327 return S_OK;
328}
329
330STDMETHODIMP BIOSSettings::COMSETTER(ACPIEnabled)(BOOL enable)
331{
332 AutoCaller autoCaller (this);
333 CheckComRCReturnRC (autoCaller.rc());
334
335 /* the machine needs to be mutable */
336 Machine::AutoMutableStateDependency adep (mParent);
337 CheckComRCReturnRC (adep.rc());
338
339 AutoWriteLock alock (this);
340
341 mData.backup();
342 mData->mACPIEnabled = enable;
343
344 return S_OK;
345}
346
347STDMETHODIMP BIOSSettings::COMGETTER(IOAPICEnabled)(BOOL *enabled)
348{
349 if (!enabled)
350 return E_POINTER;
351
352 AutoCaller autoCaller (this);
353 CheckComRCReturnRC (autoCaller.rc());
354
355 AutoReadLock alock (this);
356
357 *enabled = mData->mIOAPICEnabled;
358
359 return S_OK;
360}
361
362STDMETHODIMP BIOSSettings::COMSETTER(IOAPICEnabled)(BOOL enable)
363{
364 AutoCaller autoCaller (this);
365 CheckComRCReturnRC (autoCaller.rc());
366
367 /* the machine needs to be mutable */
368 Machine::AutoMutableStateDependency adep (mParent);
369 CheckComRCReturnRC (adep.rc());
370
371 AutoWriteLock alock (this);
372
373 mData.backup();
374 mData->mIOAPICEnabled = enable;
375
376 return S_OK;
377}
378
379STDMETHODIMP BIOSSettings::COMGETTER(PXEDebugEnabled)(BOOL *enabled)
380{
381 if (!enabled)
382 return E_POINTER;
383
384 AutoCaller autoCaller (this);
385 CheckComRCReturnRC (autoCaller.rc());
386
387 AutoReadLock alock (this);
388
389 *enabled = mData->mPXEDebugEnabled;
390
391 return S_OK;
392}
393
394STDMETHODIMP BIOSSettings::COMSETTER(PXEDebugEnabled)(BOOL enable)
395{
396 AutoCaller autoCaller (this);
397 CheckComRCReturnRC (autoCaller.rc());
398
399 /* the machine needs to be mutable */
400 Machine::AutoMutableStateDependency adep (mParent);
401 CheckComRCReturnRC (adep.rc());
402
403 AutoWriteLock alock (this);
404
405 mData.backup();
406 mData->mPXEDebugEnabled = enable;
407
408 return S_OK;
409}
410
411STDMETHODIMP BIOSSettings::COMGETTER(IDEControllerType)(IDEControllerType_T *aControllerType)
412{
413 if (!aControllerType)
414 return E_POINTER;
415
416 AutoCaller autoCaller (this);
417 CheckComRCReturnRC (autoCaller.rc());
418
419 AutoReadLock alock (this);
420
421 *aControllerType = mData->mIDEControllerType;
422
423 return S_OK;
424}
425
426STDMETHODIMP BIOSSettings::COMSETTER(IDEControllerType)(IDEControllerType_T aControllerType)
427{
428 AutoCaller autoCaller (this);
429 CheckComRCReturnRC (autoCaller.rc());
430
431 /* the machine needs to be mutable */
432 Machine::AutoMutableStateDependency adep (mParent);
433 CheckComRCReturnRC (adep.rc());
434
435 AutoWriteLock alock (this);
436
437 /* make sure the value is allowed */
438 switch (aControllerType)
439 {
440 case IDEControllerType_PIIX3:
441 case IDEControllerType_PIIX4:
442 break;
443 default:
444 return setError (E_INVALIDARG,
445 tr("Invalid IDE controller type '%d'"),
446 aControllerType);
447 }
448
449 mData.backup();
450
451 mData->mIDEControllerType = aControllerType;
452
453 return S_OK;
454}
455
456STDMETHODIMP BIOSSettings::COMGETTER(TimeOffset)(LONG64 *offset)
457{
458 if (!offset)
459 return E_POINTER;
460
461 AutoCaller autoCaller (this);
462 CheckComRCReturnRC (autoCaller.rc());
463
464 AutoReadLock alock (this);
465
466 *offset = mData->mTimeOffset;
467
468 return S_OK;
469}
470
471STDMETHODIMP BIOSSettings::COMSETTER(TimeOffset)(LONG64 offset)
472{
473 AutoCaller autoCaller (this);
474 CheckComRCReturnRC (autoCaller.rc());
475
476 /* the machine needs to be mutable */
477 Machine::AutoMutableStateDependency adep (mParent);
478 CheckComRCReturnRC (adep.rc());
479
480 AutoWriteLock alock (this);
481
482 mData.backup();
483 mData->mTimeOffset = offset;
484
485 return S_OK;
486}
487
488
489// IBIOSSettings methods
490/////////////////////////////////////////////////////////////////////////////
491
492// public methods only for internal purposes
493/////////////////////////////////////////////////////////////////////////////
494
495/**
496 * Loads settings from the given machine node.
497 * May be called once right after this object creation.
498 *
499 * @param aMachineNode <Machine> node.
500 *
501 * @note Locks this object for writing.
502 */
503HRESULT BIOSSettings::loadSettings (const settings::Key &aMachineNode)
504{
505 using namespace settings;
506
507 AssertReturn (!aMachineNode.isNull(), E_FAIL);
508
509 AutoCaller autoCaller (this);
510 AssertComRCReturnRC (autoCaller.rc());
511
512 AutoWriteLock alock (this);
513
514 /* Note: we assume that the default values for attributes of optional
515 * nodes are assigned in the Data::Data() constructor and don't do it
516 * here. It implies that this method may only be called after constructing
517 * a new BIOSSettings object while all its data fields are in the default
518 * values. Exceptions are fields whose creation time defaults don't match
519 * values that should be applied when these fields are not explicitly set
520 * in the settings file (for backwards compatibility reasons). This takes
521 * place when a setting of a newly created object must default to A while
522 * the same setting of an object loaded from the old settings file must
523 * default to B. */
524
525 /* BIOS node (required) */
526 Key biosNode = aMachineNode.key ("BIOS");
527
528 /* ACPI (required) */
529 {
530 Key acpiNode = biosNode.key ("ACPI");
531
532 mData->mACPIEnabled = acpiNode.value <bool> ("enabled");
533 }
534
535 /* IOAPIC (optional) */
536 {
537 Key ioapicNode = biosNode.findKey ("IOAPIC");
538 if (!ioapicNode.isNull())
539 mData->mIOAPICEnabled = ioapicNode.value <bool> ("enabled");
540 }
541
542 /* Logo (optional) */
543 {
544 Key logoNode = biosNode.findKey ("Logo");
545 if (!logoNode.isNull())
546 {
547 mData->mLogoFadeIn = logoNode.value <bool> ("fadeIn");
548 mData->mLogoFadeOut = logoNode.value <bool> ("fadeOut");
549 mData->mLogoDisplayTime = logoNode.value <ULONG> ("displayTime");
550 mData->mLogoImagePath = logoNode.stringValue ("imagePath");
551 }
552 }
553
554 /* boot menu (optional) */
555 {
556 Key bootMenuNode = biosNode.findKey ("BootMenu");
557 if (!bootMenuNode.isNull())
558 {
559 mData->mBootMenuMode = BIOSBootMenuMode_MessageAndMenu;
560 const char *modeStr = bootMenuNode.stringValue ("mode");
561
562 if (strcmp (modeStr, "Disabled") == 0)
563 mData->mBootMenuMode = BIOSBootMenuMode_Disabled;
564 else if (strcmp (modeStr, "MenuOnly") == 0)
565 mData->mBootMenuMode = BIOSBootMenuMode_MenuOnly;
566 else if (strcmp (modeStr, "MessageAndMenu") == 0)
567 mData->mBootMenuMode = BIOSBootMenuMode_MessageAndMenu;
568 else
569 ComAssertMsgFailedRet (("Invalid boot menu mode '%s'\n", modeStr),
570 E_FAIL);
571 }
572 }
573
574 /* PXE debug logging (optional) */
575 {
576 Key pxedebugNode = biosNode.findKey ("PXEDebug");
577 if (!pxedebugNode.isNull())
578 mData->mPXEDebugEnabled = pxedebugNode.value <bool> ("enabled");
579 }
580
581 /* time offset (optional) */
582 {
583 Key timeOffsetNode = biosNode.findKey ("TimeOffset");
584 if (!timeOffsetNode.isNull())
585 mData->mTimeOffset = timeOffsetNode.value <LONG64> ("value");
586 }
587
588 /* IDE controller type (optional, for old machines that lack this node,
589 * defaults to PIIX3) */
590 {
591 mData->mIDEControllerType = IDEControllerType_PIIX3;
592
593 Key ideControllerNode = biosNode.findKey ("IDEController");
594 if (!ideControllerNode.isNull())
595 {
596 const char *typeStr = ideControllerNode.stringValue ("type");
597 if (strcmp (typeStr, "PIIX3") == 0)
598 mData->mIDEControllerType = IDEControllerType_PIIX3;
599 else if (strcmp (typeStr, "PIIX4") == 0)
600 mData->mIDEControllerType = IDEControllerType_PIIX4;
601 else
602 ComAssertMsgFailedRet (("Invalid boot menu mode '%s'\n", typeStr),
603 E_FAIL);
604 }
605 }
606
607 return S_OK;
608}
609
610/**
611 * Saves settings to the given machine node.
612 *
613 * @param aMachineNode <Machine> node.
614 *
615 * @note Locks this object for reading.
616 */
617HRESULT BIOSSettings::saveSettings (settings::Key &aMachineNode)
618{
619 using namespace settings;
620
621 AssertReturn (!aMachineNode.isNull(), E_FAIL);
622
623 AutoCaller autoCaller (this);
624 AssertComRCReturnRC (autoCaller.rc());
625
626 AutoReadLock alock (this);
627
628 Key biosNode = aMachineNode.createKey ("BIOS");
629
630 /* ACPI */
631 {
632 Key acpiNode = biosNode.createKey ("ACPI");
633 acpiNode.setValue <bool> ("enabled", !!mData->mACPIEnabled);
634 }
635
636 /* IOAPIC */
637 {
638 Key ioapicNode = biosNode.createKey ("IOAPIC");
639 ioapicNode.setValue <bool> ("enabled", !!mData->mIOAPICEnabled);
640 }
641
642 /* BIOS logo (optional) **/
643 {
644 Key logoNode = biosNode.createKey ("Logo");
645 logoNode.setValue <bool> ("fadeIn", !!mData->mLogoFadeIn);
646 logoNode.setValue <bool> ("fadeOut", !!mData->mLogoFadeOut);
647 logoNode.setValue <ULONG> ("displayTime", mData->mLogoDisplayTime);
648 logoNode.setValueOr <Bstr> ("imagePath", mData->mLogoImagePath, Bstr::Null);
649 }
650
651 /* boot menu (optional) */
652 {
653 Key bootMenuNode = biosNode.createKey ("BootMenu");
654 const char *modeStr = NULL;
655 switch (mData->mBootMenuMode)
656 {
657 case BIOSBootMenuMode_Disabled:
658 modeStr = "Disabled";
659 break;
660 case BIOSBootMenuMode_MenuOnly:
661 modeStr = "MenuOnly";
662 break;
663 case BIOSBootMenuMode_MessageAndMenu:
664 modeStr = "MessageAndMenu";
665 break;
666 default:
667 ComAssertMsgFailedRet (("Invalid boot menu type: %d\n",
668 mData->mBootMenuMode),
669 E_FAIL);
670 }
671 bootMenuNode.setStringValue ("mode", modeStr);
672 }
673
674 /* time offset (optional) */
675 {
676 Key timeOffsetNode = biosNode.createKey ("TimeOffset");
677 timeOffsetNode.setValue <LONG64> ("value", mData->mTimeOffset);
678 }
679
680 /* PXE debug flag (optional) */
681 {
682 Key pxedebugNode = biosNode.createKey ("PXEDebug");
683 pxedebugNode.setValue <bool> ("enabled", !!mData->mPXEDebugEnabled);
684 }
685
686 /* IDE controller type */
687 {
688 Key ideControllerNode = biosNode.createKey ("IDEController");
689 const char *ideControllerTypeStr = NULL;
690 switch (mData->mIDEControllerType)
691 {
692 case IDEControllerType_PIIX3:
693 ideControllerTypeStr = "PIIX3";
694 break;
695 case IDEControllerType_PIIX4:
696 ideControllerTypeStr = "PIIX4";
697 break;
698 default:
699 ComAssertMsgFailedRet (("Invalid IDE Controller type: %d\n",
700 mData->mIDEControllerType),
701 E_FAIL);
702 }
703 ideControllerNode.setStringValue ("type", ideControllerTypeStr);
704 }
705
706 return S_OK;
707}
708
709void BIOSSettings::commit()
710{
711 AutoWriteLock alock (this);
712 if (mData.isBackedUp())
713 {
714 mData.commit();
715 if (mPeer)
716 {
717 // attach new data to the peer and re-share it
718 AutoWriteLock peerlock (mPeer);
719 mPeer->mData.attach (mData);
720 }
721 }
722}
723
724void BIOSSettings::copyFrom (BIOSSettings *aThat)
725{
726 AutoWriteLock alock (this);
727
728 // this will back up current data
729 mData.assignCopy (aThat->mData);
730}
731
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