VirtualBox

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

Last change on this file since 100842 was 100717, checked in by vboxsync, 17 months ago

Main/src-client/ConsoleImplConfigArmV8: Mirror the network settings code from x86 to get all the options configured for a VM like bridging, etc., bugref:10384 [follow up fix as IOM only supports guest page size aligned ranges right now]

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 61.8 KB
Line 
1/* $Id: ConsoleImplConfigArmV8.cpp 100717 2023-07-27 12:18:19Z 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#include "VMMDev.h"
39
40// generated header
41#include "SchemaDefs.h"
42
43#include "AutoCaller.h"
44
45#include <iprt/base64.h>
46#include <iprt/buildconfig.h>
47#include <iprt/ctype.h>
48#include <iprt/dir.h>
49#include <iprt/fdt.h>
50#include <iprt/file.h>
51#include <iprt/param.h>
52#include <iprt/path.h>
53#include <iprt/string.h>
54#include <iprt/system.h>
55#if 0 /* enable to play with lots of memory. */
56# include <iprt/env.h>
57#endif
58#include <iprt/stream.h>
59
60#include <iprt/formats/arm-psci.h>
61
62#include <VBox/vmm/vmmr3vtable.h>
63#include <VBox/vmm/vmapi.h>
64#include <VBox/err.h>
65#include <VBox/param.h>
66#include <VBox/version.h>
67#ifdef VBOX_WITH_SHARED_CLIPBOARD
68# include <VBox/HostServices/VBoxClipboardSvc.h>
69#endif
70#ifdef VBOX_WITH_DRAG_AND_DROP
71# include "GuestImpl.h"
72# include "GuestDnDPrivate.h"
73#endif
74
75#ifdef VBOX_WITH_EXTPACK
76# include "ExtPackManagerImpl.h"
77#endif
78
79
80/*********************************************************************************************************************************
81* Internal Functions *
82*********************************************************************************************************************************/
83
84/* Darwin compile kludge */
85#undef PVM
86
87#ifdef VBOX_WITH_VIRT_ARMV8
88/**
89 * Worker for configConstructor.
90 *
91 * @return VBox status code.
92 * @param pUVM The user mode VM handle.
93 * @param pVM The cross context VM handle.
94 * @param pVMM The VMM vtable.
95 * @param pAlock The automatic lock instance. This is for when we have
96 * to leave it in order to avoid deadlocks (ext packs and
97 * more).
98 *
99 * @todo This is a big hack at the moment and provides a static VM config to work with, will be adjusted later
100 * on to adhere to the VM config when sorting out the API bits.
101 */
102int Console::i_configConstructorArmV8(PUVM pUVM, PVM pVM, PCVMMR3VTABLE pVMM, AutoWriteLock *pAlock)
103{
104 RT_NOREF(pVM /* when everything is disabled */);
105 VMMDev *pVMMDev = m_pVMMDev; Assert(pVMMDev);
106 ComPtr<IMachine> pMachine = i_machine();
107
108 HRESULT hrc;
109 Utf8Str strTmp;
110 Bstr bstr;
111
112 RTFDT hFdt = NIL_RTFDT;
113 int vrc = RTFdtCreateEmpty(&hFdt);
114 AssertRCReturn(vrc, vrc);
115
116#define H() AssertLogRelMsgReturnStmt(!FAILED(hrc), ("hrc=%Rhrc\n", hrc), RTFdtDestroy(hFdt), VERR_MAIN_CONFIG_CONSTRUCTOR_COM_ERROR)
117#define VRC() AssertLogRelMsgReturnStmt(RT_SUCCESS(vrc), ("vrc=%Rrc\n", vrc), RTFdtDestroy(hFdt), vrc)
118
119
120 /*
121 * Get necessary objects and frequently used parameters.
122 */
123 ComPtr<IVirtualBox> virtualBox;
124 hrc = pMachine->COMGETTER(Parent)(virtualBox.asOutParam()); H();
125
126 ComPtr<IHost> host;
127 hrc = virtualBox->COMGETTER(Host)(host.asOutParam()); H();
128
129 ComPtr<ISystemProperties> systemProperties;
130 hrc = virtualBox->COMGETTER(SystemProperties)(systemProperties.asOutParam()); H();
131
132 ComPtr<IBIOSSettings> biosSettings;
133 hrc = pMachine->COMGETTER(BIOSSettings)(biosSettings.asOutParam()); H();
134
135 ComPtr<INvramStore> nvramStore;
136 hrc = pMachine->COMGETTER(NonVolatileStore)(nvramStore.asOutParam()); H();
137
138 hrc = pMachine->COMGETTER(HardwareUUID)(bstr.asOutParam()); H();
139 RTUUID HardwareUuid;
140 vrc = RTUuidFromUtf16(&HardwareUuid, bstr.raw());
141 AssertRCReturn(vrc, vrc);
142
143 ULONG cRamMBs;
144 hrc = pMachine->COMGETTER(MemorySize)(&cRamMBs); H();
145 uint64_t const cbRam = cRamMBs * (uint64_t)_1M;
146
147 /** @todo This will be 100% wrong but is required for getting the maximum number of network adapters. */
148 ChipsetType_T chipsetType;
149 hrc = pMachine->COMGETTER(ChipsetType)(&chipsetType); H();
150
151 ULONG cCpus = 1;
152 hrc = pMachine->COMGETTER(CPUCount)(&cCpus); H();
153
154 ULONG ulCpuExecutionCap = 100;
155 hrc = pMachine->COMGETTER(CPUExecutionCap)(&ulCpuExecutionCap); H();
156
157 Bstr osTypeId;
158 hrc = pMachine->COMGETTER(OSTypeId)(osTypeId.asOutParam()); H();
159 LogRel(("Guest OS type: '%s'\n", Utf8Str(osTypeId).c_str()));
160
161 ULONG maxNetworkAdapters;
162 hrc = systemProperties->GetMaxNetworkAdapters(chipsetType, &maxNetworkAdapters); H();
163
164 /*
165 * Get root node first.
166 * This is the only node in the tree.
167 */
168 PCFGMNODE pRoot = pVMM->pfnCFGMR3GetRootU(pUVM);
169 Assert(pRoot);
170
171 // catching throws from InsertConfigString and friends.
172 try
173 {
174
175 /*
176 * Set the root (and VMM) level values.
177 */
178 hrc = pMachine->COMGETTER(Name)(bstr.asOutParam()); H();
179 InsertConfigString(pRoot, "Name", bstr);
180 InsertConfigBytes(pRoot, "UUID", &HardwareUuid, sizeof(HardwareUuid));
181 InsertConfigInteger(pRoot, "NumCPUs", cCpus);
182 InsertConfigInteger(pRoot, "CpuExecutionCap", ulCpuExecutionCap);
183 InsertConfigInteger(pRoot, "TimerMillies", 10);
184
185 uint32_t idPHandleIntCtrl = RTFdtPHandleAllocate(hFdt);
186 Assert(idPHandleIntCtrl != UINT32_MAX);
187 uint32_t idPHandleIntCtrlMsi = RTFdtPHandleAllocate(hFdt);
188 Assert(idPHandleIntCtrlMsi != UINT32_MAX); RT_NOREF(idPHandleIntCtrlMsi);
189 uint32_t idPHandleAbpPClk = RTFdtPHandleAllocate(hFdt);
190 Assert(idPHandleAbpPClk != UINT32_MAX);
191 uint32_t idPHandleGpio = RTFdtPHandleAllocate(hFdt);
192 Assert(idPHandleGpio != UINT32_MAX);
193
194 uint32_t aidPHandleCpus[VMM_MAX_CPU_COUNT];
195 for (uint32_t i = 0; i < cCpus; i++)
196 {
197 aidPHandleCpus[i] = RTFdtPHandleAllocate(hFdt);
198 Assert(aidPHandleCpus[i] != UINT32_MAX);
199 }
200
201 vrc = RTFdtNodePropertyAddU32( hFdt, "interrupt-parent", idPHandleIntCtrl); VRC();
202 vrc = RTFdtNodePropertyAddString(hFdt, "model", "linux,dummy-virt"); VRC();
203 vrc = RTFdtNodePropertyAddU32( hFdt, "#size-cells", 2); VRC();
204 vrc = RTFdtNodePropertyAddU32( hFdt, "#address-cells", 2); VRC();
205 vrc = RTFdtNodePropertyAddString(hFdt, "compatible", "linux,dummy-virt"); VRC();
206
207 /* Configure the Power State Coordination Interface. */
208 vrc = RTFdtNodeAdd(hFdt, "psci"); VRC();
209 vrc = RTFdtNodePropertyAddU32( hFdt, "migrate", ARM_PSCI_FUNC_ID_CREATE_FAST_32(ARM_PSCI_FUNC_ID_MIGRATE)); VRC();
210 vrc = RTFdtNodePropertyAddU32( hFdt, "cpu_on", ARM_PSCI_FUNC_ID_CREATE_FAST_32(ARM_PSCI_FUNC_ID_CPU_ON)); VRC();
211 vrc = RTFdtNodePropertyAddU32( hFdt, "cpu_off", ARM_PSCI_FUNC_ID_CREATE_FAST_32(ARM_PSCI_FUNC_ID_CPU_OFF)); VRC();
212 vrc = RTFdtNodePropertyAddU32( hFdt, "cpu_suspend", ARM_PSCI_FUNC_ID_CREATE_FAST_32(ARM_PSCI_FUNC_ID_CPU_SUSPEND)); VRC();
213 vrc = RTFdtNodePropertyAddString(hFdt, "method", "hvc"); VRC();
214 vrc = RTFdtNodePropertyAddStringList(hFdt, "compatible", 3,
215 "arm,psci-1.0", "arm,psci-0.2", "arm,psci"); VRC();
216 vrc = RTFdtNodeFinalize(hFdt); VRC();
217
218 /* Configure some misc system wide properties. */
219 vrc = RTFdtNodeAdd(hFdt, "chosen"); VRC();
220 vrc = RTFdtNodePropertyAddString(hFdt, "stdout-path", "/pl011@9000000"); VRC();
221 vrc = RTFdtNodeFinalize(hFdt);
222
223 /* Configure the timer and clock. */
224 vrc = RTFdtNodeAdd(hFdt, "timer"); VRC();
225 vrc = RTFdtNodePropertyAddCellsU32(hFdt, "interrupts", 12,
226 0x01, 0x0d, 0x104,
227 0x01, 0x0e, 0x104,
228 0x01, 0x0b, 0x104,
229 0x01, 0x0a, 0x104); VRC();
230 vrc = RTFdtNodePropertyAddEmpty( hFdt, "always-on"); VRC();
231 vrc = RTFdtNodePropertyAddString( hFdt, "compatible", "arm,armv7-timer"); VRC();
232 vrc = RTFdtNodeFinalize(hFdt);
233
234 vrc = RTFdtNodeAdd(hFdt, "apb-clk"); VRC();
235 vrc = RTFdtNodePropertyAddU32( hFdt, "phandle", idPHandleAbpPClk); VRC();
236 vrc = RTFdtNodePropertyAddString( hFdt, "clock-output-names", "clk24mhz"); VRC();
237 vrc = RTFdtNodePropertyAddU32( hFdt, "clock-frequency", 24 * 1000 * 1000); VRC();
238 vrc = RTFdtNodePropertyAddU32( hFdt, "#clock-cells", 0); VRC();
239 vrc = RTFdtNodePropertyAddString( hFdt, "compatible", "fixed-clock"); VRC();
240 vrc = RTFdtNodeFinalize(hFdt);
241
242 /* Configure gpio keys (non functional at the moment). */
243 vrc = RTFdtNodeAdd(hFdt, "gpio-keys"); VRC();
244 vrc = RTFdtNodePropertyAddString(hFdt, "compatible", "gpio-keys"); VRC();
245
246 vrc = RTFdtNodeAdd(hFdt, "poweroff"); VRC();
247 vrc = RTFdtNodePropertyAddCellsU32(hFdt, "gpios", 3, idPHandleGpio, 3, 0); VRC();
248 vrc = RTFdtNodePropertyAddU32( hFdt, "linux,code", 0x74); VRC();
249 vrc = RTFdtNodePropertyAddString( hFdt, "label", "GPIO Key Poweroff"); VRC();
250 vrc = RTFdtNodeFinalize(hFdt); VRC();
251
252 vrc = RTFdtNodeFinalize(hFdt); VRC();
253
254 /*
255 * NEM
256 */
257 PCFGMNODE pNEM;
258 InsertConfigNode(pRoot, "NEM", &pNEM);
259
260 /*
261 * MM values.
262 */
263 PCFGMNODE pMM;
264 InsertConfigNode(pRoot, "MM", &pMM);
265
266 /*
267 * Memory setup.
268 */
269 PCFGMNODE pMem = NULL;
270 InsertConfigNode(pMM, "MemRegions", &pMem);
271
272 PCFGMNODE pMemRegion = NULL;
273 InsertConfigNode(pMem, "Conventional", &pMemRegion);
274 InsertConfigInteger(pMemRegion, "GCPhysStart", 0x40000000);
275 InsertConfigInteger(pMemRegion, "Size", cbRam);
276
277 vrc = RTFdtNodeAddF(hFdt, "memory@%RX32", 0x40000000); VRC();
278 vrc = RTFdtNodePropertyAddCellsU32(hFdt, "reg", 4,
279 0, 0x40000000,
280 (uint32_t)(cbRam >> 32), cbRam & UINT32_MAX); VRC();
281 vrc = RTFdtNodePropertyAddString( hFdt, "device_type", "memory"); VRC();
282 vrc = RTFdtNodeFinalize(hFdt); VRC();
283
284 /* Configure the CPUs in the system, only one socket and cluster at the moment. */
285 vrc = RTFdtNodeAdd(hFdt, "cpus"); VRC();
286 vrc = RTFdtNodePropertyAddU32(hFdt, "#size-cells", 0); VRC();
287 vrc = RTFdtNodePropertyAddU32(hFdt, "#address-cells", 1); VRC();
288
289 vrc = RTFdtNodeAdd(hFdt, "socket0"); VRC();
290 vrc = RTFdtNodeAdd(hFdt, "cluster0"); VRC();
291
292 for (uint32_t i = 0; i < cCpus; i++)
293 {
294 vrc = RTFdtNodeAddF(hFdt, "core%u", i); VRC();
295 vrc = RTFdtNodePropertyAddU32(hFdt, "cpu", aidPHandleCpus[i]); VRC();
296 vrc = RTFdtNodeFinalize(hFdt); VRC();
297 }
298
299 vrc = RTFdtNodeFinalize(hFdt); VRC();
300 vrc = RTFdtNodeFinalize(hFdt); VRC();
301
302 for (uint32_t i = 0; i < cCpus; i++)
303 {
304 vrc = RTFdtNodeAddF(hFdt, "cpu@%u", i); VRC();
305 vrc = RTFdtNodePropertyAddU32(hFdt, "phandle", aidPHandleCpus[i]); VRC();
306 vrc = RTFdtNodePropertyAddU32(hFdt, "reg", i); VRC();
307 vrc = RTFdtNodePropertyAddString(hFdt, "compatible", "arm,cortex-a15"); VRC();
308 vrc = RTFdtNodePropertyAddString(hFdt, "device_type", "cpu"); VRC();
309 if (cCpus > 1)
310 {
311 vrc = RTFdtNodePropertyAddString(hFdt, "enable-method", "psci"); VRC();
312 }
313 vrc = RTFdtNodeFinalize(hFdt); VRC();
314 }
315
316 vrc = RTFdtNodeFinalize(hFdt); VRC();
317
318
319 /*
320 * PDM config.
321 * Load drivers in VBoxC.[so|dll]
322 */
323 PCFGMNODE pPDM;
324 PCFGMNODE pNode;
325 PCFGMNODE pMod;
326 InsertConfigNode(pRoot, "PDM", &pPDM);
327 InsertConfigNode(pPDM, "Devices", &pNode);
328 InsertConfigNode(pPDM, "Drivers", &pNode);
329 InsertConfigNode(pNode, "VBoxC", &pMod);
330#ifdef VBOX_WITH_XPCOM
331 // VBoxC is located in the components subdirectory
332 char szPathVBoxC[RTPATH_MAX];
333 vrc = RTPathAppPrivateArch(szPathVBoxC, RTPATH_MAX - sizeof("/components/VBoxC")); AssertRC(vrc);
334 strcat(szPathVBoxC, "/components/VBoxC");
335 InsertConfigString(pMod, "Path", szPathVBoxC);
336#else
337 InsertConfigString(pMod, "Path", "VBoxC");
338#endif
339
340
341 /*
342 * Block cache settings.
343 */
344 PCFGMNODE pPDMBlkCache;
345 InsertConfigNode(pPDM, "BlkCache", &pPDMBlkCache);
346
347 /* I/O cache size */
348 ULONG ioCacheSize = 5;
349 hrc = pMachine->COMGETTER(IOCacheSize)(&ioCacheSize); H();
350 InsertConfigInteger(pPDMBlkCache, "CacheSize", ioCacheSize * _1M);
351
352 /*
353 * Bandwidth groups.
354 */
355 ComPtr<IBandwidthControl> bwCtrl;
356
357 hrc = pMachine->COMGETTER(BandwidthControl)(bwCtrl.asOutParam()); H();
358
359 com::SafeIfaceArray<IBandwidthGroup> bwGroups;
360 hrc = bwCtrl->GetAllBandwidthGroups(ComSafeArrayAsOutParam(bwGroups)); H();
361
362 PCFGMNODE pAc;
363 InsertConfigNode(pPDM, "AsyncCompletion", &pAc);
364 PCFGMNODE pAcFile;
365 InsertConfigNode(pAc, "File", &pAcFile);
366 PCFGMNODE pAcFileBwGroups;
367 InsertConfigNode(pAcFile, "BwGroups", &pAcFileBwGroups);
368#ifdef VBOX_WITH_NETSHAPER
369 PCFGMNODE pNetworkShaper;
370 InsertConfigNode(pPDM, "NetworkShaper", &pNetworkShaper);
371 PCFGMNODE pNetworkBwGroups;
372 InsertConfigNode(pNetworkShaper, "BwGroups", &pNetworkBwGroups);
373#endif /* VBOX_WITH_NETSHAPER */
374
375 for (size_t i = 0; i < bwGroups.size(); i++)
376 {
377 Bstr strName;
378 hrc = bwGroups[i]->COMGETTER(Name)(strName.asOutParam()); H();
379 if (strName.isEmpty())
380 return pVMM->pfnVMR3SetError(pUVM, VERR_CFGM_NO_NODE, RT_SRC_POS, N_("No bandwidth group name specified"));
381
382 BandwidthGroupType_T enmType = BandwidthGroupType_Null;
383 hrc = bwGroups[i]->COMGETTER(Type)(&enmType); H();
384 LONG64 cMaxBytesPerSec = 0;
385 hrc = bwGroups[i]->COMGETTER(MaxBytesPerSec)(&cMaxBytesPerSec); H();
386
387 if (enmType == BandwidthGroupType_Disk)
388 {
389 PCFGMNODE pBwGroup;
390 InsertConfigNode(pAcFileBwGroups, Utf8Str(strName).c_str(), &pBwGroup);
391 InsertConfigInteger(pBwGroup, "Max", cMaxBytesPerSec);
392 InsertConfigInteger(pBwGroup, "Start", cMaxBytesPerSec);
393 InsertConfigInteger(pBwGroup, "Step", 0);
394 }
395#ifdef VBOX_WITH_NETSHAPER
396 else if (enmType == BandwidthGroupType_Network)
397 {
398 /* Network bandwidth groups. */
399 PCFGMNODE pBwGroup;
400 InsertConfigNode(pNetworkBwGroups, Utf8Str(strName).c_str(), &pBwGroup);
401 InsertConfigInteger(pBwGroup, "Max", cMaxBytesPerSec);
402 }
403#endif /* VBOX_WITH_NETSHAPER */
404 }
405
406 /*
407 * Devices
408 */
409 PCFGMNODE pDevices = NULL; /* /Devices */
410 PCFGMNODE pDev = NULL; /* /Devices/Dev/ */
411 PCFGMNODE pInst = NULL; /* /Devices/Dev/0/ */
412 PCFGMNODE pCfg = NULL; /* /Devices/Dev/.../Config/ */
413 PCFGMNODE pLunL0 = NULL; /* /Devices/Dev/0/LUN#0/ */
414 PCFGMNODE pLunL1 = NULL; /* /Devices/Dev/0/LUN#0/AttachedDriver/ */
415
416 InsertConfigNode(pRoot, "Devices", &pDevices);
417
418 InsertConfigNode(pDevices, "efi-armv8", &pDev);
419 InsertConfigNode(pDev, "0", &pInst);
420 InsertConfigNode(pInst, "Config", &pCfg);
421 InsertConfigInteger(pCfg, "GCPhysLoadAddress", 0);
422 InsertConfigString(pCfg, "EfiRom", "VBoxEFIAArch64.fd");
423 InsertConfigInteger(pCfg, "GCPhysFdtAddress", 0x40000000);
424 InsertConfigString(pCfg, "FdtId", "fdt");
425 InsertConfigNode(pInst, "LUN#0", &pLunL0);
426 InsertConfigString(pLunL0, "Driver", "ResourceStore");
427
428 vrc = RTFdtNodeAddF(hFdt, "platform-bus@%RX32", 0x0c000000); VRC();
429 vrc = RTFdtNodePropertyAddU32( hFdt, "interrupt-parent", idPHandleIntCtrl); VRC();
430 vrc = RTFdtNodePropertyAddCellsU32(hFdt, "ranges", 4, 0, 0, 0x0c000000, 0x02000000); VRC();
431 vrc = RTFdtNodePropertyAddU32( hFdt, "#address-cells", 1); VRC();
432 vrc = RTFdtNodePropertyAddU32( hFdt, "#size-cells", 1); VRC();
433 vrc = RTFdtNodePropertyAddStringList(hFdt, "compatible", 2,
434 "qemu,platform", "simple-bus"); VRC();
435 vrc = RTFdtNodeFinalize(hFdt); VRC();
436
437 InsertConfigNode(pDevices, "gic", &pDev);
438 InsertConfigNode(pDev, "0", &pInst);
439 InsertConfigInteger(pInst, "Trusted", 1);
440 InsertConfigNode(pInst, "Config", &pCfg);
441 InsertConfigInteger(pCfg, "DistributorMmioBase", 0x08000000);
442 InsertConfigInteger(pCfg, "RedistributorMmioBase", 0x080a0000);
443
444 vrc = RTFdtNodeAddF(hFdt, "intc@%RX32", 0x08000000); VRC();
445 vrc = RTFdtNodePropertyAddU32( hFdt, "phandle", idPHandleIntCtrl); VRC();
446 vrc = RTFdtNodePropertyAddCellsU32(hFdt, "reg", 8,
447 0, 0x08000000, 0, 0x10000,
448 0, 0x080a0000, 0, 0xf60000); VRC();
449 vrc = RTFdtNodePropertyAddU32( hFdt, "#redistributor-regions", 1); VRC();
450 vrc = RTFdtNodePropertyAddString( hFdt, "compatible", "arm,gic-v3"); VRC();
451 vrc = RTFdtNodePropertyAddEmpty( hFdt, "ranges"); VRC();
452 vrc = RTFdtNodePropertyAddU32( hFdt, "#size-cells", 2); VRC();
453 vrc = RTFdtNodePropertyAddU32( hFdt, "#address-cells", 2); VRC();
454 vrc = RTFdtNodePropertyAddEmpty( hFdt, "interrupt-controller"); VRC();
455 vrc = RTFdtNodePropertyAddU32( hFdt, "#interrupt-cells", 3); VRC();
456
457#if 0
458 vrc = RTFdtNodeAddF(hFdt, "its@%RX32", 0x08080000); VRC();
459 vrc = RTFdtNodePropertyAddU32( hFdt, "phandle", idPHandleIntCtrlMsi); VRC();
460 vrc = RTFdtNodePropertyAddCellsU32(hFdt, "reg", 4, 0, 0x08080000, 0, 0x20000); VRC();
461 vrc = RTFdtNodePropertyAddU32( hFdt, "#msi-cells", 1); VRC();
462 vrc = RTFdtNodePropertyAddEmpty( hFdt, "msi-controller"); VRC();
463 vrc = RTFdtNodePropertyAddString( hFdt, "compatible", "arm,gic-v3-its"); VRC();
464 vrc = RTFdtNodeFinalize(hFdt); VRC();
465#endif
466
467 vrc = RTFdtNodeFinalize(hFdt); VRC();
468
469
470 InsertConfigNode(pDevices, "qemu-fw-cfg", &pDev);
471 InsertConfigNode(pDev, "0", &pInst);
472 InsertConfigNode(pInst, "Config", &pCfg);
473 InsertConfigInteger(pCfg, "MmioSize", 4096);
474 InsertConfigInteger(pCfg, "MmioBase", 0x09020000);
475 InsertConfigInteger(pCfg, "DmaEnabled", 1);
476 InsertConfigInteger(pCfg, "QemuRamfbSupport", 0);
477 InsertConfigNode(pInst, "LUN#0", &pLunL0);
478 InsertConfigString(pLunL0, "Driver", "MainDisplay");
479
480 vrc = RTFdtNodeAddF(hFdt, "fw-cfg@%RX32", 0x09020000); VRC();
481 vrc = RTFdtNodePropertyAddEmpty( hFdt, "dma-coherent"); VRC();
482 vrc = RTFdtNodePropertyAddCellsU32(hFdt, "reg", 4, 0, 0x09020000, 0, 0x18); VRC();
483 vrc = RTFdtNodePropertyAddString( hFdt, "compatible", "qemu,fw-cfg-mmio"); VRC();
484 vrc = RTFdtNodeFinalize(hFdt); VRC();
485
486
487 InsertConfigNode(pDevices, "flash-cfi", &pDev);
488 InsertConfigNode(pDev, "0", &pInst);
489 InsertConfigNode(pInst, "Config", &pCfg);
490 InsertConfigInteger(pCfg, "BaseAddress", 64 * _1M);
491 InsertConfigInteger(pCfg, "Size", 768 * _1K);
492 InsertConfigString(pCfg, "FlashFile", "nvram");
493 /* Attach the NVRAM storage driver. */
494 InsertConfigNode(pInst, "LUN#0", &pLunL0);
495 InsertConfigString(pLunL0, "Driver", "NvramStore");
496
497 vrc = RTFdtNodeAddF(hFdt, "flash@%RX32", 0); VRC();
498 vrc = RTFdtNodePropertyAddU32( hFdt, "bank-width", 4); VRC();
499 vrc = RTFdtNodePropertyAddCellsU32(hFdt, "reg", 8,
500 0, 0, 0, 0x04000000,
501 0, 0x04000000, 0, 0x04000000); VRC();
502 vrc = RTFdtNodePropertyAddString( hFdt, "compatible", "cfi-flash"); VRC();
503 vrc = RTFdtNodeFinalize(hFdt); VRC();
504
505 InsertConfigNode(pDevices, "arm-pl011", &pDev);
506 for (ULONG ulInstance = 0; ulInstance < 1 /** @todo SchemaDefs::SerialPortCount*/; ++ulInstance)
507 {
508 ComPtr<ISerialPort> serialPort;
509 hrc = pMachine->GetSerialPort(ulInstance, serialPort.asOutParam()); H();
510 BOOL fEnabledSerPort = FALSE;
511 if (serialPort)
512 {
513 hrc = serialPort->COMGETTER(Enabled)(&fEnabledSerPort); H();
514 }
515 if (!fEnabledSerPort)
516 {
517 m_aeSerialPortMode[ulInstance] = PortMode_Disconnected;
518 continue;
519 }
520
521 InsertConfigNode(pDev, Utf8StrFmt("%u", ulInstance).c_str(), &pInst);
522 InsertConfigInteger(pInst, "Trusted", 1); /* boolean */
523 InsertConfigNode(pInst, "Config", &pCfg);
524
525 InsertConfigInteger(pCfg, "Irq", 1);
526 InsertConfigInteger(pCfg, "MmioBase", 0x09000000);
527
528 BOOL fServer;
529 hrc = serialPort->COMGETTER(Server)(&fServer); H();
530 hrc = serialPort->COMGETTER(Path)(bstr.asOutParam()); H();
531
532 PortMode_T eHostMode;
533 hrc = serialPort->COMGETTER(HostMode)(&eHostMode); H();
534
535 m_aeSerialPortMode[ulInstance] = eHostMode;
536 if (eHostMode != PortMode_Disconnected)
537 {
538 vrc = i_configSerialPort(pInst, eHostMode, Utf8Str(bstr).c_str(), RT_BOOL(fServer));
539 if (RT_FAILURE(vrc))
540 return vrc;
541 }
542 }
543
544 vrc = RTFdtNodeAddF(hFdt, "pl011@%RX32", 0x09000000); VRC();
545 vrc = RTFdtNodePropertyAddStringList(hFdt, "clock-names", 2, "uartclk", "apb_pclk"); VRC();
546 vrc = RTFdtNodePropertyAddCellsU32(hFdt, "clocks", 2,
547 idPHandleAbpPClk, idPHandleAbpPClk); VRC();
548 vrc = RTFdtNodePropertyAddCellsU32(hFdt, "interrupts", 3, 0x00, 0x01, 0x04); VRC();
549 vrc = RTFdtNodePropertyAddCellsU32(hFdt, "reg", 4, 0, 0x09000000, 0, 0x1000); VRC();
550 vrc = RTFdtNodePropertyAddStringList(hFdt, "compatible", 2,
551 "arm,pl011", "arm,primecell"); VRC();
552 vrc = RTFdtNodeFinalize(hFdt); VRC();
553
554 InsertConfigNode(pDevices, "arm-pl031-rtc", &pDev);
555 InsertConfigNode(pDev, "0", &pInst);
556 InsertConfigNode(pInst, "Config", &pCfg);
557 InsertConfigInteger(pCfg, "Irq", 2);
558 InsertConfigInteger(pCfg, "MmioBase", 0x09010000);
559 vrc = RTFdtNodeAddF(hFdt, "pl032@%RX32", 0x09010000); VRC();
560 vrc = RTFdtNodePropertyAddString( hFdt, "clock-names", "apb_pclk"); VRC();
561 vrc = RTFdtNodePropertyAddU32( hFdt, "clocks", idPHandleAbpPClk); VRC();
562 vrc = RTFdtNodePropertyAddCellsU32(hFdt, "interrupts", 3, 0x00, 0x02, 0x04); VRC();
563 vrc = RTFdtNodePropertyAddCellsU32(hFdt, "reg", 4, 0, 0x09010000, 0, 0x1000); VRC();
564 vrc = RTFdtNodePropertyAddStringList(hFdt, "compatible", 2,
565 "arm,pl031", "arm,primecell"); VRC();
566 vrc = RTFdtNodeFinalize(hFdt); VRC();
567
568 InsertConfigNode(pDevices, "arm-pl061-gpio",&pDev);
569 InsertConfigNode(pDev, "0", &pInst);
570 InsertConfigNode(pInst, "Config", &pCfg);
571 InsertConfigInteger(pCfg, "Irq", 7);
572 InsertConfigInteger(pCfg, "MmioBase", 0x09030000);
573 vrc = RTFdtNodeAddF(hFdt, "pl061@%RX32", 0x09030000); VRC();
574 vrc = RTFdtNodePropertyAddU32( hFdt, "phandle", idPHandleGpio); VRC();
575 vrc = RTFdtNodePropertyAddString( hFdt, "clock-names", "apb_pclk"); VRC();
576 vrc = RTFdtNodePropertyAddU32( hFdt, "clocks", idPHandleAbpPClk); VRC();
577 vrc = RTFdtNodePropertyAddCellsU32(hFdt, "interrupts", 3, 0x00, 0x07, 0x04); VRC();
578 vrc = RTFdtNodePropertyAddEmpty( hFdt, "gpio-controller"); VRC();
579 vrc = RTFdtNodePropertyAddU32( hFdt, "#gpio-cells", 2); VRC();
580 vrc = RTFdtNodePropertyAddStringList(hFdt, "compatible", 2,
581 "arm,pl061", "arm,primecell"); VRC();
582 vrc = RTFdtNodePropertyAddCellsU32(hFdt, "reg", 4, 0, 0x09030000, 0, 0x1000); VRC();
583 vrc = RTFdtNodeFinalize(hFdt); VRC();
584
585 InsertConfigNode(pDevices, "pci-generic-ecam", &pDev);
586 InsertConfigNode(pDev, "0", &pInst);
587 InsertConfigNode(pInst, "Config", &pCfg);
588 InsertConfigInteger(pCfg, "MmioEcamBase", 0x3f000000);
589 InsertConfigInteger(pCfg, "MmioEcamLength", 0x01000000);
590 InsertConfigInteger(pCfg, "MmioPioBase", 0x3eff0000);
591 InsertConfigInteger(pCfg, "MmioPioSize", 0x0000ffff);
592 InsertConfigInteger(pCfg, "IntPinA", 3);
593 InsertConfigInteger(pCfg, "IntPinB", 4);
594 InsertConfigInteger(pCfg, "IntPinC", 5);
595 InsertConfigInteger(pCfg, "IntPinD", 6);
596 vrc = RTFdtNodeAddF(hFdt, "pcie@%RX32", 0x10000000); VRC();
597 vrc = RTFdtNodePropertyAddCellsU32(hFdt, "interrupt-map-mask", 4, 0x1800, 0, 0, 7); VRC();
598 vrc = RTFdtNodePropertyAddCellsU32(hFdt, "interrupt-map", 16 * 10,
599 0x00, 0x00, 0x00, 0x01, idPHandleIntCtrl, 0x00, 0x00, 0x00, 0x03, 0x04,
600 0x00, 0x00, 0x00, 0x02, idPHandleIntCtrl, 0x00, 0x00, 0x00, 0x04, 0x04,
601 0x00, 0x00, 0x00, 0x03, idPHandleIntCtrl, 0x00, 0x00, 0x00, 0x05, 0x04,
602 0x00, 0x00, 0x00, 0x04, idPHandleIntCtrl, 0x00, 0x00, 0x00, 0x06, 0x04,
603 0x800, 0x00, 0x00, 0x01, idPHandleIntCtrl, 0x00, 0x00, 0x00, 0x04, 0x04,
604 0x800, 0x00, 0x00, 0x02, idPHandleIntCtrl, 0x00, 0x00, 0x00, 0x05, 0x04,
605 0x800, 0x00, 0x00, 0x03, idPHandleIntCtrl, 0x00, 0x00, 0x00, 0x06, 0x04,
606 0x800, 0x00, 0x00, 0x04, idPHandleIntCtrl, 0x00, 0x00, 0x00, 0x03, 0x04,
607 0x1000, 0x00, 0x00, 0x01, idPHandleIntCtrl, 0x00, 0x00, 0x00, 0x05, 0x04,
608 0x1000, 0x00, 0x00, 0x02, idPHandleIntCtrl, 0x00, 0x00, 0x00, 0x06, 0x04,
609 0x1000, 0x00, 0x00, 0x03, idPHandleIntCtrl, 0x00, 0x00, 0x00, 0x03, 0x04,
610 0x1000, 0x00, 0x00, 0x04, idPHandleIntCtrl, 0x00, 0x00, 0x00, 0x04, 0x04,
611 0x1800, 0x00, 0x00, 0x01, idPHandleIntCtrl, 0x00, 0x00, 0x00, 0x06, 0x04,
612 0x1800, 0x00, 0x00, 0x02, idPHandleIntCtrl, 0x00, 0x00, 0x00, 0x03, 0x04,
613 0x1800, 0x00, 0x00, 0x03, idPHandleIntCtrl, 0x00, 0x00, 0x00, 0x04, 0x04,
614 0x1800, 0x00, 0x00, 0x04, idPHandleIntCtrl, 0x00, 0x00, 0x00, 0x05, 0x04); VRC();
615 vrc = RTFdtNodePropertyAddU32( hFdt, "#interrupt-cells", 1); VRC();
616 vrc = RTFdtNodePropertyAddCellsU32(hFdt, "ranges", 14,
617 0x1000000, 0, 0, 0, 0x3eff0000, 0, 0x10000,
618 0x2000000, 0, 0x10000000, 0, 0x10000000, 0,
619 0x2eff0000); VRC();
620 vrc = RTFdtNodePropertyAddCellsU32(hFdt, "reg", 4, 0, 0x3f000000, 0, 0x1000000); VRC();
621 /** @todo msi-map */
622 vrc = RTFdtNodePropertyAddEmpty( hFdt, "dma-coherent"); VRC();
623 vrc = RTFdtNodePropertyAddCellsU32(hFdt, "bus-range", 2, 0, 0xf); VRC();
624 vrc = RTFdtNodePropertyAddU32( hFdt, "linux,pci-domain", 0); VRC();
625 vrc = RTFdtNodePropertyAddU32( hFdt, "#size-cells", 2); VRC();
626 vrc = RTFdtNodePropertyAddU32( hFdt, "#address-cells", 3); VRC();
627 vrc = RTFdtNodePropertyAddString( hFdt, "device_type", "pci"); VRC();
628 vrc = RTFdtNodePropertyAddString( hFdt, "compatible", "pci-host-ecam-generic"); VRC();
629 vrc = RTFdtNodeFinalize(hFdt); VRC();
630
631 InsertConfigNode(pDevices, "vga", &pDev);
632 InsertConfigNode(pDev, "0", &pInst);
633 InsertConfigInteger(pInst, "Trusted", 1);
634 InsertConfigInteger(pInst, "PCIBusNo", 0);
635 InsertConfigInteger(pInst, "PCIDeviceNo", 2);
636 InsertConfigInteger(pInst, "PCIFunctionNo", 0);
637 InsertConfigNode(pInst, "Config", &pCfg);
638 InsertConfigInteger(pCfg, "VRamSize", 32 * _1M);
639 InsertConfigInteger(pCfg, "MonitorCount", 1);
640 i_attachStatusDriver(pInst, DeviceType_Graphics3D);
641 InsertConfigInteger(pCfg, "VMSVGAEnabled", true);
642 InsertConfigInteger(pCfg, "VMSVGAPciBarLayout", true);
643 InsertConfigInteger(pCfg, "VMSVGAPciId", true);
644 InsertConfigInteger(pCfg, "VMSVGA3dEnabled", false);
645 InsertConfigInteger(pCfg, "VmSvga3", true);
646 InsertConfigInteger(pCfg, "VmSvgaExposeLegacyVga", false);
647
648 /* Attach the display. */
649 InsertConfigNode(pInst, "LUN#0", &pLunL0);
650 InsertConfigString(pLunL0, "Driver", "MainDisplay");
651 InsertConfigNode(pLunL0, "Config", &pCfg);
652
653
654 InsertConfigNode(pDevices, "VMMDev", &pDev);
655 InsertConfigNode(pDev, "0", &pInst);
656 InsertConfigInteger(pInst, "Trusted", 1);
657 InsertConfigInteger(pInst, "PCIBusNo", 0);
658 InsertConfigInteger(pInst, "PCIDeviceNo", 0);
659 InsertConfigInteger(pInst, "PCIFunctionNo", 0);
660 InsertConfigNode(pInst, "Config", &pCfg);
661 InsertConfigInteger(pCfg, "MmioReq", 1);
662
663 /* the VMM device's Main driver */
664 InsertConfigNode(pInst, "LUN#0", &pLunL0);
665 InsertConfigString(pLunL0, "Driver", "HGCM");
666 InsertConfigNode(pLunL0, "Config", &pCfg);
667
668 /*
669 * Attach the status driver.
670 */
671 i_attachStatusDriver(pInst, DeviceType_SharedFolder);
672
673#ifdef VBOX_WITH_SHARED_CLIPBOARD
674 /*
675 * Shared Clipboard.
676 */
677 {
678 ClipboardMode_T enmClipboardMode = ClipboardMode_Disabled;
679 hrc = pMachine->COMGETTER(ClipboardMode)(&enmClipboardMode); H();
680# ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
681 BOOL fFileTransfersEnabled;
682 hrc = pMachine->COMGETTER(ClipboardFileTransfersEnabled)(&fFileTransfersEnabled); H();
683# endif
684
685 /* Load the service */
686 vrc = pVMMDev->hgcmLoadService("VBoxSharedClipboard", "VBoxSharedClipboard");
687 if (RT_SUCCESS(vrc))
688 {
689 LogRel(("Shared Clipboard: Service loaded\n"));
690
691 /* Set initial clipboard mode. */
692 vrc = i_changeClipboardMode(enmClipboardMode);
693 AssertLogRelMsg(RT_SUCCESS(vrc), ("Shared Clipboard: Failed to set initial clipboard mode (%d): vrc=%Rrc\n",
694 enmClipboardMode, vrc));
695
696 /* Setup the service. */
697 VBOXHGCMSVCPARM parm;
698 HGCMSvcSetU32(&parm, !i_useHostClipboard());
699 vrc = pVMMDev->hgcmHostCall("VBoxSharedClipboard", VBOX_SHCL_HOST_FN_SET_HEADLESS, 1, &parm);
700 AssertLogRelMsg(RT_SUCCESS(vrc), ("Shared Clipboard: Failed to set initial headless mode (%RTbool): vrc=%Rrc\n",
701 !i_useHostClipboard(), vrc));
702
703# ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
704 vrc = i_changeClipboardFileTransferMode(RT_BOOL(fFileTransfersEnabled));
705 AssertLogRelMsg(RT_SUCCESS(vrc), ("Shared Clipboard: Failed to set initial file transfers mode (%u): vrc=%Rrc\n",
706 fFileTransfersEnabled, vrc));
707
708 /** @todo Register area callbacks? (See also deregistration todo in Console::i_powerDown.) */
709# endif
710 }
711 else
712 LogRel(("Shared Clipboard: Not available, vrc=%Rrc\n", vrc));
713 vrc = VINF_SUCCESS; /* None of the potential failures above are fatal. */
714 }
715#endif /* VBOX_WITH_SHARED_CLIPBOARD */
716
717#ifdef VBOX_WITH_DRAG_AND_DROP
718 /*
719 * Drag and Drop.
720 */
721 {
722 DnDMode_T enmMode = DnDMode_Disabled;
723 hrc = pMachine->COMGETTER(DnDMode)(&enmMode); H();
724
725 /* Load the service */
726 vrc = pVMMDev->hgcmLoadService("VBoxDragAndDropSvc", "VBoxDragAndDropSvc");
727 if (RT_FAILURE(vrc))
728 {
729 LogRel(("Drag and drop service is not available, vrc=%Rrc\n", vrc));
730 /* That is not a fatal failure. */
731 vrc = VINF_SUCCESS;
732 }
733 else
734 {
735 vrc = HGCMHostRegisterServiceExtension(&m_hHgcmSvcExtDragAndDrop, "VBoxDragAndDropSvc",
736 &GuestDnD::notifyDnDDispatcher,
737 GuestDnDInst());
738 if (RT_FAILURE(vrc))
739 Log(("Cannot register VBoxDragAndDropSvc extension, vrc=%Rrc\n", vrc));
740 else
741 {
742 LogRel(("Drag and drop service loaded\n"));
743 vrc = i_changeDnDMode(enmMode);
744 }
745 }
746 }
747#endif /* VBOX_WITH_DRAG_AND_DROP */
748
749 InsertConfigNode(pDevices, "usb-xhci", &pDev);
750 InsertConfigNode(pDev, "0", &pInst);
751 InsertConfigInteger(pInst, "Trusted", 1);
752 InsertConfigInteger(pInst, "PCIBusNo", 0);
753 InsertConfigInteger(pInst, "PCIDeviceNo", 1);
754 InsertConfigInteger(pInst, "PCIFunctionNo", 0);
755 InsertConfigNode(pInst, "Config", &pCfg);
756 InsertConfigNode(pInst, "LUN#0", &pLunL0);
757 InsertConfigString(pLunL0, "Driver","VUSBRootHub");
758 InsertConfigNode(pInst, "LUN#1", &pLunL0);
759 InsertConfigString(pLunL0, "Driver","VUSBRootHub");
760
761 /*
762 * Network adapters
763 */
764 PCFGMNODE pDevE1000 = NULL; /* E1000-type devices */
765 InsertConfigNode(pDevices, "e1000", &pDevE1000);
766 PCFGMNODE pDevVirtioNet = NULL; /* Virtio network devices */
767 InsertConfigNode(pDevices, "virtio-net", &pDevVirtioNet);
768
769 for (ULONG uInstance = 0; uInstance < maxNetworkAdapters; ++uInstance)
770 {
771 ComPtr<INetworkAdapter> networkAdapter;
772 hrc = pMachine->GetNetworkAdapter(uInstance, networkAdapter.asOutParam()); H();
773 BOOL fEnabledNetAdapter = FALSE;
774 hrc = networkAdapter->COMGETTER(Enabled)(&fEnabledNetAdapter); H();
775 if (!fEnabledNetAdapter)
776 continue;
777
778 /*
779 * The virtual hardware type. Create appropriate device first.
780 */
781 const char *pszAdapterName = "pcnet";
782 NetworkAdapterType_T adapterType;
783 hrc = networkAdapter->COMGETTER(AdapterType)(&adapterType); H();
784 switch (adapterType)
785 {
786#ifdef VBOX_WITH_E1000
787 case NetworkAdapterType_I82540EM:
788 case NetworkAdapterType_I82543GC:
789 case NetworkAdapterType_I82545EM:
790 pDev = pDevE1000;
791 pszAdapterName = "e1000";
792 break;
793#endif
794#ifdef VBOX_WITH_VIRTIO
795 case NetworkAdapterType_Virtio:
796 pDev = pDevVirtioNet;
797 pszAdapterName = "virtio-net";
798 break;
799#endif /* VBOX_WITH_VIRTIO */
800 case NetworkAdapterType_Am79C970A:
801 case NetworkAdapterType_Am79C973:
802 case NetworkAdapterType_Am79C960:
803 case NetworkAdapterType_NE1000:
804 case NetworkAdapterType_NE2000:
805 case NetworkAdapterType_WD8003:
806 case NetworkAdapterType_WD8013:
807 case NetworkAdapterType_ELNK2:
808 case NetworkAdapterType_ELNK1:
809 default:
810 AssertMsgFailed(("Invalid/Unsupported network adapter type '%d' for slot '%d'", adapterType, uInstance));
811 return pVMM->pfnVMR3SetError(pUVM, VERR_INVALID_PARAMETER, RT_SRC_POS,
812 N_("Invalid/Unsupported network adapter type '%d' for slot '%d'"), adapterType, uInstance);
813 }
814
815 InsertConfigNode(pDev, Utf8StrFmt("%u", uInstance).c_str(), &pInst);
816 InsertConfigInteger(pInst, "Trusted", 1); /* boolean */
817 /* the first network card gets the PCI ID 3, the next 3 gets 8..10,
818 * next 4 get 16..19. */
819 int iPCIDeviceNo;
820 switch (uInstance)
821 {
822 case 0:
823 iPCIDeviceNo = 3;
824 break;
825 case 1: case 2: case 3:
826 iPCIDeviceNo = uInstance - 1 + 8;
827 break;
828 case 4: case 5: case 6: case 7:
829 iPCIDeviceNo = uInstance - 4 + 16;
830 break;
831 default:
832 /* auto assignment */
833 iPCIDeviceNo = -1;
834 break;
835 }
836
837 InsertConfigNode(pInst, "Config", &pCfg);
838
839 /*
840 * The virtual hardware type. PCNet supports three types, E1000 three,
841 * but VirtIO only one.
842 */
843 switch (adapterType)
844 {
845 case NetworkAdapterType_Am79C970A:
846 InsertConfigString(pCfg, "ChipType", "Am79C970A");
847 break;
848 case NetworkAdapterType_Am79C973:
849 InsertConfigString(pCfg, "ChipType", "Am79C973");
850 break;
851 case NetworkAdapterType_Am79C960:
852 InsertConfigString(pCfg, "ChipType", "Am79C960");
853 break;
854 case NetworkAdapterType_I82540EM:
855 InsertConfigInteger(pCfg, "AdapterType", 0);
856 break;
857 case NetworkAdapterType_I82543GC:
858 InsertConfigInteger(pCfg, "AdapterType", 1);
859 break;
860 case NetworkAdapterType_I82545EM:
861 InsertConfigInteger(pCfg, "AdapterType", 2);
862 break;
863 case NetworkAdapterType_Virtio:
864 {
865 uint32_t GCPhysMmioBase = 0x0a000000 + uInstance * GUEST_PAGE_SIZE;
866 uint32_t uIrq = 16 + uInstance;
867
868 InsertConfigInteger(pCfg, "MmioBase", GCPhysMmioBase);
869 InsertConfigInteger(pCfg, "Irq", uIrq);
870
871 vrc = RTFdtNodeAddF(hFdt, "virtio_mmio@%RX32", GCPhysMmioBase); VRC();
872 vrc = RTFdtNodePropertyAddEmpty( hFdt, "dma-coherent"); VRC();
873 vrc = RTFdtNodePropertyAddCellsU32(hFdt, "interrupts", 3, 0x00, uIrq, 0x04); VRC();
874 vrc = RTFdtNodePropertyAddCellsU32(hFdt, "reg", 4, 0, GCPhysMmioBase, 0, 0x200); VRC();
875 vrc = RTFdtNodePropertyAddString(hFdt, "compatible", "virtio,mmio"); VRC();
876 vrc = RTFdtNodeFinalize(hFdt); VRC();
877 break;
878 }
879 case NetworkAdapterType_NE1000:
880 InsertConfigString(pCfg, "DeviceType", "NE1000");
881 break;
882 case NetworkAdapterType_NE2000:
883 InsertConfigString(pCfg, "DeviceType", "NE2000");
884 break;
885 case NetworkAdapterType_WD8003:
886 InsertConfigString(pCfg, "DeviceType", "WD8003");
887 break;
888 case NetworkAdapterType_WD8013:
889 InsertConfigString(pCfg, "DeviceType", "WD8013");
890 break;
891 case NetworkAdapterType_ELNK2:
892 InsertConfigString(pCfg, "DeviceType", "3C503");
893 break;
894 case NetworkAdapterType_ELNK1:
895 break;
896 case NetworkAdapterType_Null: AssertFailedBreak(); /* (compiler warnings) */
897#ifdef VBOX_WITH_XPCOM_CPP_ENUM_HACK
898 case NetworkAdapterType_32BitHack: AssertFailedBreak(); /* (compiler warnings) */
899#endif
900 }
901
902 /*
903 * Get the MAC address and convert it to binary representation
904 */
905 Bstr macAddr;
906 hrc = networkAdapter->COMGETTER(MACAddress)(macAddr.asOutParam()); H();
907 Assert(!macAddr.isEmpty());
908 Utf8Str macAddrUtf8 = macAddr;
909#ifdef VBOX_WITH_CLOUD_NET
910 NetworkAttachmentType_T eAttachmentType;
911 hrc = networkAdapter->COMGETTER(AttachmentType)(&eAttachmentType); H();
912 if (eAttachmentType == NetworkAttachmentType_Cloud)
913 {
914 mGateway.setLocalMacAddress(macAddrUtf8);
915 /* We'll insert cloud MAC later, when it becomes known. */
916 }
917 else
918 {
919#endif
920 char *macStr = (char*)macAddrUtf8.c_str();
921 Assert(strlen(macStr) == 12);
922 RTMAC Mac;
923 RT_ZERO(Mac);
924 char *pMac = (char*)&Mac;
925 for (uint32_t i = 0; i < 6; ++i)
926 {
927 int c1 = *macStr++ - '0';
928 if (c1 > 9)
929 c1 -= 7;
930 int c2 = *macStr++ - '0';
931 if (c2 > 9)
932 c2 -= 7;
933 *pMac++ = (char)(((c1 & 0x0f) << 4) | (c2 & 0x0f));
934 }
935 InsertConfigBytes(pCfg, "MAC", &Mac, sizeof(Mac));
936#ifdef VBOX_WITH_CLOUD_NET
937 }
938#endif
939 /*
940 * Check if the cable is supposed to be unplugged
941 */
942 BOOL fCableConnected;
943 hrc = networkAdapter->COMGETTER(CableConnected)(&fCableConnected); H();
944 InsertConfigInteger(pCfg, "CableConnected", fCableConnected ? 1 : 0);
945
946 /*
947 * Line speed to report from custom drivers
948 */
949 ULONG ulLineSpeed;
950 hrc = networkAdapter->COMGETTER(LineSpeed)(&ulLineSpeed); H();
951 InsertConfigInteger(pCfg, "LineSpeed", ulLineSpeed);
952
953 /*
954 * Attach the status driver.
955 */
956 i_attachStatusDriver(pInst, DeviceType_Network);
957
958 /*
959 * Configure the network card now
960 */
961 bool fIgnoreConnectFailure = mMachineState == MachineState_Restoring;
962 vrc = i_configNetwork(pszAdapterName,
963 uInstance,
964 0,
965 networkAdapter,
966 pCfg,
967 pLunL0,
968 pInst,
969 false /*fAttachDetach*/,
970 fIgnoreConnectFailure,
971 pUVM,
972 pVMM);
973 if (RT_FAILURE(vrc))
974 return vrc;
975 }
976
977 PCFGMNODE pUsb = NULL;
978 InsertConfigNode(pRoot, "USB", &pUsb);
979
980 /*
981 * Storage controllers.
982 */
983 com::SafeIfaceArray<IStorageController> ctrls;
984 PCFGMNODE aCtrlNodes[StorageControllerType_VirtioSCSI + 1] = {};
985 hrc = pMachine->COMGETTER(StorageControllers)(ComSafeArrayAsOutParam(ctrls)); H();
986
987 for (size_t i = 0; i < ctrls.size(); ++i)
988 {
989 DeviceType_T *paLedDevType = NULL;
990
991 StorageControllerType_T enmCtrlType;
992 hrc = ctrls[i]->COMGETTER(ControllerType)(&enmCtrlType); H();
993 AssertRelease((unsigned)enmCtrlType < RT_ELEMENTS(aCtrlNodes)
994 || enmCtrlType == StorageControllerType_USB);
995
996 StorageBus_T enmBus;
997 hrc = ctrls[i]->COMGETTER(Bus)(&enmBus); H();
998
999 Bstr controllerName;
1000 hrc = ctrls[i]->COMGETTER(Name)(controllerName.asOutParam()); H();
1001
1002 ULONG ulInstance = 999;
1003 hrc = ctrls[i]->COMGETTER(Instance)(&ulInstance); H();
1004
1005 BOOL fUseHostIOCache;
1006 hrc = ctrls[i]->COMGETTER(UseHostIOCache)(&fUseHostIOCache); H();
1007
1008 BOOL fBootable;
1009 hrc = ctrls[i]->COMGETTER(Bootable)(&fBootable); H();
1010
1011 PCFGMNODE pCtlInst = NULL;
1012 const char *pszCtrlDev = i_storageControllerTypeToStr(enmCtrlType);
1013 if (enmCtrlType != StorageControllerType_USB)
1014 {
1015 /* /Devices/<ctrldev>/ */
1016 pDev = aCtrlNodes[enmCtrlType];
1017 if (!pDev)
1018 {
1019 InsertConfigNode(pDevices, pszCtrlDev, &pDev);
1020 aCtrlNodes[enmCtrlType] = pDev; /* IDE variants are handled in the switch */
1021 }
1022
1023 /* /Devices/<ctrldev>/<instance>/ */
1024 InsertConfigNode(pDev, Utf8StrFmt("%u", ulInstance).c_str(), &pCtlInst);
1025
1026 /* Device config: /Devices/<ctrldev>/<instance>/<values> & /ditto/Config/<values> */
1027 InsertConfigInteger(pCtlInst, "Trusted", 1);
1028 InsertConfigNode(pCtlInst, "Config", &pCfg);
1029 }
1030
1031 switch (enmCtrlType)
1032 {
1033 case StorageControllerType_USB:
1034 {
1035 if (pUsb)
1036 {
1037 /*
1038 * USB MSDs are handled a bit different as the device instance
1039 * doesn't match the storage controller instance but the port.
1040 */
1041 InsertConfigNode(pUsb, "Msd", &pDev);
1042 pCtlInst = pDev;
1043 }
1044 else
1045 return pVMM->pfnVMR3SetError(pUVM, VERR_NOT_FOUND, RT_SRC_POS,
1046 N_("There is no USB controller enabled but there\n"
1047 "is at least one USB storage device configured for this VM.\n"
1048 "To fix this problem either enable the USB controller or remove\n"
1049 "the storage device from the VM"));
1050 break;
1051 }
1052
1053 case StorageControllerType_IntelAhci:
1054 {
1055 InsertConfigInteger(pCtlInst, "PCIBusNo", 0);
1056 InsertConfigInteger(pCtlInst, "PCIDeviceNo", 3);
1057 InsertConfigInteger(pCtlInst, "PCIFunctionNo", 0);
1058
1059 ULONG cPorts = 0;
1060 hrc = ctrls[i]->COMGETTER(PortCount)(&cPorts); H();
1061 InsertConfigInteger(pCfg, "PortCount", cPorts);
1062 InsertConfigInteger(pCfg, "Bootable", fBootable);
1063
1064 com::SafeIfaceArray<IMediumAttachment> atts;
1065 hrc = pMachine->GetMediumAttachmentsOfController(controllerName.raw(),
1066 ComSafeArrayAsOutParam(atts)); H();
1067
1068 /* Configure the hotpluggable flag for the port. */
1069 for (unsigned idxAtt = 0; idxAtt < atts.size(); ++idxAtt)
1070 {
1071 IMediumAttachment *pMediumAtt = atts[idxAtt];
1072
1073 LONG lPortNum = 0;
1074 hrc = pMediumAtt->COMGETTER(Port)(&lPortNum); H();
1075
1076 BOOL fHotPluggable = FALSE;
1077 hrc = pMediumAtt->COMGETTER(HotPluggable)(&fHotPluggable); H();
1078 if (SUCCEEDED(hrc))
1079 {
1080 PCFGMNODE pPortCfg;
1081 char szName[24];
1082 RTStrPrintf(szName, sizeof(szName), "Port%d", lPortNum);
1083
1084 InsertConfigNode(pCfg, szName, &pPortCfg);
1085 InsertConfigInteger(pPortCfg, "Hotpluggable", fHotPluggable ? 1 : 0);
1086 }
1087 }
1088 break;
1089 }
1090 case StorageControllerType_VirtioSCSI:
1091 {
1092 InsertConfigInteger(pCtlInst, "PCIBusNo", 0);
1093 InsertConfigInteger(pCtlInst, "PCIDeviceNo", 3);
1094 InsertConfigInteger(pCtlInst, "PCIFunctionNo", 0);
1095
1096 ULONG cPorts = 0;
1097 hrc = ctrls[i]->COMGETTER(PortCount)(&cPorts); H();
1098 InsertConfigInteger(pCfg, "NumTargets", cPorts);
1099 InsertConfigInteger(pCfg, "Bootable", fBootable);
1100
1101 /* Attach the status driver */
1102 i_attachStatusDriver(pCtlInst, RT_BIT_32(DeviceType_HardDisk) | RT_BIT_32(DeviceType_DVD) /*?*/,
1103 cPorts, &paLedDevType, &mapMediumAttachments, pszCtrlDev, ulInstance);
1104 break;
1105 }
1106
1107 case StorageControllerType_NVMe:
1108 {
1109 InsertConfigInteger(pCtlInst, "PCIBusNo", 0);
1110 InsertConfigInteger(pCtlInst, "PCIDeviceNo", 3);
1111 InsertConfigInteger(pCtlInst, "PCIFunctionNo", 0);
1112
1113 /* Attach the status driver */
1114 i_attachStatusDriver(pCtlInst, RT_BIT_32(DeviceType_HardDisk) | RT_BIT_32(DeviceType_DVD) /*?*/,
1115 1, &paLedDevType, &mapMediumAttachments, pszCtrlDev, ulInstance);
1116 break;
1117 }
1118
1119 case StorageControllerType_LsiLogic:
1120 case StorageControllerType_BusLogic:
1121 case StorageControllerType_PIIX3:
1122 case StorageControllerType_PIIX4:
1123 case StorageControllerType_ICH6:
1124 case StorageControllerType_I82078:
1125 case StorageControllerType_LsiLogicSas:
1126
1127 default:
1128 AssertLogRelMsgFailedReturn(("invalid storage controller type: %d\n", enmCtrlType), VERR_MAIN_CONFIG_CONSTRUCTOR_IPE);
1129 }
1130
1131 /* Attach the media to the storage controllers. */
1132 com::SafeIfaceArray<IMediumAttachment> atts;
1133 hrc = pMachine->GetMediumAttachmentsOfController(controllerName.raw(),
1134 ComSafeArrayAsOutParam(atts)); H();
1135
1136 /* Builtin I/O cache - per device setting. */
1137 BOOL fBuiltinIOCache = true;
1138 hrc = pMachine->COMGETTER(IOCacheEnabled)(&fBuiltinIOCache); H();
1139
1140 bool fInsertDiskIntegrityDrv = false;
1141 Bstr strDiskIntegrityFlag;
1142 hrc = pMachine->GetExtraData(Bstr("VBoxInternal2/EnableDiskIntegrityDriver").raw(),
1143 strDiskIntegrityFlag.asOutParam());
1144 if ( hrc == S_OK
1145 && strDiskIntegrityFlag == "1")
1146 fInsertDiskIntegrityDrv = true;
1147
1148 for (size_t j = 0; j < atts.size(); ++j)
1149 {
1150 IMediumAttachment *pMediumAtt = atts[j];
1151 vrc = i_configMediumAttachment(pszCtrlDev,
1152 ulInstance,
1153 enmBus,
1154 !!fUseHostIOCache,
1155 enmCtrlType == StorageControllerType_NVMe ? false : !!fBuiltinIOCache,
1156 fInsertDiskIntegrityDrv,
1157 false /* fSetupMerge */,
1158 0 /* uMergeSource */,
1159 0 /* uMergeTarget */,
1160 pMediumAtt,
1161 mMachineState,
1162 NULL /* phrc */,
1163 false /* fAttachDetach */,
1164 false /* fForceUnmount */,
1165 false /* fHotplug */,
1166 pUVM,
1167 pVMM,
1168 paLedDevType,
1169 NULL /* ppLunL0 */);
1170 if (RT_FAILURE(vrc))
1171 return vrc;
1172 }
1173 H();
1174 }
1175 H();
1176
1177 InsertConfigNode(pUsb, "HidKeyboard", &pDev);
1178 InsertConfigNode(pDev, "0", &pInst);
1179 InsertConfigInteger(pInst, "Trusted", 1);
1180 InsertConfigNode(pInst, "Config", &pCfg);
1181 InsertConfigNode(pInst, "LUN#0", &pLunL0);
1182 InsertConfigString(pLunL0, "Driver", "KeyboardQueue");
1183 InsertConfigNode(pLunL0, "AttachedDriver", &pLunL1);
1184 InsertConfigString(pLunL1, "Driver", "MainKeyboard");
1185
1186 InsertConfigNode(pUsb, "HidMouse", &pDev);
1187 InsertConfigNode(pDev, "0", &pInst);
1188 InsertConfigNode(pInst, "Config", &pCfg);
1189 InsertConfigString(pCfg, "Mode", "absolute");
1190 InsertConfigNode(pInst, "LUN#0", &pLunL0);
1191 InsertConfigString(pLunL0, "Driver", "MouseQueue");
1192 InsertConfigNode(pLunL0, "Config", &pCfg);
1193 InsertConfigInteger(pCfg, "QueueSize", 128);
1194
1195 InsertConfigNode(pLunL0, "AttachedDriver", &pLunL1);
1196 InsertConfigString(pLunL1, "Driver", "MainMouse");
1197 }
1198 catch (ConfigError &x)
1199 {
1200 RTFdtDestroy(hFdt);
1201
1202 // InsertConfig threw something:
1203 pVMM->pfnVMR3SetError(pUVM, x.m_vrc, RT_SRC_POS, "Caught ConfigError: %Rrc - %s", x.m_vrc, x.what());
1204 return x.m_vrc;
1205 }
1206 catch (HRESULT hrcXcpt)
1207 {
1208 RTFdtDestroy(hFdt);
1209 AssertLogRelMsgFailedReturn(("hrc=%Rhrc\n", hrcXcpt), VERR_MAIN_CONFIG_CONSTRUCTOR_COM_ERROR);
1210 }
1211
1212#ifdef VBOX_WITH_EXTPACK
1213 /*
1214 * Call the extension pack hooks if everything went well thus far.
1215 */
1216 if (RT_SUCCESS(vrc))
1217 {
1218 pAlock->release();
1219 vrc = mptrExtPackManager->i_callAllVmConfigureVmmHooks(this, pVM, pVMM);
1220 pAlock->acquire();
1221 }
1222#endif
1223
1224 vrc = RTFdtNodeAdd(hFdt, "chosen"); VRC();
1225 vrc = RTFdtNodePropertyAddString( hFdt, "stdout-path", "pl011@9000000"); VRC();
1226 vrc = RTFdtNodePropertyAddString( hFdt, "stdin-path", "pl011@9000000"); VRC();
1227 vrc = RTFdtNodeFinalize(hFdt);
1228
1229 /* Finalize the FDT and add it to the resource store. */
1230 vrc = RTFdtFinalize(hFdt);
1231 AssertRCReturnStmt(vrc, RTFdtDestroy(hFdt), vrc);
1232
1233 RTVFSFILE hVfsFileFdt = NIL_RTVFSFILE;
1234 vrc = RTVfsMemFileCreate(NIL_RTVFSIOSTREAM, 0 /*cbEstimate*/, &hVfsFileFdt);
1235 AssertRCReturnStmt(vrc, RTFdtDestroy(hFdt), vrc);
1236 RTVFSIOSTREAM hVfsIosFdt = RTVfsFileToIoStream(hVfsFileFdt);
1237 AssertRelease(hVfsIosFdt != NIL_RTVFSIOSTREAM);
1238
1239 vrc = RTFdtDumpToVfsIoStrm(hFdt, RTFDTTYPE_DTB, 0 /*fFlags*/, hVfsIosFdt, NULL /*pErrInfo*/);
1240 RTVfsIoStrmRelease(hVfsIosFdt);
1241 if (RT_SUCCESS(vrc))
1242 vrc = mptrResourceStore->i_addItem("fdt", "fdt", hVfsFileFdt);
1243 RTVfsFileRelease(hVfsFileFdt);
1244 AssertRCReturnStmt(vrc, RTFdtDestroy(hFdt), vrc);
1245
1246 /* Dump the DTB for debugging purposes if requested. */
1247 Bstr DtbDumpVal;
1248 hrc = mMachine->GetExtraData(Bstr("VBoxInternal2/DumpDtb").raw(),
1249 DtbDumpVal.asOutParam());
1250 if ( hrc == S_OK
1251 && DtbDumpVal.isNotEmpty())
1252 {
1253 vrc = RTFdtDumpToFile(hFdt, RTFDTTYPE_DTB, 0 /*fFlags*/, Utf8Str(DtbDumpVal).c_str(), NULL /*pErrInfo*/);
1254 AssertRCReturnStmt(vrc, RTFdtDestroy(hFdt), vrc);
1255 }
1256
1257
1258 /*
1259 * Apply the CFGM overlay.
1260 */
1261 if (RT_SUCCESS(vrc))
1262 vrc = i_configCfgmOverlay(pRoot, virtualBox, pMachine);
1263
1264 /*
1265 * Dump all extradata API settings tweaks, both global and per VM.
1266 */
1267 if (RT_SUCCESS(vrc))
1268 vrc = i_configDumpAPISettingsTweaks(virtualBox, pMachine);
1269
1270#undef H
1271
1272 pAlock->release(); /* Avoid triggering the lock order inversion check. */
1273
1274 /*
1275 * Register VM state change handler.
1276 */
1277 int vrc2 = pVMM->pfnVMR3AtStateRegister(pUVM, Console::i_vmstateChangeCallback, this);
1278 AssertRC(vrc2);
1279 if (RT_SUCCESS(vrc))
1280 vrc = vrc2;
1281
1282 /*
1283 * Register VM runtime error handler.
1284 */
1285 vrc2 = pVMM->pfnVMR3AtRuntimeErrorRegister(pUVM, Console::i_atVMRuntimeErrorCallback, this);
1286 AssertRC(vrc2);
1287 if (RT_SUCCESS(vrc))
1288 vrc = vrc2;
1289
1290 pAlock->acquire();
1291
1292 LogFlowFunc(("vrc = %Rrc\n", vrc));
1293 LogFlowFuncLeave();
1294
1295 return vrc;
1296}
1297#endif /* !VBOX_WITH_VIRT_ARMV8 */
1298
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