VirtualBox

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

Last change on this file since 55899 was 55899, checked in by vboxsync, 10 years ago

PGM: Added an access origin to memory read & write calls that respects handlers. This will later be passed to the access handler, so that things like the page pool (and potentially others) can query IEM about instruction details when needed.

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