VirtualBox

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

Last change on this file since 94018 was 93554, checked in by vboxsync, 3 years ago

VMM: Changed PAGE_SIZE -> GUEST_PAGE_SIZE / HOST_PAGE_SIZE, PAGE_SHIFT -> GUEST_PAGE_SHIFT / HOST_PAGE_SHIFT, and PAGE_OFFSET_MASK -> GUEST_PAGE_OFFSET_MASK / HOST_PAGE_OFFSET_MASK. Also removed most usage of ASMMemIsZeroPage and ASMMemZeroPage since the host and guest page size doesn't need to be the same any more. Some work left to do in the page pool code. bugref:9898

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 32.2 KB
Line 
1/* $Id: tstAnimate.cpp 93554 2022-02-02 22:57:02Z vboxsync $ */
2/** @file
3 * VBox Animation Testcase / Tool.
4 */
5
6/*
7 * Copyright (C) 2006-2022 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/ssm.h>
29#include <VBox/vmm/dbgf.h>
30#include <VBox/err.h>
31#include <VBox/vmm/pdmifs.h>
32#include <VBox/param.h>
33#include <VBox/log.h>
34#include <iprt/assert.h>
35#include <iprt/alloc.h>
36#include <iprt/initterm.h>
37#include <iprt/semaphore.h>
38#include <iprt/string.h>
39#include <iprt/stream.h>
40#include <iprt/file.h>
41#include <iprt/thread.h>
42#include <iprt/ctype.h>
43#include <iprt/uuid.h>
44
45#include <signal.h>
46
47
48/*********************************************************************************************************************************
49* Global Variables *
50*********************************************************************************************************************************/
51static volatile bool g_fSignaled = false;
52
53
54static void SigInterrupt(int iSignal) RT_NOTHROW_DEF
55{
56 NOREF(iSignal);
57 signal(SIGINT, SigInterrupt);
58 g_fSignaled = true;
59 RTPrintf("caught SIGINT\n");
60}
61
62typedef DECLCALLBACKTYPE(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 DECLCALLBACKTYPE(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 DECLCALLBACKTYPE(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 DECLCALLBACKTYPE(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/* variables - putting in global scope to avoid MSC warning C4640. */
128static struct
129{
130 const char *pszVar;
131 int (*pfnHandler)(PVM pVM, char *pszVar, char *pszValue, void *pvUser);
132 PFNRT pvUser;
133} g_aVars[] =
134{
135 { "eax", scriptGPReg, (PFNRT)CPUMSetGuestEAX },
136 { "ebx", scriptGPReg, (PFNRT)CPUMSetGuestEBX },
137 { "ecx", scriptGPReg, (PFNRT)CPUMSetGuestECX },
138 { "edx", scriptGPReg, (PFNRT)CPUMSetGuestEDX },
139 { "esp", scriptGPReg, (PFNRT)CPUMSetGuestESP },
140 { "ebp", scriptGPReg, (PFNRT)CPUMSetGuestEBP },
141 { "esi", scriptGPReg, (PFNRT)CPUMSetGuestESI },
142 { "edi", scriptGPReg, (PFNRT)CPUMSetGuestEDI },
143 { "efl", scriptGPReg, (PFNRT)CPUMSetGuestEFlags },
144 { "eip", scriptGPReg, (PFNRT)CPUMSetGuestEIP },
145 { "ss", scriptSelReg, (PFNRT)CPUMSetGuestSS },
146 { "cs", scriptSelReg, (PFNRT)CPUMSetGuestCS },
147 { "ds", scriptSelReg, (PFNRT)CPUMSetGuestDS },
148 { "es", scriptSelReg, (PFNRT)CPUMSetGuestES },
149 { "fs", scriptSelReg, (PFNRT)CPUMSetGuestFS },
150 { "gs", scriptSelReg, (PFNRT)CPUMSetGuestGS },
151 { "cr0", scriptSysReg, (PFNRT)CPUMSetGuestCR0 },
152 { "cr2", scriptSysReg, (PFNRT)CPUMSetGuestCR2 },
153 { "cr3", scriptSysReg, (PFNRT)CPUMSetGuestCR3 },
154 { "cr4", scriptSysReg, (PFNRT)CPUMSetGuestCR4 },
155 { "ldtr",scriptSelReg, (PFNRT)CPUMSetGuestLDTR },
156 { "tr", scriptSelReg, (PFNRT)CPUMSetGuestTR },
157 { "idtr",scriptDtrReg, (PFNRT)CPUMSetGuestIDTR },
158 { "gdtr",scriptDtrReg, (PFNRT)CPUMSetGuestGDTR }
159};
160
161
162static int scriptCommand(PVM pVM, const char *pszIn, size_t cch)
163{
164 NOREF(cch);
165 int rc = VINF_SUCCESS;
166 char *psz = RTStrDup(pszIn);
167 char *pszEqual = strchr(psz, '=');
168 if (pszEqual)
169 {
170 /*
171 * var = value
172 */
173 *pszEqual = '\0';
174 RTStrStripR(psz);
175 char *pszValue = RTStrStrip(pszEqual + 1);
176
177 rc = -1;
178 for (unsigned i = 0; i < RT_ELEMENTS(g_aVars); i++)
179 {
180 if (!strcmp(psz, g_aVars[i].pszVar))
181 {
182 rc = g_aVars[i].pfnHandler(pVM, psz, pszValue, (void *)(uintptr_t)g_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 = RTFileQuerySize(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 (RT_C_IS_SPACE(*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 && RT_C_IS_SPACE(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 % (GUEST_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[GUEST_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 >= 0x100000) /* ASSUME size of a8Page is a power of 2. */
309 PGMPhysWrite(pVM, GCPhys, &au8Page, cbRead, PGMACCESSORIGIN_DEBUGGER);
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 * @callback_method_impl{FNCFGMCONSTRUCTOR, Creates the default configuration.}
322 *
323 * This assumes an empty tree.
324 */
325static DECLCALLBACK(int) cfgmR3CreateDefault(PUVM pUVM, PVM pVM, PCVMMR3VTABLE pVMM, void *pvUser)
326{
327 RT_NOREF(pUVM, pVMM);
328 uint64_t cbMem = *(uint64_t *)pvUser;
329 int rc;
330 int rcAll = VINF_SUCCESS;
331 bool fIOAPIC = false;
332#define UPDATERC() do { if (RT_FAILURE(rc) && RT_SUCCESS(rcAll)) rcAll = rc; } while (0)
333
334 /*
335 * Create VM default values.
336 */
337 PCFGMNODE pRoot = CFGMR3GetRoot(pVM);
338 rc = CFGMR3InsertString(pRoot, "Name", "Default VM");
339 UPDATERC();
340 rc = CFGMR3InsertInteger(pRoot, "RamSize", cbMem);
341 UPDATERC();
342 rc = CFGMR3InsertInteger(pRoot, "TimerMillies", 10);
343 UPDATERC();
344 rc = CFGMR3InsertInteger(pRoot, "RawR3Enabled", 0);
345 UPDATERC();
346 /** @todo CFGM Defaults: RawR0, PATMEnabled and CASMEnabled needs attention later. */
347 rc = CFGMR3InsertInteger(pRoot, "RawR0Enabled", 0);
348 UPDATERC();
349 rc = CFGMR3InsertInteger(pRoot, "PATMEnabled", 0);
350 UPDATERC();
351 rc = CFGMR3InsertInteger(pRoot, "CSAMEnabled", 0);
352 UPDATERC();
353
354 /*
355 * PDM.
356 */
357 PCFGMNODE pPdm;
358 rc = CFGMR3InsertNode(pRoot, "PDM", &pPdm);
359 UPDATERC();
360 PCFGMNODE pDevices = NULL;
361 rc = CFGMR3InsertNode(pPdm, "Devices", &pDevices);
362 UPDATERC();
363 rc = CFGMR3InsertInteger(pDevices, "LoadBuiltin", 1); /* boolean */
364 UPDATERC();
365 PCFGMNODE pDrivers = NULL;
366 rc = CFGMR3InsertNode(pPdm, "Drivers", &pDrivers);
367 UPDATERC();
368 rc = CFGMR3InsertInteger(pDrivers, "LoadBuiltin", 1); /* boolean */
369 UPDATERC();
370
371
372 /*
373 * Devices
374 */
375 pDevices = NULL;
376 rc = CFGMR3InsertNode(pRoot, "Devices", &pDevices);
377 UPDATERC();
378 /* device */
379 PCFGMNODE pDev = NULL;
380 PCFGMNODE pInst = NULL;
381 PCFGMNODE pCfg = NULL;
382#if 0
383 PCFGMNODE pLunL0 = NULL;
384 PCFGMNODE pLunL1 = NULL;
385#endif
386
387 /*
388 * PC Arch.
389 */
390 rc = CFGMR3InsertNode(pDevices, "pcarch", &pDev);
391 UPDATERC();
392 rc = CFGMR3InsertNode(pDev, "0", &pInst);
393 UPDATERC();
394 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */
395 UPDATERC();
396 rc = CFGMR3InsertNode(pInst, "Config", &pCfg);
397 UPDATERC();
398
399 /*
400 * PC Bios.
401 */
402 rc = CFGMR3InsertNode(pDevices, "pcbios", &pDev);
403 UPDATERC();
404 rc = CFGMR3InsertNode(pDev, "0", &pInst);
405 UPDATERC();
406 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */
407 UPDATERC();
408 rc = CFGMR3InsertNode(pInst, "Config", &pCfg);
409 UPDATERC();
410 rc = CFGMR3InsertString(pCfg, "BootDevice0", "IDE");
411 UPDATERC();
412 rc = CFGMR3InsertString(pCfg, "BootDevice1", "NONE");
413 UPDATERC();
414 rc = CFGMR3InsertString(pCfg, "BootDevice2", "NONE");
415 UPDATERC();
416 rc = CFGMR3InsertString(pCfg, "BootDevice3", "NONE");
417 UPDATERC();
418 rc = CFGMR3InsertString(pCfg, "HardDiskDevice", "piix3ide");
419 UPDATERC();
420 rc = CFGMR3InsertString(pCfg, "FloppyDevice", "i82078");
421 rc = CFGMR3InsertInteger(pCfg, "IOAPIC", fIOAPIC); UPDATERC();
422 RTUUID Uuid;
423 RTUuidClear(&Uuid);
424 rc = CFGMR3InsertBytes(pCfg, "UUID", &Uuid, sizeof(Uuid)); UPDATERC();
425 /* Bios logo. */
426 rc = CFGMR3InsertInteger(pCfg, "FadeIn", 0);
427 UPDATERC();
428 rc = CFGMR3InsertInteger(pCfg, "FadeOut", 0);
429 UPDATERC();
430 rc = CFGMR3InsertInteger(pCfg, "LogoTime", 0);
431 UPDATERC();
432 rc = CFGMR3InsertString(pCfg, "LogoFile", "");
433 UPDATERC();
434
435 /*
436 * ACPI
437 */
438 rc = CFGMR3InsertNode(pDevices, "acpi", &pDev); UPDATERC();
439 rc = CFGMR3InsertNode(pDev, "0", &pInst); UPDATERC();
440 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ UPDATERC();
441 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); 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
613/**
614 * Entry point.
615 */
616extern "C" DECLEXPORT(int) TrustedMain(int argc, char **argv, char **envp)
617{
618 RT_NOREF1(envp);
619 int rcRet = 1;
620 int rc;
621 RTR3InitExe(argc, &argv, RTR3INIT_FLAGS_TRY_SUPLIB);
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 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 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 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 rc = RTFileQuerySize(FileRawMem, &cbMem);
802 AssertReleaseRC(rc);
803 cbMem -= offRawMem;
804 cbMem &= ~(uint64_t)GUEST_PAGE_OFFSET_MASK;
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 PUVM pUVM;
831 rc = VMR3Create(1, NULL, NULL, NULL, cfgmR3CreateDefault, &cbMem, &pVM, &pUVM);
832 if (RT_SUCCESS(rc))
833 {
834 /*
835 * Load memory.
836 */
837 if (FileRawMem != NIL_RTFILE)
838 rc = VMR3ReqCallWaitU(pUVM, VMCPUID_ANY, (PFNRT)loadMem, 3, pVM, FileRawMem, &offRawMem);
839 else
840 rc = VMR3ReqCallWaitU(pUVM, VMCPUID_ANY, (PFNRT)SSMR3Load,
841 7, pVM, pszSavedState, (uintptr_t)NULL /*pStreamOps*/, (uintptr_t)NULL /*pvUser*/,
842 SSMAFTER_DEBUG_IT, (uintptr_t)NULL /*pfnProgress*/, (uintptr_t)NULL /*pvProgressUser*/);
843 if (RT_SUCCESS(rc))
844 {
845 /*
846 * Load register script.
847 */
848 if (FileScript != NIL_RTFILE)
849 rc = VMR3ReqCallWaitU(pUVM, VMCPUID_ANY, (PFNRT)scriptRun, 2, pVM, FileScript);
850 if (RT_SUCCESS(rc))
851 {
852 if (fPowerOn)
853 {
854 /*
855 * Adjust warpspeed?
856 */
857 if (u32WarpDrive != 100)
858 {
859 rc = TMR3SetWarpDrive(pUVM, u32WarpDrive);
860 if (RT_FAILURE(rc))
861 RTPrintf("warning: TMVirtualSetWarpDrive(,%u) -> %Rrc\n", u32WarpDrive, rc);
862 }
863
864 /*
865 * Start the thing with single stepping and stuff enabled.
866 * (Try make sure we don't execute anything in raw mode.)
867 */
868 RTPrintf("info: powering on the VM...\n");
869 RTLogGroupSettings(NULL, "+REM_DISAS.e.l.f");
870 rc = VERR_NOT_IMPLEMENTED; /** @todo need some EM single-step indicator (was REMR3DisasEnableStepping) */
871 if (RT_SUCCESS(rc))
872 {
873 rc = EMR3SetExecutionPolicy(pUVM, EMEXECPOLICY_RECOMPILE_RING0, true); AssertReleaseRC(rc);
874 rc = EMR3SetExecutionPolicy(pUVM, EMEXECPOLICY_RECOMPILE_RING3, true); AssertReleaseRC(rc);
875 DBGFR3Info(pUVM, "cpumguest", "verbose", NULL);
876 if (fPowerOn)
877 rc = VMR3PowerOn(pUVM);
878 if (RT_SUCCESS(rc))
879 {
880 RTPrintf("info: VM is running\n");
881 signal(SIGINT, SigInterrupt);
882 while (!g_fSignaled)
883 RTThreadSleep(1000);
884 }
885 else
886 RTPrintf("error: Failed to power on the VM: %Rrc\n", rc);
887 }
888 else
889 RTPrintf("error: Failed to enabled singlestepping: %Rrc\n", rc);
890 }
891 else
892 {
893 /*
894 * Don't start it, just enter the debugger.
895 */
896 RTPrintf("info: entering debugger...\n");
897 DBGFR3Info(pUVM, "cpumguest", "verbose", NULL);
898 signal(SIGINT, SigInterrupt);
899 while (!g_fSignaled)
900 RTThreadSleep(1000);
901 }
902 RTPrintf("info: shutting down the VM...\n");
903 }
904 /* execScript complains */
905 }
906 else if (FileRawMem == NIL_RTFILE) /* loadMem complains, SSMR3Load doesn't */
907 RTPrintf("tstAnimate: error: SSMR3Load failed: rc=%Rrc\n", rc);
908 rcRet = RT_SUCCESS(rc) ? 0 : 1;
909
910 /*
911 * Cleanup.
912 */
913 rc = VMR3Destroy(pUVM);
914 if (!RT_SUCCESS(rc))
915 {
916 RTPrintf("tstAnimate: error: failed to destroy vm! rc=%Rrc\n", rc);
917 rcRet++;
918 }
919
920 VMR3ReleaseUVM(pUVM);
921 }
922 else
923 {
924 RTPrintf("tstAnimate: fatal error: failed to create vm! rc=%Rrc\n", rc);
925 rcRet++;
926 }
927
928 return rcRet;
929}
930
931
932#if !defined(VBOX_WITH_HARDENING) || !defined(RT_OS_WINDOWS)
933/**
934 * Main entry point.
935 */
936int main(int argc, char **argv, char **envp)
937{
938 return TrustedMain(argc, argv, envp);
939}
940#endif
941
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