VirtualBox

source: vbox/trunk/src/VBox/Main/src-client/ConsoleImplConfigArmV8.cpp@ 100606

Last change on this file since 100606 was 100108, checked in by vboxsync, 18 months ago

*: Fix build issues when setting VBOX_WITH_WARNINGS_AS_ERRORS=1 on darwin.arm64 and make it a default, bugref:10469

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 47.9 KB
Line 
1/* $Id: ConsoleImplConfigArmV8.cpp 100108 2023-06-07 20:05:13Z vboxsync $ */
2/** @file
3 * VBox Console COM Class implementation - VM Configuration Bits for ARMv8.
4 */
5
6/*
7 * Copyright (C) 2023 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28
29/*********************************************************************************************************************************
30* Header Files *
31*********************************************************************************************************************************/
32#define LOG_GROUP LOG_GROUP_MAIN_CONSOLE
33#include "LoggingNew.h"
34
35#include "ConsoleImpl.h"
36#include "ResourceStoreImpl.h"
37#include "Global.h"
38
39// generated header
40#include "SchemaDefs.h"
41
42#include "AutoCaller.h"
43
44#include <iprt/base64.h>
45#include <iprt/buildconfig.h>
46#include <iprt/ctype.h>
47#include <iprt/dir.h>
48#include <iprt/fdt.h>
49#include <iprt/file.h>
50#include <iprt/param.h>
51#include <iprt/path.h>
52#include <iprt/string.h>
53#include <iprt/system.h>
54#if 0 /* enable to play with lots of memory. */
55# include <iprt/env.h>
56#endif
57#include <iprt/stream.h>
58
59#include <iprt/formats/arm-psci.h>
60
61#include <VBox/vmm/vmmr3vtable.h>
62#include <VBox/vmm/vmapi.h>
63#include <VBox/err.h>
64#include <VBox/param.h>
65#include <VBox/version.h>
66
67#ifdef VBOX_WITH_EXTPACK
68# include "ExtPackManagerImpl.h"
69#endif
70
71
72/*********************************************************************************************************************************
73* Internal Functions *
74*********************************************************************************************************************************/
75
76/* Darwin compile kludge */
77#undef PVM
78
79#ifdef VBOX_WITH_VIRT_ARMV8
80/**
81 * Worker for configConstructor.
82 *
83 * @return VBox status code.
84 * @param pUVM The user mode VM handle.
85 * @param pVM The cross context VM handle.
86 * @param pVMM The VMM vtable.
87 * @param pAlock The automatic lock instance. This is for when we have
88 * to leave it in order to avoid deadlocks (ext packs and
89 * more).
90 *
91 * @todo This is a big hack at the moment and provides a static VM config to work with, will be adjusted later
92 * on to adhere to the VM config when sorting out the API bits.
93 */
94int Console::i_configConstructorArmV8(PUVM pUVM, PVM pVM, PCVMMR3VTABLE pVMM, AutoWriteLock *pAlock)
95{
96 RT_NOREF(pVM /* when everything is disabled */);
97 VMMDev *pVMMDev = m_pVMMDev; Assert(pVMMDev); RT_NOREF(pVMMDev); /** @todo Comes later. */
98 ComPtr<IMachine> pMachine = i_machine();
99
100 HRESULT hrc;
101 Utf8Str strTmp;
102 Bstr bstr;
103
104 RTFDT hFdt = NIL_RTFDT;
105 int vrc = RTFdtCreateEmpty(&hFdt);
106 AssertRCReturn(vrc, vrc);
107
108#define H() AssertLogRelMsgReturnStmt(!FAILED(hrc), ("hrc=%Rhrc\n", hrc), RTFdtDestroy(hFdt), VERR_MAIN_CONFIG_CONSTRUCTOR_COM_ERROR)
109#define VRC() AssertLogRelMsgReturnStmt(RT_SUCCESS(vrc), ("vrc=%Rrc\n", vrc), RTFdtDestroy(hFdt), vrc)
110
111
112 /*
113 * Get necessary objects and frequently used parameters.
114 */
115 ComPtr<IVirtualBox> virtualBox;
116 hrc = pMachine->COMGETTER(Parent)(virtualBox.asOutParam()); H();
117
118 ComPtr<IHost> host;
119 hrc = virtualBox->COMGETTER(Host)(host.asOutParam()); H();
120
121 ComPtr<ISystemProperties> systemProperties;
122 hrc = virtualBox->COMGETTER(SystemProperties)(systemProperties.asOutParam()); H();
123
124 ComPtr<IBIOSSettings> biosSettings;
125 hrc = pMachine->COMGETTER(BIOSSettings)(biosSettings.asOutParam()); H();
126
127 ComPtr<INvramStore> nvramStore;
128 hrc = pMachine->COMGETTER(NonVolatileStore)(nvramStore.asOutParam()); H();
129
130 hrc = pMachine->COMGETTER(HardwareUUID)(bstr.asOutParam()); H();
131 RTUUID HardwareUuid;
132 vrc = RTUuidFromUtf16(&HardwareUuid, bstr.raw());
133 AssertRCReturn(vrc, vrc);
134
135 ULONG cRamMBs;
136 hrc = pMachine->COMGETTER(MemorySize)(&cRamMBs); H();
137 uint64_t const cbRam = cRamMBs * (uint64_t)_1M;
138
139 ULONG cCpus = 1;
140 hrc = pMachine->COMGETTER(CPUCount)(&cCpus); H();
141
142 ULONG ulCpuExecutionCap = 100;
143 hrc = pMachine->COMGETTER(CPUExecutionCap)(&ulCpuExecutionCap); H();
144
145 Bstr osTypeId;
146 hrc = pMachine->COMGETTER(OSTypeId)(osTypeId.asOutParam()); H();
147 LogRel(("Guest OS type: '%s'\n", Utf8Str(osTypeId).c_str()));
148
149 /*
150 * Get root node first.
151 * This is the only node in the tree.
152 */
153 PCFGMNODE pRoot = pVMM->pfnCFGMR3GetRootU(pUVM);
154 Assert(pRoot);
155
156 // catching throws from InsertConfigString and friends.
157 try
158 {
159
160 /*
161 * Set the root (and VMM) level values.
162 */
163 hrc = pMachine->COMGETTER(Name)(bstr.asOutParam()); H();
164 InsertConfigString(pRoot, "Name", bstr);
165 InsertConfigBytes(pRoot, "UUID", &HardwareUuid, sizeof(HardwareUuid));
166 InsertConfigInteger(pRoot, "NumCPUs", cCpus);
167 InsertConfigInteger(pRoot, "CpuExecutionCap", ulCpuExecutionCap);
168 InsertConfigInteger(pRoot, "TimerMillies", 10);
169
170 uint32_t idPHandleIntCtrl = RTFdtPHandleAllocate(hFdt);
171 Assert(idPHandleIntCtrl != UINT32_MAX);
172 uint32_t idPHandleIntCtrlMsi = RTFdtPHandleAllocate(hFdt);
173 Assert(idPHandleIntCtrlMsi != UINT32_MAX); RT_NOREF(idPHandleIntCtrlMsi);
174 uint32_t idPHandleAbpPClk = RTFdtPHandleAllocate(hFdt);
175 Assert(idPHandleAbpPClk != UINT32_MAX);
176 uint32_t idPHandleGpio = RTFdtPHandleAllocate(hFdt);
177 Assert(idPHandleGpio != UINT32_MAX);
178
179 uint32_t aidPHandleCpus[VMM_MAX_CPU_COUNT];
180 for (uint32_t i = 0; i < cCpus; i++)
181 {
182 aidPHandleCpus[i] = RTFdtPHandleAllocate(hFdt);
183 Assert(aidPHandleCpus[i] != UINT32_MAX);
184 }
185
186 vrc = RTFdtNodePropertyAddU32( hFdt, "interrupt-parent", idPHandleIntCtrl); VRC();
187 vrc = RTFdtNodePropertyAddString(hFdt, "model", "linux,dummy-virt"); VRC();
188 vrc = RTFdtNodePropertyAddU32( hFdt, "#size-cells", 2); VRC();
189 vrc = RTFdtNodePropertyAddU32( hFdt, "#address-cells", 2); VRC();
190 vrc = RTFdtNodePropertyAddString(hFdt, "compatible", "linux,dummy-virt"); VRC();
191
192 /* Configure the Power State Coordination Interface. */
193 vrc = RTFdtNodeAdd(hFdt, "psci"); VRC();
194 vrc = RTFdtNodePropertyAddU32( hFdt, "migrate", ARM_PSCI_FUNC_ID_CREATE_FAST_32(ARM_PSCI_FUNC_ID_MIGRATE)); VRC();
195 vrc = RTFdtNodePropertyAddU32( hFdt, "cpu_on", ARM_PSCI_FUNC_ID_CREATE_FAST_32(ARM_PSCI_FUNC_ID_CPU_ON)); VRC();
196 vrc = RTFdtNodePropertyAddU32( hFdt, "cpu_off", ARM_PSCI_FUNC_ID_CREATE_FAST_32(ARM_PSCI_FUNC_ID_CPU_OFF)); VRC();
197 vrc = RTFdtNodePropertyAddU32( hFdt, "cpu_suspend", ARM_PSCI_FUNC_ID_CREATE_FAST_32(ARM_PSCI_FUNC_ID_CPU_SUSPEND)); VRC();
198 vrc = RTFdtNodePropertyAddString(hFdt, "method", "hvc"); VRC();
199 vrc = RTFdtNodePropertyAddStringList(hFdt, "compatible", 3,
200 "arm,psci-1.0", "arm,psci-0.2", "arm,psci"); VRC();
201 vrc = RTFdtNodeFinalize(hFdt); VRC();
202
203 /* Configure some misc system wide properties. */
204 vrc = RTFdtNodeAdd(hFdt, "chosen"); VRC();
205 vrc = RTFdtNodePropertyAddString(hFdt, "stdout-path", "/pl011@9000000"); VRC();
206 vrc = RTFdtNodeFinalize(hFdt);
207
208 /* Configure the timer and clock. */
209 vrc = RTFdtNodeAdd(hFdt, "timer"); VRC();
210 vrc = RTFdtNodePropertyAddCellsU32(hFdt, "interrupts", 12,
211 0x01, 0x0d, 0x104,
212 0x01, 0x0e, 0x104,
213 0x01, 0x0b, 0x104,
214 0x01, 0x0a, 0x104); VRC();
215 vrc = RTFdtNodePropertyAddEmpty( hFdt, "always-on"); VRC();
216 vrc = RTFdtNodePropertyAddString( hFdt, "compatible", "arm,armv7-timer"); VRC();
217 vrc = RTFdtNodeFinalize(hFdt);
218
219 vrc = RTFdtNodeAdd(hFdt, "apb-clk"); VRC();
220 vrc = RTFdtNodePropertyAddU32( hFdt, "phandle", idPHandleAbpPClk); VRC();
221 vrc = RTFdtNodePropertyAddString( hFdt, "clock-output-names", "clk24mhz"); VRC();
222 vrc = RTFdtNodePropertyAddU32( hFdt, "clock-frequency", 24 * 1000 * 1000); VRC();
223 vrc = RTFdtNodePropertyAddU32( hFdt, "#clock-cells", 0); VRC();
224 vrc = RTFdtNodePropertyAddString( hFdt, "compatible", "fixed-clock"); VRC();
225 vrc = RTFdtNodeFinalize(hFdt);
226
227 /* Configure gpio keys (non functional at the moment). */
228 vrc = RTFdtNodeAdd(hFdt, "gpio-keys"); VRC();
229 vrc = RTFdtNodePropertyAddString(hFdt, "compatible", "gpio-keys"); VRC();
230
231 vrc = RTFdtNodeAdd(hFdt, "poweroff"); VRC();
232 vrc = RTFdtNodePropertyAddCellsU32(hFdt, "gpios", 3, idPHandleGpio, 3, 0); VRC();
233 vrc = RTFdtNodePropertyAddU32( hFdt, "linux,code", 0x74); VRC();
234 vrc = RTFdtNodePropertyAddString( hFdt, "label", "GPIO Key Poweroff"); VRC();
235 vrc = RTFdtNodeFinalize(hFdt); VRC();
236
237 vrc = RTFdtNodeFinalize(hFdt); VRC();
238
239 /*
240 * NEM
241 */
242 PCFGMNODE pNEM;
243 InsertConfigNode(pRoot, "NEM", &pNEM);
244
245 /*
246 * MM values.
247 */
248 PCFGMNODE pMM;
249 InsertConfigNode(pRoot, "MM", &pMM);
250
251 /*
252 * Memory setup.
253 */
254 PCFGMNODE pMem = NULL;
255 InsertConfigNode(pMM, "MemRegions", &pMem);
256
257 PCFGMNODE pMemRegion = NULL;
258 InsertConfigNode(pMem, "Conventional", &pMemRegion);
259 InsertConfigInteger(pMemRegion, "GCPhysStart", 0x40000000);
260 InsertConfigInteger(pMemRegion, "Size", cbRam);
261
262 vrc = RTFdtNodeAddF(hFdt, "memory@%RX32", 0x40000000); VRC();
263 vrc = RTFdtNodePropertyAddCellsU32(hFdt, "reg", 4,
264 0, 0x40000000,
265 (uint32_t)(cbRam >> 32), cbRam & UINT32_MAX); VRC();
266 vrc = RTFdtNodePropertyAddString( hFdt, "device_type", "memory"); VRC();
267 vrc = RTFdtNodeFinalize(hFdt); VRC();
268
269 /* Configure the CPUs in the system, only one socket and cluster at the moment. */
270 vrc = RTFdtNodeAdd(hFdt, "cpus"); VRC();
271 vrc = RTFdtNodePropertyAddU32(hFdt, "#size-cells", 0); VRC();
272 vrc = RTFdtNodePropertyAddU32(hFdt, "#address-cells", 1); VRC();
273
274 vrc = RTFdtNodeAdd(hFdt, "socket0"); VRC();
275 vrc = RTFdtNodeAdd(hFdt, "cluster0"); VRC();
276
277 for (uint32_t i = 0; i < cCpus; i++)
278 {
279 vrc = RTFdtNodeAddF(hFdt, "core%u", i); VRC();
280 vrc = RTFdtNodePropertyAddU32(hFdt, "cpu", aidPHandleCpus[i]); VRC();
281 vrc = RTFdtNodeFinalize(hFdt); VRC();
282 }
283
284 vrc = RTFdtNodeFinalize(hFdt); VRC();
285 vrc = RTFdtNodeFinalize(hFdt); VRC();
286
287 for (uint32_t i = 0; i < cCpus; i++)
288 {
289 vrc = RTFdtNodeAddF(hFdt, "cpu@%u", i); VRC();
290 vrc = RTFdtNodePropertyAddU32(hFdt, "phandle", aidPHandleCpus[i]); VRC();
291 vrc = RTFdtNodePropertyAddU32(hFdt, "reg", i); VRC();
292 vrc = RTFdtNodePropertyAddString(hFdt, "compatible", "arm,cortex-a15"); VRC();
293 vrc = RTFdtNodePropertyAddString(hFdt, "device_type", "cpu"); VRC();
294 if (cCpus > 1)
295 {
296 vrc = RTFdtNodePropertyAddString(hFdt, "enable-method", "psci"); VRC();
297 }
298 vrc = RTFdtNodeFinalize(hFdt); VRC();
299 }
300
301 vrc = RTFdtNodeFinalize(hFdt); VRC();
302
303
304 /*
305 * PDM config.
306 * Load drivers in VBoxC.[so|dll]
307 */
308 PCFGMNODE pPDM;
309 PCFGMNODE pNode;
310 PCFGMNODE pMod;
311 InsertConfigNode(pRoot, "PDM", &pPDM);
312 InsertConfigNode(pPDM, "Devices", &pNode);
313 InsertConfigNode(pPDM, "Drivers", &pNode);
314 InsertConfigNode(pNode, "VBoxC", &pMod);
315#ifdef VBOX_WITH_XPCOM
316 // VBoxC is located in the components subdirectory
317 char szPathVBoxC[RTPATH_MAX];
318 vrc = RTPathAppPrivateArch(szPathVBoxC, RTPATH_MAX - sizeof("/components/VBoxC")); AssertRC(vrc);
319 strcat(szPathVBoxC, "/components/VBoxC");
320 InsertConfigString(pMod, "Path", szPathVBoxC);
321#else
322 InsertConfigString(pMod, "Path", "VBoxC");
323#endif
324
325
326 /*
327 * Block cache settings.
328 */
329 PCFGMNODE pPDMBlkCache;
330 InsertConfigNode(pPDM, "BlkCache", &pPDMBlkCache);
331
332 /* I/O cache size */
333 ULONG ioCacheSize = 5;
334 hrc = pMachine->COMGETTER(IOCacheSize)(&ioCacheSize); H();
335 InsertConfigInteger(pPDMBlkCache, "CacheSize", ioCacheSize * _1M);
336
337 /*
338 * Bandwidth groups.
339 */
340 ComPtr<IBandwidthControl> bwCtrl;
341
342 hrc = pMachine->COMGETTER(BandwidthControl)(bwCtrl.asOutParam()); H();
343
344 com::SafeIfaceArray<IBandwidthGroup> bwGroups;
345 hrc = bwCtrl->GetAllBandwidthGroups(ComSafeArrayAsOutParam(bwGroups)); H();
346
347 PCFGMNODE pAc;
348 InsertConfigNode(pPDM, "AsyncCompletion", &pAc);
349 PCFGMNODE pAcFile;
350 InsertConfigNode(pAc, "File", &pAcFile);
351 PCFGMNODE pAcFileBwGroups;
352 InsertConfigNode(pAcFile, "BwGroups", &pAcFileBwGroups);
353#ifdef VBOX_WITH_NETSHAPER
354 PCFGMNODE pNetworkShaper;
355 InsertConfigNode(pPDM, "NetworkShaper", &pNetworkShaper);
356 PCFGMNODE pNetworkBwGroups;
357 InsertConfigNode(pNetworkShaper, "BwGroups", &pNetworkBwGroups);
358#endif /* VBOX_WITH_NETSHAPER */
359
360 for (size_t i = 0; i < bwGroups.size(); i++)
361 {
362 Bstr strName;
363 hrc = bwGroups[i]->COMGETTER(Name)(strName.asOutParam()); H();
364 if (strName.isEmpty())
365 return pVMM->pfnVMR3SetError(pUVM, VERR_CFGM_NO_NODE, RT_SRC_POS, N_("No bandwidth group name specified"));
366
367 BandwidthGroupType_T enmType = BandwidthGroupType_Null;
368 hrc = bwGroups[i]->COMGETTER(Type)(&enmType); H();
369 LONG64 cMaxBytesPerSec = 0;
370 hrc = bwGroups[i]->COMGETTER(MaxBytesPerSec)(&cMaxBytesPerSec); H();
371
372 if (enmType == BandwidthGroupType_Disk)
373 {
374 PCFGMNODE pBwGroup;
375 InsertConfigNode(pAcFileBwGroups, Utf8Str(strName).c_str(), &pBwGroup);
376 InsertConfigInteger(pBwGroup, "Max", cMaxBytesPerSec);
377 InsertConfigInteger(pBwGroup, "Start", cMaxBytesPerSec);
378 InsertConfigInteger(pBwGroup, "Step", 0);
379 }
380#ifdef VBOX_WITH_NETSHAPER
381 else if (enmType == BandwidthGroupType_Network)
382 {
383 /* Network bandwidth groups. */
384 PCFGMNODE pBwGroup;
385 InsertConfigNode(pNetworkBwGroups, Utf8Str(strName).c_str(), &pBwGroup);
386 InsertConfigInteger(pBwGroup, "Max", cMaxBytesPerSec);
387 }
388#endif /* VBOX_WITH_NETSHAPER */
389 }
390
391 /*
392 * Devices
393 */
394 PCFGMNODE pDevices = NULL; /* /Devices */
395 PCFGMNODE pDev = NULL; /* /Devices/Dev/ */
396 PCFGMNODE pInst = NULL; /* /Devices/Dev/0/ */
397 PCFGMNODE pCfg = NULL; /* /Devices/Dev/.../Config/ */
398 PCFGMNODE pLunL0 = NULL; /* /Devices/Dev/0/LUN#0/ */
399 PCFGMNODE pLunL1 = NULL; /* /Devices/Dev/0/LUN#0/AttachedDriver/ */
400 PCFGMNODE pLunL1Cfg = NULL; /* /Devices/Dev/0/LUN#0/AttachedDriver/Config */
401
402 InsertConfigNode(pRoot, "Devices", &pDevices);
403
404 InsertConfigNode(pDevices, "efi-armv8", &pDev);
405 InsertConfigNode(pDev, "0", &pInst);
406 InsertConfigNode(pInst, "Config", &pCfg);
407 InsertConfigInteger(pCfg, "GCPhysLoadAddress", 0);
408 InsertConfigString(pCfg, "EfiRom", "VBoxEFIAArch64.fd");
409 InsertConfigInteger(pCfg, "GCPhysFdtAddress", 0x40000000);
410 InsertConfigString(pCfg, "FdtId", "fdt");
411 InsertConfigNode(pInst, "LUN#0", &pLunL0);
412 InsertConfigString(pLunL0, "Driver", "ResourceStore");
413
414 vrc = RTFdtNodeAddF(hFdt, "platform-bus@%RX32", 0x0c000000); VRC();
415 vrc = RTFdtNodePropertyAddU32( hFdt, "interrupt-parent", idPHandleIntCtrl); VRC();
416 vrc = RTFdtNodePropertyAddCellsU32(hFdt, "ranges", 4, 0, 0, 0x0c000000, 0x02000000); VRC();
417 vrc = RTFdtNodePropertyAddU32( hFdt, "#address-cells", 1); VRC();
418 vrc = RTFdtNodePropertyAddU32( hFdt, "#size-cells", 1); VRC();
419 vrc = RTFdtNodePropertyAddStringList(hFdt, "compatible", 2,
420 "qemu,platform", "simple-bus"); VRC();
421 vrc = RTFdtNodeFinalize(hFdt); VRC();
422
423 InsertConfigNode(pDevices, "gic", &pDev);
424 InsertConfigNode(pDev, "0", &pInst);
425 InsertConfigInteger(pInst, "Trusted", 1);
426 InsertConfigNode(pInst, "Config", &pCfg);
427 InsertConfigInteger(pCfg, "DistributorMmioBase", 0x08000000);
428 InsertConfigInteger(pCfg, "RedistributorMmioBase", 0x080a0000);
429
430 vrc = RTFdtNodeAddF(hFdt, "intc@%RX32", 0x08000000); VRC();
431 vrc = RTFdtNodePropertyAddU32( hFdt, "phandle", idPHandleIntCtrl); VRC();
432 vrc = RTFdtNodePropertyAddCellsU32(hFdt, "reg", 8,
433 0, 0x08000000, 0, 0x10000,
434 0, 0x080a0000, 0, 0xf60000); VRC();
435 vrc = RTFdtNodePropertyAddU32( hFdt, "#redistributor-regions", 1); VRC();
436 vrc = RTFdtNodePropertyAddString( hFdt, "compatible", "arm,gic-v3"); VRC();
437 vrc = RTFdtNodePropertyAddEmpty( hFdt, "ranges"); VRC();
438 vrc = RTFdtNodePropertyAddU32( hFdt, "#size-cells", 2); VRC();
439 vrc = RTFdtNodePropertyAddU32( hFdt, "#address-cells", 2); VRC();
440 vrc = RTFdtNodePropertyAddEmpty( hFdt, "interrupt-controller"); VRC();
441 vrc = RTFdtNodePropertyAddU32( hFdt, "#interrupt-cells", 3); VRC();
442
443#if 0
444 vrc = RTFdtNodeAddF(hFdt, "its@%RX32", 0x08080000); VRC();
445 vrc = RTFdtNodePropertyAddU32( hFdt, "phandle", idPHandleIntCtrlMsi); VRC();
446 vrc = RTFdtNodePropertyAddCellsU32(hFdt, "reg", 4, 0, 0x08080000, 0, 0x20000); VRC();
447 vrc = RTFdtNodePropertyAddU32( hFdt, "#msi-cells", 1); VRC();
448 vrc = RTFdtNodePropertyAddEmpty( hFdt, "msi-controller"); VRC();
449 vrc = RTFdtNodePropertyAddString( hFdt, "compatible", "arm,gic-v3-its"); VRC();
450 vrc = RTFdtNodeFinalize(hFdt); VRC();
451#endif
452
453 vrc = RTFdtNodeFinalize(hFdt); VRC();
454
455
456 InsertConfigNode(pDevices, "qemu-fw-cfg", &pDev);
457 InsertConfigNode(pDev, "0", &pInst);
458 InsertConfigNode(pInst, "Config", &pCfg);
459 InsertConfigInteger(pCfg, "MmioSize", 4096);
460 InsertConfigInteger(pCfg, "MmioBase", 0x09020000);
461 InsertConfigInteger(pCfg, "DmaEnabled", 1);
462 InsertConfigInteger(pCfg, "QemuRamfbSupport", 1);
463 InsertConfigNode(pInst, "LUN#0", &pLunL0);
464 InsertConfigString(pLunL0, "Driver", "MainDisplay");
465
466 vrc = RTFdtNodeAddF(hFdt, "fw-cfg@%RX32", 0x09020000); VRC();
467 vrc = RTFdtNodePropertyAddEmpty( hFdt, "dma-coherent"); VRC();
468 vrc = RTFdtNodePropertyAddCellsU32(hFdt, "reg", 4, 0, 0x09020000, 0, 0x18); VRC();
469 vrc = RTFdtNodePropertyAddString( hFdt, "compatible", "qemu,fw-cfg-mmio"); VRC();
470 vrc = RTFdtNodeFinalize(hFdt); VRC();
471
472
473 InsertConfigNode(pDevices, "flash-cfi", &pDev);
474 InsertConfigNode(pDev, "0", &pInst);
475 InsertConfigNode(pInst, "Config", &pCfg);
476 InsertConfigInteger(pCfg, "BaseAddress", 64 * _1M);
477 InsertConfigInteger(pCfg, "Size", 768 * _1K);
478 InsertConfigString(pCfg, "FlashFile", "nvram");
479 /* Attach the NVRAM storage driver. */
480 InsertConfigNode(pInst, "LUN#0", &pLunL0);
481 InsertConfigString(pLunL0, "Driver", "NvramStore");
482
483 vrc = RTFdtNodeAddF(hFdt, "flash@%RX32", 0); VRC();
484 vrc = RTFdtNodePropertyAddU32( hFdt, "bank-width", 4); VRC();
485 vrc = RTFdtNodePropertyAddCellsU32(hFdt, "reg", 8,
486 0, 0, 0, 0x04000000,
487 0, 0x04000000, 0, 0x04000000); VRC();
488 vrc = RTFdtNodePropertyAddString( hFdt, "compatible", "cfi-flash"); VRC();
489 vrc = RTFdtNodeFinalize(hFdt); VRC();
490
491 InsertConfigNode(pDevices, "arm-pl011", &pDev);
492 for (ULONG ulInstance = 0; ulInstance < 1 /** @todo SchemaDefs::SerialPortCount*/; ++ulInstance)
493 {
494 ComPtr<ISerialPort> serialPort;
495 hrc = pMachine->GetSerialPort(ulInstance, serialPort.asOutParam()); H();
496 BOOL fEnabledSerPort = FALSE;
497 if (serialPort)
498 {
499 hrc = serialPort->COMGETTER(Enabled)(&fEnabledSerPort); H();
500 }
501 if (!fEnabledSerPort)
502 {
503 m_aeSerialPortMode[ulInstance] = PortMode_Disconnected;
504 continue;
505 }
506
507 InsertConfigNode(pDev, Utf8StrFmt("%u", ulInstance).c_str(), &pInst);
508 InsertConfigInteger(pInst, "Trusted", 1); /* boolean */
509 InsertConfigNode(pInst, "Config", &pCfg);
510
511 InsertConfigInteger(pCfg, "Irq", 1);
512 InsertConfigInteger(pCfg, "MmioBase", 0x09000000);
513
514 BOOL fServer;
515 hrc = serialPort->COMGETTER(Server)(&fServer); H();
516 hrc = serialPort->COMGETTER(Path)(bstr.asOutParam()); H();
517
518 PortMode_T eHostMode;
519 hrc = serialPort->COMGETTER(HostMode)(&eHostMode); H();
520
521 m_aeSerialPortMode[ulInstance] = eHostMode;
522 if (eHostMode != PortMode_Disconnected)
523 {
524 vrc = i_configSerialPort(pInst, eHostMode, Utf8Str(bstr).c_str(), RT_BOOL(fServer));
525 if (RT_FAILURE(vrc))
526 return vrc;
527 }
528 }
529
530 vrc = RTFdtNodeAddF(hFdt, "pl011@%RX32", 0x09000000); VRC();
531 vrc = RTFdtNodePropertyAddStringList(hFdt, "clock-names", 2, "uartclk", "apb_pclk"); VRC();
532 vrc = RTFdtNodePropertyAddCellsU32(hFdt, "clocks", 2,
533 idPHandleAbpPClk, idPHandleAbpPClk); VRC();
534 vrc = RTFdtNodePropertyAddCellsU32(hFdt, "interrupts", 3, 0x00, 0x01, 0x04); VRC();
535 vrc = RTFdtNodePropertyAddCellsU32(hFdt, "reg", 4, 0, 0x09000000, 0, 0x1000); VRC();
536 vrc = RTFdtNodePropertyAddStringList(hFdt, "compatible", 2,
537 "arm,pl011", "arm,primecell"); VRC();
538 vrc = RTFdtNodeFinalize(hFdt); VRC();
539
540 InsertConfigNode(pDevices, "arm-pl031-rtc", &pDev);
541 InsertConfigNode(pDev, "0", &pInst);
542 InsertConfigNode(pInst, "Config", &pCfg);
543 InsertConfigInteger(pCfg, "Irq", 2);
544 InsertConfigInteger(pCfg, "MmioBase", 0x09010000);
545 vrc = RTFdtNodeAddF(hFdt, "pl032@%RX32", 0x09010000); VRC();
546 vrc = RTFdtNodePropertyAddString( hFdt, "clock-names", "apb_pclk"); VRC();
547 vrc = RTFdtNodePropertyAddU32( hFdt, "clocks", idPHandleAbpPClk); VRC();
548 vrc = RTFdtNodePropertyAddCellsU32(hFdt, "interrupts", 3, 0x00, 0x02, 0x04); VRC();
549 vrc = RTFdtNodePropertyAddCellsU32(hFdt, "reg", 4, 0, 0x09010000, 0, 0x1000); VRC();
550 vrc = RTFdtNodePropertyAddStringList(hFdt, "compatible", 2,
551 "arm,pl031", "arm,primecell"); VRC();
552 vrc = RTFdtNodeFinalize(hFdt); VRC();
553
554 InsertConfigNode(pDevices, "arm-pl061-gpio",&pDev);
555 InsertConfigNode(pDev, "0", &pInst);
556 InsertConfigNode(pInst, "Config", &pCfg);
557 InsertConfigInteger(pCfg, "Irq", 7);
558 InsertConfigInteger(pCfg, "MmioBase", 0x09030000);
559 vrc = RTFdtNodeAddF(hFdt, "pl061@%RX32", 0x09030000); VRC();
560 vrc = RTFdtNodePropertyAddU32( hFdt, "phandle", idPHandleGpio); VRC();
561 vrc = RTFdtNodePropertyAddString( hFdt, "clock-names", "apb_pclk"); VRC();
562 vrc = RTFdtNodePropertyAddU32( hFdt, "clocks", idPHandleAbpPClk); VRC();
563 vrc = RTFdtNodePropertyAddCellsU32(hFdt, "interrupts", 3, 0x00, 0x07, 0x04); VRC();
564 vrc = RTFdtNodePropertyAddEmpty( hFdt, "gpio-controller"); VRC();
565 vrc = RTFdtNodePropertyAddU32( hFdt, "#gpio-cells", 2); VRC();
566 vrc = RTFdtNodePropertyAddStringList(hFdt, "compatible", 2,
567 "arm,pl061", "arm,primecell"); VRC();
568 vrc = RTFdtNodePropertyAddCellsU32(hFdt, "reg", 4, 0, 0x09030000, 0, 0x1000); VRC();
569 vrc = RTFdtNodeFinalize(hFdt); VRC();
570
571 InsertConfigNode(pDevices, "pci-generic-ecam", &pDev);
572 InsertConfigNode(pDev, "0", &pInst);
573 InsertConfigNode(pInst, "Config", &pCfg);
574 InsertConfigInteger(pCfg, "MmioEcamBase", 0x3f000000);
575 InsertConfigInteger(pCfg, "MmioEcamLength", 0x01000000);
576 InsertConfigInteger(pCfg, "MmioPioBase", 0x3eff0000);
577 InsertConfigInteger(pCfg, "MmioPioSize", 0x0000ffff);
578 InsertConfigInteger(pCfg, "IntPinA", 3);
579 InsertConfigInteger(pCfg, "IntPinB", 4);
580 InsertConfigInteger(pCfg, "IntPinC", 5);
581 InsertConfigInteger(pCfg, "IntPinD", 6);
582 vrc = RTFdtNodeAddF(hFdt, "pcie@%RX32", 0x10000000); VRC();
583 vrc = RTFdtNodePropertyAddCellsU32(hFdt, "interrupt-map-mask", 4, 0x1800, 0, 0, 7); VRC();
584 vrc = RTFdtNodePropertyAddCellsU32(hFdt, "interrupt-map", 16 * 10,
585 0x00, 0x00, 0x00, 0x01, idPHandleIntCtrl, 0x00, 0x00, 0x00, 0x03, 0x04,
586 0x00, 0x00, 0x00, 0x02, idPHandleIntCtrl, 0x00, 0x00, 0x00, 0x04, 0x04,
587 0x00, 0x00, 0x00, 0x03, idPHandleIntCtrl, 0x00, 0x00, 0x00, 0x05, 0x04,
588 0x00, 0x00, 0x00, 0x04, idPHandleIntCtrl, 0x00, 0x00, 0x00, 0x06, 0x04,
589 0x800, 0x00, 0x00, 0x01, idPHandleIntCtrl, 0x00, 0x00, 0x00, 0x04, 0x04,
590 0x800, 0x00, 0x00, 0x02, idPHandleIntCtrl, 0x00, 0x00, 0x00, 0x05, 0x04,
591 0x800, 0x00, 0x00, 0x03, idPHandleIntCtrl, 0x00, 0x00, 0x00, 0x06, 0x04,
592 0x800, 0x00, 0x00, 0x04, idPHandleIntCtrl, 0x00, 0x00, 0x00, 0x03, 0x04,
593 0x1000, 0x00, 0x00, 0x01, idPHandleIntCtrl, 0x00, 0x00, 0x00, 0x05, 0x04,
594 0x1000, 0x00, 0x00, 0x02, idPHandleIntCtrl, 0x00, 0x00, 0x00, 0x06, 0x04,
595 0x1000, 0x00, 0x00, 0x03, idPHandleIntCtrl, 0x00, 0x00, 0x00, 0x03, 0x04,
596 0x1000, 0x00, 0x00, 0x04, idPHandleIntCtrl, 0x00, 0x00, 0x00, 0x04, 0x04,
597 0x1800, 0x00, 0x00, 0x01, idPHandleIntCtrl, 0x00, 0x00, 0x00, 0x06, 0x04,
598 0x1800, 0x00, 0x00, 0x02, idPHandleIntCtrl, 0x00, 0x00, 0x00, 0x03, 0x04,
599 0x1800, 0x00, 0x00, 0x03, idPHandleIntCtrl, 0x00, 0x00, 0x00, 0x04, 0x04,
600 0x1800, 0x00, 0x00, 0x04, idPHandleIntCtrl, 0x00, 0x00, 0x00, 0x05, 0x04); VRC();
601 vrc = RTFdtNodePropertyAddU32( hFdt, "#interrupt-cells", 1); VRC();
602 vrc = RTFdtNodePropertyAddCellsU32(hFdt, "ranges", 14,
603 0x1000000, 0, 0, 0, 0x3eff0000, 0, 0x10000,
604 0x2000000, 0, 0x10000000, 0, 0x10000000, 0,
605 0x2eff0000); VRC();
606 vrc = RTFdtNodePropertyAddCellsU32(hFdt, "reg", 4, 0, 0x3f000000, 0, 0x1000000); VRC();
607 /** @todo msi-map */
608 vrc = RTFdtNodePropertyAddEmpty( hFdt, "dma-coherent"); VRC();
609 vrc = RTFdtNodePropertyAddCellsU32(hFdt, "bus-range", 2, 0, 0xf); VRC();
610 vrc = RTFdtNodePropertyAddU32( hFdt, "linux,pci-domain", 0); VRC();
611 vrc = RTFdtNodePropertyAddU32( hFdt, "#size-cells", 2); VRC();
612 vrc = RTFdtNodePropertyAddU32( hFdt, "#address-cells", 3); VRC();
613 vrc = RTFdtNodePropertyAddString( hFdt, "device_type", "pci"); VRC();
614 vrc = RTFdtNodePropertyAddString( hFdt, "compatible", "pci-host-ecam-generic"); VRC();
615 vrc = RTFdtNodeFinalize(hFdt); VRC();
616
617 InsertConfigNode(pDevices, "usb-xhci", &pDev);
618 InsertConfigNode(pDev, "0", &pInst);
619 InsertConfigInteger(pInst, "Trusted", 1);
620 InsertConfigInteger(pInst, "PCIBusNo", 0);
621 InsertConfigInteger(pInst, "PCIDeviceNo", 2);
622 InsertConfigInteger(pInst, "PCIFunctionNo", 0);
623 InsertConfigNode(pInst, "Config", &pCfg);
624 InsertConfigNode(pInst, "LUN#0", &pLunL0);
625 InsertConfigString(pLunL0, "Driver","VUSBRootHub");
626 InsertConfigNode(pInst, "LUN#1", &pLunL0);
627 InsertConfigString(pLunL0, "Driver","VUSBRootHub");
628
629 InsertConfigNode(pDevices, "e1000", &pDev);
630 InsertConfigNode(pDev, "0", &pInst);
631 InsertConfigInteger(pInst, "Trusted", 1);
632 InsertConfigInteger(pInst, "PCIBusNo", 0);
633 InsertConfigInteger(pInst, "PCIDeviceNo", 1);
634 InsertConfigInteger(pInst, "PCIFunctionNo", 0);
635 InsertConfigNode(pInst, "Config", &pCfg);
636 InsertConfigInteger(pCfg, "CableConnected", 1);
637 InsertConfigInteger(pCfg, "LineSpeed", 0);
638 InsertConfigInteger(pCfg, "AdapterType", 0);
639
640 const char *pszMac = "080027ede92c";
641 Assert(strlen(pszMac) == 12);
642 RTMAC Mac;
643 RT_ZERO(Mac);
644 char *pMac = (char*)&Mac;
645 for (uint32_t i = 0; i < 6; ++i)
646 {
647 int c1 = *pszMac++ - '0';
648 if (c1 > 9)
649 c1 -= 7;
650 int c2 = *pszMac++ - '0';
651 if (c2 > 9)
652 c2 -= 7;
653 *pMac++ = (char)(((c1 & 0x0f) << 4) | (c2 & 0x0f));
654 }
655 InsertConfigBytes(pCfg, "MAC", &Mac, sizeof(Mac));
656 InsertConfigNode(pInst, "LUN#0", &pLunL0);
657 InsertConfigString(pLunL0, "Driver", "NAT");
658 InsertConfigNode(pLunL0, "Config", &pLunL1Cfg);
659 InsertConfigString(pLunL1Cfg, "Network", "10.0.2.0/24");
660 InsertConfigString(pLunL1Cfg, "TFTPPrefix", "/Users/vbox/Library/VirtualBox/TFTP");
661 InsertConfigString(pLunL1Cfg, "BootFile", "default.pxe");
662 InsertConfigInteger(pLunL1Cfg, "AliasMode", 0);
663 InsertConfigInteger(pLunL1Cfg, "DNSProxy", 0);
664 InsertConfigInteger(pLunL1Cfg, "LocalhostReachable", 1);
665 InsertConfigInteger(pLunL1Cfg, "PassDomain", 1);
666 InsertConfigInteger(pLunL1Cfg, "UseHostResolver", 0);
667
668 PCFGMNODE pUsb = NULL;
669 InsertConfigNode(pRoot, "USB", &pUsb);
670
671 /*
672 * Storage controllers.
673 */
674 com::SafeIfaceArray<IStorageController> ctrls;
675 PCFGMNODE aCtrlNodes[StorageControllerType_VirtioSCSI + 1] = {};
676 hrc = pMachine->COMGETTER(StorageControllers)(ComSafeArrayAsOutParam(ctrls)); H();
677
678 for (size_t i = 0; i < ctrls.size(); ++i)
679 {
680 DeviceType_T *paLedDevType = NULL;
681
682 StorageControllerType_T enmCtrlType;
683 hrc = ctrls[i]->COMGETTER(ControllerType)(&enmCtrlType); H();
684 AssertRelease((unsigned)enmCtrlType < RT_ELEMENTS(aCtrlNodes)
685 || enmCtrlType == StorageControllerType_USB);
686
687 StorageBus_T enmBus;
688 hrc = ctrls[i]->COMGETTER(Bus)(&enmBus); H();
689
690 Bstr controllerName;
691 hrc = ctrls[i]->COMGETTER(Name)(controllerName.asOutParam()); H();
692
693 ULONG ulInstance = 999;
694 hrc = ctrls[i]->COMGETTER(Instance)(&ulInstance); H();
695
696 BOOL fUseHostIOCache;
697 hrc = ctrls[i]->COMGETTER(UseHostIOCache)(&fUseHostIOCache); H();
698
699 BOOL fBootable;
700 hrc = ctrls[i]->COMGETTER(Bootable)(&fBootable); H();
701
702 PCFGMNODE pCtlInst = NULL;
703 const char *pszCtrlDev = i_storageControllerTypeToStr(enmCtrlType);
704 if (enmCtrlType != StorageControllerType_USB)
705 {
706 /* /Devices/<ctrldev>/ */
707 pDev = aCtrlNodes[enmCtrlType];
708 if (!pDev)
709 {
710 InsertConfigNode(pDevices, pszCtrlDev, &pDev);
711 aCtrlNodes[enmCtrlType] = pDev; /* IDE variants are handled in the switch */
712 }
713
714 /* /Devices/<ctrldev>/<instance>/ */
715 InsertConfigNode(pDev, Utf8StrFmt("%u", ulInstance).c_str(), &pCtlInst);
716
717 /* Device config: /Devices/<ctrldev>/<instance>/<values> & /ditto/Config/<values> */
718 InsertConfigInteger(pCtlInst, "Trusted", 1);
719 InsertConfigNode(pCtlInst, "Config", &pCfg);
720 }
721
722 switch (enmCtrlType)
723 {
724 case StorageControllerType_USB:
725 {
726 if (pUsb)
727 {
728 /*
729 * USB MSDs are handled a bit different as the device instance
730 * doesn't match the storage controller instance but the port.
731 */
732 InsertConfigNode(pUsb, "Msd", &pDev);
733 pCtlInst = pDev;
734 }
735 else
736 return pVMM->pfnVMR3SetError(pUVM, VERR_NOT_FOUND, RT_SRC_POS,
737 N_("There is no USB controller enabled but there\n"
738 "is at least one USB storage device configured for this VM.\n"
739 "To fix this problem either enable the USB controller or remove\n"
740 "the storage device from the VM"));
741 break;
742 }
743
744 case StorageControllerType_IntelAhci:
745 {
746 InsertConfigInteger(pCtlInst, "PCIBusNo", 0);
747 InsertConfigInteger(pCtlInst, "PCIDeviceNo", 3);
748 InsertConfigInteger(pCtlInst, "PCIFunctionNo", 0);
749
750 ULONG cPorts = 0;
751 hrc = ctrls[i]->COMGETTER(PortCount)(&cPorts); H();
752 InsertConfigInteger(pCfg, "PortCount", cPorts);
753 InsertConfigInteger(pCfg, "Bootable", fBootable);
754
755 com::SafeIfaceArray<IMediumAttachment> atts;
756 hrc = pMachine->GetMediumAttachmentsOfController(controllerName.raw(),
757 ComSafeArrayAsOutParam(atts)); H();
758
759 /* Configure the hotpluggable flag for the port. */
760 for (unsigned idxAtt = 0; idxAtt < atts.size(); ++idxAtt)
761 {
762 IMediumAttachment *pMediumAtt = atts[idxAtt];
763
764 LONG lPortNum = 0;
765 hrc = pMediumAtt->COMGETTER(Port)(&lPortNum); H();
766
767 BOOL fHotPluggable = FALSE;
768 hrc = pMediumAtt->COMGETTER(HotPluggable)(&fHotPluggable); H();
769 if (SUCCEEDED(hrc))
770 {
771 PCFGMNODE pPortCfg;
772 char szName[24];
773 RTStrPrintf(szName, sizeof(szName), "Port%d", lPortNum);
774
775 InsertConfigNode(pCfg, szName, &pPortCfg);
776 InsertConfigInteger(pPortCfg, "Hotpluggable", fHotPluggable ? 1 : 0);
777 }
778 }
779 break;
780 }
781 case StorageControllerType_VirtioSCSI:
782 {
783 InsertConfigInteger(pCtlInst, "PCIBusNo", 0);
784 InsertConfigInteger(pCtlInst, "PCIDeviceNo", 3);
785 InsertConfigInteger(pCtlInst, "PCIFunctionNo", 0);
786
787 ULONG cPorts = 0;
788 hrc = ctrls[i]->COMGETTER(PortCount)(&cPorts); H();
789 InsertConfigInteger(pCfg, "NumTargets", cPorts);
790 InsertConfigInteger(pCfg, "Bootable", fBootable);
791
792 /* Attach the status driver */
793 i_attachStatusDriver(pCtlInst, RT_BIT_32(DeviceType_HardDisk) | RT_BIT_32(DeviceType_DVD) /*?*/,
794 cPorts, &paLedDevType, &mapMediumAttachments, pszCtrlDev, ulInstance);
795 break;
796 }
797
798 case StorageControllerType_LsiLogic:
799 case StorageControllerType_BusLogic:
800 case StorageControllerType_PIIX3:
801 case StorageControllerType_PIIX4:
802 case StorageControllerType_ICH6:
803 case StorageControllerType_I82078:
804 case StorageControllerType_LsiLogicSas:
805 case StorageControllerType_NVMe:
806
807 default:
808 AssertLogRelMsgFailedReturn(("invalid storage controller type: %d\n", enmCtrlType), VERR_MAIN_CONFIG_CONSTRUCTOR_IPE);
809 }
810
811 /* Attach the media to the storage controllers. */
812 com::SafeIfaceArray<IMediumAttachment> atts;
813 hrc = pMachine->GetMediumAttachmentsOfController(controllerName.raw(),
814 ComSafeArrayAsOutParam(atts)); H();
815
816 /* Builtin I/O cache - per device setting. */
817 BOOL fBuiltinIOCache = true;
818 hrc = pMachine->COMGETTER(IOCacheEnabled)(&fBuiltinIOCache); H();
819
820 bool fInsertDiskIntegrityDrv = false;
821 Bstr strDiskIntegrityFlag;
822 hrc = pMachine->GetExtraData(Bstr("VBoxInternal2/EnableDiskIntegrityDriver").raw(),
823 strDiskIntegrityFlag.asOutParam());
824 if ( hrc == S_OK
825 && strDiskIntegrityFlag == "1")
826 fInsertDiskIntegrityDrv = true;
827
828 for (size_t j = 0; j < atts.size(); ++j)
829 {
830 IMediumAttachment *pMediumAtt = atts[j];
831 vrc = i_configMediumAttachment(pszCtrlDev,
832 ulInstance,
833 enmBus,
834 !!fUseHostIOCache,
835 enmCtrlType == StorageControllerType_NVMe ? false : !!fBuiltinIOCache,
836 fInsertDiskIntegrityDrv,
837 false /* fSetupMerge */,
838 0 /* uMergeSource */,
839 0 /* uMergeTarget */,
840 pMediumAtt,
841 mMachineState,
842 NULL /* phrc */,
843 false /* fAttachDetach */,
844 false /* fForceUnmount */,
845 false /* fHotplug */,
846 pUVM,
847 pVMM,
848 paLedDevType,
849 NULL /* ppLunL0 */);
850 if (RT_FAILURE(vrc))
851 return vrc;
852 }
853 H();
854 }
855 H();
856
857 InsertConfigNode(pUsb, "HidKeyboard", &pDev);
858 InsertConfigNode(pDev, "0", &pInst);
859 InsertConfigInteger(pInst, "Trusted", 1);
860 InsertConfigNode(pInst, "Config", &pCfg);
861 InsertConfigNode(pInst, "LUN#0", &pLunL0);
862 InsertConfigString(pLunL0, "Driver", "KeyboardQueue");
863 InsertConfigNode(pLunL0, "AttachedDriver", &pLunL1);
864 InsertConfigString(pLunL1, "Driver", "MainKeyboard");
865
866 InsertConfigNode(pUsb, "HidMouse", &pDev);
867 InsertConfigNode(pDev, "0", &pInst);
868 InsertConfigNode(pInst, "Config", &pCfg);
869 InsertConfigString(pCfg, "Mode", "absolute");
870 InsertConfigNode(pInst, "LUN#0", &pLunL0);
871 InsertConfigString(pLunL0, "Driver", "MouseQueue");
872 InsertConfigNode(pLunL0, "Config", &pCfg);
873 InsertConfigInteger(pCfg, "QueueSize", 128);
874
875 InsertConfigNode(pLunL0, "AttachedDriver", &pLunL1);
876 InsertConfigString(pLunL1, "Driver", "MainMouse");
877 }
878 catch (ConfigError &x)
879 {
880 RTFdtDestroy(hFdt);
881
882 // InsertConfig threw something:
883 pVMM->pfnVMR3SetError(pUVM, x.m_vrc, RT_SRC_POS, "Caught ConfigError: %Rrc - %s", x.m_vrc, x.what());
884 return x.m_vrc;
885 }
886 catch (HRESULT hrcXcpt)
887 {
888 RTFdtDestroy(hFdt);
889 AssertLogRelMsgFailedReturn(("hrc=%Rhrc\n", hrcXcpt), VERR_MAIN_CONFIG_CONSTRUCTOR_COM_ERROR);
890 }
891
892#ifdef VBOX_WITH_EXTPACK
893 /*
894 * Call the extension pack hooks if everything went well thus far.
895 */
896 if (RT_SUCCESS(vrc))
897 {
898 pAlock->release();
899 vrc = mptrExtPackManager->i_callAllVmConfigureVmmHooks(this, pVM, pVMM);
900 pAlock->acquire();
901 }
902#endif
903
904 /* Finalize the FDT and add it to the resource store. */
905 vrc = RTFdtFinalize(hFdt);
906 AssertRCReturnStmt(vrc, RTFdtDestroy(hFdt), vrc);
907
908 RTVFSFILE hVfsFileFdt = NIL_RTVFSFILE;
909 vrc = RTVfsMemFileCreate(NIL_RTVFSIOSTREAM, 0 /*cbEstimate*/, &hVfsFileFdt);
910 AssertRCReturnStmt(vrc, RTFdtDestroy(hFdt), vrc);
911 RTVFSIOSTREAM hVfsIosFdt = RTVfsFileToIoStream(hVfsFileFdt);
912 AssertRelease(hVfsIosFdt != NIL_RTVFSIOSTREAM);
913
914 vrc = RTFdtDumpToVfsIoStrm(hFdt, RTFDTTYPE_DTB, 0 /*fFlags*/, hVfsIosFdt, NULL /*pErrInfo*/);
915 RTVfsIoStrmRelease(hVfsIosFdt);
916 if (RT_SUCCESS(vrc))
917 vrc = mptrResourceStore->i_addItem("fdt", "fdt", hVfsFileFdt);
918 RTVfsFileRelease(hVfsFileFdt);
919 AssertRCReturnStmt(vrc, RTFdtDestroy(hFdt), vrc);
920
921 /* Dump the DTB for debugging purposes if requested. */
922 Bstr DtbDumpVal;
923 hrc = mMachine->GetExtraData(Bstr("VBoxInternal2/DumpDtb").raw(),
924 DtbDumpVal.asOutParam());
925 if ( hrc == S_OK
926 && DtbDumpVal.isNotEmpty())
927 {
928 vrc = RTFdtDumpToFile(hFdt, RTFDTTYPE_DTB, 0 /*fFlags*/, Utf8Str(DtbDumpVal).c_str(), NULL /*pErrInfo*/);
929 AssertRCReturnStmt(vrc, RTFdtDestroy(hFdt), vrc);
930 }
931
932
933 /*
934 * Apply the CFGM overlay.
935 */
936 if (RT_SUCCESS(vrc))
937 vrc = i_configCfgmOverlay(pRoot, virtualBox, pMachine);
938
939 /*
940 * Dump all extradata API settings tweaks, both global and per VM.
941 */
942 if (RT_SUCCESS(vrc))
943 vrc = i_configDumpAPISettingsTweaks(virtualBox, pMachine);
944
945#undef H
946
947 pAlock->release(); /* Avoid triggering the lock order inversion check. */
948
949 /*
950 * Register VM state change handler.
951 */
952 int vrc2 = pVMM->pfnVMR3AtStateRegister(pUVM, Console::i_vmstateChangeCallback, this);
953 AssertRC(vrc2);
954 if (RT_SUCCESS(vrc))
955 vrc = vrc2;
956
957 /*
958 * Register VM runtime error handler.
959 */
960 vrc2 = pVMM->pfnVMR3AtRuntimeErrorRegister(pUVM, Console::i_atVMRuntimeErrorCallback, this);
961 AssertRC(vrc2);
962 if (RT_SUCCESS(vrc))
963 vrc = vrc2;
964
965 pAlock->acquire();
966
967 LogFlowFunc(("vrc = %Rrc\n", vrc));
968 LogFlowFuncLeave();
969
970 return vrc;
971}
972#endif /* !VBOX_WITH_VIRT_ARMV8 */
973
Note: See TracBrowser for help on using the repository browser.

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