VirtualBox

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

Last change on this file since 23012 was 23012, checked in by vboxsync, 15 years ago

VMM,Devices,Main: VMR3ReqCall w/ RT_INDEFINITE_WAIT -> VMR3ReqCallWait.

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