VirtualBox

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

Last change on this file since 62596 was 62478, checked in by vboxsync, 8 years ago

(C) 2016

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