VirtualBox

Changeset 101035 in vbox for trunk/src/VBox/Main/xml


Ignore:
Timestamp:
Sep 7, 2023 8:59:15 AM (20 months ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
158992
Message:

Initial commit (based draft v2 / on patch v5) for implementing platform architecture support for x86 and ARM. bugref:10384

Location:
trunk/src/VBox/Main/xml
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/xml/Settings.cpp

    r99723 r101035  
    430430            else if (uMinor == 19)
    431431                sv = SettingsVersion_v1_19;
    432             else if (uMinor > 19)
     432            else if (uMinor == 20)
     433                sv = SettingsVersion_v1_20;
     434            else if (uMinor > 20)
    433435                sv = SettingsVersion_Future;
    434436        }
     
    10721074            break;
    10731075
     1076        case SettingsVersion_v1_20:
     1077            pcszVersion = "1.20";
     1078            break;
     1079
    10741080        default:
    10751081            // catch human error: the assertion below will trigger in debug
     
    10941100                // but as it's an omission of someone who changed this file
    10951101                // it's the only generic possibility.
    1096                 pcszVersion = "1.19";
    1097                 m->sv = SettingsVersion_v1_19;
     1102                pcszVersion = "1.20";
     1103                m->sv = SettingsVersion_v1_20;
    10981104            }
    10991105            break;
     
    16481654////////////////////////////////////////////////////////////////////////////////
    16491655
     1656PlatformProperties::PlatformProperties()
     1657    : fExclusiveHwVirt(true)
     1658{
     1659#if defined(RT_OS_DARWIN) || defined(RT_OS_WINDOWS) || defined(RT_OS_SOLARIS)
     1660    fExclusiveHwVirt = false; /** BUGBUG Does this apply to MacOS on ARM as well? */
     1661#endif
     1662}
     1663
    16501664/**
    16511665 * Constructor. Needs to set sane defaults which stand the test of time.
     
    16541668    : uProxyMode(ProxyMode_System)
    16551669    , uLogHistoryCount(3)
    1656     , fExclusiveHwVirt(true)
    1657 {
    1658 #if defined(RT_OS_DARWIN) || defined(RT_OS_WINDOWS) || defined(RT_OS_SOLARIS)
    1659     fExclusiveHwVirt = false;
    1660 #endif
     1670{
    16611671}
    16621672
     
    23522362                        pelmGlobalChild->getAttributeValue("autostartDatabasePath", systemProperties.strAutostartDatabasePath);
    23532363                        pelmGlobalChild->getAttributeValue("defaultFrontend", systemProperties.strDefaultFrontend);
    2354                         pelmGlobalChild->getAttributeValue("exclusiveHwVirt", systemProperties.fExclusiveHwVirt);
     2364                        if (m->sv < SettingsVersion_v1_20) /* exclusiveHwVirt was part of SystemProperties for < v1.20. */
     2365                            pelmGlobalChild->getAttributeValue("exclusiveHwVirt", platformProperties.fExclusiveHwVirt);
    23552366                        if (!pelmGlobalChild->getAttributeValue("proxyMode", systemProperties.uProxyMode))
    23562367                            fCopyProxySettingsFromExtraData = true;
    23572368                        pelmGlobalChild->getAttributeValue("proxyUrl", systemProperties.strProxyUrl);
    23582369                        pelmGlobalChild->getAttributeValue("LanguageId", systemProperties.strLanguageId);
     2370                    }
     2371                    if (   pelmGlobalChild->nameEquals("PlatformProperties")
     2372                        && m->sv >= SettingsVersion_v1_20)
     2373                    {
     2374                        /* Since settings v1.20 exclusiveHwVirt is part of PlatformProperties. */
     2375                        pelmGlobalChild->getAttributeValue("exclusiveHwVirt", platformProperties.fExclusiveHwVirt);
    23592376                    }
    23602377#ifdef VBOX_WITH_UPDATE_AGENT
     
    26502667        pelmSysProps->setAttribute("proxyUrl", systemProperties.strProxyUrl);
    26512668    pelmSysProps->setAttribute("proxyMode", systemProperties.uProxyMode);
    2652     pelmSysProps->setAttribute("exclusiveHwVirt", systemProperties.fExclusiveHwVirt);
     2669    if (m->sv >= SettingsVersion_v1_20) /* Since settings v1.20 exclusiveHwVirt is part of PlatformProperties. */
     2670    {
     2671        xml::ElementNode *pelmPlatProps = pelmGlobal->createChild("PlatformProperties");
     2672        pelmPlatProps->setAttribute("exclusiveHwVirt", platformProperties.fExclusiveHwVirt);
     2673    }
     2674    else
     2675        pelmSysProps->setAttribute("exclusiveHwVirt", platformProperties.fExclusiveHwVirt);
    26532676    if (systemProperties.strLanguageId.isNotEmpty())
    26542677        pelmSysProps->setAttribute("LanguageId", systemProperties.strLanguageId);
     
    27262749 * Constructor. Needs to set sane defaults which stand the test of time.
    27272750 */
    2728 BIOSSettings::BIOSSettings() :
     2751FirmwareSettings::FirmwareSettings() :
     2752    firmwareType(FirmwareType_BIOS),
    27292753    fACPIEnabled(true),
    27302754    fIOAPICEnabled(false),
     
    27342758    fSmbiosUuidLittleEndian(true),
    27352759    ulLogoDisplayTime(0),
    2736     biosBootMenuMode(BIOSBootMenuMode_MessageAndMenu),
     2760    enmBootMenuMode(FirmwareBootMenuMode_MessageAndMenu),
    27372761    apicMode(APICMode_APIC),
    27382762    llTimeOffset(0)
     
    27412765
    27422766/**
    2743  * Check if all settings have default values.
    2744  */
    2745 bool BIOSSettings::areDefaultSettings() const
    2746 {
    2747     return fACPIEnabled
    2748         && !fIOAPICEnabled
    2749         && fLogoFadeIn
    2750         && fLogoFadeOut
    2751         && !fPXEDebugEnabled
    2752         && !fSmbiosUuidLittleEndian
    2753         && ulLogoDisplayTime == 0
    2754         && biosBootMenuMode == BIOSBootMenuMode_MessageAndMenu
    2755         && apicMode == APICMode_APIC
    2756         && llTimeOffset == 0
    2757         && strLogoImagePath.isEmpty();
     2767 * Returns if all settings have default values.
     2768 *
     2769 * @returns \c true if all settings have default values, \c false if not.
     2770 * @param   enmCPUArch              CPU architecture to use for checking the default values for.
     2771 */
     2772bool FirmwareSettings::areDefaultSettings(CPUArchitecture_T enmCPUArch) const
     2773{
     2774    switch (enmCPUArch)
     2775    {
     2776        case CPUArchitecture_x86:
     2777            RT_FALL_THROUGH();
     2778        case CPUArchitecture_AMD64:
     2779            return
     2780                   firmwareType == FirmwareType_BIOS
     2781                && !fIOAPICEnabled
     2782                && fLogoFadeIn
     2783                && fLogoFadeOut
     2784                && !fPXEDebugEnabled
     2785                && !fSmbiosUuidLittleEndian
     2786                && ulLogoDisplayTime == 0
     2787                && enmBootMenuMode == FirmwareBootMenuMode_MessageAndMenu
     2788                && apicMode == APICMode_APIC
     2789                && llTimeOffset == 0
     2790                && strLogoImagePath.isEmpty();
     2791
     2792        case CPUArchitecture_ARMv8_32:
     2793            RT_FALL_THROUGH();
     2794        case CPUArchitecture_ARMv8_64:
     2795            return
     2796                   (    enmCPUArch == CPUArchitecture_ARMv8_32
     2797                    ? firmwareType == FirmwareType_EFI32
     2798                    : firmwareType == FirmwareType_EFI64)
     2799                && !fIOAPICEnabled
     2800                && fLogoFadeIn
     2801                && fLogoFadeOut
     2802                && !fPXEDebugEnabled
     2803                && !fSmbiosUuidLittleEndian
     2804                && ulLogoDisplayTime == 0
     2805                && enmBootMenuMode == FirmwareBootMenuMode_MessageAndMenu
     2806                && apicMode == APICMode_APIC
     2807                && llTimeOffset == 0
     2808                && strLogoImagePath.isEmpty();
     2809            break;
     2810
     2811        default:
     2812            break;
     2813    }
     2814
     2815    AssertFailedReturn(false);
    27582816}
    27592817
     
    27632821 * machine settings have really changed and thus need to be written out to disk.
    27642822 */
    2765 bool BIOSSettings::operator==(const BIOSSettings &d) const
     2823bool FirmwareSettings::operator==(const FirmwareSettings &d) const
    27662824{
    27672825    return (this == &d)
    2768         || (   fACPIEnabled            == d.fACPIEnabled
     2826        || (   firmwareType            == d.firmwareType
     2827            && fACPIEnabled            == d.fACPIEnabled
    27692828            && fIOAPICEnabled          == d.fIOAPICEnabled
    27702829            && fLogoFadeIn             == d.fLogoFadeIn
     
    27732832            && fSmbiosUuidLittleEndian == d.fSmbiosUuidLittleEndian
    27742833            && ulLogoDisplayTime       == d.ulLogoDisplayTime
    2775             && biosBootMenuMode        == d.biosBootMenuMode
     2834            && enmBootMenuMode        == d.enmBootMenuMode
    27762835            && apicMode                == d.apicMode
    27772836            && llTimeOffset            == d.llTimeOffset
     
    36293688    ulSlot(0),
    36303689    fEnabled(false),
    3631     ulIOBase(0x3f8),
     3690    ulIOAddress(0x3f8),
    36323691    ulIRQ(4),
    36333692    portMode(PortMode_Disconnected),
     
    36473706        || (   ulSlot            == s.ulSlot
    36483707            && fEnabled          == s.fEnabled
    3649             && ulIOBase          == s.ulIOBase
     3708            && ulIOAddress       == s.ulIOAddress
    36503709            && ulIRQ             == s.ulIRQ
    36513710            && portMode          == s.portMode
     
    37743833 * Constructor. Needs to set sane defaults which stand the test of time.
    37753834 */
    3776 CpuIdLeaf::CpuIdLeaf() :
     3835CpuIdLeafX86::CpuIdLeafX86() :
    37773836    idx(UINT32_MAX),
    37783837    idxSub(0),
     
    37893848 * machine settings have really changed and thus need to be written out to disk.
    37903849 */
    3791 bool CpuIdLeaf::operator==(const CpuIdLeaf &c) const
     3850bool CpuIdLeafX86::operator==(const CpuIdLeafX86 &c) const
    37923851{
    37933852    return (this == &c)
     
    39033962}
    39043963
    3905 
    3906 /**
    3907  * Constructor. Needs to set sane defaults which stand the test of time.
    3908  */
    3909 Hardware::Hardware() :
    3910     strVersion("1"),
    3911     fHardwareVirt(true),
    3912     fNestedPaging(true),
    3913     fVPID(true),
    3914     fUnrestrictedExecution(true),
    3915     fHardwareVirtForce(false),
    3916     fUseNativeApi(false),
    3917     fTripleFaultReset(false),
     3964#ifdef VBOX_WITH_VIRT_ARMV8
     3965PlatformARM::PlatformARM()
     3966    /** @todo BUGBUG Anything for ARM here? */
     3967{
     3968
     3969}
     3970
     3971bool PlatformARM::operator==(const PlatformARM& h) const
     3972{
     3973    RT_NOREF(h);
     3974    return true; /** @todo BUGBUG Anything for ARM here? */
     3975}
     3976#endif /* VBOX_WITH_VIRT_ARMV8 */
     3977
     3978PlatformX86::PlatformX86() :
    39183979    fPAE(false),
    39193980    fAPIC(true),
    39203981    fX2APIC(false),
     3982    fHPETEnabled(false),
     3983    enmLongMode(HC_ARCH_BITS == 64 ? PlatformX86::LongMode_Enabled : PlatformX86::LongMode_Disabled),
     3984    fTripleFaultReset(false),
    39213985    fIBPBOnVMExit(false),
    39223986    fIBPBOnVMEntry(false),
     
    39273991    fMDSClearOnSched(true),
    39283992    fMDSClearOnVMEntry(false),
    3929     fNestedHWVirt(false),
    3930     fVirtVmsaveVmload(true),
    3931     enmLongMode(HC_ARCH_BITS == 64 ? Hardware::LongMode_Enabled : Hardware::LongMode_Disabled),
     3993    fHWVirtEx(true),
     3994    fHWVirtExNestedPaging(true),
     3995    fHWVirtExVPID(true),
     3996    fHWVirtExUX(true),
     3997    fHWVirtExForce(false),
     3998    fHWVirtExUseNativeApi(false),
     3999    fHWVirtExVirtVmsaveVmload(true),
     4000    fNestedHWVirt(false)
     4001{
     4002    /* The default value for PAE depends on the host:
     4003     * - 64 bits host -> always true
     4004     * - 32 bits host -> true for Windows & Darwin (masked off if the host cpu doesn't support it anyway)
     4005     */
     4006#if HC_ARCH_BITS == 64 || defined(RT_OS_WINDOWS) || defined(RT_OS_DARWIN)
     4007    fPAE = true;
     4008#endif
     4009
     4010    /* The default value of large page supports depends on the host:
     4011     * - 64 bits host -> true, unless it's Linux (pending further prediction work due to excessively expensive large page allocations)
     4012     * - 32 bits host -> false
     4013     */
     4014#if HC_ARCH_BITS == 64 && !defined(RT_OS_LINUX)
     4015    fHWVirtExLargePages = true; /** @todo BUGBUG Does this apply for ARM as well? */
     4016#else
     4017    /* Not supported on 32 bits hosts. */
     4018    fHWVirtExLargePages = false;
     4019#endif
     4020}
     4021
     4022/**
     4023 * Comparison operator. This gets called from MachineConfigFile::operator==,
     4024 * which in turn gets called from Platform::saveSettings to figure out whether
     4025 * machine settings have really changed and thus need to be written out to disk.
     4026 */
     4027bool PlatformX86::operator==(const PlatformX86& h) const
     4028{
     4029    return (this == &h)
     4030        || (   fPAE                         == h.fPAE
     4031            && fAPIC                        == h.fAPIC
     4032            && fX2APIC                      == h.fX2APIC
     4033            && fHPETEnabled                 == h.fHPETEnabled
     4034            && enmLongMode                  == h.enmLongMode
     4035            && llCpuIdLeafs                 == h.llCpuIdLeafs
     4036            && fTripleFaultReset            == h.fTripleFaultReset
     4037            && fIBPBOnVMExit                == h.fIBPBOnVMExit
     4038            && fIBPBOnVMEntry               == h.fIBPBOnVMEntry
     4039            && fSpecCtrl                    == h.fSpecCtrl
     4040            && fSpecCtrlByHost              == h.fSpecCtrlByHost
     4041            && fL1DFlushOnSched             == h.fL1DFlushOnSched
     4042            && fL1DFlushOnVMEntry           == h.fL1DFlushOnVMEntry
     4043            && fMDSClearOnSched             == h.fMDSClearOnSched
     4044            && fMDSClearOnVMEntry           == h.fMDSClearOnVMEntry
     4045            && fHWVirtEx                    == h.fHWVirtEx
     4046            && fHWVirtExNestedPaging        == h.fHWVirtExNestedPaging
     4047            && fHWVirtExLargePages          == h.fHWVirtExLargePages
     4048            && fHWVirtExVPID                == h.fHWVirtExVPID
     4049            && fHWVirtExUX                  == h.fHWVirtExUX
     4050            && fHWVirtExForce               == h.fHWVirtExForce
     4051            && fHWVirtExUseNativeApi        == h.fHWVirtExUseNativeApi
     4052            && fHWVirtExVirtVmsaveVmload    == h.fHWVirtExVirtVmsaveVmload
     4053            && fNestedHWVirt                == h.fNestedHWVirt);
     4054}
     4055
     4056/**
     4057 * Constructor. Needs to set sane defaults which stand the test of time.
     4058 */
     4059Platform::Platform() :
     4060    architectureType(PlatformArchitecture_x86), /* We default to x86 here, as this is what we ever had so far. */
     4061    chipsetType(ChipsetType_PIIX3),
     4062    iommuType(IommuType_None),
     4063    fRTCUseUTC(false)
     4064{
     4065}
     4066
     4067/**
     4068 * Comparison operator. This gets called from MachineConfigFile::operator==,
     4069 * which in turn gets called from Platform::saveSettings to figure out whether
     4070 * machine settings have really changed and thus need to be written out to disk.
     4071 */
     4072bool Platform::operator==(const Platform& h) const
     4073{
     4074    bool fRc = (this == &h)
     4075            || (   architectureType == h.architectureType
     4076                && chipsetType      == h.chipsetType
     4077                && iommuType        == h.iommuType
     4078                && fRTCUseUTC       == h.fRTCUseUTC);
     4079    if (fRc)
     4080    {
     4081        switch (architectureType)
     4082        {
     4083            case PlatformArchitecture_x86:
     4084                return x86 == h.x86;
     4085#ifdef VBOX_WITH_VIRT_ARMV8
     4086            case PlatformArchitecture_ARM:
     4087                return arm == h.arm;
     4088#endif
     4089            default:
     4090                AssertFailedReturn(false);
     4091        }
     4092    }
     4093
     4094    return fRc;
     4095}
     4096
     4097/**
     4098 * Constructor. Needs to set sane defaults which stand the test of time.
     4099 */
     4100Hardware::Hardware() :
     4101    strVersion("1"),
    39324102    cCPUs(1),
    39334103    fCpuHotPlug(false),
    3934     fHPETEnabled(false),
    39354104    ulCpuExecutionCap(100),
    39364105    uCpuIdPortabilityLevel(0),
    39374106    strCpuProfile("host"),
    39384107    ulMemorySizeMB((uint32_t)-1),
    3939     firmwareType(FirmwareType_BIOS),
    39404108    pointingHIDType(PointingHIDType_PS2Mouse),
    39414109    keyboardHIDType(KeyboardHIDType_PS2Keyboard),
    3942     chipsetType(ChipsetType_PIIX3),
    3943     iommuType(IommuType_None),
    39444110    paravirtProvider(ParavirtProvider_Legacy), // default for old VMs, for new ones it's ParavirtProvider_Default
    39454111    strParavirtDebug(""),
     
    39514117    fPageFusionEnabled(false)
    39524118{
    3953     mapBootOrder[0] = DeviceType_Floppy;
     4119    mapBootOrder[0] = DeviceType_Floppy; /** @todo BUGBUG Handle ARM. */
    39544120    mapBootOrder[1] = DeviceType_DVD;
    39554121    mapBootOrder[2] = DeviceType_HardDisk;
    3956 
    3957     /* The default value for PAE depends on the host:
    3958      * - 64 bits host -> always true
    3959      * - 32 bits host -> true for Windows & Darwin (masked off if the host cpu doesn't support it anyway)
    3960      */
    3961 #if HC_ARCH_BITS == 64 || defined(RT_OS_WINDOWS) || defined(RT_OS_DARWIN)
    3962     fPAE = true;
    3963 #endif
    3964 
    3965     /* The default value of large page supports depends on the host:
    3966      * - 64 bits host -> true, unless it's Linux (pending further prediction work due to excessively expensive large page allocations)
    3967      * - 32 bits host -> false
    3968      */
    3969 #if HC_ARCH_BITS == 64 && !defined(RT_OS_LINUX)
    3970     fLargePages = true;
    3971 #else
    3972     /* Not supported on 32 bits hosts. */
    3973     fLargePages = false;
    3974 #endif
    39754122}
    39764123
     
    40304177        || (   strVersion                     == h.strVersion
    40314178            && uuid                           == h.uuid
    4032             && fHardwareVirt                  == h.fHardwareVirt
    4033             && fNestedPaging                  == h.fNestedPaging
    4034             && fLargePages                    == h.fLargePages
    4035             && fVPID                          == h.fVPID
    4036             && fUnrestrictedExecution         == h.fUnrestrictedExecution
    4037             && fHardwareVirtForce             == h.fHardwareVirtForce
    4038             && fUseNativeApi                  == h.fUseNativeApi
    4039             && fPAE                           == h.fPAE
    4040             && enmLongMode                    == h.enmLongMode
    4041             && fTripleFaultReset              == h.fTripleFaultReset
    4042             && fAPIC                          == h.fAPIC
    4043             && fX2APIC                        == h.fX2APIC
    4044             && fIBPBOnVMExit                  == h.fIBPBOnVMExit
    4045             && fIBPBOnVMEntry                 == h.fIBPBOnVMEntry
    4046             && fSpecCtrl                      == h.fSpecCtrl
    4047             && fSpecCtrlByHost                == h.fSpecCtrlByHost
    4048             && fL1DFlushOnSched               == h.fL1DFlushOnSched
    4049             && fL1DFlushOnVMEntry             == h.fL1DFlushOnVMEntry
    4050             && fMDSClearOnSched               == h.fMDSClearOnSched
    4051             && fMDSClearOnVMEntry             == h.fMDSClearOnVMEntry
    4052             && fNestedHWVirt                  == h.fNestedHWVirt
    4053             && fVirtVmsaveVmload              == h.fVirtVmsaveVmload
    40544179            && cCPUs                          == h.cCPUs
    40554180            && fCpuHotPlug                    == h.fCpuHotPlug
     
    40574182            && uCpuIdPortabilityLevel         == h.uCpuIdPortabilityLevel
    40584183            && strCpuProfile                  == h.strCpuProfile
    4059             && fHPETEnabled                   == h.fHPETEnabled
    40604184            && llCpus                         == h.llCpus
    4061             && llCpuIdLeafs                   == h.llCpuIdLeafs
    40624185            && ulMemorySizeMB                 == h.ulMemorySizeMB
    40634186            && mapBootOrder                   == h.mapBootOrder
    4064             && firmwareType                   == h.firmwareType
    40654187            && pointingHIDType                == h.pointingHIDType
    40664188            && keyboardHIDType                == h.keyboardHIDType
    4067             && chipsetType                    == h.chipsetType
    4068             && iommuType                      == h.iommuType
    40694189            && paravirtProvider               == h.paravirtProvider
    40704190            && strParavirtDebug               == h.strParavirtDebug
    40714191            && fEmulatedUSBCardReader         == h.fEmulatedUSBCardReader
    40724192            && vrdeSettings                   == h.vrdeSettings
    4073             && biosSettings                   == h.biosSettings
     4193            && platformSettings               == h.platformSettings
     4194            && firmwareSettings               == h.firmwareSettings
    40744195            && nvramSettings                  == h.nvramSettings
    40754196            && graphicsAdapter                == h.graphicsAdapter
     
    42864407    fTeleporterEnabled(false),
    42874408    uTeleporterPort(0),
    4288     fRTCUseUTC(false),
    42894409    enmVMPriority(VMProcPriority_Default)
    42904410{
     
    43114431            && strTeleporterAddress       == c.strTeleporterAddress
    43124432            && strTeleporterPassword      == c.strTeleporterPassword
    4313             && fRTCUseUTC                 == c.fRTCUseUTC
    43144433            && ovIcon                     == c.ovIcon
    43154434            && enmVMPriority              == c.enmVMPriority);
     
    44614580
    44624581/**
    4463  * Called from MachineConfigFile::readHardware() to read cpu information.
     4582 * Called from MachineConfigFile::readHardware() to read CPU information.
     4583 *
    44644584 * @param elmCpu
    44654585 * @param ll
     
    44824602
    44834603/**
    4484  * Called from MachineConfigFile::readHardware() to cpuid information.
     4604 * Called from MachineConfigFile::readPlatformX86() to read x86 CPUID information.
     4605 *
    44854606 * @param elmCpuid
    44864607 * @param ll
    44874608 */
    4488 void MachineConfigFile::readCpuIdTree(const xml::ElementNode &elmCpuid,
    4489                                       CpuIdLeafsList &ll)
     4609void MachineConfigFile::readCpuIdTreeX86(const xml::ElementNode &elmCpuid,
     4610                                         CpuIdLeafsX86List &ll)
    44904611{
    44914612    xml::NodesLoop nl1(elmCpuid, "CpuIdLeaf");
     
    44934614    while ((pelmCpuIdLeaf = nl1.forAllNodes()))
    44944615    {
    4495         CpuIdLeaf leaf;
     4616        CpuIdLeafX86 leaf;
    44964617
    44974618        if (!pelmCpuIdLeaf->getAttributeValue("id", leaf.idx))
    4498             throw ConfigFileError(this, pelmCpuIdLeaf, N_("Required CpuId/@id attribute is missing"));
     4619            throw ConfigFileError(this, pelmCpuIdLeaf, N_("Required CpuIdLeaf/@id attribute is missing"));
    44994620
    45004621        if (!pelmCpuIdLeaf->getAttributeValue("subleaf", leaf.idxSub))
     
    47894910        if (!pelmPort->getAttributeValue("enabled", port.fEnabled))
    47904911            throw ConfigFileError(this, pelmPort, N_("Required UART/Port/@enabled attribute is missing"));
    4791         if (!pelmPort->getAttributeValue("IOBase", port.ulIOBase))
    4792             throw ConfigFileError(this, pelmPort, N_("Required UART/Port/@IOBase attribute is missing"));
     4912        if (m->sv >= SettingsVersion_v1_20) /* IOBase was changed to IOAddress since settings v1.20. */
     4913        {
     4914            if (!pelmPort->getAttributeValue("IOAddress", port.ulIOAddress))
     4915               throw ConfigFileError(this, pelmPort, N_("Required UART/Port/@IOAddress attribute is missing"));
     4916        }
     4917        else /* Settings < v1.20. */
     4918        {
     4919            if (!pelmPort->getAttributeValue("IOBase", port.ulIOAddress))
     4920               throw ConfigFileError(this, pelmPort, N_("Required UART/Port/@IOBase attribute is missing"));
     4921        }
    47934922        if (!pelmPort->getAttributeValue("IRQ", port.ulIRQ))
    47944923            throw ConfigFileError(this, pelmPort, N_("Required UART/Port/@IRQ attribute is missing"));
     
    50595188
    50605189/**
     5190 * Reads the x86 CPUID tree.
     5191 *
     5192 * For settings >= v1.20 these were stored under the "Platform/x86/CPU" node.
     5193 * For settings <  v1.20 these were stored under the "Hardware/CPU" node.
     5194 *
     5195 * @param elmPlatformOrHardware     Platform or Hardware node to read from.
     5196 * @param platX86                   Where to store the platform settings.
     5197 */
     5198void MachineConfigFile::readPlatformCPUIDTreeX86(const xml::ElementNode &elmChild,
     5199                                                 PlatformX86 &platX86)
     5200{
     5201    const xml::ElementNode *pelmCPUChild;
     5202    if ((pelmCPUChild = elmChild.findChildElement("CpuIdTree")))
     5203        readCpuIdTreeX86(*pelmCPUChild, platX86.llCpuIdLeafs);
     5204}
     5205
     5206/**
     5207 * Reads the x86 platform settings.
     5208 *
     5209 * For settings >= v1.20 these were stored under the "Platform/x86" node.
     5210 * For settings <  v1.20 these were stored under the "Hardware" node.
     5211 *
     5212 * @param elmPlatformX86OrHardware  Platform/x86 or Hardware node to read from.
     5213 * @param platX86                   Where to store the x86 platform settings.
     5214 */
     5215void MachineConfigFile::readPlatformX86(const xml::ElementNode &elmPlatformX86OrHardware,
     5216                                        PlatformX86 &platX86)
     5217{
     5218    xml::NodesLoop nl1(elmPlatformX86OrHardware);
     5219
     5220    const xml::ElementNode *pelChild;
     5221    while ((pelChild = nl1.forAllNodes()))
     5222    {
     5223        if (pelChild->nameEquals("HPET"))
     5224        {
     5225            pelChild->getAttributeValue("enabled", platX86.fHPETEnabled);
     5226        }
     5227        else if (pelChild->nameEquals("CPU"))
     5228        {
     5229            const xml::ElementNode *pelmCPUChild;
     5230            if ((pelmCPUChild = pelChild->findChildElement("HardwareVirtEx")))
     5231                pelmCPUChild->getAttributeValue("enabled", platX86.fHWVirtEx);
     5232            if ((pelmCPUChild = pelChild->findChildElement("HardwareVirtExNestedPaging")))
     5233                pelmCPUChild->getAttributeValue("enabled", platX86.fHWVirtExNestedPaging);
     5234            if ((pelmCPUChild = pelChild->findChildElement("HardwareVirtExLargePages")))
     5235                pelmCPUChild->getAttributeValue("enabled", platX86.fHWVirtExLargePages);
     5236            if ((pelmCPUChild = pelChild->findChildElement("HardwareVirtExVPID")))
     5237                pelmCPUChild->getAttributeValue("enabled", platX86.fHWVirtExVPID);
     5238            if ((pelmCPUChild = pelChild->findChildElement("HardwareVirtExUX")))
     5239                pelmCPUChild->getAttributeValue("enabled", platX86.fHWVirtExUX);
     5240            if ((pelmCPUChild = pelChild->findChildElement("HardwareVirtForce")))
     5241                pelmCPUChild->getAttributeValue("enabled", platX86.fHWVirtExForce);
     5242            if ((pelmCPUChild = pelChild->findChildElement("HardwareVirtExUseNativeApi")))
     5243                pelmCPUChild->getAttributeValue("enabled", platX86.fHWVirtExUseNativeApi);
     5244            if ((pelmCPUChild = pelChild->findChildElement("HardwareVirtExVirtVmsaveVmload")))
     5245                pelmCPUChild->getAttributeValue("enabled", platX86.fHWVirtExVirtVmsaveVmload);
     5246
     5247            if (!(pelmCPUChild = pelChild->findChildElement("PAE")))
     5248            {
     5249                /* The default for pre 3.1 was false, so we must respect that. */
     5250                if (m->sv < SettingsVersion_v1_9)
     5251                    platX86.fPAE = false;
     5252            }
     5253            else
     5254                pelmCPUChild->getAttributeValue("enabled", platX86.fPAE);
     5255
     5256            bool fLongMode;
     5257            if (   (pelmCPUChild = pelChild->findChildElement("LongMode"))
     5258                && pelmCPUChild->getAttributeValue("enabled", fLongMode) )
     5259                platX86.enmLongMode = fLongMode ? PlatformX86::LongMode_Enabled : PlatformX86::LongMode_Disabled;
     5260            else
     5261                platX86.enmLongMode = PlatformX86::LongMode_Legacy;
     5262
     5263            if ((pelmCPUChild = pelChild->findChildElement("TripleFaultReset")))
     5264                pelmCPUChild->getAttributeValue("enabled", platX86.fTripleFaultReset);
     5265            if ((pelmCPUChild = pelChild->findChildElement("APIC")))
     5266                pelmCPUChild->getAttributeValue("enabled", platX86.fAPIC);
     5267            if ((pelmCPUChild = pelChild->findChildElement("X2APIC")))
     5268                pelmCPUChild->getAttributeValue("enabled", platX86.fX2APIC);
     5269
     5270            if ((pelmCPUChild = pelChild->findChildElement("IBPBOn")))
     5271            {
     5272                pelmCPUChild->getAttributeValue("vmexit", platX86.fIBPBOnVMExit);
     5273                pelmCPUChild->getAttributeValue("vmentry", platX86.fIBPBOnVMEntry);
     5274            }
     5275            if ((pelmCPUChild = pelChild->findChildElement("SpecCtrl")))
     5276                pelmCPUChild->getAttributeValue("enabled", platX86.fSpecCtrl);
     5277            if ((pelmCPUChild = pelChild->findChildElement("SpecCtrlByHost")))
     5278                pelmCPUChild->getAttributeValue("enabled", platX86.fSpecCtrlByHost);
     5279            if ((pelmCPUChild = pelChild->findChildElement("L1DFlushOn")))
     5280            {
     5281                pelmCPUChild->getAttributeValue("scheduling", platX86.fL1DFlushOnSched);
     5282                pelmCPUChild->getAttributeValue("vmentry", platX86.fL1DFlushOnVMEntry);
     5283            }
     5284            if ((pelmCPUChild = pelChild->findChildElement("MDSClearOn")))
     5285            {
     5286                pelmCPUChild->getAttributeValue("scheduling", platX86.fMDSClearOnSched);
     5287                pelmCPUChild->getAttributeValue("vmentry", platX86.fMDSClearOnVMEntry);
     5288            }
     5289            if ((pelmCPUChild = pelChild->findChildElement("NestedHWVirt")))
     5290                pelmCPUChild->getAttributeValue("enabled", platX86.fNestedHWVirt);
     5291
     5292            readPlatformCPUIDTreeX86(*pelChild, platX86);
     5293        }
     5294    }
     5295}
     5296
     5297/**
     5298 * Reads the platform settings.
     5299 *
     5300 * For settings >= v1.20 (>= VirtualBox 7.1) these were stored under the "Platform" node.
     5301 * For settings <  v1.20 (<= VirtualBox 7.0) these were stored under the "Hardware" node.
     5302 *
     5303 * @param elmPlatformOrHardware     Platform or Hardware node to read from.
     5304 * @param plat                      Where to store the platform settings.
     5305 */
     5306void MachineConfigFile::readPlatform(const xml::ElementNode &elmPlatformOrHardware,
     5307                                     Platform &plat)
     5308{
     5309    /*
     5310     * Platform-generic stuff.
     5311     */
     5312    xml::NodesLoop nl1(elmPlatformOrHardware);
     5313    const xml::ElementNode *pelmChild;
     5314    while ((pelmChild = nl1.forAllNodes()))
     5315    {
     5316        if (pelmChild->nameEquals("Chipset"))
     5317        {
     5318            Utf8Str strChipsetType;
     5319            if (pelmChild->getAttributeValue("type", strChipsetType))
     5320            {
     5321                if (strChipsetType == "PIIX3")
     5322                    plat.chipsetType = ChipsetType_PIIX3;
     5323                else if (strChipsetType == "ICH9")
     5324                    plat.chipsetType = ChipsetType_ICH9;
     5325                else if (strChipsetType == "ARMv8Virtual")
     5326                    plat.chipsetType = ChipsetType_ARMv8Virtual;
     5327                else
     5328                    throw ConfigFileError(this,
     5329                                          pelmChild,
     5330                                          N_("Invalid value '%s' in Chipset/@type"),
     5331                                          strChipsetType.c_str());
     5332            }
     5333        }
     5334        else if (pelmChild->nameEquals("Iommu"))
     5335        {
     5336            Utf8Str strIommuType;
     5337            if (pelmChild->getAttributeValue("type", strIommuType))
     5338            {
     5339                if (strIommuType == "None")
     5340                    plat.iommuType = IommuType_None;
     5341                else if (strIommuType == "Automatic")
     5342                    plat.iommuType = IommuType_Automatic;
     5343                else if (strIommuType == "AMD")
     5344                    plat.iommuType = IommuType_AMD;
     5345                else if (strIommuType == "Intel")
     5346                    plat.iommuType = IommuType_Intel;
     5347                else
     5348                    throw ConfigFileError(this,
     5349                                          pelmChild,
     5350                                          N_("Invalid value '%s' in Iommu/@type"),
     5351                                          strIommuType.c_str());
     5352            }
     5353        }
     5354        else if (pelmChild->nameEquals("RTC"))
     5355        {
     5356            Utf8Str strLocalOrUTC;
     5357            plat.fRTCUseUTC =    pelmChild->getAttributeValue("localOrUTC", strLocalOrUTC)
     5358                              && strLocalOrUTC == "UTC";
     5359        }
     5360    }
     5361
     5362    if (m->sv >= SettingsVersion_v1_20) /* Settings v1.20 introduced platform architecture support. */
     5363    {
     5364        Utf8Str strArch;
     5365        if (elmPlatformOrHardware.getAttributeValue("architecture", strArch))
     5366        {
     5367            if (strArch.equalsIgnoreCase("x86"))
     5368                plat.architectureType = PlatformArchitecture_x86;
     5369            else if (strArch.equalsIgnoreCase("ARM"))
     5370                plat.architectureType = PlatformArchitecture_ARM;
     5371            else
     5372                throw ConfigFileError(this,
     5373                                      &elmPlatformOrHardware,
     5374                                      N_("Platform/@architecture '%s' invalid"), strArch.c_str());
     5375        }
     5376        else
     5377            throw ConfigFileError(this, &elmPlatformOrHardware, N_("Platform/@architecture missing"));
     5378    }
     5379
     5380    /*
     5381     * Platform-specific stuff.
     5382     */
     5383    switch (plat.architectureType)
     5384    {
     5385        case PlatformArchitecture_x86:
     5386        {
     5387            const xml::ElementNode *pelmPlatformX86OrHardware;
     5388            if (m->sv >= SettingsVersion_v1_20) /* Settings v1.20 introduced platform support with a x86 sub node. */
     5389            {
     5390                pelmPlatformX86OrHardware = elmPlatformOrHardware.findChildElement("x86");
     5391                if (!pelmPlatformX86OrHardware)
     5392                    throw ConfigFileError(this, &elmPlatformOrHardware, N_("Required Platform/@x86 element is missing"));
     5393            }
     5394            else /* For settings < v1.20 we stored everyhing in the Hardware node. */
     5395                pelmPlatformX86OrHardware = &elmPlatformOrHardware;
     5396
     5397            readPlatformX86(*pelmPlatformX86OrHardware, plat.x86);
     5398            break;
     5399        }
     5400
     5401#ifdef VBOX_WITH_VIRT_ARMV8
     5402        case PlatformArchitecture_ARM:
     5403        {
     5404            /** @todo BUGBUG Implement loading ARM platform stuff here. */
     5405            break;
     5406        }
     5407#endif
     5408        default:
     5409            AssertFailed();
     5410            break;
     5411    }
     5412}
     5413
     5414/**
    50615415 * Reads in a \<Hardware\> block and stores it in the given structure. Used
    50625416 * both directly from readMachine and from readSnapshot, since snapshots
     
    51345488            }
    51355489
    5136             if ((pelmCPUChild = pelmHwChild->findChildElement("HardwareVirtEx")))
    5137             {
    5138                 pelmCPUChild->getAttributeValue("enabled", hw.fHardwareVirt);
    5139             }
    5140             if ((pelmCPUChild = pelmHwChild->findChildElement("HardwareVirtExNestedPaging")))
    5141                 pelmCPUChild->getAttributeValue("enabled", hw.fNestedPaging);
    5142             if ((pelmCPUChild = pelmHwChild->findChildElement("HardwareVirtExLargePages")))
    5143                 pelmCPUChild->getAttributeValue("enabled", hw.fLargePages);
    5144             if ((pelmCPUChild = pelmHwChild->findChildElement("HardwareVirtExVPID")))
    5145                 pelmCPUChild->getAttributeValue("enabled", hw.fVPID);
    5146             if ((pelmCPUChild = pelmHwChild->findChildElement("HardwareVirtExUX")))
    5147                 pelmCPUChild->getAttributeValue("enabled", hw.fUnrestrictedExecution);
    5148             if ((pelmCPUChild = pelmHwChild->findChildElement("HardwareVirtForce")))
    5149                 pelmCPUChild->getAttributeValue("enabled", hw.fHardwareVirtForce);
    5150             if ((pelmCPUChild = pelmHwChild->findChildElement("HardwareVirtExUseNativeApi")))
    5151                 pelmCPUChild->getAttributeValue("enabled", hw.fUseNativeApi);
    5152             if ((pelmCPUChild = pelmHwChild->findChildElement("HardwareVirtExVirtVmsaveVmload")))
    5153                 pelmCPUChild->getAttributeValue("enabled", hw.fVirtVmsaveVmload);
    5154 
    5155             if (!(pelmCPUChild = pelmHwChild->findChildElement("PAE")))
    5156             {
    5157                 /* The default for pre 3.1 was false, so we must respect that. */
    5158                 if (m->sv < SettingsVersion_v1_9)
    5159                     hw.fPAE = false;
    5160             }
    5161             else
    5162                 pelmCPUChild->getAttributeValue("enabled", hw.fPAE);
    5163 
    5164             bool fLongMode;
    5165             if (   (pelmCPUChild = pelmHwChild->findChildElement("LongMode"))
    5166                 && pelmCPUChild->getAttributeValue("enabled", fLongMode) )
    5167                 hw.enmLongMode = fLongMode ? Hardware::LongMode_Enabled : Hardware::LongMode_Disabled;
    5168             else
    5169                 hw.enmLongMode = Hardware::LongMode_Legacy;
    5170 
    51715490            if ((pelmCPUChild = pelmHwChild->findChildElement("SyntheticCpu")))
    51725491            {
     
    51775496            pelmHwChild->getAttributeValue("CpuIdPortabilityLevel", hw.uCpuIdPortabilityLevel);
    51785497            pelmHwChild->getAttributeValue("CpuProfile", hw.strCpuProfile);
    5179 
    5180             if ((pelmCPUChild = pelmHwChild->findChildElement("TripleFaultReset")))
    5181                 pelmCPUChild->getAttributeValue("enabled", hw.fTripleFaultReset);
    5182 
    5183             if ((pelmCPUChild = pelmHwChild->findChildElement("APIC")))
    5184                 pelmCPUChild->getAttributeValue("enabled", hw.fAPIC);
    5185             if ((pelmCPUChild = pelmHwChild->findChildElement("X2APIC")))
    5186                 pelmCPUChild->getAttributeValue("enabled", hw.fX2APIC);
    5187             if (hw.fX2APIC)
    5188                 hw.fAPIC = true;
    5189             pelmCPUChild = pelmHwChild->findChildElement("IBPBOn");
    5190             if (pelmCPUChild)
    5191             {
    5192                 pelmCPUChild->getAttributeValue("vmexit", hw.fIBPBOnVMExit);
    5193                 pelmCPUChild->getAttributeValue("vmentry", hw.fIBPBOnVMEntry);
    5194             }
    5195             pelmCPUChild = pelmHwChild->findChildElement("SpecCtrl");
    5196             if (pelmCPUChild)
    5197                 pelmCPUChild->getAttributeValue("enabled", hw.fSpecCtrl);
    5198             pelmCPUChild = pelmHwChild->findChildElement("SpecCtrlByHost");
    5199             if (pelmCPUChild)
    5200                 pelmCPUChild->getAttributeValue("enabled", hw.fSpecCtrlByHost);
    5201             pelmCPUChild = pelmHwChild->findChildElement("L1DFlushOn");
    5202             if (pelmCPUChild)
    5203             {
    5204                 pelmCPUChild->getAttributeValue("scheduling", hw.fL1DFlushOnSched);
    5205                 pelmCPUChild->getAttributeValue("vmentry", hw.fL1DFlushOnVMEntry);
    5206             }
    5207             pelmCPUChild = pelmHwChild->findChildElement("MDSClearOn");
    5208             if (pelmCPUChild)
    5209             {
    5210                 pelmCPUChild->getAttributeValue("scheduling", hw.fMDSClearOnSched);
    5211                 pelmCPUChild->getAttributeValue("vmentry", hw.fMDSClearOnVMEntry);
    5212             }
    5213             pelmCPUChild = pelmHwChild->findChildElement("NestedHWVirt");
    5214             if (pelmCPUChild)
    5215                 pelmCPUChild->getAttributeValue("enabled", hw.fNestedHWVirt);
    5216 
    5217             if ((pelmCPUChild = pelmHwChild->findChildElement("CpuIdTree")))
    5218                 readCpuIdTree(*pelmCPUChild, hw.llCpuIdLeafs);
    52195498        }
    52205499        else if (pelmHwChild->nameEquals("Memory"))
     
    52225501            pelmHwChild->getAttributeValue("RAMSize", hw.ulMemorySizeMB);
    52235502            pelmHwChild->getAttributeValue("PageFusion", hw.fPageFusionEnabled);
    5224         }
    5225         else if (pelmHwChild->nameEquals("Firmware"))
    5226         {
    5227             Utf8Str strFirmwareType;
    5228             if (pelmHwChild->getAttributeValue("type", strFirmwareType))
    5229             {
    5230                 if (    (strFirmwareType == "BIOS")
    5231                      || (strFirmwareType == "1")                // some trunk builds used the number here
    5232                    )
    5233                     hw.firmwareType = FirmwareType_BIOS;
    5234                 else if (    (strFirmwareType == "EFI")
    5235                           || (strFirmwareType == "2")           // some trunk builds used the number here
    5236                         )
    5237                     hw.firmwareType = FirmwareType_EFI;
    5238                 else if (    strFirmwareType == "EFI32")
    5239                     hw.firmwareType = FirmwareType_EFI32;
    5240                 else if (    strFirmwareType == "EFI64")
    5241                     hw.firmwareType = FirmwareType_EFI64;
    5242                 else if (    strFirmwareType == "EFIDUAL")
    5243                     hw.firmwareType = FirmwareType_EFIDUAL;
    5244                 else
    5245                     throw ConfigFileError(this,
    5246                                           pelmHwChild,
    5247                                           N_("Invalid value '%s' in Firmware/@type"),
    5248                                           strFirmwareType.c_str());
    5249             }
    52505503        }
    52515504        else if (pelmHwChild->nameEquals("HID"))
     
    52915544            }
    52925545        }
    5293         else if (pelmHwChild->nameEquals("Chipset"))
    5294         {
    5295             Utf8Str strChipsetType;
    5296             if (pelmHwChild->getAttributeValue("type", strChipsetType))
    5297             {
    5298                 if (strChipsetType == "PIIX3")
    5299                     hw.chipsetType = ChipsetType_PIIX3;
    5300                 else if (strChipsetType == "ICH9")
    5301                     hw.chipsetType = ChipsetType_ICH9;
    5302                 else
    5303                     throw ConfigFileError(this,
    5304                                           pelmHwChild,
    5305                                           N_("Invalid value '%s' in Chipset/@type"),
    5306                                           strChipsetType.c_str());
    5307             }
    5308         }
    5309         else if (pelmHwChild->nameEquals("Iommu"))
    5310         {
    5311             Utf8Str strIommuType;
    5312             if (pelmHwChild->getAttributeValue("type", strIommuType))
    5313             {
    5314                 if (strIommuType == "None")
    5315                     hw.iommuType = IommuType_None;
    5316                 else if (strIommuType == "Automatic")
    5317                     hw.iommuType = IommuType_Automatic;
    5318                 else if (strIommuType == "AMD")
    5319                     hw.iommuType = IommuType_AMD;
    5320                 else if (strIommuType == "Intel")
    5321                     hw.iommuType = IommuType_Intel;
    5322                 else
    5323                     throw ConfigFileError(this,
    5324                                           pelmHwChild,
    5325                                           N_("Invalid value '%s' in Iommu/@type"),
    5326                                           strIommuType.c_str());
    5327             }
    5328         }
    53295546        else if (pelmHwChild->nameEquals("Paravirt"))
    53305547        {
     
    53535570            pelmHwChild->getAttributeValue("debug", hw.strParavirtDebug);
    53545571        }
    5355         else if (pelmHwChild->nameEquals("HPET"))
    5356         {
    5357             pelmHwChild->getAttributeValue("enabled", hw.fHPETEnabled);
    5358         }
    53595572        else if (pelmHwChild->nameEquals("Boot"))
    53605573        {
     
    55035716            }
    55045717        }
    5505         else if (pelmHwChild->nameEquals("BIOS"))
    5506         {
    5507             const xml::ElementNode *pelmBIOSChild;
    5508             if ((pelmBIOSChild = pelmHwChild->findChildElement("ACPI")))
    5509                 pelmBIOSChild->getAttributeValue("enabled", hw.biosSettings.fACPIEnabled);
    5510             if ((pelmBIOSChild = pelmHwChild->findChildElement("IOAPIC")))
    5511                 pelmBIOSChild->getAttributeValue("enabled", hw.biosSettings.fIOAPICEnabled);
    5512             if ((pelmBIOSChild = pelmHwChild->findChildElement("APIC")))
    5513             {
    5514                 Utf8Str strAPIC;
    5515                 if (pelmBIOSChild->getAttributeValue("mode", strAPIC))
     5718        /* Since v1.20 (VBox 7.1) we store BIOS / UEFI settings inside the "Firmware" element.
     5719         * Older versions (< v1.20) stored those settings in a "BIOS" element (see down below) for that. See also down below. */
     5720        else if (   pelmHwChild->nameEquals("BIOS")
     5721                 || pelmHwChild->nameEquals("Firmware"))
     5722        {
     5723            /* For settings <  v1.20 we already has an element "Firmware", which only contained the firmware type. The rest lived in the "BIOS" element.
     5724             * For settings >= v1.20 we moved the "BIOS" element attributes also to "Firmware". */
     5725            if (pelmHwChild->nameEquals("Firmware"))
     5726            {
     5727                Utf8Str strFirmwareType;
     5728                if (pelmHwChild->getAttributeValue("type", strFirmwareType))
    55165729                {
    5517                     strAPIC.toUpper();
    5518                     if (strAPIC == "DISABLED")
    5519                         hw.biosSettings.apicMode = APICMode_Disabled;
    5520                     else if (strAPIC == "APIC")
    5521                         hw.biosSettings.apicMode = APICMode_APIC;
    5522                     else if (strAPIC == "X2APIC")
    5523                         hw.biosSettings.apicMode = APICMode_X2APIC;
     5730                    if (    (strFirmwareType == "BIOS")
     5731                         || (strFirmwareType == "1")                // some trunk builds used the number here
     5732                       )
     5733                        hw.firmwareSettings.firmwareType = FirmwareType_BIOS;
     5734                    else if (    (strFirmwareType == "EFI")
     5735                              || (strFirmwareType == "2")           // some trunk builds used the number here
     5736                            )
     5737                        hw.firmwareSettings.firmwareType = FirmwareType_EFI;
     5738                    else if (    strFirmwareType == "EFI32")
     5739                        hw.firmwareSettings.firmwareType = FirmwareType_EFI32;
     5740                    else if (    strFirmwareType == "EFI64")
     5741                        hw.firmwareSettings.firmwareType = FirmwareType_EFI64;
     5742                    else if (    strFirmwareType == "EFIDUAL")
     5743                        hw.firmwareSettings.firmwareType = FirmwareType_EFIDUAL;
    55245744                    else
    5525                         throw ConfigFileError(this, pelmBIOSChild, N_("Invalid value '%s' in APIC/@mode attribute"), strAPIC.c_str());
     5745                        throw ConfigFileError(this,
     5746                                              pelmHwChild,
     5747                                              N_("Invalid value '%s' in Firmware/@type"),
     5748                                              strFirmwareType.c_str());
    55265749                }
    55275750            }
    5528             if ((pelmBIOSChild = pelmHwChild->findChildElement("Logo")))
    5529             {
    5530                 pelmBIOSChild->getAttributeValue("fadeIn", hw.biosSettings.fLogoFadeIn);
    5531                 pelmBIOSChild->getAttributeValue("fadeOut", hw.biosSettings.fLogoFadeOut);
    5532                 pelmBIOSChild->getAttributeValue("displayTime", hw.biosSettings.ulLogoDisplayTime);
    5533                 pelmBIOSChild->getAttributeValue("imagePath", hw.biosSettings.strLogoImagePath);
    5534             }
    5535             if ((pelmBIOSChild = pelmHwChild->findChildElement("BootMenu")))
    5536             {
    5537                 Utf8Str strBootMenuMode;
    5538                 if (pelmBIOSChild->getAttributeValue("mode", strBootMenuMode))
     5751
     5752            /* Read the firmware settings either from the "Firmware" or "BIOS" elements, depending on the settings version. */
     5753            if (   (   pelmHwChild->nameEquals("Firmware")
     5754                    && m->sv >= SettingsVersion_v1_20)
     5755                || (   pelmHwChild->nameEquals("BIOS")
     5756                    && m->sv < SettingsVersion_v1_20)
     5757               )
     5758            {
     5759                const xml::ElementNode *pelmFirmwareOrBIOSChild;
     5760                if ((pelmFirmwareOrBIOSChild = pelmHwChild->findChildElement("ACPI")))
     5761                    pelmFirmwareOrBIOSChild->getAttributeValue("enabled", hw.firmwareSettings.fACPIEnabled);
     5762                if ((pelmFirmwareOrBIOSChild = pelmHwChild->findChildElement("IOAPIC")))
     5763                    pelmFirmwareOrBIOSChild->getAttributeValue("enabled", hw.firmwareSettings.fIOAPICEnabled);
     5764                if ((pelmFirmwareOrBIOSChild = pelmHwChild->findChildElement("APIC")))
    55395765                {
    5540                     // settings before 1.3 used lower case so make sure this is case-insensitive
    5541                     strBootMenuMode.toUpper();
    5542                     if (strBootMenuMode == "DISABLED")
    5543                         hw.biosSettings.biosBootMenuMode = BIOSBootMenuMode_Disabled;
    5544                     else if (strBootMenuMode == "MENUONLY")
    5545                         hw.biosSettings.biosBootMenuMode = BIOSBootMenuMode_MenuOnly;
    5546                     else if (strBootMenuMode == "MESSAGEANDMENU")
    5547                         hw.biosSettings.biosBootMenuMode = BIOSBootMenuMode_MessageAndMenu;
    5548                     else
    5549                         throw ConfigFileError(this, pelmBIOSChild, N_("Invalid value '%s' in BootMenu/@mode attribute"), strBootMenuMode.c_str());
     5766                    Utf8Str strAPIC;
     5767                    if (pelmFirmwareOrBIOSChild->getAttributeValue("mode", strAPIC))
     5768                    {
     5769                        strAPIC.toUpper();
     5770                        if (strAPIC == "DISABLED")
     5771                            hw.firmwareSettings.apicMode = APICMode_Disabled;
     5772                        else if (strAPIC == "APIC")
     5773                            hw.firmwareSettings.apicMode = APICMode_APIC;
     5774                        else if (strAPIC == "X2APIC")
     5775                            hw.firmwareSettings.apicMode = APICMode_X2APIC;
     5776                        else
     5777                            throw ConfigFileError(this, pelmFirmwareOrBIOSChild, N_("Invalid value '%s' in APIC/@mode attribute"), strAPIC.c_str());
     5778                    }
    55505779                }
    5551             }
    5552             if ((pelmBIOSChild = pelmHwChild->findChildElement("PXEDebug")))
    5553                 pelmBIOSChild->getAttributeValue("enabled", hw.biosSettings.fPXEDebugEnabled);
    5554             if ((pelmBIOSChild = pelmHwChild->findChildElement("TimeOffset")))
    5555                 pelmBIOSChild->getAttributeValue("value", hw.biosSettings.llTimeOffset);
    5556             if ((pelmBIOSChild = pelmHwChild->findChildElement("NVRAM")))
    5557             {
    5558                 pelmBIOSChild->getAttributeValue("path", hw.nvramSettings.strNvramPath);
    5559                 if (m->sv >= SettingsVersion_v1_19)
     5780                if ((pelmFirmwareOrBIOSChild = pelmHwChild->findChildElement("Logo")))
    55605781                {
    5561                     pelmBIOSChild->getAttributeValue("keyId", hw.nvramSettings.strKeyId);
    5562                     pelmBIOSChild->getAttributeValue("keyStore", hw.nvramSettings.strKeyStore);
     5782                    pelmFirmwareOrBIOSChild->getAttributeValue("fadeIn", hw.firmwareSettings.fLogoFadeIn);
     5783                    pelmFirmwareOrBIOSChild->getAttributeValue("fadeOut", hw.firmwareSettings.fLogoFadeOut);
     5784                    pelmFirmwareOrBIOSChild->getAttributeValue("displayTime", hw.firmwareSettings.ulLogoDisplayTime);
     5785                    pelmFirmwareOrBIOSChild->getAttributeValue("imagePath", hw.firmwareSettings.strLogoImagePath);
    55635786                }
    5564             }
    5565             if ((pelmBIOSChild = pelmHwChild->findChildElement("SmbiosUuidLittleEndian")))
    5566                 pelmBIOSChild->getAttributeValue("enabled", hw.biosSettings.fSmbiosUuidLittleEndian);
    5567             else
    5568                 hw.biosSettings.fSmbiosUuidLittleEndian = false; /* Default for existing VMs. */
    5569 
    5570             // legacy BIOS/IDEController (pre 1.7)
    5571             if (    (m->sv < SettingsVersion_v1_7)
    5572                  && (pelmBIOSChild = pelmHwChild->findChildElement("IDEController"))
    5573                )
    5574             {
    5575                 StorageController sctl;
    5576                 sctl.strName = "IDE Controller";
    5577                 sctl.storageBus = StorageBus_IDE;
    5578 
    5579                 Utf8Str strType;
    5580                 if (pelmBIOSChild->getAttributeValue("type", strType))
     5787                if ((pelmFirmwareOrBIOSChild = pelmHwChild->findChildElement("BootMenu")))
    55815788                {
    5582                     if (strType == "PIIX3")
    5583                         sctl.controllerType = StorageControllerType_PIIX3;
    5584                     else if (strType == "PIIX4")
    5585                         sctl.controllerType = StorageControllerType_PIIX4;
    5586                     else if (strType == "ICH6")
    5587                         sctl.controllerType = StorageControllerType_ICH6;
    5588                     else
    5589                         throw ConfigFileError(this, pelmBIOSChild, N_("Invalid value '%s' for IDEController/@type attribute"), strType.c_str());
     5789                    Utf8Str strBootMenuMode;
     5790                    if (pelmFirmwareOrBIOSChild->getAttributeValue("mode", strBootMenuMode))
     5791                    {
     5792                        // settings before 1.3 used lower case so make sure this is case-insensitive
     5793                        strBootMenuMode.toUpper();
     5794                        if (strBootMenuMode == "DISABLED")
     5795                            hw.firmwareSettings.enmBootMenuMode = FirmwareBootMenuMode_Disabled;
     5796                        else if (strBootMenuMode == "MENUONLY")
     5797                            hw.firmwareSettings.enmBootMenuMode = FirmwareBootMenuMode_MenuOnly;
     5798                        else if (strBootMenuMode == "MESSAGEANDMENU")
     5799                            hw.firmwareSettings.enmBootMenuMode = FirmwareBootMenuMode_MessageAndMenu;
     5800                        else
     5801                            throw ConfigFileError(this, pelmFirmwareOrBIOSChild, N_("Invalid value '%s' in BootMenu/@mode attribute"), strBootMenuMode.c_str());
     5802                    }
    55905803                }
    5591                 sctl.ulPortCount = 2;
    5592                 hw.storage.llStorageControllers.push_back(sctl);
     5804                if ((pelmFirmwareOrBIOSChild = pelmHwChild->findChildElement("PXEDebug")))
     5805                    pelmFirmwareOrBIOSChild->getAttributeValue("enabled", hw.firmwareSettings.fPXEDebugEnabled);
     5806                if ((pelmFirmwareOrBIOSChild = pelmHwChild->findChildElement("TimeOffset")))
     5807                    pelmFirmwareOrBIOSChild->getAttributeValue("value", hw.firmwareSettings.llTimeOffset);
     5808                if ((pelmFirmwareOrBIOSChild = pelmHwChild->findChildElement("NVRAM")))
     5809                {
     5810                    pelmFirmwareOrBIOSChild->getAttributeValue("path", hw.nvramSettings.strNvramPath);
     5811                    if (m->sv >= SettingsVersion_v1_19)
     5812                    {
     5813                        pelmFirmwareOrBIOSChild->getAttributeValue("keyId", hw.nvramSettings.strKeyId);
     5814                        pelmFirmwareOrBIOSChild->getAttributeValue("keyStore", hw.nvramSettings.strKeyStore);
     5815                    }
     5816                }
     5817                if ((pelmFirmwareOrBIOSChild = pelmHwChild->findChildElement("SmbiosUuidLittleEndian")))
     5818                    pelmFirmwareOrBIOSChild->getAttributeValue("enabled", hw.firmwareSettings.fSmbiosUuidLittleEndian);
     5819                else
     5820                    hw.firmwareSettings.fSmbiosUuidLittleEndian = false; /* Default for existing VMs. */
     5821
     5822                // legacy BIOS/IDEController (pre 1.7)
     5823                if (    (m->sv < SettingsVersion_v1_7)
     5824                     && (pelmFirmwareOrBIOSChild = pelmHwChild->findChildElement("IDEController"))
     5825                   )
     5826                {
     5827                    StorageController sctl;
     5828                    sctl.strName = "IDE Controller";
     5829                    sctl.storageBus = StorageBus_IDE;
     5830
     5831                    Utf8Str strType;
     5832                    if (pelmFirmwareOrBIOSChild->getAttributeValue("type", strType))
     5833                    {
     5834                        if (strType == "PIIX3")
     5835                            sctl.controllerType = StorageControllerType_PIIX3;
     5836                        else if (strType == "PIIX4")
     5837                            sctl.controllerType = StorageControllerType_PIIX4;
     5838                        else if (strType == "ICH6")
     5839                            sctl.controllerType = StorageControllerType_ICH6;
     5840                        else
     5841                            throw ConfigFileError(this, pelmFirmwareOrBIOSChild, N_("Invalid value '%s' for IDEController/@type attribute"), strType.c_str());
     5842                    }
     5843                    sctl.ulPortCount = 2;
     5844                    hw.storage.llStorageControllers.push_back(sctl);
     5845                }
    55935846            }
    55945847        }
     
    57015954        else if (pelmHwChild->nameEquals("Network"))
    57025955            readNetworkAdapters(*pelmHwChild, hw.llNetworkAdapters);
    5703         else if (pelmHwChild->nameEquals("RTC"))
    5704         {
    5705             Utf8Str strLocalOrUTC;
    5706             machineUserData.fRTCUseUTC = pelmHwChild->getAttributeValue("localOrUTC", strLocalOrUTC)
    5707                                       && strLocalOrUTC == "UTC";
    5708         }
    57095956        else if (    pelmHwChild->nameEquals("UART")
    57105957                  || pelmHwChild->nameEquals("Uart")      // used before 1.3
     
    58646111            readStorageControllers(*pelmHwChild, hw.storage);
    58656112    }
     6113
     6114    /* We read the platform settings here, which were part of the "Hardware" node for settings < 1.2.0.
     6115     * For newer settings (>= v1.20) we read the platform settings outside readHardware(). */
     6116    if (m->sv < SettingsVersion_v1_20)
     6117        readPlatform(elmHardware, hw.platformSettings);
    58666118
    58676119    if (hw.ulMemorySizeMB == (uint32_t)-1)
     
    64826734
    64836735        pElement->getAttributeValuePath("stateFile", pSnap->strStateFile);      // online snapshots only
     6736
     6737        /* We read the platform settings here for newer settings (>= v1.20).
     6738         * For older settings (< v1.20) we read the platform settings in readHardware(). */
     6739        if (m->sv >= SettingsVersion_v1_20)
     6740        {
     6741            const xml::ElementNode *pelmPlatform;
     6742            if (!(pelmPlatform = pElement->findChildElement("Platform")))
     6743                throw ConfigFileError(this, pElement, N_("Required Snapshot/@Platform element is missing"));
     6744            readPlatform(*pelmPlatform, pSnap->hardware.platformSettings);
     6745        }
    64846746
    64856747        // parse Hardware before the other elements because other things depend on it
     
    66766938        parseBase64(machineUserData.ovIcon, str, &elmMachine);
    66776939
     6940        /* We read the platform settings here for newer settings (>= v1.20).
     6941         * For older settings (< v1.20) we read the platform settings in readHardware(). */
     6942        if (m->sv >= SettingsVersion_v1_20)
     6943        {
     6944            const xml::ElementNode *pelmPlatform;
     6945            if (!(pelmPlatform = elmMachine.findChildElement("Platform")))
     6946                throw ConfigFileError(this, &elmMachine, N_("Required Machine/@Platform element is missing"));
     6947            readPlatform(*pelmPlatform, hardwareMachine.platformSettings);
     6948        }
     6949
    66786950        // parse Hardware before the other elements because other things depend on it
    66796951        const xml::ElementNode *pelmHardware;
    66806952        if (!(pelmHardware = elmMachine.findChildElement("Hardware")))
    6681             throw ConfigFileError(this, &elmMachine, N_("Required Machine/Hardware element is missing"));
     6953            throw ConfigFileError(this, &elmMachine, N_("Required Machine/@Hardware element is missing"));
    66826954        readHardware(*pelmHardware, hardwareMachine);
    66836955
     
    68227094
    68237095/**
    6824  * Creates a \<Hardware\> node under elmParent and then writes out the XML
     7096 * Writes x86-specific platform settings out to the XML.
     7097 *
     7098 * For settings >= v1.20 this creates a \<x86\> node under elmParent.
    68257099 * keys under that. Called for both the \<Machine\> node and for snapshots.
    6826  * @param elmParent
    6827  * @param hw
    6828  * @param fl
    6829  * @param pllElementsWithUuidAttributes
    6830  */
    6831 void MachineConfigFile::buildHardwareXML(xml::ElementNode &elmParent,
    6832                                          const Hardware &hw,
    6833                                          uint32_t fl,
    6834                                          std::list<xml::ElementNode*> *pllElementsWithUuidAttributes)
    6835 {
    6836     xml::ElementNode *pelmHardware = elmParent.createChild("Hardware");
    6837 
    6838     if (   m->sv >= SettingsVersion_v1_4
    6839         && (m->sv < SettingsVersion_v1_7 ? hw.strVersion != "1" : hw.strVersion != "2"))
    6840         pelmHardware->setAttribute("version", hw.strVersion);
    6841 
    6842     if ((m->sv >= SettingsVersion_v1_9)
    6843          && !hw.uuid.isZero()
    6844          && hw.uuid.isValid()
    6845        )
    6846         pelmHardware->setAttribute("uuid", hw.uuid.toStringCurly());
    6847 
    6848     xml::ElementNode *pelmCPU      = pelmHardware->createChild("CPU");
    6849 
    6850     if (!hw.fHardwareVirt)
    6851         pelmCPU->createChild("HardwareVirtEx")->setAttribute("enabled", hw.fHardwareVirt);
    6852     if (!hw.fNestedPaging)
    6853         pelmCPU->createChild("HardwareVirtExNestedPaging")->setAttribute("enabled", hw.fNestedPaging);
    6854     if (!hw.fVPID)
    6855         pelmCPU->createChild("HardwareVirtExVPID")->setAttribute("enabled", hw.fVPID);
    6856     if (!hw.fUnrestrictedExecution)
    6857         pelmCPU->createChild("HardwareVirtExUX")->setAttribute("enabled", hw.fUnrestrictedExecution);
     7100 *
     7101 * @param elmParent                         Parent element.
     7102 *                                          For settings >= v1.20 this is the \<Platform\> element.
     7103 *                                          For settings  < v1.20 this is the \<Hardware\> element.
     7104 * @param elmCPU                            CPU element platform-generic settings.
     7105 *                                          For settings >= v1.20 this is the \<Platform/CPU\> element.
     7106 *                                          For settings  < v1.20 this is the \<Hardware/CPU\> element.
     7107 * @param platX86                           x86-specific platform settings to use for building the XML.
     7108 */
     7109void MachineConfigFile::buildPlatformX86XML(xml::ElementNode &elmParent, xml::ElementNode &elmCPU, const PlatformX86 &platX86)
     7110{
     7111    xml::ElementNode *pelmX86Root;
     7112    xml::ElementNode *pelmX86CPU;
     7113    if (m->sv >= SettingsVersion_v1_20)
     7114    {
     7115        pelmX86Root = elmParent.createChild("x86");
     7116        pelmX86CPU  = pelmX86Root->createChild("CPU");
     7117
     7118    }
     7119    else
     7120    {
     7121        pelmX86Root = &elmParent; /* Before settings v1.20 the x86-specifics were sprinkled across the Machine element. */
     7122        pelmX86CPU  = &elmCPU;    /* Use the generic CPU element, even for x86-specific things. */
     7123    }
     7124
     7125    if (   (m->sv >= SettingsVersion_v1_10)
     7126        && platX86.fHPETEnabled)
     7127    {
     7128        xml::ElementNode *pelmHPET = pelmX86Root->createChild("HPET");
     7129        pelmHPET->setAttribute("enabled", platX86.fHPETEnabled);
     7130    }
     7131
     7132    // HardwareVirtExLargePages has too crazy default handling, must always save this setting.
     7133    pelmX86CPU->createChild("HardwareVirtExLargePages")->setAttribute("enabled", platX86.fHWVirtExLargePages);
     7134
     7135    if (m->sv >= SettingsVersion_v1_9)
     7136    {
     7137        if (platX86.fHWVirtExForce)
     7138            pelmX86CPU->createChild("HardwareVirtForce")->setAttribute("enabled", platX86.fHWVirtExForce);
     7139    }
     7140
     7141    if (m->sv >= SettingsVersion_v1_9 && platX86.fHWVirtExUseNativeApi)
     7142        pelmX86CPU->createChild("HardwareVirtExUseNativeApi")->setAttribute("enabled", platX86.fHWVirtExUseNativeApi);
     7143
     7144    if (!platX86.fHWVirtEx)
     7145        pelmX86CPU->createChild("HardwareVirtEx")->setAttribute("enabled", platX86.fHWVirtEx);
     7146    if (!platX86.fHWVirtExNestedPaging)
     7147        pelmX86CPU->createChild("HardwareVirtExNestedPaging")->setAttribute("enabled", platX86.fHWVirtExNestedPaging);
     7148    if (!platX86.fHWVirtExVPID)
     7149        pelmX86CPU->createChild("HardwareVirtExVPID")->setAttribute("enabled", platX86.fHWVirtExVPID);
     7150    if (!platX86.fHWVirtExUX)
     7151        pelmX86CPU->createChild("HardwareVirtExUX")->setAttribute("enabled", platX86.fHWVirtExUX);
    68587152    // PAE has too crazy default handling, must always save this setting.
    6859     pelmCPU->createChild("PAE")->setAttribute("enabled", hw.fPAE);
     7153    pelmX86CPU->createChild("PAE")->setAttribute("enabled", platX86.fPAE);
    68607154    if (m->sv >= SettingsVersion_v1_16)
    68617155    {
    6862         if (hw.fIBPBOnVMEntry || hw.fIBPBOnVMExit)
    6863         {
    6864             xml::ElementNode *pelmChild = pelmCPU->createChild("IBPBOn");
    6865             if (hw.fIBPBOnVMExit)
    6866                 pelmChild->setAttribute("vmexit", hw.fIBPBOnVMExit);
    6867             if (hw.fIBPBOnVMEntry)
    6868                 pelmChild->setAttribute("vmentry", hw.fIBPBOnVMEntry);
    6869         }
    6870         if (hw.fSpecCtrl)
    6871             pelmCPU->createChild("SpecCtrl")->setAttribute("enabled", hw.fSpecCtrl);
    6872         if (hw.fSpecCtrlByHost)
    6873             pelmCPU->createChild("SpecCtrlByHost")->setAttribute("enabled", hw.fSpecCtrlByHost);
    6874         if (!hw.fL1DFlushOnSched || hw.fL1DFlushOnVMEntry)
    6875         {
    6876             xml::ElementNode *pelmChild = pelmCPU->createChild("L1DFlushOn");
    6877             if (!hw.fL1DFlushOnSched)
    6878                 pelmChild->setAttribute("scheduling", hw.fL1DFlushOnSched);
    6879             if (hw.fL1DFlushOnVMEntry)
    6880                 pelmChild->setAttribute("vmentry", hw.fL1DFlushOnVMEntry);
    6881         }
    6882         if (!hw.fMDSClearOnSched || hw.fMDSClearOnVMEntry)
    6883         {
    6884             xml::ElementNode *pelmChild = pelmCPU->createChild("MDSClearOn");
    6885             if (!hw.fMDSClearOnSched)
    6886                 pelmChild->setAttribute("scheduling", hw.fMDSClearOnSched);
    6887             if (hw.fMDSClearOnVMEntry)
    6888                 pelmChild->setAttribute("vmentry", hw.fMDSClearOnVMEntry);
    6889         }
    6890     }
    6891     if (m->sv >= SettingsVersion_v1_17 && hw.fNestedHWVirt)
    6892         pelmCPU->createChild("NestedHWVirt")->setAttribute("enabled", hw.fNestedHWVirt);
    6893 
    6894     if (m->sv >= SettingsVersion_v1_18 && !hw.fVirtVmsaveVmload)
    6895         pelmCPU->createChild("HardwareVirtExVirtVmsaveVmload")->setAttribute("enabled", hw.fVirtVmsaveVmload);
    6896 
    6897     if (m->sv >= SettingsVersion_v1_14 && hw.enmLongMode != Hardware::LongMode_Legacy)
     7156        if (platX86.fIBPBOnVMEntry || platX86.fIBPBOnVMExit)
     7157        {
     7158            xml::ElementNode *pelmChild = pelmX86CPU->createChild("IBPBOn");
     7159            if (platX86.fIBPBOnVMExit)
     7160                pelmChild->setAttribute("vmexit", platX86.fIBPBOnVMExit);
     7161            if (platX86.fIBPBOnVMEntry)
     7162                pelmChild->setAttribute("vmentry", platX86.fIBPBOnVMEntry);
     7163        }
     7164        if (platX86.fSpecCtrl)
     7165            pelmX86CPU->createChild("SpecCtrl")->setAttribute("enabled", platX86.fSpecCtrl);
     7166        if (platX86.fSpecCtrlByHost)
     7167            pelmX86CPU->createChild("SpecCtrlByHost")->setAttribute("enabled", platX86.fSpecCtrlByHost);
     7168        if (!platX86.fL1DFlushOnSched || platX86.fL1DFlushOnVMEntry)
     7169        {
     7170            xml::ElementNode *pelmChild = pelmX86CPU->createChild("L1DFlushOn");
     7171            if (!platX86.fL1DFlushOnSched)
     7172                pelmChild->setAttribute("scheduling", platX86.fL1DFlushOnSched);
     7173            if (platX86.fL1DFlushOnVMEntry)
     7174                pelmChild->setAttribute("vmentry", platX86.fL1DFlushOnVMEntry);
     7175        }
     7176        if (!platX86.fMDSClearOnSched || platX86.fMDSClearOnVMEntry)
     7177        {
     7178            xml::ElementNode *pelmChild = pelmX86CPU->createChild("MDSClearOn");
     7179            if (!platX86.fMDSClearOnSched)
     7180                pelmChild->setAttribute("scheduling", platX86.fMDSClearOnSched);
     7181            if (platX86.fMDSClearOnVMEntry)
     7182                pelmChild->setAttribute("vmentry", platX86.fMDSClearOnVMEntry);
     7183        }
     7184    }
     7185    if (m->sv >= SettingsVersion_v1_17 && platX86.fNestedHWVirt)
     7186        pelmX86CPU->createChild("NestedHWVirt")->setAttribute("enabled", platX86.fNestedHWVirt);
     7187
     7188    if (m->sv >= SettingsVersion_v1_18 && !platX86.fHWVirtExVirtVmsaveVmload)
     7189        pelmX86CPU->createChild("HardwareVirtExVirtVmsaveVmload")->setAttribute("enabled", platX86.fHWVirtExVirtVmsaveVmload);
     7190
     7191    if (m->sv >= SettingsVersion_v1_14 && platX86.enmLongMode != PlatformX86::LongMode_Legacy)
    68987192    {
    68997193        // LongMode has too crazy default handling, must always save this setting.
    6900         pelmCPU->createChild("LongMode")->setAttribute("enabled", hw.enmLongMode == Hardware::LongMode_Enabled);
    6901     }
    6902 
    6903     if (hw.fTripleFaultReset)
    6904         pelmCPU->createChild("TripleFaultReset")->setAttribute("enabled", hw.fTripleFaultReset);
     7194        pelmX86CPU->createChild("LongMode")->setAttribute("enabled", platX86.enmLongMode == PlatformX86::LongMode_Enabled);
     7195    }
     7196
     7197    if (platX86.fTripleFaultReset)
     7198        pelmX86CPU->createChild("TripleFaultReset")->setAttribute("enabled", platX86.fTripleFaultReset);
    69057199    if (m->sv >= SettingsVersion_v1_14)
    69067200    {
    6907         if (hw.fX2APIC)
    6908             pelmCPU->createChild("X2APIC")->setAttribute("enabled", hw.fX2APIC);
    6909         else if (!hw.fAPIC)
    6910             pelmCPU->createChild("APIC")->setAttribute("enabled", hw.fAPIC);
    6911     }
     7201        if (platX86.fX2APIC)
     7202            pelmX86CPU->createChild("X2APIC")->setAttribute("enabled", platX86.fX2APIC);
     7203        else if (!platX86.fAPIC)
     7204            pelmX86CPU->createChild("APIC")->setAttribute("enabled", platX86.fAPIC);
     7205    }
     7206
     7207    xml::ElementNode *pelmCpuIdTree = NULL;
     7208    for (CpuIdLeafsX86List::const_iterator it  = platX86.llCpuIdLeafs.begin();
     7209                                           it != platX86.llCpuIdLeafs.end();
     7210         ++it)
     7211    {
     7212        const CpuIdLeafX86 &leaf = *it;
     7213
     7214        if (pelmCpuIdTree == NULL)
     7215             pelmCpuIdTree = pelmX86CPU->createChild("CpuIdTree");
     7216
     7217        xml::ElementNode *pelmCpuIdLeaf = pelmCpuIdTree->createChild("CpuIdLeaf");
     7218        pelmCpuIdLeaf->setAttribute("id",  leaf.idx);
     7219        if (leaf.idxSub != 0)
     7220            pelmCpuIdLeaf->setAttribute("subleaf",  leaf.idxSub);
     7221        pelmCpuIdLeaf->setAttribute("eax", leaf.uEax);
     7222        pelmCpuIdLeaf->setAttribute("ebx", leaf.uEbx);
     7223        pelmCpuIdLeaf->setAttribute("ecx", leaf.uEcx);
     7224        pelmCpuIdLeaf->setAttribute("edx", leaf.uEdx);
     7225    }
     7226}
     7227
     7228/**
     7229 * Stores platform-generic and platform-specific data and then writes out the XML.
     7230 *
     7231 * For settings >= v.120 this creates a \<Platform\> node under elmParent.
     7232 * For settings  < v.120 this stores the data directly under elmParent.
     7233 *
     7234 * Called for both the \<Machine\> node and for snapshots.
     7235 *
     7236 * @param elmParent                         Parent element.
     7237 * @param hw                                Hardware settings to use for building the XML.
     7238 *                                          For CPU stuff we don't have in Platform (yet).
     7239 * @param plat                              Platform settings to use for building the XML.
     7240 */
     7241void MachineConfigFile::buildPlatformXML(xml::ElementNode &elmParent,
     7242                                         const Hardware &hw, const Platform &plat)
     7243{
     7244    xml::ElementNode *pelmPlatformOrHardware;
     7245    if (m->sv >= SettingsVersion_v1_20) /* Since settings v1.20 we have a dedicated Platform element. */
     7246    {
     7247        pelmPlatformOrHardware = elmParent.createChild("Platform");
     7248
     7249        switch (plat.architectureType)
     7250        {
     7251            case PlatformArchitecture_x86:
     7252                pelmPlatformOrHardware->setAttribute("architecture", "x86");
     7253                break;
     7254
     7255            case PlatformArchitecture_ARM:
     7256                pelmPlatformOrHardware->setAttribute("architecture", "ARM");
     7257                break;
     7258
     7259            default:
     7260                AssertFailed();
     7261                break;
     7262        }
     7263    }
     7264    else /* For settings < v1.20 we use the parent element (which is Hardware). */
     7265        pelmPlatformOrHardware = &elmParent;
     7266
     7267    if (   m->sv >= SettingsVersion_v1_10
     7268        && plat.fRTCUseUTC)
     7269    {
     7270        xml::ElementNode *pelmRTC = pelmPlatformOrHardware->createChild("RTC");
     7271        pelmRTC->setAttribute("localOrUTC", plat.fRTCUseUTC ? "UTC" : "local");
     7272    }
     7273
     7274    if (m->sv >= SettingsVersion_v1_11)
     7275    {
     7276        if (plat.chipsetType != ChipsetType_PIIX3)
     7277        {
     7278            xml::ElementNode *pelmChipset = pelmPlatformOrHardware->createChild("Chipset");
     7279            const char *pcszChipset;
     7280
     7281            switch (plat.chipsetType)
     7282            {
     7283                case ChipsetType_PIIX3:             pcszChipset = "PIIX3";        break;
     7284                case ChipsetType_ICH9:              pcszChipset = "ICH9";         break;
     7285                case ChipsetType_ARMv8Virtual:      pcszChipset = "ARMv8Virtual"; break;
     7286                default:            Assert(false);  pcszChipset = "PIIX3";        break;
     7287            }
     7288            pelmChipset->setAttribute("type", pcszChipset);
     7289        }
     7290    }
     7291
     7292    if (   m->sv >= SettingsVersion_v1_19
     7293        && plat.iommuType != IommuType_None)
     7294    {
     7295        const char *pcszIommuType;
     7296        switch (plat.iommuType)
     7297        {
     7298            case IommuType_None:         pcszIommuType = "None";        break;
     7299            case IommuType_Automatic:    pcszIommuType = "Automatic";   break;
     7300            case IommuType_AMD:          pcszIommuType = "AMD";         break;
     7301            case IommuType_Intel:        pcszIommuType = "Intel";       break;
     7302            default:     Assert(false);  pcszIommuType = "None";        break;
     7303        }
     7304
     7305        xml::ElementNode *pelmIommu = pelmPlatformOrHardware->createChild("Iommu");
     7306        pelmIommu->setAttribute("type", pcszIommuType);
     7307    }
     7308
     7309    xml::ElementNode *pelmCPU = pelmPlatformOrHardware->createChild("CPU");
     7310
    69127311    if (hw.cCPUs > 1)
    69137312        pelmCPU->setAttribute("count", hw.cCPUs);
     
    69197318        pelmCPU->setAttribute("CpuProfile", hw.strCpuProfile);
    69207319
    6921     // HardwareVirtExLargePages has too crazy default handling, must always save this setting.
    6922     pelmCPU->createChild("HardwareVirtExLargePages")->setAttribute("enabled", hw.fLargePages);
    6923 
    6924     if (m->sv >= SettingsVersion_v1_9)
    6925     {
    6926         if (hw.fHardwareVirtForce)
    6927             pelmCPU->createChild("HardwareVirtForce")->setAttribute("enabled", hw.fHardwareVirtForce);
    6928     }
    6929 
    6930     if (m->sv >= SettingsVersion_v1_9 && hw.fUseNativeApi)
    6931         pelmCPU->createChild("HardwareVirtExUseNativeApi")->setAttribute("enabled", hw.fUseNativeApi);
    6932 
    69337320    if (m->sv >= SettingsVersion_v1_10)
    69347321    {
     
    69517338    }
    69527339
    6953     xml::ElementNode *pelmCpuIdTree = NULL;
    6954     for (CpuIdLeafsList::const_iterator it = hw.llCpuIdLeafs.begin();
    6955          it != hw.llCpuIdLeafs.end();
    6956          ++it)
    6957     {
    6958         const CpuIdLeaf &leaf = *it;
    6959 
    6960         if (pelmCpuIdTree == NULL)
    6961              pelmCpuIdTree = pelmCPU->createChild("CpuIdTree");
    6962 
    6963         xml::ElementNode *pelmCpuIdLeaf = pelmCpuIdTree->createChild("CpuIdLeaf");
    6964         pelmCpuIdLeaf->setAttribute("id",  leaf.idx);
    6965         if (leaf.idxSub != 0)
    6966             pelmCpuIdLeaf->setAttribute("subleaf",  leaf.idxSub);
    6967         pelmCpuIdLeaf->setAttribute("eax", leaf.uEax);
    6968         pelmCpuIdLeaf->setAttribute("ebx", leaf.uEbx);
    6969         pelmCpuIdLeaf->setAttribute("ecx", leaf.uEcx);
    6970         pelmCpuIdLeaf->setAttribute("edx", leaf.uEdx);
    6971     }
     7340    /* We only store specific stuff for the selected platform. */
     7341    if (plat.architectureType == PlatformArchitecture_x86)
     7342        buildPlatformX86XML(*pelmPlatformOrHardware, *pelmCPU, plat.x86);
     7343    /** @todo BUGBUG Put ARM stuff here. */
     7344}
     7345
     7346/**
     7347 * Creates a \<Hardware\> node under elmParent and then writes out the XML
     7348 * keys under that. Called for both the \<Machine\> node and for snapshots.
     7349 *
     7350 * @param elmParent                         Parent element.
     7351 * @param hw                                Hardware settings to use for building the XML.
     7352 * @param fl                                Flags.
     7353 * @param pllElementsWithUuidAttributes     Document me.
     7354 */
     7355void MachineConfigFile::buildHardwareXML(xml::ElementNode &elmParent,
     7356                                         const Hardware &hw,
     7357                                         uint32_t fl,
     7358                                         std::list<xml::ElementNode*> *pllElementsWithUuidAttributes)
     7359{
     7360    xml::ElementNode *pelmHardware = elmParent.createChild("Hardware");
     7361
     7362    if (   m->sv >= SettingsVersion_v1_4
     7363        && (m->sv < SettingsVersion_v1_7 ? hw.strVersion != "1" : hw.strVersion != "2"))
     7364        pelmHardware->setAttribute("version", hw.strVersion);
     7365
     7366    if ((m->sv >= SettingsVersion_v1_9)
     7367         && !hw.uuid.isZero()
     7368         && hw.uuid.isValid()
     7369       )
     7370        pelmHardware->setAttribute("uuid", hw.uuid.toStringCurly());
    69727371
    69737372    xml::ElementNode *pelmMemory = pelmHardware->createChild("Memory");
     
    69777376        if (hw.fPageFusionEnabled)
    69787377            pelmMemory->setAttribute("PageFusion", hw.fPageFusionEnabled);
    6979     }
    6980 
    6981     if (    (m->sv >= SettingsVersion_v1_9)
    6982          && (hw.firmwareType >= FirmwareType_EFI)
    6983        )
    6984     {
    6985         xml::ElementNode *pelmFirmware = pelmHardware->createChild("Firmware");
    6986         const char *pcszFirmware;
    6987 
    6988         switch (hw.firmwareType)
    6989         {
    6990             case FirmwareType_EFI:      pcszFirmware = "EFI";     break;
    6991             case FirmwareType_EFI32:    pcszFirmware = "EFI32";   break;
    6992             case FirmwareType_EFI64:    pcszFirmware = "EFI64";   break;
    6993             case FirmwareType_EFIDUAL:  pcszFirmware = "EFIDUAL"; break;
    6994             default:                    pcszFirmware = "None";    break;
    6995         }
    6996         pelmFirmware->setAttribute("type", pcszFirmware);
    69977378    }
    69987379
     
    70347415    }
    70357416
    7036     if (    (m->sv >= SettingsVersion_v1_10)
    7037         &&  hw.fHPETEnabled
    7038        )
    7039     {
    7040         xml::ElementNode *pelmHPET = pelmHardware->createChild("HPET");
    7041         pelmHPET->setAttribute("enabled", hw.fHPETEnabled);
    7042     }
    7043 
    7044     if (    (m->sv >= SettingsVersion_v1_11)
    7045        )
    7046     {
    7047         if (hw.chipsetType != ChipsetType_PIIX3)
    7048         {
    7049             xml::ElementNode *pelmChipset = pelmHardware->createChild("Chipset");
    7050             const char *pcszChipset;
    7051 
    7052             switch (hw.chipsetType)
    7053             {
    7054                 case ChipsetType_PIIX3:             pcszChipset = "PIIX3";   break;
    7055                 case ChipsetType_ICH9:              pcszChipset = "ICH9";    break;
    7056                 default:            Assert(false);  pcszChipset = "PIIX3";   break;
    7057             }
    7058             pelmChipset->setAttribute("type", pcszChipset);
    7059         }
    7060     }
     7417
    70617418
    70627419    if (    (m->sv >= SettingsVersion_v1_15)
     
    70827439            && hw.strParavirtDebug.isNotEmpty())
    70837440            pelmParavirt->setAttribute("debug", hw.strParavirtDebug);
    7084     }
    7085 
    7086     if (   m->sv >= SettingsVersion_v1_19
    7087         && hw.iommuType != IommuType_None)
    7088     {
    7089         const char *pcszIommuType;
    7090         switch (hw.iommuType)
    7091         {
    7092             case IommuType_None:         pcszIommuType = "None";        break;
    7093             case IommuType_Automatic:    pcszIommuType = "Automatic";   break;
    7094             case IommuType_AMD:          pcszIommuType = "AMD";         break;
    7095             case IommuType_Intel:        pcszIommuType = "Intel";       break;
    7096             default:     Assert(false);  pcszIommuType = "None";        break;
    7097         }
    7098 
    7099         xml::ElementNode *pelmIommu = pelmHardware->createChild("Iommu");
    7100         pelmIommu->setAttribute("type", pcszIommuType);
    71017441    }
    71027442
     
    72457585    }
    72467586
    7247     if (!hw.biosSettings.areDefaultSettings() || !hw.nvramSettings.areDefaultSettings())
    7248     {
    7249         xml::ElementNode *pelmBIOS = pelmHardware->createChild("BIOS");
    7250         if (!hw.biosSettings.fACPIEnabled)
    7251             pelmBIOS->createChild("ACPI")->setAttribute("enabled", hw.biosSettings.fACPIEnabled);
    7252         if (hw.biosSettings.fIOAPICEnabled)
    7253             pelmBIOS->createChild("IOAPIC")->setAttribute("enabled", hw.biosSettings.fIOAPICEnabled);
    7254         if (hw.biosSettings.apicMode != APICMode_APIC)
     7587    if (   !hw.firmwareSettings.areDefaultSettings(  hw.platformSettings.architectureType == PlatformArchitecture_ARM
     7588                                                   /* Good enough for now (we don't support ARMv7). */
     7589                                                   ? CPUArchitecture_ARMv8_64 : CPUArchitecture_x86)
     7590        || !hw.nvramSettings.areDefaultSettings())
     7591    {
     7592        xml::ElementNode *pelmFirmwareOrBIOS;
     7593        if (m->sv >= SettingsVersion_v1_20) /* Since settings v1.20 the element was renamed to "Firmware". */
     7594            pelmFirmwareOrBIOS = pelmHardware->createChild("Firmware");
     7595        else
     7596            pelmFirmwareOrBIOS = pelmHardware->createChild("BIOS");
     7597
     7598        if (   (m->sv >= SettingsVersion_v1_9)
     7599            && (hw.firmwareSettings.firmwareType >= FirmwareType_EFI)
     7600           )
     7601        {
     7602            const char *pcszFirmware;
     7603
     7604            switch (hw.firmwareSettings.firmwareType)
     7605            {
     7606                case FirmwareType_EFI:      pcszFirmware = "EFI";     break;
     7607                case FirmwareType_EFI32:    pcszFirmware = "EFI32";   break;
     7608                case FirmwareType_EFI64:    pcszFirmware = "EFI64";   break;
     7609                case FirmwareType_EFIDUAL:  pcszFirmware = "EFIDUAL"; break;
     7610                default:                    pcszFirmware = "None";    break;
     7611            }
     7612            pelmFirmwareOrBIOS->setAttribute("type", pcszFirmware);
     7613        }
     7614
     7615        if (!hw.firmwareSettings.fACPIEnabled)
     7616            pelmFirmwareOrBIOS->createChild("ACPI")->setAttribute("enabled", hw.firmwareSettings.fACPIEnabled);
     7617        if (hw.firmwareSettings.fIOAPICEnabled)
     7618            pelmFirmwareOrBIOS->createChild("IOAPIC")->setAttribute("enabled", hw.firmwareSettings.fIOAPICEnabled);
     7619        if (hw.firmwareSettings.apicMode != APICMode_APIC)
    72557620        {
    72567621            const char *pcszAPIC;
    7257             switch (hw.biosSettings.apicMode)
     7622            switch (hw.firmwareSettings.apicMode)
    72587623            {
    72597624                case APICMode_Disabled:
     
    72687633                    break;
    72697634            }
    7270             pelmBIOS->createChild("APIC")->setAttribute("mode", pcszAPIC);
    7271         }
    7272 
    7273         if (   !hw.biosSettings.fLogoFadeIn
    7274             || !hw.biosSettings.fLogoFadeOut
    7275             || hw.biosSettings.ulLogoDisplayTime
    7276             || !hw.biosSettings.strLogoImagePath.isEmpty())
    7277         {
    7278             xml::ElementNode *pelmLogo = pelmBIOS->createChild("Logo");
    7279             pelmLogo->setAttribute("fadeIn", hw.biosSettings.fLogoFadeIn);
    7280             pelmLogo->setAttribute("fadeOut", hw.biosSettings.fLogoFadeOut);
    7281             pelmLogo->setAttribute("displayTime", hw.biosSettings.ulLogoDisplayTime);
    7282             if (!hw.biosSettings.strLogoImagePath.isEmpty())
    7283                 pelmLogo->setAttribute("imagePath", hw.biosSettings.strLogoImagePath);
    7284         }
    7285 
    7286         if (hw.biosSettings.biosBootMenuMode != BIOSBootMenuMode_MessageAndMenu)
     7635            pelmFirmwareOrBIOS->createChild("APIC")->setAttribute("mode", pcszAPIC);
     7636        }
     7637
     7638        if (   !hw.firmwareSettings.fLogoFadeIn
     7639            || !hw.firmwareSettings.fLogoFadeOut
     7640            ||  hw.firmwareSettings.ulLogoDisplayTime
     7641            || !hw.firmwareSettings.strLogoImagePath.isEmpty())
     7642        {
     7643            xml::ElementNode *pelmLogo = pelmFirmwareOrBIOS->createChild("Logo");
     7644            pelmLogo->setAttribute("fadeIn", hw.firmwareSettings.fLogoFadeIn);
     7645            pelmLogo->setAttribute("fadeOut", hw.firmwareSettings.fLogoFadeOut);
     7646            pelmLogo->setAttribute("displayTime", hw.firmwareSettings.ulLogoDisplayTime);
     7647            if (!hw.firmwareSettings.strLogoImagePath.isEmpty())
     7648                pelmLogo->setAttribute("imagePath", hw.firmwareSettings.strLogoImagePath);
     7649        }
     7650
     7651        if (hw.firmwareSettings.enmBootMenuMode != FirmwareBootMenuMode_MessageAndMenu)
    72877652        {
    72887653            const char *pcszBootMenu;
    7289             switch (hw.biosSettings.biosBootMenuMode)
    7290             {
    7291                 case BIOSBootMenuMode_Disabled: pcszBootMenu = "Disabled"; break;
    7292                 case BIOSBootMenuMode_MenuOnly: pcszBootMenu = "MenuOnly"; break;
    7293                 default: /*BIOSBootMenuMode_MessageAndMenu*/ pcszBootMenu = "MessageAndMenu"; break;
    7294             }
    7295             pelmBIOS->createChild("BootMenu")->setAttribute("mode", pcszBootMenu);
    7296         }
    7297         if (hw.biosSettings.llTimeOffset)
    7298             pelmBIOS->createChild("TimeOffset")->setAttribute("value", hw.biosSettings.llTimeOffset);
    7299         if (hw.biosSettings.fPXEDebugEnabled)
    7300             pelmBIOS->createChild("PXEDebug")->setAttribute("enabled", hw.biosSettings.fPXEDebugEnabled);
     7654            switch (hw.firmwareSettings.enmBootMenuMode)
     7655            {
     7656                case FirmwareBootMenuMode_Disabled: pcszBootMenu = "Disabled"; break;
     7657                case FirmwareBootMenuMode_MenuOnly: pcszBootMenu = "MenuOnly"; break;
     7658                default: /*FirmwareBootMenuMode_MessageAndMenu*/ pcszBootMenu = "MessageAndMenu"; break;
     7659            }
     7660            pelmFirmwareOrBIOS->createChild("BootMenu")->setAttribute("mode", pcszBootMenu);
     7661        }
     7662        if (hw.firmwareSettings.llTimeOffset)
     7663            pelmFirmwareOrBIOS->createChild("TimeOffset")->setAttribute("value", hw.firmwareSettings.llTimeOffset);
     7664        if (hw.firmwareSettings.fPXEDebugEnabled)
     7665            pelmFirmwareOrBIOS->createChild("PXEDebug")->setAttribute("enabled", hw.firmwareSettings.fPXEDebugEnabled);
    73017666        if (!hw.nvramSettings.areDefaultSettings())
    73027667        {
    7303             xml::ElementNode *pelmNvram = pelmBIOS->createChild("NVRAM");
     7668            xml::ElementNode *pelmNvram = pelmFirmwareOrBIOS->createChild("NVRAM");
    73047669            if (!hw.nvramSettings.strNvramPath.isEmpty())
    73057670                pelmNvram->setAttribute("path", hw.nvramSettings.strNvramPath);
     
    73127677            }
    73137678        }
    7314         if (hw.biosSettings.fSmbiosUuidLittleEndian)
    7315             pelmBIOS->createChild("SmbiosUuidLittleEndian")->setAttribute("enabled", hw.biosSettings.fSmbiosUuidLittleEndian);
     7679        if (hw.firmwareSettings.fSmbiosUuidLittleEndian)
     7680            pelmFirmwareOrBIOS->createChild("SmbiosUuidLittleEndian")->setAttribute("enabled", hw.firmwareSettings.fSmbiosUuidLittleEndian);
    73167681    }
    73177682
     
    76267991            pelmPort->setAttribute("slot", port.ulSlot);
    76277992            pelmPort->setAttribute("enabled", port.fEnabled);
    7628             pelmPort->setAttributeHex("IOBase", port.ulIOBase);
     7993            pelmPort->setAttributeHex("IOAddress", port.ulIOAddress);
    76297994            pelmPort->setAttribute("IRQ", port.ulIRQ);
    76307995
     
    78078172            }
    78088173        }
    7809     }
    7810 
    7811     if (m->sv >= SettingsVersion_v1_10 && machineUserData.fRTCUseUTC)
    7812     {
    7813         xml::ElementNode *pelmRTC = pelmHardware->createChild("RTC");
    7814         pelmRTC->setAttribute("localOrUTC", machineUserData.fRTCUseUTC ? "UTC" : "local");
    78158174    }
    78168175
     
    86028961        buildRecordingXML(*pelmSnapshot, pSnap->recordingSettings);
    86038962        // note: Groups exist only for Machine, not for Snapshot
     8963
     8964        if (m->sv < SettingsVersion_v1_20) /* Before settings v1.20 the platform stuff lived directly in the Hardware element. */
     8965        {
     8966            xml::ElementNode *pelHardware = unconst(pelmSnapshot->findChildElement("Hardware"));
     8967            if (pelHardware)
     8968                buildPlatformXML(*pelHardware, pSnap->hardware, pSnap->hardware.platformSettings);
     8969        }
     8970        else /* Now lives outside of "Hardware", in "Platform". */
     8971            buildPlatformXML(*pelmSnapshot, pSnap->hardware, pSnap->hardware.platformSettings);
    86048972
    86058973        if (pSnap->llChildSnapshots.size())
     
    87809148
    87819149    buildGroupsXML(elmMachine, machineUserData.llGroups);
     9150
     9151    /* Note: Must come *after* buildHardwareXML(), as the "Hardware" branch is needed. */
     9152    if (m->sv < SettingsVersion_v1_20)
     9153    {
     9154        xml::ElementNode *pelHardware = unconst(elmMachine.findChildElement("Hardware"));
     9155        if (pelHardware)
     9156            buildPlatformXML(*pelHardware, hardwareMachine, hardwareMachine.platformSettings);
     9157    }
     9158    else /* Now lives outside of "Hardware", in "Platform". */
     9159        buildPlatformXML(elmMachine, hardwareMachine, hardwareMachine.platformSettings);
    87829160}
    87839161
     
    89949372void MachineConfigFile::bumpSettingsVersionIfNeeded()
    89959373{
     9374    if (m->sv < SettingsVersion_v1_20)
     9375    {
     9376        // VirtualBox 7.1 (settings v1.20) adds support for different VM platforms.
     9377        if (   hardwareMachine.platformSettings.architectureType != PlatformArchitecture_None
     9378            && hardwareMachine.platformSettings.architectureType != PlatformArchitecture_x86)
     9379        {
     9380            /* Note: The new chipset type ARMv8Virtual implies setting the platform architecture type to ARM. */
     9381            m->sv = SettingsVersion_v1_20;
     9382            return;
     9383        }
     9384    }
     9385
    89969386    if (m->sv < SettingsVersion_v1_19)
    89979387    {
    89989388        // VirtualBox 7.0 adds iommu device and full VM encryption.
    8999         if (   hardwareMachine.iommuType != IommuType_None
     9389        if (   hardwareMachine.platformSettings.iommuType != IommuType_None
    90009390            || strKeyId.isNotEmpty()
    90019391            || strKeyStore.isNotEmpty()
     
    90679457
    90689458        // VirtualBox 6.1 adds AMD-V virtualized VMSAVE/VMLOAD setting.
    9069         if (hardwareMachine.fVirtVmsaveVmload == false)
     9459        if (hardwareMachine.platformSettings.x86.fHWVirtExVirtVmsaveVmload == false)
    90709460        {
    90719461            m->sv = SettingsVersion_v1_18;
     
    91149504
    91159505        // VirtualBox 6.0 adds nested hardware virtualization, using native API (NEM).
    9116         if (   hardwareMachine.fNestedHWVirt
    9117             || hardwareMachine.fUseNativeApi)
     9506        if (   hardwareMachine.platformSettings.x86.fNestedHWVirt
     9507            || hardwareMachine.platformSettings.x86.fHWVirtExUseNativeApi)
    91189508        {
    91199509            m->sv = SettingsVersion_v1_17;
     
    91519541        // options, cpu profile, APIC settings (CPU capability and BIOS).
    91529542
    9153         if (   hardwareMachine.strParavirtDebug.isNotEmpty()
     9543        if (    hardwareMachine.strParavirtDebug.isNotEmpty()
    91549544            || (!hardwareMachine.strCpuProfile.equals("host") && hardwareMachine.strCpuProfile.isNotEmpty())
    9155             || hardwareMachine.biosSettings.apicMode != APICMode_APIC
    9156             || !hardwareMachine.fAPIC
    9157             || hardwareMachine.fX2APIC
    9158             || hardwareMachine.fIBPBOnVMExit
    9159             || hardwareMachine.fIBPBOnVMEntry
    9160             || hardwareMachine.fSpecCtrl
    9161             || hardwareMachine.fSpecCtrlByHost
    9162             || !hardwareMachine.fL1DFlushOnSched
    9163             || hardwareMachine.fL1DFlushOnVMEntry
    9164             || !hardwareMachine.fMDSClearOnSched
    9165             || hardwareMachine.fMDSClearOnVMEntry)
     9545            ||  hardwareMachine.firmwareSettings.apicMode != APICMode_APIC
     9546            || !hardwareMachine.platformSettings.x86.fAPIC
     9547            ||  hardwareMachine.platformSettings.x86.fX2APIC
     9548            ||  hardwareMachine.platformSettings.x86.fIBPBOnVMExit
     9549            ||  hardwareMachine.platformSettings.x86.fIBPBOnVMEntry
     9550            ||  hardwareMachine.platformSettings.x86.fSpecCtrl
     9551            ||  hardwareMachine.platformSettings.x86.fSpecCtrlByHost
     9552            || !hardwareMachine.platformSettings.x86.fL1DFlushOnSched
     9553            ||  hardwareMachine.platformSettings.x86.fL1DFlushOnVMEntry
     9554            || !hardwareMachine.platformSettings.x86.fMDSClearOnSched
     9555            ||  hardwareMachine.platformSettings.x86.fMDSClearOnVMEntry)
    91669556        {
    91679557            m->sv = SettingsVersion_v1_16;
     
    91829572        }
    91839573
    9184         for (CpuIdLeafsList::const_iterator it = hardwareMachine.llCpuIdLeafs.begin();
    9185              it != hardwareMachine.llCpuIdLeafs.end();
     9574        for (CpuIdLeafsX86List::const_iterator it = hardwareMachine.platformSettings.x86.llCpuIdLeafs.begin();
     9575             it != hardwareMachine.platformSettings.x86.llCpuIdLeafs.end();
    91869576             ++it)
    91879577            if (it->idxSub != 0)
     
    92809670        if (   !hardwareMachine.strDefaultFrontend.isEmpty()
    92819671            || hardwareMachine.graphicsAdapter.graphicsControllerType != GraphicsControllerType_VBoxVGA
    9282             || hardwareMachine.enmLongMode != Hardware::LongMode_Legacy
     9672            || hardwareMachine.platformSettings.x86.enmLongMode != PlatformX86::LongMode_Legacy
    92839673            || machineUserData.ovIcon.size() > 0
    92849674            || recordingSettings.common.fEnabled)
     
    94089798             || machineUserData.strOsType == "JRockitVE"
    94099799             || hardwareMachine.ioSettings.llBandwidthGroups.size()
    9410              || hardwareMachine.chipsetType == ChipsetType_ICH9
     9800             || hardwareMachine.platformSettings.chipsetType == ChipsetType_ICH9
    94119801           )
    94129802            m->sv = SettingsVersion_v1_11;
     
    95899979            || (hardwareMachine.fPageFusionEnabled)
    95909980                // and CPU hotplug, RTC timezone control, HID type and HPET
    9591             || machineUserData.fRTCUseUTC
     9981            || hardwareMachine.platformSettings.fRTCUseUTC
    95929982            || hardwareMachine.fCpuHotPlug
    95939983            || hardwareMachine.pointingHIDType != PointingHIDType_PS2Mouse
    95949984            || hardwareMachine.keyboardHIDType != KeyboardHIDType_PS2Keyboard
    9595             || hardwareMachine.fHPETEnabled
     9985            || hardwareMachine.platformSettings.x86.fHPETEnabled
    95969986           )
    95979987            m->sv = SettingsVersion_v1_10;
     
    965210042    // all the following require settings version 1.9
    965310043    if (    (m->sv < SettingsVersion_v1_9)
    9654          && (    (hardwareMachine.firmwareType >= FirmwareType_EFI)
     10044        && (    (hardwareMachine.firmwareSettings.firmwareType >= FirmwareType_EFI)
    965510045              || machineUserData.fTeleporterEnabled
    965610046              || machineUserData.uTeleporterPort
  • trunk/src/VBox/Main/xml/VirtualBox-settings.xsd

    r98108 r101035  
    218218</xsd:simpleType>
    219219
    220 <xsd:simpleType name="TBIOSBootMenuModeType">
     220<xsd:simpleType name="TFirmwareBootMenuModeType">
    221221  <xsd:restriction base="xsd:string">
    222222    <xsd:enumeration value="Disabled"/>
     
    456456  <xsd:attribute name="LogHistoryCount" type="xsd:unsignedInt" default="3"/>
    457457  <xsd:attribute name="defaultVRDEExtPack" type="xsd:string"/>
    458   <xsd:attribute name="exclusiveHwVirt" type="xsd:boolean"/>
     458  <xsd:attribute name="exclusiveHwVirt" type="xsd:boolean"/> <!-- deprecated since v1.20 -->
    459459  <xsd:attribute name="proxyMode" type="xsd:string"/>
    460460</xsd:complexType>
     
    582582</xsd:complexType>
    583583
     584<xsd:complexType name="THardwareVirtExUseNativeApi">
     585  <xsd:attribute name="enabled" type="xsd:boolean"/>
     586</xsd:complexType>
     587
     588<xsd:complexType name="TIBPBOn">
     589  <xsd:attribute name="vmexit" type="xsd:boolean"/>
     590  <xsd:attribute name="vmentry" type="xsd:boolean"/>
     591</xsd:complexType>
     592
     593<xsd:complexType name="TSpecCtrl">
     594  <xsd:attribute name="enabled" type="xsd:boolean"/>
     595</xsd:complexType>
     596
     597<xsd:complexType name="TSpecCtrlByHost">
     598  <xsd:attribute name="enabled" type="xsd:boolean"/>
     599</xsd:complexType>
     600
     601<xsd:complexType name="TL1DFlushOn">
     602  <xsd:attribute name="scheduling" type="xsd:boolean"/>
     603  <xsd:attribute name="vmentry" type="xsd:boolean"/>
     604</xsd:complexType>
     605
     606<xsd:complexType name="TMDSClearOn">
     607  <xsd:attribute name="scheduling" type="xsd:boolean"/>
     608  <xsd:attribute name="vmentry" type="xsd:boolean"/>
     609</xsd:complexType>
     610
     611<xsd:complexType name="TNestedHWVirt">
     612  <xsd:attribute name="enabled" type="xsd:boolean"/>
     613</xsd:complexType>
     614
     615<xsd:complexType name="THardwareVirtExVirtVmsaveVmload">
     616  <xsd:attribute name="enabled" type="xsd:boolean"/>
     617</xsd:complexType>
     618
     619<xsd:complexType name="TTripleFaultReset">
     620  <xsd:attribute name="enabled" type="xsd:boolean"/>
     621</xsd:complexType>
     622
     623<xsd:complexType name="TX2APIC">
     624  <xsd:attribute name="enabled" type="xsd:boolean"/>
     625</xsd:complexType>
     626
     627<xsd:complexType name="TAPIC">
     628  <xsd:attribute name="enabled" type="xsd:boolean"/>
     629</xsd:complexType>
     630
    584631<xsd:simpleType name="TCPUCount">
    585632  <xsd:restriction base="xsd:unsignedInt">
     
    589636</xsd:simpleType>
    590637
    591 <xsd:complexType name="TCpuIdLeaf">
     638<xsd:complexType name="TCpuIdLeafX86">
    592639  <xsd:attribute name="id"        type="xsd:unsignedInt"       use="required"/>
    593640  <xsd:attribute name="eax"       type="xsd:unsignedInt"       use="required"/>
     
    597644</xsd:complexType>
    598645
    599 <xsd:complexType name="TCpuIdTree">
    600   <xsd:sequence>
    601     <xsd:element name="CpuIdLeaf" type="TCpuIdLeaf"
     646<xsd:complexType name="TCpuIdTreeX86">
     647  <xsd:sequence>
     648    <xsd:element name="CpuIdLeaf" type="TCpuIdLeafX86"
    602649                 minOccurs="0" maxOccurs="unbounded"/>
    603650  </xsd:sequence>
    604651</xsd:complexType>
    605652
    606 <xsd:complexType name="TCPU">
    607   <xsd:sequence>
     653<xsd:complexType name="TCPUX86"> <!-- Contains the "x86" sub element of the CPU element. New since v1.20. -->
     654  <xsd:sequence>
     655    <xsd:element name="HPET" type="THPET" minOccurs="0"/>
     656    <xsd:element name="HardwareVirtExLargePages" type="THardwareVirtExLargePages" minOccurs="0"/>
     657    <xsd:element name="HardwareVirtForce" type="THardwareVirtForce" minOccurs="0"/>
     658    <xsd:element name="HardwareVirtExUseNativeApi" type="THardwareVirtExUseNativeApi" minOccurs="0"/>
    608659    <xsd:element name="HardwareVirtEx" type="THWVirtExType" minOccurs="0"/>
    609660    <xsd:element name="HardwareVirtExNestedPaging" type="THWVirtExNestedPagingType" minOccurs="0"/>
     
    611662    <xsd:element name="HardwareVirtExUX" type="THWVirtExUXType" minOccurs="0"/>
    612663    <xsd:element name="PAE" type="TPAEType" minOccurs="0"/>
     664    <xsd:element name="IBPBOn" type="TIBPBOn" minOccurs="0"/>
     665    <xsd:element name="SpecCtrl" type="TSpecCtrl" minOccurs="0"/>
     666    <xsd:element name="SpecCtrlByHost" type="TSpecCtrlByHost" minOccurs="0"/>
     667    <xsd:element name="L1DFlushOn" type="TL1DFlushOn" minOccurs="0"/>
     668    <xsd:element name="MDSClearOn" type="TMDSClearOn" minOccurs="0"/>
     669    <xsd:element name="NestedHWVirt" type="TNestedHWVirt" minOccurs="0"/>
     670    <xsd:element name="HardwareVirtExVirtVmsaveVmload" type="THardwareVirtExVirtVmsaveVmload" minOccurs="0"/>
    613671    <xsd:element name="LongMode" type="TLongModeType" minOccurs="0"/>
    614     <xsd:element name="HardwareVirtExLargePages" type="THardwareVirtExLargePages" minOccurs="0"/>
    615     <xsd:element name="HardwareVirtForce" type="THardwareVirtForce" minOccurs="0"/>
     672    <xsd:element name="TripleFaultReset" type="TTripleFaultReset" minOccurs="0"/>
     673    <xsd:element name="X2APIC" type="TX2APIC" minOccurs="0"/>
     674    <xsd:element name="APIC" type="TAPIC" minOccurs="0"/>
     675    <xsd:element name="CpuIdTree" type="TCpuIdTreeX86" minOccurs="0">
     676      <xsd:unique name="TCPUX86-CpuIdTree-CpuIdLeaf">
     677        <xsd:selector xpath="vb:CpuIdLeaf"/>
     678        <xsd:field xpath="@id"/>
     679      </xsd:unique>
     680    </xsd:element>
     681  </xsd:sequence>
     682</xsd:complexType>
     683
     684<xsd:complexType name="TCPU">
     685  <xsd:sequence>
     686    <xsd:element name="HardwareVirtEx" type="THWVirtExType" minOccurs="0"/> <!-- deprecated since v1.20. -->
     687    <xsd:element name="HardwareVirtExNestedPaging" type="THWVirtExNestedPagingType" minOccurs="0"/> <!-- deprecated since v1.20. -->
     688    <xsd:element name="HardwareVirtExVPID" type="THWVirtExVPIDType" minOccurs="0"/> <!-- deprecated since v1.20. -->
     689    <xsd:element name="HardwareVirtExUX" type="THWVirtExUXType" minOccurs="0"/> <!-- deprecated since v1.20. -->
     690    <xsd:element name="PAE" type="TPAEType" minOccurs="0"/> <!-- deprecated since v1.20. -->
     691    <xsd:element name="LongMode" type="TLongModeType" minOccurs="0"/> <!-- deprecated since v1.20. -->
     692    <xsd:element name="HardwareVirtExLargePages" type="THardwareVirtExLargePages" minOccurs="0"/> <!-- deprecated since v1.20. -->
     693    <xsd:element name="HardwareVirtForce" type="THardwareVirtForce" minOccurs="0"/> <!-- deprecated since v1.20. -->
    616694    <xsd:element name="SyntheticCpu" type="TSyntheticCpuType" minOccurs="0"/>
    617     <xsd:element name="CpuIdTree" type="TCpuIdTree" minOccurs="0">
     695    <xsd:element name="CpuIdTree" type="TCpuIdTreeX86" minOccurs="0"> <!-- deprecated since v1.20. -->
    618696      <xsd:unique name="TCPU-CpuIdTree-CpuIdLeaf">
    619697        <xsd:selector xpath="vb:CpuIdLeaf"/>
     
    720798</xsd:complexType>
    721799
    722 <xsd:complexType name="TBIOS">
     800<xsd:complexType name="TFirmware"> <!-- Note: Is named as element "BIOS" for settings < v1.20. -->
    723801  <xsd:all>
    724802    <xsd:element name="ACPI" minOccurs="0">
     
    742820    <xsd:element name="BootMenu" minOccurs="0">
    743821      <xsd:complexType>
    744         <xsd:attribute name="mode" type="TBIOSBootMenuModeType" default="MessageAndMenu"/>
     822        <xsd:attribute name="mode" type="TFirmwareBootMenuModeType" default="MessageAndMenu"/>
    745823      </xsd:complexType>
    746824    </xsd:element>
     
    780858    </xsd:element>
    781859  </xsd:all>
     860  <xsd:attribute name="type" type="TFirmwareType" use="required"/> <!-- new since v1.20. -->
    782861</xsd:complexType>
    783862
     
    12811360</xsd:complexType>
    12821361
    1283 <xsd:complexType name="TFirmware">
    1284   <xsd:attribute name="type" use="required">
    1285     <xsd:simpleType>
    1286       <xsd:restriction base="xsd:token">
    1287         <xsd:enumeration value="BIOS"/>
    1288         <xsd:enumeration value="EFI"/>
    1289         <xsd:enumeration value="EFI32"/>
    1290         <xsd:enumeration value="EFI64"/>
    1291         <xsd:enumeration value="EFIDUAL"/>
    1292       </xsd:restriction>
    1293     </xsd:simpleType>
    1294   </xsd:attribute>
    1295 </xsd:complexType>
     1362<xsd:simpleType name="TFirmwareType">
     1363  <xsd:restriction base="xsd:token">
     1364    <xsd:enumeration value="BIOS"/>
     1365    <xsd:enumeration value="EFI"/>
     1366    <xsd:enumeration value="EFI32"/>
     1367    <xsd:enumeration value="EFI64"/>
     1368    <xsd:enumeration value="EFIDUAL"/>
     1369  </xsd:restriction>
     1370</xsd:simpleType>
    12961371
    12971372<xsd:complexType name="THID">
     
    13271402        <xsd:enumeration value="PIIX3"/>
    13281403        <xsd:enumeration value="ICH9"/>
     1404      </xsd:restriction>
     1405    </xsd:simpleType>
     1406  </xsd:attribute>
     1407</xsd:complexType>
     1408
     1409<xsd:complexType name="TIommu"> <!-- new since v1.19. -->
     1410  <xsd:attribute name="type" use="required">
     1411    <xsd:simpleType>
     1412      <xsd:restriction base="xsd:token">
     1413        <xsd:enumeration value="None"/>
     1414        <xsd:enumeration value="Automatic"/>
     1415        <xsd:enumeration value="AMD"/>
     1416        <xsd:enumeration value="Intel"/>
    13291417      </xsd:restriction>
    13301418    </xsd:simpleType>
     
    13551443</xsd:complexType>
    13561444
     1445<xsd:simpleType name="TPlatformArchitecture"> <!-- new since v1.20. -->
     1446  <xsd:restriction base="xsd:token">
     1447    <xsd:enumeration value="None"/>
     1448    <xsd:enumeration value="x86"/>
     1449    <xsd:enumeration value="ARM"/>
     1450  </xsd:restriction>
     1451</xsd:simpleType>
     1452
     1453<xsd:complexType name="TPlatformProperties"> <!-- new since v1.20. -->
     1454  <xsd:attribute name="exclusiveHwVirt" type="xsd:boolean"/>
     1455</xsd:complexType>
     1456
     1457<xsd:complexType name="TPlatformX86"> <!-- new since v1.20. -->
     1458</xsd:complexType>
     1459
     1460<xsd:complexType name="TPlatformARM"> <!-- new since v1.20. -->
     1461</xsd:complexType>
     1462
     1463<xsd:complexType name="TPlatform"> <!-- new since v1.20. -->
     1464  <xsd:all>
     1465    <xsd:element name="Chipset" type="TChipset" minOccurs="0"/>
     1466    <xsd:element name="Iommu" type="TIommu" minOccurs="0"/>
     1467    <xsd:element name="RTC" type="TRTC" minOccurs="0"/>
     1468    <xsd:element name="CPU" type="TCPU"/>
     1469    <xsd:element name="x86" type="TPlatformX86" minOccurs="0"/>
     1470  </xsd:all>
     1471  <xsd:attribute name="architecture" type="TPlatformArchitecture" use="required"/>
     1472</xsd:complexType>
     1473
    13571474<xsd:complexType name="THardware">
    13581475  <xsd:all>
    1359     <xsd:element name="CPU" type="TCPU" minOccurs="0"/>
     1476    <xsd:element name="CPU" type="TCPU" minOccurs="0"/> <!-- deprecated since v1.20. -->
    13601477    <xsd:element name="Memory" type="TMemory"/>
    13611478    <xsd:element name="Firmware" type="TFirmware" minOccurs="0"/>
    13621479    <xsd:element name="HID" type="THID" minOccurs="0"/>
    1363     <xsd:element name="HPET" type="THPET" minOccurs="0"/>
    1364     <xsd:element name="Chipset" type="TChipset" minOccurs="0"/>
     1480    <xsd:element name="HPET" type="THPET" minOccurs="0"/> <!-- deprecated since v1.20. -->
     1481    <xsd:element name="Chipset" type="TChipset" minOccurs="0"/> <!-- deprecated since v1.20. -->
    13651482    <xsd:element name="Paravirt" type="TParavirt" minOccurs="0"/>
    13661483    <xsd:element name="Boot" type="TBoot" minOccurs="0">
     
    13741491    <xsd:element name="VideoCapture" type="TVideoCapture" minOccurs="0"/>
    13751492    <xsd:element name="RemoteDisplay" type="TRemoteDisplay" minOccurs="0"/>
    1376     <xsd:element name="BIOS" type="TBIOS" minOccurs="0"/>
     1493    <xsd:element name="BIOS" type="TFirmware" minOccurs="0"/> <!-- deprecated since v1.20. -->
    13771494    <xsd:element name="DVDDrive" type="TDVDDrive" minOccurs="0"/>
    13781495    <xsd:element name="FloppyDrive" type="TFloppyDrive" minOccurs="0"/>
     
    14111528    </xsd:element>
    14121529    <xsd:element name="AudioAdapter" type="TAudioAdapter" minOccurs="0"/>
    1413     <xsd:element name="RTC" type="TRTC" minOccurs="0"/>
     1530    <xsd:element name="RTC" type="TRTC" minOccurs="0"/> <!-- deprecated since v1.20. -->
    14141531    <xsd:element name="SharedFolders" type="TSharedFolders" minOccurs="0">
    14151532      <xsd:unique name="THardware-SharedFolders-SharedFolder">
     
    14511568    <xsd:element name="Teleporter" type="TTeleporter" minOccurs="0"/>
    14521569    <xsd:element name="Hardware" type="THardware"/>
     1570    <xsd:element name="Platform" type="TPlatform" minOccurs="0"/> <!-- new since v1.20. -->
    14531571    <xsd:element name="StorageControllers" type="TStorageControllers" minOccurs="0"/>
    14541572    <xsd:element name="HardDiskAttachments" type="THardDiskAttachments" minOccurs="0"/> <!-- deprecated -->
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette