VirtualBox

source: vbox/trunk/src/VBox/VMM/testcase/tstAnimate.cpp@ 103025

Last change on this file since 103025 was 99897, checked in by vboxsync, 18 months ago

VMM/EM,DBGF: Repurposing the inner REM execution loop for IEM/recompiler. Cleanups. bugref:10369

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 32.4 KB
Line 
1/* $Id: tstAnimate.cpp 99897 2023-05-22 11:43:38Z vboxsync $ */
2/** @file
3 * VBox Animation Testcase / Tool.
4 */
5
6/*
7 * Copyright (C) 2006-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#include <VBox/vmm/vm.h>
33#include <VBox/vmm/vmm.h>
34#include <VBox/vmm/cpum.h>
35#include <VBox/vmm/cfgm.h>
36#include <VBox/vmm/em.h>
37#include <VBox/vmm/pgm.h>
38#include <VBox/vmm/ssm.h>
39#include <VBox/vmm/dbgf.h>
40#include <VBox/err.h>
41#include <VBox/vmm/pdmifs.h>
42#include <VBox/param.h>
43#include <VBox/log.h>
44#include <iprt/assert.h>
45#include <iprt/alloc.h>
46#include <iprt/initterm.h>
47#include <iprt/semaphore.h>
48#include <iprt/string.h>
49#include <iprt/stream.h>
50#include <iprt/file.h>
51#include <iprt/thread.h>
52#include <iprt/ctype.h>
53#include <iprt/uuid.h>
54
55#include <signal.h>
56
57
58/*********************************************************************************************************************************
59* Global Variables *
60*********************************************************************************************************************************/
61static volatile bool g_fSignaled = false;
62
63
64static void SigInterrupt(int iSignal) RT_NOTHROW_DEF
65{
66 NOREF(iSignal);
67 signal(SIGINT, SigInterrupt);
68 g_fSignaled = true;
69 RTPrintf("caught SIGINT\n");
70}
71
72typedef DECLCALLBACKTYPE(int, FNSETGUESTGPR,(PVM, uint32_t));
73typedef FNSETGUESTGPR *PFNSETGUESTGPR;
74static int scriptGPReg(PVM pVM, char *pszVar, char *pszValue, void *pvUser)
75{
76 NOREF(pszVar);
77 uint32_t u32;
78 int rc = RTStrToUInt32Ex(pszValue, NULL, 16, &u32);
79 if (RT_FAILURE(rc))
80 return rc;
81 return ((PFNSETGUESTGPR)(uintptr_t)pvUser)(pVM, u32);
82}
83
84typedef DECLCALLBACKTYPE(int, FNSETGUESTSEL,(PVM, uint16_t));
85typedef FNSETGUESTSEL *PFNSETGUESTSEL;
86static int scriptSelReg(PVM pVM, char *pszVar, char *pszValue, void *pvUser)
87{
88 NOREF(pszVar);
89 uint16_t u16;
90 int rc = RTStrToUInt16Ex(pszValue, NULL, 16, &u16);
91 if (RT_FAILURE(rc))
92 return rc;
93 return ((PFNSETGUESTSEL)(uintptr_t)pvUser)(pVM, u16);
94}
95
96typedef DECLCALLBACKTYPE(int, FNSETGUESTSYS,(PVM, uint32_t));
97typedef FNSETGUESTSYS *PFNSETGUESTSYS;
98static int scriptSysReg(PVM pVM, char *pszVar, char *pszValue, void *pvUser)
99{
100 NOREF(pszVar);
101 uint32_t u32;
102 int rc = RTStrToUInt32Ex(pszValue, NULL, 16, &u32);
103 if (RT_FAILURE(rc))
104 return rc;
105 return ((PFNSETGUESTSYS)(uintptr_t)pvUser)(pVM, u32);
106}
107
108
109typedef DECLCALLBACKTYPE(int, FNSETGUESTDTR,(PVM, uint32_t, uint16_t));
110typedef FNSETGUESTDTR *PFNSETGUESTDTR;
111static int scriptDtrReg(PVM pVM, char *pszVar, char *pszValue, void *pvUser)
112{
113 NOREF(pszVar);
114 char *pszPart2 = strchr(pszValue, ':');
115 if (!pszPart2)
116 return -1;
117 *pszPart2++ = '\0';
118 pszPart2 = RTStrStripL(pszPart2);
119 pszValue = RTStrStripR(pszValue);
120
121 uint32_t u32;
122 int rc = RTStrToUInt32Ex(pszValue, NULL, 16, &u32);
123 if (RT_FAILURE(rc))
124 return rc;
125
126 uint16_t u16;
127 rc = RTStrToUInt16Ex(pszPart2, NULL, 16, &u16);
128 if (RT_FAILURE(rc))
129 return rc;
130
131 return ((PFNSETGUESTDTR)(uintptr_t)pvUser)(pVM, u32, u16);
132}
133
134
135
136
137/* variables - putting in global scope to avoid MSC warning C4640. */
138static struct
139{
140 const char *pszVar;
141 int (*pfnHandler)(PVM pVM, char *pszVar, char *pszValue, void *pvUser);
142 PFNRT pvUser;
143} g_aVars[] =
144{
145 { "eax", scriptGPReg, (PFNRT)CPUMSetGuestEAX },
146 { "ebx", scriptGPReg, (PFNRT)CPUMSetGuestEBX },
147 { "ecx", scriptGPReg, (PFNRT)CPUMSetGuestECX },
148 { "edx", scriptGPReg, (PFNRT)CPUMSetGuestEDX },
149 { "esp", scriptGPReg, (PFNRT)CPUMSetGuestESP },
150 { "ebp", scriptGPReg, (PFNRT)CPUMSetGuestEBP },
151 { "esi", scriptGPReg, (PFNRT)CPUMSetGuestESI },
152 { "edi", scriptGPReg, (PFNRT)CPUMSetGuestEDI },
153 { "efl", scriptGPReg, (PFNRT)CPUMSetGuestEFlags },
154 { "eip", scriptGPReg, (PFNRT)CPUMSetGuestEIP },
155 { "ss", scriptSelReg, (PFNRT)CPUMSetGuestSS },
156 { "cs", scriptSelReg, (PFNRT)CPUMSetGuestCS },
157 { "ds", scriptSelReg, (PFNRT)CPUMSetGuestDS },
158 { "es", scriptSelReg, (PFNRT)CPUMSetGuestES },
159 { "fs", scriptSelReg, (PFNRT)CPUMSetGuestFS },
160 { "gs", scriptSelReg, (PFNRT)CPUMSetGuestGS },
161 { "cr0", scriptSysReg, (PFNRT)CPUMSetGuestCR0 },
162 { "cr2", scriptSysReg, (PFNRT)CPUMSetGuestCR2 },
163 { "cr3", scriptSysReg, (PFNRT)CPUMSetGuestCR3 },
164 { "cr4", scriptSysReg, (PFNRT)CPUMSetGuestCR4 },
165 { "ldtr",scriptSelReg, (PFNRT)CPUMSetGuestLDTR },
166 { "tr", scriptSelReg, (PFNRT)CPUMSetGuestTR },
167 { "idtr",scriptDtrReg, (PFNRT)CPUMSetGuestIDTR },
168 { "gdtr",scriptDtrReg, (PFNRT)CPUMSetGuestGDTR }
169};
170
171
172static int scriptCommand(PVM pVM, const char *pszIn, size_t cch)
173{
174 NOREF(cch);
175 int rc = VINF_SUCCESS;
176 char *psz = RTStrDup(pszIn);
177 char *pszEqual = strchr(psz, '=');
178 if (pszEqual)
179 {
180 /*
181 * var = value
182 */
183 *pszEqual = '\0';
184 RTStrStripR(psz);
185 char *pszValue = RTStrStrip(pszEqual + 1);
186
187 rc = -1;
188 for (unsigned i = 0; i < RT_ELEMENTS(g_aVars); i++)
189 {
190 if (!strcmp(psz, g_aVars[i].pszVar))
191 {
192 rc = g_aVars[i].pfnHandler(pVM, psz, pszValue, (void *)(uintptr_t)g_aVars[i].pvUser);
193 break;
194 }
195 }
196 }
197
198 RTStrFree(psz);
199 return rc;
200}
201
202static DECLCALLBACK(int) scriptRun(PVM pVM, RTFILE File)
203{
204 RTPrintf("info: running script...\n");
205 uint64_t cb;
206 int rc = RTFileQuerySize(File, &cb);
207 if (RT_SUCCESS(rc))
208 {
209 if (cb == 0)
210 return VINF_SUCCESS;
211 if (cb < _1M)
212 {
213 char *pszBuf = (char *)RTMemAllocZ(cb + 1);
214 if (pszBuf)
215 {
216 rc = RTFileRead(File, pszBuf, cb, NULL);
217 if (RT_SUCCESS(rc))
218 {
219 pszBuf[cb] = '\0';
220
221 /*
222 * Now process what's in the buffer.
223 */
224 char *psz = pszBuf;
225 while (psz && *psz)
226 {
227 /* skip blanks. */
228 while (RT_C_IS_SPACE(*psz))
229 psz++;
230 if (!*psz)
231 break;
232
233 /* end of line */
234 char *pszNext;
235 char *pszEnd = strchr(psz, '\n');
236 if (!pszEnd)
237 pszEnd = strchr(psz, '\r');
238 if (!pszEnd)
239 pszNext = pszEnd = strchr(psz, '\0');
240 else
241 pszNext = pszEnd + 1;
242
243 if (*psz != ';' && *psz != '#' && *psz != '/')
244 {
245 /* strip end */
246 *pszEnd = '\0';
247 while (pszEnd > psz && RT_C_IS_SPACE(pszEnd[-1]))
248 *--pszEnd = '\0';
249
250 /* process the line */
251 RTPrintf("debug: executing script line '%s'\n", psz);
252 rc = scriptCommand(pVM, psz, pszEnd - psz);
253 if (RT_FAILURE(rc))
254 {
255 RTPrintf("error: '%s' failed: %Rrc\n", psz, rc);
256 break;
257 }
258 }
259 /* else comment line */
260
261 /* next */
262 psz = pszNext;
263 }
264
265 }
266 else
267 RTPrintf("error: failed to read script file: %Rrc\n", rc);
268 RTMemFree(pszBuf);
269 }
270 else
271 {
272 RTPrintf("error: Out of memory. (%d bytes)\n", cb + 1);
273 rc = VERR_NO_MEMORY;
274 }
275 }
276 else
277 RTPrintf("error: script file is too large (0x%llx bytes)\n", cb);
278 }
279 else
280 RTPrintf("error: couldn't get size of script file: %Rrc\n", rc);
281
282 return rc;
283}
284
285
286static DECLCALLBACK(int) loadMem(PVM pVM, RTFILE File, uint64_t *poff)
287{
288 uint64_t off = *poff;
289 RTPrintf("info: loading memory...\n");
290
291 int rc = RTFileSeek(File, off, RTFILE_SEEK_BEGIN, NULL);
292 if (RT_SUCCESS(rc))
293 {
294 RTGCPHYS GCPhys = 0;
295 for (;;)
296 {
297 if (!(GCPhys % (GUEST_PAGE_SIZE * 0x1000)))
298 RTPrintf("info: %RGp...\n", GCPhys);
299
300 /* read a page from the file */
301 size_t cbRead = 0;
302 uint8_t au8Page[GUEST_PAGE_SIZE * 16];
303 rc = RTFileRead(File, &au8Page, sizeof(au8Page), &cbRead);
304 if (RT_SUCCESS(rc) && !cbRead)
305 rc = RTFileRead(File, &au8Page, sizeof(au8Page), &cbRead);
306 if (RT_SUCCESS(rc) && !cbRead)
307 rc = VERR_EOF;
308 if (RT_FAILURE(rc) || rc == VINF_EOF)
309 {
310 if (rc == VERR_EOF)
311 rc = VINF_SUCCESS;
312 else
313 RTPrintf("error: Read error %Rrc while reading the raw memory file.\n", rc);
314 break;
315 }
316
317 /* Write that page to the guest - skip known rom areas for now. */
318 if (GCPhys < 0xa0000 || GCPhys >= 0x100000) /* ASSUME size of a8Page is a power of 2. */
319 PGMPhysWrite(pVM, GCPhys, &au8Page, cbRead, PGMACCESSORIGIN_DEBUGGER);
320 GCPhys += cbRead;
321 }
322 }
323 else
324 RTPrintf("error: Failed to seek to 0x%llx in the raw memory file. rc=%Rrc\n", off, rc);
325
326 return rc;
327}
328
329
330/**
331 * @callback_method_impl{FNCFGMCONSTRUCTOR, Creates the default configuration.}
332 *
333 * This assumes an empty tree.
334 */
335static DECLCALLBACK(int) cfgmR3CreateDefault(PUVM pUVM, PVM pVM, PCVMMR3VTABLE pVMM, void *pvUser)
336{
337 RT_NOREF(pUVM, pVMM);
338 uint64_t cbMem = *(uint64_t *)pvUser;
339 int rc;
340 int rcAll = VINF_SUCCESS;
341 bool fIOAPIC = false;
342#define UPDATERC() do { if (RT_FAILURE(rc) && RT_SUCCESS(rcAll)) rcAll = rc; } while (0)
343
344 /*
345 * Create VM default values.
346 */
347 PCFGMNODE pRoot = CFGMR3GetRoot(pVM);
348 rc = CFGMR3InsertString(pRoot, "Name", "Default VM");
349 UPDATERC();
350 rc = CFGMR3InsertInteger(pRoot, "RamSize", cbMem);
351 UPDATERC();
352 rc = CFGMR3InsertInteger(pRoot, "TimerMillies", 10);
353 UPDATERC();
354 rc = CFGMR3InsertInteger(pRoot, "RawR3Enabled", 0);
355 UPDATERC();
356 /** @todo CFGM Defaults: RawR0, PATMEnabled and CASMEnabled needs attention later. */
357 rc = CFGMR3InsertInteger(pRoot, "RawR0Enabled", 0);
358 UPDATERC();
359 rc = CFGMR3InsertInteger(pRoot, "PATMEnabled", 0);
360 UPDATERC();
361 rc = CFGMR3InsertInteger(pRoot, "CSAMEnabled", 0);
362 UPDATERC();
363
364 /*
365 * PDM.
366 */
367 PCFGMNODE pPdm;
368 rc = CFGMR3InsertNode(pRoot, "PDM", &pPdm);
369 UPDATERC();
370 PCFGMNODE pDevices = NULL;
371 rc = CFGMR3InsertNode(pPdm, "Devices", &pDevices);
372 UPDATERC();
373 rc = CFGMR3InsertInteger(pDevices, "LoadBuiltin", 1); /* boolean */
374 UPDATERC();
375 PCFGMNODE pDrivers = NULL;
376 rc = CFGMR3InsertNode(pPdm, "Drivers", &pDrivers);
377 UPDATERC();
378 rc = CFGMR3InsertInteger(pDrivers, "LoadBuiltin", 1); /* boolean */
379 UPDATERC();
380
381
382 /*
383 * Devices
384 */
385 pDevices = NULL;
386 rc = CFGMR3InsertNode(pRoot, "Devices", &pDevices);
387 UPDATERC();
388 /* device */
389 PCFGMNODE pDev = NULL;
390 PCFGMNODE pInst = NULL;
391 PCFGMNODE pCfg = NULL;
392#if 0
393 PCFGMNODE pLunL0 = NULL;
394 PCFGMNODE pLunL1 = NULL;
395#endif
396
397 /*
398 * PC Arch.
399 */
400 rc = CFGMR3InsertNode(pDevices, "pcarch", &pDev);
401 UPDATERC();
402 rc = CFGMR3InsertNode(pDev, "0", &pInst);
403 UPDATERC();
404 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */
405 UPDATERC();
406 rc = CFGMR3InsertNode(pInst, "Config", &pCfg);
407 UPDATERC();
408
409 /*
410 * PC Bios.
411 */
412 rc = CFGMR3InsertNode(pDevices, "pcbios", &pDev);
413 UPDATERC();
414 rc = CFGMR3InsertNode(pDev, "0", &pInst);
415 UPDATERC();
416 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */
417 UPDATERC();
418 rc = CFGMR3InsertNode(pInst, "Config", &pCfg);
419 UPDATERC();
420 rc = CFGMR3InsertString(pCfg, "BootDevice0", "IDE");
421 UPDATERC();
422 rc = CFGMR3InsertString(pCfg, "BootDevice1", "NONE");
423 UPDATERC();
424 rc = CFGMR3InsertString(pCfg, "BootDevice2", "NONE");
425 UPDATERC();
426 rc = CFGMR3InsertString(pCfg, "BootDevice3", "NONE");
427 UPDATERC();
428 rc = CFGMR3InsertString(pCfg, "HardDiskDevice", "piix3ide");
429 UPDATERC();
430 rc = CFGMR3InsertString(pCfg, "FloppyDevice", "i82078");
431 rc = CFGMR3InsertInteger(pCfg, "IOAPIC", fIOAPIC); UPDATERC();
432 RTUUID Uuid;
433 RTUuidClear(&Uuid);
434 rc = CFGMR3InsertBytes(pCfg, "UUID", &Uuid, sizeof(Uuid)); UPDATERC();
435 /* Bios logo. */
436 rc = CFGMR3InsertInteger(pCfg, "FadeIn", 0);
437 UPDATERC();
438 rc = CFGMR3InsertInteger(pCfg, "FadeOut", 0);
439 UPDATERC();
440 rc = CFGMR3InsertInteger(pCfg, "LogoTime", 0);
441 UPDATERC();
442 rc = CFGMR3InsertString(pCfg, "LogoFile", "");
443 UPDATERC();
444
445 /*
446 * ACPI
447 */
448 rc = CFGMR3InsertNode(pDevices, "acpi", &pDev); UPDATERC();
449 rc = CFGMR3InsertNode(pDev, "0", &pInst); UPDATERC();
450 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ UPDATERC();
451 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); UPDATERC();
452 rc = CFGMR3InsertInteger(pCfg, "IOAPIC", fIOAPIC); UPDATERC();
453 rc = CFGMR3InsertInteger(pInst, "PCIDeviceNo", 7); UPDATERC();
454 rc = CFGMR3InsertInteger(pInst, "PCIFunctionNo", 0); UPDATERC();
455
456 /*
457 * DMA
458 */
459 rc = CFGMR3InsertNode(pDevices, "8237A", &pDev); UPDATERC();
460 rc = CFGMR3InsertNode(pDev, "0", &pInst); UPDATERC();
461 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ UPDATERC();
462
463 /*
464 * PCI bus.
465 */
466 rc = CFGMR3InsertNode(pDevices, "pci", &pDev); /* piix3 */
467 UPDATERC();
468 rc = CFGMR3InsertNode(pDev, "0", &pInst);
469 UPDATERC();
470 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */
471 UPDATERC();
472 rc = CFGMR3InsertNode(pInst, "Config", &pCfg);
473 UPDATERC();
474 rc = CFGMR3InsertInteger(pCfg, "IOAPIC", fIOAPIC); UPDATERC();
475
476 /*
477 * PS/2 keyboard & mouse
478 */
479 rc = CFGMR3InsertNode(pDevices, "pckbd", &pDev);
480 UPDATERC();
481 rc = CFGMR3InsertNode(pDev, "0", &pInst);
482 UPDATERC();
483 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ UPDATERC();
484 rc = CFGMR3InsertNode(pInst, "Config", &pCfg);
485 UPDATERC();
486
487 /*
488 * Floppy
489 */
490 rc = CFGMR3InsertNode(pDevices, "i82078", &pDev); UPDATERC();
491 rc = CFGMR3InsertNode(pDev, "0", &pInst); UPDATERC();
492 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); UPDATERC();
493 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); UPDATERC();
494 rc = CFGMR3InsertInteger(pCfg, "IRQ", 6); UPDATERC();
495 rc = CFGMR3InsertInteger(pCfg, "DMA", 2); UPDATERC();
496 rc = CFGMR3InsertInteger(pCfg, "MemMapped", 0 ); UPDATERC();
497 rc = CFGMR3InsertInteger(pCfg, "IOBase", 0x3f0); UPDATERC();
498
499 /*
500 * i8254 Programmable Interval Timer And Dummy Speaker
501 */
502 rc = CFGMR3InsertNode(pDevices, "i8254", &pDev);
503 UPDATERC();
504 rc = CFGMR3InsertNode(pDev, "0", &pInst);
505 UPDATERC();
506 rc = CFGMR3InsertNode(pInst, "Config", &pCfg);
507 UPDATERC();
508
509 /*
510 * i8259 Programmable Interrupt Controller.
511 */
512 rc = CFGMR3InsertNode(pDevices, "i8259", &pDev);
513 UPDATERC();
514 rc = CFGMR3InsertNode(pDev, "0", &pInst);
515 UPDATERC();
516 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */
517 UPDATERC();
518 rc = CFGMR3InsertNode(pInst, "Config", &pCfg);
519 UPDATERC();
520
521 /*
522 * APIC.
523 */
524 rc = CFGMR3InsertNode(pDevices, "apic", &pDev); UPDATERC();
525 rc = CFGMR3InsertNode(pDev, "0", &pInst); UPDATERC();
526 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ UPDATERC();
527 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); UPDATERC();
528 rc = CFGMR3InsertInteger(pCfg, "IOAPIC", fIOAPIC); UPDATERC();
529
530 if (fIOAPIC)
531 {
532 /*
533 * I/O Advanced Programmable Interrupt Controller.
534 */
535 rc = CFGMR3InsertNode(pDevices, "ioapic", &pDev); UPDATERC();
536 rc = CFGMR3InsertNode(pDev, "0", &pInst); UPDATERC();
537 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ UPDATERC();
538 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); UPDATERC();
539 }
540
541
542 /*
543 * RTC MC146818.
544 */
545 rc = CFGMR3InsertNode(pDevices, "mc146818", &pDev); UPDATERC();
546 rc = CFGMR3InsertNode(pDev, "0", &pInst); UPDATERC();
547 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); UPDATERC();
548
549 /*
550 * VGA.
551 */
552 rc = CFGMR3InsertNode(pDevices, "vga", &pDev); UPDATERC();
553 rc = CFGMR3InsertNode(pDev, "0", &pInst); UPDATERC();
554 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ UPDATERC();
555 rc = CFGMR3InsertInteger(pInst, "PCIDeviceNo", 2); UPDATERC();
556 rc = CFGMR3InsertInteger(pInst, "PCIFunctionNo", 0); UPDATERC();
557 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); UPDATERC();
558 rc = CFGMR3InsertInteger(pCfg, "VRamSize", 8 * _1M); UPDATERC();
559 rc = CFGMR3InsertInteger(pCfg, "CustomVideoModes", 0);
560 rc = CFGMR3InsertInteger(pCfg, "HeightReduction", 0); UPDATERC();
561 //rc = CFGMR3InsertInteger(pCfg, "MonitorCount", 1); UPDATERC();
562
563 /*
564 * IDE controller.
565 */
566 rc = CFGMR3InsertNode(pDevices, "piix3ide", &pDev); /* piix3 */
567 UPDATERC();
568 rc = CFGMR3InsertNode(pDev, "0", &pInst);
569 UPDATERC();
570 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */
571 UPDATERC();
572 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); UPDATERC();
573 rc = CFGMR3InsertInteger(pInst, "PCIDeviceNo", 1); UPDATERC();
574 rc = CFGMR3InsertInteger(pInst, "PCIFunctionNo", 1); UPDATERC();
575
576 /*
577 * Network card.
578 */
579 rc = CFGMR3InsertNode(pDevices, "pcnet", &pDev); UPDATERC();
580 rc = CFGMR3InsertNode(pDev, "0", &pInst); UPDATERC();
581 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ UPDATERC();
582 rc = CFGMR3InsertInteger(pInst, "PCIDeviceNo", 3); UPDATERC();
583 rc = CFGMR3InsertInteger(pInst, "PCIFunctionNo", 0); UPDATERC();
584 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); UPDATERC();
585 rc = CFGMR3InsertInteger(pCfg, "Am79C973", 1); UPDATERC();
586 RTMAC Mac;
587 Mac.au16[0] = 0x0080;
588 Mac.au16[2] = Mac.au16[1] = 0x8086;
589 rc = CFGMR3InsertBytes(pCfg, "MAC", &Mac, sizeof(Mac)); UPDATERC();
590
591 /*
592 * VMM Device
593 */
594 rc = CFGMR3InsertNode(pDevices, "VMMDev", &pDev); UPDATERC();
595 rc = CFGMR3InsertNode(pDev, "0", &pInst); UPDATERC();
596 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); UPDATERC();
597 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ UPDATERC();
598 rc = CFGMR3InsertInteger(pInst, "PCIDeviceNo", 4); UPDATERC();
599 rc = CFGMR3InsertInteger(pInst, "PCIFunctionNo", 0); UPDATERC();
600
601 /*
602 * ...
603 */
604
605#undef UPDATERC
606 return rcAll;
607}
608
609static void syntax(void)
610{
611 RTPrintf("Syntax: tstAnimate < -r <raw-mem-file> | -z <saved-state> > \n"
612 " [-o <rawmem offset>]\n"
613 " [-s <script file>]\n"
614 " [-m <memory size>]\n"
615 " [-w <warp drive percent>]\n"
616 " [-p]\n"
617 "\n"
618 "The script is on the form:\n"
619 "<reg>=<value>\n");
620}
621
622
623/**
624 * Entry point.
625 */
626extern "C" DECLEXPORT(int) TrustedMain(int argc, char **argv, char **envp)
627{
628 RT_NOREF1(envp);
629 int rcRet = 1;
630 int rc;
631 RTR3InitExe(argc, &argv, RTR3INIT_FLAGS_TRY_SUPLIB);
632
633 /*
634 * Parse input.
635 */
636 if (argc <= 1)
637 {
638 syntax();
639 return 1;
640 }
641
642 bool fPowerOn = false;
643 uint32_t u32WarpDrive = 100; /* % */
644 uint64_t cbMem = ~0ULL;
645 const char *pszSavedState = NULL;
646 const char *pszRawMem = NULL;
647 uint64_t offRawMem = 0;
648 const char *pszScript = NULL;
649 for (int i = 1; i < argc; i++)
650 {
651 if (argv[i][0] == '-')
652 {
653 /* check that it's on short form */
654 if (argv[i][2])
655 {
656 if ( strcmp(argv[i], "--help")
657 && strcmp(argv[i], "-help"))
658 RTPrintf("tstAnimate: Syntax error: Unknown argument '%s'.\n", argv[i]);
659 else
660 syntax();
661 return 1;
662 }
663
664 /* check for 2nd argument */
665 switch (argv[i][1])
666 {
667 case 'r':
668 case 'o':
669 case 'c':
670 case 'm':
671 case 'w':
672 case 'z':
673 if (i + 1 < argc)
674 break;
675 RTPrintf("tstAnimate: Syntax error: '%s' takes a 2nd argument.\n", argv[i]);
676 return 1;
677 }
678
679 /* process argument */
680 switch (argv[i][1])
681 {
682 case 'r':
683 pszRawMem = argv[++i];
684 break;
685
686 case 'z':
687 pszSavedState = argv[++i];
688 break;
689
690 case 'o':
691 {
692 rc = RTStrToUInt64Ex(argv[++i], NULL, 0, &offRawMem);
693 if (RT_FAILURE(rc))
694 {
695 RTPrintf("tstAnimate: Syntax error: Invalid offset given to -o.\n");
696 return 1;
697 }
698 break;
699 }
700
701 case 'm':
702 {
703 char *pszNext;
704 rc = RTStrToUInt64Ex(argv[++i], &pszNext, 0, &cbMem);
705 if (RT_FAILURE(rc))
706 {
707 RTPrintf("tstAnimate: Syntax error: Invalid memory size given to -m.\n");
708 return 1;
709 }
710 switch (*pszNext)
711 {
712 case 'G': cbMem *= _1G; pszNext++; break;
713 case 'M': cbMem *= _1M; pszNext++; break;
714 case 'K': cbMem *= _1K; pszNext++; break;
715 case '\0': break;
716 default:
717 RTPrintf("tstAnimate: Syntax error: Invalid memory size given to -m.\n");
718 return 1;
719 }
720 if (*pszNext)
721 {
722 RTPrintf("tstAnimate: Syntax error: Invalid memory size given to -m.\n");
723 return 1;
724 }
725 break;
726 }
727
728 case 's':
729 pszScript = argv[++i];
730 break;
731
732 case 'p':
733 fPowerOn = true;
734 break;
735
736 case 'w':
737 {
738 rc = RTStrToUInt32Ex(argv[++i], NULL, 0, &u32WarpDrive);
739 if (RT_FAILURE(rc))
740 {
741 RTPrintf("tstAnimate: Syntax error: Invalid number given to -w.\n");
742 return 1;
743 }
744 break;
745 }
746
747 case 'h':
748 case 'H':
749 case '?':
750 syntax();
751 return 1;
752
753 default:
754 RTPrintf("tstAnimate: Syntax error: Unknown argument '%s'.\n", argv[i]);
755 return 1;
756 }
757 }
758 else
759 {
760 RTPrintf("tstAnimate: Syntax error at arg no. %d '%s'.\n", i, argv[i]);
761 syntax();
762 return 1;
763 }
764 }
765
766 /*
767 * Check that the basic requirements are met.
768 */
769 if (pszRawMem && pszSavedState)
770 {
771 RTPrintf("tstAnimate: Syntax error: Either -z or -r, not both.\n");
772 return 1;
773 }
774 if (!pszRawMem && !pszSavedState)
775 {
776 RTPrintf("tstAnimate: Syntax error: The -r argument is compulsory.\n");
777 return 1;
778 }
779
780 /*
781 * Open the files.
782 */
783 RTFILE FileRawMem = NIL_RTFILE;
784 if (pszRawMem)
785 {
786 rc = RTFileOpen(&FileRawMem, pszRawMem, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE);
787 if (RT_FAILURE(rc))
788 {
789 RTPrintf("tstAnimate: error: Failed to open '%s': %Rrc\n", pszRawMem, rc);
790 return 1;
791 }
792 }
793 RTFILE FileScript = NIL_RTFILE;
794 if (pszScript)
795 {
796 rc = RTFileOpen(&FileScript, pszScript, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE);
797 if (RT_FAILURE(rc))
798 {
799 RTPrintf("tstAnimate: error: Failed to open '%s': %Rrc\n", pszScript, rc);
800 return 1;
801 }
802 }
803
804 /*
805 * Figure the memsize if not specified.
806 */
807 if (cbMem == ~0ULL)
808 {
809 if (FileRawMem != NIL_RTFILE)
810 {
811 rc = RTFileQuerySize(FileRawMem, &cbMem);
812 AssertReleaseRC(rc);
813 cbMem -= offRawMem;
814 cbMem &= ~(uint64_t)GUEST_PAGE_OFFSET_MASK;
815 }
816 else
817 {
818 RTPrintf("tstAnimate: error: too lazy to figure out the memsize in a saved state.\n");
819 return 1;
820 }
821 }
822 RTPrintf("tstAnimate: info: cbMem=0x%llx bytes\n", cbMem);
823
824 /*
825 * Open a release log.
826 */
827 static const char * const s_apszGroups[] = VBOX_LOGGROUP_NAMES;
828 PRTLOGGER pRelLogger;
829 rc = RTLogCreate(&pRelLogger, RTLOGFLAGS_PREFIX_TIME_PROG, "all", "VBOX_RELEASE_LOG",
830 RT_ELEMENTS(s_apszGroups), s_apszGroups, RTLOGDEST_FILE, "./tstAnimate.log");
831 if (RT_SUCCESS(rc))
832 RTLogRelSetDefaultInstance(pRelLogger);
833 else
834 RTPrintf("tstAnimate: rtLogCreateEx failed - %Rrc\n", rc);
835
836 /*
837 * Create empty VM.
838 */
839 PVM pVM;
840 PUVM pUVM;
841 rc = VMR3Create(1 /*cCpus*/, NULL, 0 /*fFlags*/, NULL, NULL, cfgmR3CreateDefault, &cbMem, &pVM, &pUVM);
842 if (RT_SUCCESS(rc))
843 {
844 /*
845 * Load memory.
846 */
847 if (FileRawMem != NIL_RTFILE)
848 rc = VMR3ReqCallWaitU(pUVM, VMCPUID_ANY, (PFNRT)loadMem, 3, pVM, FileRawMem, &offRawMem);
849 else
850 rc = VMR3ReqCallWaitU(pUVM, VMCPUID_ANY, (PFNRT)SSMR3Load,
851 7, pVM, pszSavedState, (uintptr_t)NULL /*pStreamOps*/, (uintptr_t)NULL /*pvUser*/,
852 SSMAFTER_DEBUG_IT, (uintptr_t)NULL /*pfnProgress*/, (uintptr_t)NULL /*pvProgressUser*/);
853 if (RT_SUCCESS(rc))
854 {
855 /*
856 * Load register script.
857 */
858 if (FileScript != NIL_RTFILE)
859 rc = VMR3ReqCallWaitU(pUVM, VMCPUID_ANY, (PFNRT)scriptRun, 2, pVM, FileScript);
860 if (RT_SUCCESS(rc))
861 {
862 if (fPowerOn)
863 {
864 /*
865 * Adjust warpspeed?
866 */
867 if (u32WarpDrive != 100)
868 {
869 rc = TMR3SetWarpDrive(pUVM, u32WarpDrive);
870 if (RT_FAILURE(rc))
871 RTPrintf("warning: TMVirtualSetWarpDrive(,%u) -> %Rrc\n", u32WarpDrive, rc);
872 }
873
874 /*
875 * Start the thing with single stepping and stuff enabled.
876 * (Try make sure we don't execute anything in raw mode.)
877 */
878 RTPrintf("info: powering on the VM...\n");
879 RTLogGroupSettings(NULL, "+REM_DISAS.e.l.f");
880 rc = VERR_NOT_IMPLEMENTED; /** @todo need some EM single-step indicator (was REMR3DisasEnableStepping) */
881 if (RT_SUCCESS(rc))
882 {
883 rc = EMR3SetExecutionPolicy(pUVM, EMEXECPOLICY_IEM_ALL, true); AssertReleaseRC(rc);
884 DBGFR3Info(pUVM, "cpumguest", "verbose", NULL);
885 if (fPowerOn)
886 rc = VMR3PowerOn(pUVM);
887 if (RT_SUCCESS(rc))
888 {
889 RTPrintf("info: VM is running\n");
890 signal(SIGINT, SigInterrupt);
891 while (!g_fSignaled)
892 RTThreadSleep(1000);
893 }
894 else
895 RTPrintf("error: Failed to power on the VM: %Rrc\n", rc);
896 }
897 else
898 RTPrintf("error: Failed to enabled singlestepping: %Rrc\n", rc);
899 }
900 else
901 {
902 /*
903 * Don't start it, just enter the debugger.
904 */
905 RTPrintf("info: entering debugger...\n");
906 DBGFR3Info(pUVM, "cpumguest", "verbose", NULL);
907 signal(SIGINT, SigInterrupt);
908 while (!g_fSignaled)
909 RTThreadSleep(1000);
910 }
911 RTPrintf("info: shutting down the VM...\n");
912 }
913 /* execScript complains */
914 }
915 else if (FileRawMem == NIL_RTFILE) /* loadMem complains, SSMR3Load doesn't */
916 RTPrintf("tstAnimate: error: SSMR3Load failed: rc=%Rrc\n", rc);
917 rcRet = RT_SUCCESS(rc) ? 0 : 1;
918
919 /*
920 * Cleanup.
921 */
922 rc = VMR3Destroy(pUVM);
923 if (!RT_SUCCESS(rc))
924 {
925 RTPrintf("tstAnimate: error: failed to destroy vm! rc=%Rrc\n", rc);
926 rcRet++;
927 }
928
929 VMR3ReleaseUVM(pUVM);
930 }
931 else
932 {
933 RTPrintf("tstAnimate: fatal error: failed to create vm! rc=%Rrc\n", rc);
934 rcRet++;
935 }
936
937 return rcRet;
938}
939
940
941#if !defined(VBOX_WITH_HARDENING) || !defined(RT_OS_WINDOWS)
942/**
943 * Main entry point.
944 */
945int main(int argc, char **argv, char **envp)
946{
947 return TrustedMain(argc, argv, envp);
948}
949#endif
950
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