VirtualBox

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

Last change on this file since 77807 was 76553, checked in by vboxsync, 6 years ago

scm --update-copyright-year

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