VirtualBox

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

Last change on this file since 34796 was 32190, checked in by vboxsync, 14 years ago

PDMDevHlpVMSuspendSaveAndPowerOff: More code.

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