VirtualBox

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

Last change on this file since 101043 was 101035, checked in by vboxsync, 18 months ago

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

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