VirtualBox

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

Last change on this file since 39333 was 39084, checked in by vboxsync, 13 years ago

VMM: -Wunused-parameter on mac.

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