VirtualBox

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

Last change on this file since 101381 was 101322, checked in by vboxsync, 8 months ago

Main/src-client/ConsoleImplConfigArmV8.cpp: Setup the EFI ROM and the FDT using the generic platform device instead of the special efi-armv8 variant (will be used for other things later), bugref:10528

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

© 2023 Oracle
ContactPrivacy policyTerms of Use