blob: 37bf34ac87d9785d3b27e2b8e5c5509408b3aabc [file] [log] [blame]
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001/* Copyright (C) 2006-2008 The Android Open Source Project
2**
3** This software is licensed under the terms of the GNU General Public
4** License version 2, as published by the Free Software Foundation, and
5** may be copied, distributed, and modified under those terms.
6**
7** This program is distributed in the hope that it will be useful,
8** but WITHOUT ANY WARRANTY; without even the implied warranty of
9** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10** GNU General Public License for more details.
11*/
12
13#include <signal.h>
14#include <unistd.h>
15#include <string.h>
16#include <sys/time.h>
17#ifdef _WIN32
18#include <process.h>
19#endif
Vladimir Chtchetkine7fbf4972010-08-11 15:30:32 -070020
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080021#include "sockets.h"
22
23#include "android/android.h"
24#include "qemu-common.h"
25#include "sysemu.h"
26#include "console.h"
David 'Digit' Turner34f29742010-05-25 18:16:10 -070027#include "user-events.h"
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080028
29#include <SDL.h>
30#include <SDL_syswm.h>
31
32#include "math.h"
33
34#include "android/charmap.h"
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080035#include "android/utils/debug.h"
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080036#include "android/config.h"
37#include "android/config/config.h"
38
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080039#include "android/user-config.h"
40#include "android/utils/bufprint.h"
David 'Digit' Turner26d41532011-03-01 15:03:07 +010041#include "android/utils/filelock.h"
David 'Digit' Turner0a879bf2011-05-12 18:45:18 +020042#include "android/utils/lineinput.h"
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080043#include "android/utils/path.h"
David 'Digit' Turner622f1532011-02-01 17:48:37 +010044#include "android/utils/tempfile.h"
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080045
David 'Digit' Turnerf8456272011-02-02 12:34:14 +010046#include "android/main-common.h"
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080047#include "android/help.h"
48#include "hw/goldfish_nand.h"
49
50#include "android/globals.h"
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080051
Xavier Ducrohetfc8ed802011-02-09 18:04:23 -080052#include "android/qemulator.h"
David 'Digit' Turner055ae422010-07-27 11:34:16 -070053#include "android/display.h"
Vladimir Chtchetkine01193622010-05-11 13:07:22 -070054
Ot ten Thijeae835ac2010-10-18 13:37:37 +010055#include "android/snapshot.h"
56
David 'Digit' Turnere3fdd072011-02-02 14:43:23 +010057#include "android/framebuffer.h"
Vladimir Chtchetkine9a33e852010-11-08 16:52:04 -080058#include "iolooper.h"
David 'Digit' Turner055ae422010-07-27 11:34:16 -070059
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080060AndroidRotation android_framebuffer_rotation;
61
62#define STRINGIFY(x) _STRINGIFY(x)
63#define _STRINGIFY(x) #x
64
David 'Digit' Turnera383d022009-12-03 13:50:00 -080065#ifdef ANDROID_SDK_TOOLS_REVISION
66# define VERSION_STRING STRINGIFY(ANDROID_SDK_TOOLS_REVISION)".0"
67#else
68# define VERSION_STRING "standalone"
69#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080070
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080071#define D(...) do { if (VERBOSE_CHECK(init)) dprint(__VA_ARGS__); } while (0)
72
73extern int control_console_start( int port ); /* in control.c */
74
75extern int qemu_milli_needed;
76
77/* the default device DPI if none is specified by the skin
78 */
79#define DEFAULT_DEVICE_DPI 165
80
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080081#ifdef CONFIG_TRACE
82extern void start_tracing(void);
83extern void stop_tracing(void);
84#endif
85
86unsigned long android_verbose;
87
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080088int qemu_main(int argc, char **argv);
89
90/* this function dumps the QEMU help */
91extern void help( void );
92extern void emulator_help( void );
93
94#define VERBOSE_OPT(str,var) { str, &var }
95
96#define _VERBOSE_TAG(x,y) { #x, VERBOSE_##x, y },
97static const struct { const char* name; int flag; const char* text; }
98verbose_options[] = {
99 VERBOSE_TAG_LIST
100 { 0, 0, 0 }
101};
102
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800103void emulator_help( void )
104{
105 STRALLOC_DEFINE(out);
106 android_help_main(out);
107 printf( "%.*s", out->n, out->s );
108 stralloc_reset(out);
109 exit(1);
110}
111
David 'Digit' Turner40841b22011-03-01 14:04:00 +0100112/* TODO: Put in shared source file */
113static char*
114_getFullFilePath( const char* rootPath, const char* fileName )
115{
116 if (path_is_absolute(fileName)) {
117 return ASTRDUP(fileName);
118 } else {
119 char temp[PATH_MAX], *p=temp, *end=p+sizeof(temp);
120
121 p = bufprint(temp, end, "%s/%s", rootPath, fileName);
122 if (p >= end) {
123 return NULL;
124 }
125 return ASTRDUP(temp);
126 }
127}
128
129static uint64_t
130_adjustPartitionSize( const char* description,
131 uint64_t imageBytes,
132 uint64_t defaultBytes,
133 int inAndroidBuild )
134{
135 char temp[64];
136 unsigned imageMB;
137 unsigned defaultMB;
138
139 if (imageBytes <= defaultBytes)
140 return defaultBytes;
141
142 imageMB = convertBytesToMB(imageBytes);
143 defaultMB = convertBytesToMB(defaultBytes);
144
145 if (imageMB > defaultMB) {
146 snprintf(temp, sizeof temp, "(%d MB > %d MB)", imageMB, defaultMB);
147 } else {
148 snprintf(temp, sizeof temp, "(%lld bytes > %lld bytes)", imageBytes, defaultBytes);
149 }
150
151 if (inAndroidBuild) {
152 dwarning("%s partition size adjusted to match image file %s\n", description, temp);
153 }
154
155 return convertMBToBytes(imageMB);
156}
157
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800158int main(int argc, char **argv)
159{
160 char tmp[MAX_PATH];
161 char* tmpend = tmp + sizeof(tmp);
162 char* args[128];
163 int n;
164 char* opt;
David 'Digit' Turner5e736932011-03-18 00:02:14 +0100165 /* The emulator always uses the first serial port for kernel messages
166 * and the second one for qemud. So start at the third if we need one
167 * for logcat or 'shell'
168 */
169 int serial = 2;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800170 int shell_serial = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800171
172 AndroidHwConfig* hw;
David 'Digit' Turnercd059b12009-08-28 19:36:27 +0200173 AvdInfo* avd;
David 'Digit' Turner74d7ace2011-02-02 13:21:03 +0100174 AConfig* skinConfig;
175 char* skinPath;
Vladimir Chtchetkine83ffd662011-02-11 12:40:59 -0800176 int inAndroidBuild;
David 'Digit' Turner40841b22011-03-01 14:04:00 +0100177 uint64_t defaultPartitionSize = convertMBToBytes(66);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800178
179 AndroidOptions opts[1];
Vladimir Chtchetkineb25bf2a2010-09-08 11:09:23 -0700180 /* net.shared_net_ip boot property value. */
181 char boot_prop_ip[64];
182 boot_prop_ip[0] = '\0';
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800183
184 args[0] = argv[0];
185
186 if ( android_parse_options( &argc, &argv, opts ) < 0 ) {
187 exit(1);
188 }
189
David 'Digit' Turnerbdb6f2d2011-02-23 15:57:25 +0100190#ifdef _WIN32
191 socket_init();
192#endif
193
194 handle_ui_options(opts);
195
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800196 while (argc-- > 1) {
197 opt = (++argv)[0];
198
199 if(!strcmp(opt, "-qemu")) {
200 argc--;
201 argv++;
202 break;
203 }
204
205 if (!strcmp(opt, "-help")) {
206 emulator_help();
207 }
208
209 if (!strncmp(opt, "-help-",6)) {
210 STRALLOC_DEFINE(out);
211 opt += 6;
212
213 if (!strcmp(opt, "all")) {
214 android_help_all(out);
215 }
216 else if (android_help_for_option(opt, out) == 0) {
217 /* ok */
218 }
219 else if (android_help_for_topic(opt, out) == 0) {
220 /* ok */
221 }
222 if (out->n > 0) {
223 printf("\n%.*s", out->n, out->s);
224 exit(0);
225 }
226
227 fprintf(stderr, "unknown option: -help-%s\n", opt);
228 fprintf(stderr, "please use -help for a list of valid topics\n");
229 exit(1);
230 }
231
232 if (opt[0] == '-') {
233 fprintf(stderr, "unknown option: %s\n", opt);
234 fprintf(stderr, "please use -help for a list of valid options\n");
235 exit(1);
236 }
237
238 fprintf(stderr, "invalid command-line parameter: %s.\n", opt);
239 fprintf(stderr, "Hint: use '@foo' to launch a virtual device named 'foo'.\n");
240 fprintf(stderr, "please use -help for more information\n");
241 exit(1);
242 }
243
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800244 if (opts->version) {
245 printf("Android emulator version %s\n"
David 'Digit' Turner5f64b872011-02-28 23:23:05 +0100246 "Copyright (C) 2006-2011 The Android Open Source Project and many others.\n"
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800247 "This program is a derivative of the QEMU CPU emulator (www.qemu.org).\n\n",
248#if defined ANDROID_BUILD_ID
249 VERSION_STRING " (build_id " STRINGIFY(ANDROID_BUILD_ID) ")" );
250#else
251 VERSION_STRING);
252#endif
253 printf(" This software is licensed under the terms of the GNU General Public\n"
254 " License version 2, as published by the Free Software Foundation, and\n"
255 " may be copied, distributed, and modified under those terms.\n\n"
256 " This program is distributed in the hope that it will be useful,\n"
257 " but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
258 " MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
259 " GNU General Public License for more details.\n\n");
260
261 exit(0);
262 }
263
David 'Digit' Turner5f64b872011-02-28 23:23:05 +0100264 if (opts->snapshot_list) {
David 'Digit' Turnerd80a7862011-05-05 10:24:43 +0200265 if (opts->snapstorage == NULL) {
266 /* Need to find the default snapstorage */
267 avd = createAVD(opts, &inAndroidBuild);
268 opts->snapstorage = avdInfo_getSnapStoragePath(avd);
269 if (opts->snapstorage != NULL) {
270 D("autoconfig: -snapstorage %s", opts->snapstorage);
271 } else {
272 if (inAndroidBuild) {
273 derror("You must use the -snapstorage <file> option to specify a snapshot storage file!\n");
274 } else {
275 derror("This AVD doesn't have snapshotting enabled!\n");
276 }
277 exit(1);
278 }
279 }
David 'Digit' Turner5f64b872011-02-28 23:23:05 +0100280 snapshot_print_and_exit(opts->snapstorage);
281 }
282
David 'Digit' Turner25eb6552011-02-25 15:07:11 +0100283 sanitizeOptions(opts);
284
David 'Digit' Turnerbdb6f2d2011-02-23 15:57:25 +0100285 /* Initialization of UI started with -attach-core should work differently
286 * than initialization of UI that starts the core. In particular....
287 */
288
289 /* -charmap is incompatible with -attach-core, because particular
290 * charmap gets set up in the running core. */
David 'Digit' Turner74d7ace2011-02-02 13:21:03 +0100291 if (android_charmap_setup(opts->charmap)) {
292 exit(1);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800293 }
294
Vladimir Chtchetkine83ffd662011-02-11 12:40:59 -0800295 /* Parses options and builds an appropriate AVD. */
David 'Digit' Turner462564f2011-02-23 13:32:37 +0100296 avd = android_avdInfo = createAVD(opts, &inAndroidBuild);
David 'Digit' Turnercd059b12009-08-28 19:36:27 +0200297
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800298 /* get the skin from the virtual device configuration */
David 'Digit' Turner25eb6552011-02-25 15:07:11 +0100299 if (opts->skindir != NULL) {
300 if (opts->skin == NULL) {
301 /* NOTE: Normally handled by sanitizeOptions(), just be safe */
302 derror("The -skindir <path> option requires a -skin <name> option");
303 exit(2);
304 }
305 } else {
306 char* skinName;
307 char* skinDir;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800308
David 'Digit' Turner25eb6552011-02-25 15:07:11 +0100309 avdInfo_getSkinInfo(avd, &skinName, &skinDir);
310
311 if (opts->skin == NULL) {
312 opts->skin = skinName;
313 D("autoconfig: -skin %s", opts->skin);
314 } else {
315 AFREE(skinName);
316 }
317
318 opts->skindir = skinDir;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800319 D("autoconfig: -skindir %s", opts->skindir);
320 }
321
322 /* Read hardware configuration */
323 hw = android_hw;
David 'Digit' Turnerb64325d2011-03-22 16:07:01 +0100324 if (avdInfo_initHwConfig(avd, hw) < 0) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800325 derror("could not read hardware configuration ?");
326 exit(1);
327 }
328
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800329 if (opts->keyset) {
330 parse_keyset(opts->keyset, opts);
331 if (!android_keyset) {
332 fprintf(stderr,
333 "emulator: WARNING: could not find keyset file named '%s',"
334 " using defaults instead\n",
335 opts->keyset);
336 }
337 }
338 if (!android_keyset) {
339 parse_keyset("default", opts);
340 if (!android_keyset) {
341 android_keyset = skin_keyset_new_from_text( skin_keyset_get_default() );
342 if (!android_keyset) {
343 fprintf(stderr, "PANIC: default keyset file is corrupted !!\n" );
344 fprintf(stderr, "PANIC: please update the code in android/skin/keyset.c\n" );
345 exit(1);
346 }
347 if (!opts->keyset)
348 write_default_keyset();
349 }
350 }
351
Dries Harnie40beab42010-05-15 17:04:47 +0200352 if (opts->shared_net_id) {
353 char* end;
354 long shared_net_id = strtol(opts->shared_net_id, &end, 0);
355 if (end == NULL || *end || shared_net_id < 1 || shared_net_id > 255) {
356 fprintf(stderr, "option -shared-net-id must be an integer between 1 and 255\n");
357 exit(1);
358 }
Vladimir Chtchetkineb25bf2a2010-09-08 11:09:23 -0700359 snprintf(boot_prop_ip, sizeof(boot_prop_ip),
360 "net.shared_net_ip=10.1.2.%ld", shared_net_id);
Dries Harnie40beab42010-05-15 17:04:47 +0200361 }
362
363
David 'Digit' Turner755811e2011-02-07 13:38:25 +0100364 user_config_init();
David 'Digit' Turner2507cab2011-02-10 16:29:17 +0100365 parse_skin_files(opts->skindir, opts->skin, opts, hw,
David 'Digit' Turner74d7ace2011-02-02 13:21:03 +0100366 &skinConfig, &skinPath);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800367
David 'Digit' Turner092361e2011-03-01 13:14:18 +0100368 if (!opts->netspeed && skin_network_speed) {
369 D("skin network speed: '%s'", skin_network_speed);
370 if (strcmp(skin_network_speed, NETWORK_SPEED_DEFAULT) != 0) {
371 opts->netspeed = (char*)skin_network_speed;
372 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800373 }
David 'Digit' Turner092361e2011-03-01 13:14:18 +0100374 if (!opts->netdelay && skin_network_delay) {
375 D("skin network delay: '%s'", skin_network_delay);
376 if (strcmp(skin_network_delay, NETWORK_DELAY_DEFAULT) != 0) {
377 opts->netdelay = (char*)skin_network_delay;
378 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800379 }
380
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800381 if (opts->trace) {
David 'Digit' Turnercd059b12009-08-28 19:36:27 +0200382 char* tracePath = avdInfo_getTracePath(avd, opts->trace);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800383 int ret;
384
385 if (tracePath == NULL) {
386 derror( "bad -trace parameter" );
387 exit(1);
388 }
389 ret = path_mkdir_if_needed( tracePath, 0755 );
390 if (ret < 0) {
391 fprintf(stderr, "could not create directory '%s'\n", tmp);
392 exit(2);
393 }
394 opts->trace = tracePath;
395 }
396
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800397 n = 1;
398 /* generate arguments for the underlying qemu main() */
David 'Digit' Turner238b4b02009-09-20 13:10:19 -0700399 {
David 'Digit' Turner0b019492011-03-01 14:02:42 +0100400 char* kernelFile = opts->kernel;
401 int kernelFileLen;
David 'Digit' Turner238b4b02009-09-20 13:10:19 -0700402
David 'Digit' Turner0b019492011-03-01 14:02:42 +0100403 if (kernelFile == NULL) {
404 kernelFile = avdInfo_getKernelPath(avd);
405 if (kernelFile == NULL) {
406 derror( "This AVD's configuration is missing a kernel file!!" );
407 exit(2);
408 }
409 D("autoconfig: -kernel %s", kernelFile);
410 }
411 if (!path_exists(kernelFile)) {
412 derror( "Invalid or missing kernel image file: %s", kernelFile );
413 exit(2);
414 }
415
416 hw->kernel_path = kernelFile;
David 'Digit' Turner238b4b02009-09-20 13:10:19 -0700417
418 /* If the kernel image name ends in "-armv7", then change the cpu
419 * type automatically. This is a poor man's approach to configuration
420 * management, but should allow us to get past building ARMv7
421 * system images with dex preopt pass without introducing too many
422 * changes to the emulator sources.
423 *
424 * XXX:
425 * A 'proper' change would require adding some sort of hardware-property
426 * to each AVD config file, then automatically determine its value for
427 * full Android builds (depending on some environment variable), plus
428 * some build system changes. I prefer not to do that for now for reasons
429 * of simplicity.
430 */
David 'Digit' Turner0b019492011-03-01 14:02:42 +0100431 kernelFileLen = strlen(kernelFile);
David 'Digit' Turner238b4b02009-09-20 13:10:19 -0700432 if (kernelFileLen > 6 && !memcmp(kernelFile + kernelFileLen - 6, "-armv7", 6)) {
433 args[n++] = "-cpu";
434 args[n++] = "cortex-a8";
435 }
436 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800437
Vladimir Chtchetkineb25bf2a2010-09-08 11:09:23 -0700438 if (boot_prop_ip[0]) {
439 args[n++] = "-boot-property";
440 args[n++] = boot_prop_ip;
441 }
442
Vladimir Chtchetkine318f17a2010-08-27 09:09:45 -0700443 if (opts->tcpdump) {
444 args[n++] = "-tcpdump";
445 args[n++] = opts->tcpdump;
446 }
447
Vladimir Chtchetkinee1316862010-08-26 09:03:54 -0700448#ifdef CONFIG_NAND_LIMITS
449 if (opts->nand_limits) {
450 args[n++] = "-nand-limits";
451 args[n++] = opts->nand_limits;
452 }
453#endif
454
David 'Digit' Turner74d7ace2011-02-02 13:21:03 +0100455 if (opts->timezone) {
456 args[n++] = "-timezone";
457 args[n++] = opts->timezone;
458 }
459
Vladimir Chtchetkinee1316862010-08-26 09:03:54 -0700460 if (opts->netspeed) {
461 args[n++] = "-netspeed";
462 args[n++] = opts->netspeed;
463 }
464 if (opts->netdelay) {
465 args[n++] = "-netdelay";
466 args[n++] = opts->netdelay;
467 }
468 if (opts->netfast) {
469 args[n++] = "-netfast";
470 }
471
Vladimir Chtchetkineb2438402010-08-24 08:55:33 -0700472 if (opts->audio) {
473 args[n++] = "-audio";
474 args[n++] = opts->audio;
475 }
476
Vladimir Chtchetkineb2438402010-08-24 08:55:33 -0700477 if (opts->cpu_delay) {
478 args[n++] = "-cpu-delay";
479 args[n++] = opts->cpu_delay;
480 }
481
Vladimir Chtchetkine7fbf4972010-08-11 15:30:32 -0700482 if (opts->dns_server) {
483 args[n++] = "-dns-server";
484 args[n++] = opts->dns_server;
485 }
486
David 'Digit' Turner0b019492011-03-01 14:02:42 +0100487 hw->disk_ramdisk_path = avdInfo_getRamdiskPath(avd);
488 D("autoconfig: -ramdisk %s", hw->disk_ramdisk_path);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800489
David 'Digit' Turner40841b22011-03-01 14:04:00 +0100490 /* -partition-size is used to specify the max size of both the system
491 * and data partition sizes.
492 */
493 if (opts->partition_size) {
494 char* end;
495 long sizeMB = strtol(opts->partition_size, &end, 0);
496 long minSizeMB = 10;
497 long maxSizeMB = LONG_MAX / ONE_MB;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800498
David 'Digit' Turner40841b22011-03-01 14:04:00 +0100499 if (sizeMB < 0 || *end != 0) {
500 derror( "-partition-size must be followed by a positive integer" );
501 exit(1);
502 }
503 if (sizeMB < minSizeMB || sizeMB > maxSizeMB) {
504 derror( "partition-size (%d) must be between %dMB and %dMB",
505 sizeMB, minSizeMB, maxSizeMB );
506 exit(1);
507 }
508 defaultPartitionSize = (uint64_t) sizeMB * ONE_MB;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800509 }
510
David 'Digit' Turner40841b22011-03-01 14:04:00 +0100511
512 /** SYSTEM PARTITION **/
513
514 if (opts->sysdir == NULL) {
515 if (avdInfo_inAndroidBuild(avd)) {
516 opts->sysdir = ASTRDUP(avdInfo_getContentPath(avd));
517 D("autoconfig: -sysdir %s", opts->sysdir);
518 }
519 }
520
521 if (opts->sysdir != NULL) {
522 if (!path_exists(opts->sysdir)) {
523 derror("Directory does not exist: %s", opts->sysdir);
524 exit(1);
525 }
526 }
527
528 {
529 char* rwImage = NULL;
530 char* initImage = NULL;
531
532 do {
533 if (opts->system == NULL) {
534 /* If -system is not used, try to find a runtime system image
535 * (i.e. system-qemu.img) in the content directory.
536 */
537 rwImage = avdInfo_getSystemImagePath(avd);
538 if (rwImage != NULL) {
539 break;
540 }
541 /* Otherwise, try to find the initial system image */
542 initImage = avdInfo_getSystemInitImagePath(avd);
543 if (initImage == NULL) {
544 derror("No initial system image for this configuration!");
545 exit(1);
546 }
547 break;
548 }
549
550 /* If -system <name> is used, use it to find the initial image */
551 if (opts->sysdir != NULL) {
552 initImage = _getFullFilePath(opts->sysdir, opts->system);
553 } else {
554 initImage = ASTRDUP(opts->system);
555 }
556 if (!path_exists(initImage)) {
557 derror("System image file doesn't exist: %s", initImage);
558 exit(1);
559 }
560
561 } while (0);
562
563 if (rwImage != NULL) {
564 /* Use the read/write image file directly */
565 hw->disk_systemPartition_path = rwImage;
566 hw->disk_systemPartition_initPath = NULL;
567 D("Using direct system image: %s", rwImage);
568 } else if (initImage != NULL) {
569 hw->disk_systemPartition_path = NULL;
570 hw->disk_systemPartition_initPath = initImage;
571 D("Using initial system image: %s", initImage);
572 }
573
574 /* Check the size of the system partition image.
575 * If we have an AVD, it must be smaller than
576 * the disk.systemPartition.size hardware property.
577 *
578 * Otherwise, we need to adjust the systemPartitionSize
579 * automatically, and print a warning.
580 *
581 */
582 const char* systemImage = hw->disk_systemPartition_path;
583 uint64_t systemBytes;
584
585 if (systemImage == NULL)
586 systemImage = hw->disk_systemPartition_initPath;
587
588 if (path_get_size(systemImage, &systemBytes) < 0) {
589 derror("Missing system image: %s", systemImage);
590 exit(1);
591 }
592
593 hw->disk_systemPartition_size =
594 _adjustPartitionSize("system", systemBytes, defaultPartitionSize,
595 avdInfo_inAndroidBuild(avd));
596 }
597
598 /** DATA PARTITION **/
599
David 'Digit' Turnerfd59c332011-03-01 00:48:52 +0100600 if (opts->datadir) {
601 if (!path_exists(opts->datadir)) {
602 derror("Invalid -datadir directory: %s", opts->datadir);
603 }
604 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800605
David 'Digit' Turnerfd59c332011-03-01 00:48:52 +0100606 {
607 char* dataImage = NULL;
608 char* initImage = NULL;
609
610 do {
611 if (!opts->data) {
612 dataImage = avdInfo_getDataImagePath(avd);
613 if (dataImage != NULL) {
614 D("autoconfig: -data %s", dataImage);
615 break;
616 }
617 dataImage = avdInfo_getDefaultDataImagePath(avd);
618 if (dataImage == NULL) {
619 derror("No data image path for this configuration!");
620 exit (1);
621 }
622 opts->wipe_data = 1;
623 break;
624 }
625
626 if (opts->datadir) {
627 dataImage = _getFullFilePath(opts->datadir, opts->data);
628 } else {
629 dataImage = ASTRDUP(opts->data);
630 }
631 } while (0);
632
633 if (opts->initdata != NULL) {
634 initImage = ASTRDUP(opts->initdata);
635 if (!path_exists(initImage)) {
636 derror("Invalid initial data image path: %s", initImage);
637 exit(1);
638 }
639 } else {
640 initImage = avdInfo_getDataInitImagePath(avd);
641 D("autoconfig: -initdata %s", initImage);
642 }
643
644 hw->disk_dataPartition_path = dataImage;
645 if (opts->wipe_data) {
646 hw->disk_dataPartition_initPath = initImage;
647 } else {
648 hw->disk_dataPartition_initPath = NULL;
649 }
650
651 uint64_t defaultBytes = defaultPartitionSize;
652 uint64_t dataBytes;
653 const char* dataPath = hw->disk_dataPartition_initPath;
654
655 if (dataPath == NULL)
656 dataPath = hw->disk_dataPartition_path;
657
658 path_get_size(dataPath, &dataBytes);
659
660 hw->disk_dataPartition_size =
661 _adjustPartitionSize("data", dataBytes, defaultBytes,
662 avdInfo_inAndroidBuild(avd));
663 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800664
David 'Digit' Turnerc480cca2011-02-25 16:43:34 +0100665 /** CACHE PARTITION **/
666
667 if (opts->no_cache) {
668 /* No cache partition at all */
669 hw->disk_cachePartition = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800670 }
David 'Digit' Turnerc480cca2011-02-25 16:43:34 +0100671 else if (!hw->disk_cachePartition) {
672 if (opts->cache) {
673 dwarning( "Emulated hardware doesn't support a cache partition. -cache option ignored!" );
674 opts->cache = NULL;
675 }
676 }
677 else
678 {
679 if (!opts->cache) {
680 /* Find the current cache partition file */
681 opts->cache = avdInfo_getCachePath(avd);
682 if (opts->cache == NULL) {
683 /* The file does not exists, we will force its creation
684 * if we are not in the Android build system. Otherwise,
685 * a temporary file will be used.
686 */
687 if (!avdInfo_inAndroidBuild(avd)) {
688 opts->cache = avdInfo_getDefaultCachePath(avd);
689 }
690 }
David 'Digit' Turner48a3c662011-03-01 14:03:20 +0100691 if (opts->cache) {
692 D("autoconfig: -cache %s", opts->cache);
693 }
David 'Digit' Turnerc480cca2011-02-25 16:43:34 +0100694 }
695
696 if (opts->cache) {
697 hw->disk_cachePartition_path = ASTRDUP(opts->cache);
698 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800699 }
700
David 'Digit' Turnerc480cca2011-02-25 16:43:34 +0100701 /** SD CARD PARTITION */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800702
David 'Digit' Turner48a3c662011-03-01 14:03:20 +0100703 if (!hw->hw_sdCard) {
704 /* No SD Card emulation, so -sdcard will be ignored */
705 if (opts->sdcard) {
706 dwarning( "Emulated hardware doesn't support SD Cards. -sdcard option ignored." );
707 opts->sdcard = NULL;
708 }
709 } else {
710 /* Auto-configure -sdcard if it is not available */
711 if (!opts->sdcard) {
712 do {
713 /* If -datadir <path> is used, look for a sdcard.img file here */
714 if (opts->datadir) {
715 bufprint(tmp, tmpend, "%s/%s", opts->datadir, "system.img");
716 if (path_exists(tmp)) {
717 opts->sdcard = strdup(tmp);
718 break;
719 }
720 }
721
722 /* Otherwise, look at the AVD's content */
723 opts->sdcard = avdInfo_getSdCardPath(avd);
724 if (opts->sdcard != NULL) {
725 break;
726 }
727
728 /* Nothing */
729 } while (0);
730
731 if (opts->sdcard) {
732 D("autoconfig: -sdcard %s", opts->sdcard);
733 }
734 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800735 }
736
737 if(opts->sdcard) {
738 uint64_t size;
739 if (path_get_size(opts->sdcard, &size) == 0) {
740 /* see if we have an sdcard image. get its size if it exists */
David 'Digit' Turner8b657e52009-12-01 13:38:21 -0800741 /* due to what looks like limitations of the MMC protocol, one has
742 * to use an SD Card image that is equal or larger than 9 MB
743 */
744 if (size < 9*1024*1024ULL) {
745 fprintf(stderr, "### WARNING: SD Card files must be at least 9MB, ignoring '%s'\n", opts->sdcard);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800746 } else {
David 'Digit' Turner48a3c662011-03-01 14:03:20 +0100747 hw->hw_sdCard_path = ASTRDUP(opts->sdcard);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800748 }
749 } else {
David 'Digit' Turner48a3c662011-03-01 14:03:20 +0100750 dwarning("no SD Card image at '%s'", opts->sdcard);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800751 }
752 }
753
David 'Digit' Turner48a3c662011-03-01 14:03:20 +0100754
755 /** SNAPSHOT STORAGE HANDLING */
756
David 'Digit' Turner5f64b872011-02-28 23:23:05 +0100757 /* Determine snapstorage path. -no-snapstorage disables all snapshotting
758 * support. This means you can't resume a snapshot at load, save it at
759 * exit, or even load/save them dynamically at runtime with the console.
760 */
761 if (opts->no_snapstorage) {
762
763 if (opts->snapshot) {
764 dwarning("ignoring -snapshot option due to the use of -no-snapstorage");
765 opts->snapshot = NULL;
766 }
767
768 if (opts->snapstorage) {
769 dwarning("ignoring -snapstorage option due to the use of -no-snapstorage");
770 opts->snapstorage = NULL;
771 }
772 }
773 else
774 {
775 if (!opts->snapstorage) {
776 opts->snapstorage = avdInfo_getSnapStoragePath(avd);
777 if (opts->snapstorage != NULL) {
778 D("autoconfig: -snapstorage %s", opts->snapstorage);
Ot ten Thije353b3b12010-10-05 17:53:30 +0100779 }
780 }
781
David 'Digit' Turner5f64b872011-02-28 23:23:05 +0100782 if (opts->snapstorage && !path_exists(opts->snapstorage)) {
783 D("no image at '%s', state snapshots disabled", opts->snapstorage);
784 opts->snapstorage = NULL;
Ot ten Thije353b3b12010-10-05 17:53:30 +0100785 }
David 'Digit' Turner5f64b872011-02-28 23:23:05 +0100786 }
787
788 /* If we have a valid snapshot storage path */
789
790 if (opts->snapstorage) {
791
792 hw->disk_snapStorage_path = ASTRDUP(opts->snapstorage);
793
794 /* -no-snapshot is equivalent to using both -no-snapshot-load
795 * and -no-snapshot-save. You can still load/save snapshots dynamically
796 * from the console though.
797 */
798 if (opts->no_snapshot) {
799
800 opts->no_snapshot_load = 1;
801 opts->no_snapshot_save = 1;
802
803 if (opts->snapshot) {
804 dwarning("ignoring -snapshot option due to the use of -no-snapshot.");
805 }
806 }
807
808 if (!opts->no_snapshot_load || !opts->no_snapshot_save) {
809 if (opts->snapshot == NULL) {
810 opts->snapshot = "default-boot";
811 D("autoconfig: -snapshot %s", opts->snapshot);
812 }
813 }
814
815 /* We still use QEMU command-line options for the following since
816 * they can change from one invokation to the next and don't really
817 * correspond to the hardware configuration itself.
818 */
819 if (!opts->no_snapshot_load) {
820 args[n++] = "-loadvm";
821 args[n++] = ASTRDUP(opts->snapshot);
822 }
823
824 if (!opts->no_snapshot_save) {
825 args[n++] = "-savevm-on-exit";
826 args[n++] = ASTRDUP(opts->snapshot);
827 }
828
Tim Baverstock622b8f42010-12-07 11:36:59 +0000829 if (opts->no_snapshot_update_time) {
David 'Digit' Turnerbdb6f2d2011-02-23 15:57:25 +0100830 args[n++] = "-snapshot-no-time-update";
Tim Baverstock622b8f42010-12-07 11:36:59 +0000831 }
Ot ten Thijeae835ac2010-10-18 13:37:37 +0100832 }
Ot ten Thije353b3b12010-10-05 17:53:30 +0100833
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800834 if (!opts->logcat || opts->logcat[0] == 0) {
835 opts->logcat = getenv("ANDROID_LOG_TAGS");
836 if (opts->logcat && opts->logcat[0] == 0)
837 opts->logcat = NULL;
838 }
839
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800840 /* we always send the kernel messages from ttyS0 to android_kmsg */
David 'Digit' Turner062dd6a2011-03-01 14:50:07 +0100841 if (opts->show_kernel) {
842 args[n++] = "-show-kernel";
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800843 }
844
845 /* XXXX: TODO: implement -shell and -logcat through qemud instead */
846 if (!opts->shell_serial) {
847#ifdef _WIN32
848 opts->shell_serial = "con:";
849#else
850 opts->shell_serial = "stdio";
851#endif
852 }
853 else
854 opts->shell = 1;
855
856 if (opts->shell || opts->logcat) {
857 args[n++] = "-serial";
858 args[n++] = opts->shell_serial;
859 shell_serial = serial++;
860 }
861
David 'Digit' Turner062dd6a2011-03-01 14:50:07 +0100862 if (opts->radio) {
863 args[n++] = "-radio";
864 args[n++] = opts->radio;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800865 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800866
David 'Digit' Turner062dd6a2011-03-01 14:50:07 +0100867 if (opts->gps) {
868 args[n++] = "-gps";
869 args[n++] = opts->gps;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800870 }
871
872 if (opts->memory) {
873 char* end;
874 long ramSize = strtol(opts->memory, &end, 0);
875 if (ramSize < 0 || *end != 0) {
876 derror( "-memory must be followed by a positive integer" );
877 exit(1);
878 }
879 if (ramSize < 32 || ramSize > 4096) {
880 derror( "physical memory size must be between 32 and 4096 MB" );
881 exit(1);
882 }
David 'Digit' Turner5377c5b2011-02-10 16:52:19 +0100883 hw->hw_ramSize = ramSize;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800884 }
885 if (!opts->memory) {
David 'Digit' Turner3bbc9192011-01-19 22:18:02 +0100886 int ramSize = hw->hw_ramSize;
887 if (ramSize <= 0) {
888 /* Compute the default RAM size based on the size of screen.
889 * This is only used when the skin doesn't provide the ram
890 * size through its hardware.ini (i.e. legacy ones) or when
891 * in the full Android build system.
892 */
David 'Digit' Turner5377c5b2011-02-10 16:52:19 +0100893 int64_t pixels = hw->hw_lcd_width * hw->hw_lcd_height;
David 'Digit' Turner3bbc9192011-01-19 22:18:02 +0100894 /* The following thresholds are a bit liberal, but we
895 * essentially want to ensure the following mappings:
896 *
897 * 320x480 -> 96
898 * 800x600 -> 128
899 * 1024x768 -> 256
900 *
901 * These are just simple heuristics, they could change in
902 * the future.
903 */
904 if (pixels <= 250000)
905 ramSize = 96;
906 else if (pixels <= 500000)
907 ramSize = 128;
908 else
909 ramSize = 256;
910 }
David 'Digit' Turner5377c5b2011-02-10 16:52:19 +0100911 hw->hw_ramSize = ramSize;
912 }
913
914 D("Physical RAM size: %dMB\n", hw->hw_ramSize);
915
916 if (hw->vm_heapSize == 0) {
917 /* Compute the default heap size based on the RAM size.
918 * Essentially, we want to ensure the following liberal mappings:
919 *
920 * 96MB RAM -> 16MB heap
921 * 128MB RAM -> 24MB heap
922 * 256MB RAM -> 48MB heap
923 */
924 int ramSize = hw->hw_ramSize;
925 int heapSize;
926
927 if (ramSize < 100)
928 heapSize = 16;
929 else if (ramSize < 192)
930 heapSize = 24;
931 else
932 heapSize = 48;
933
934 hw->vm_heapSize = heapSize;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800935 }
936
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800937 if (opts->trace) {
938 args[n++] = "-trace";
939 args[n++] = opts->trace;
940 args[n++] = "-tracing";
941 args[n++] = "off";
942 }
943
Vladimir Chtchetkineb25bf2a2010-09-08 11:09:23 -0700944 /* Pass boot properties to the core. */
945 if (opts->prop != NULL) {
946 ParamList* pl = opts->prop;
947 for ( ; pl != NULL; pl = pl->next ) {
948 args[n++] = "-boot-property";
949 args[n++] = pl->param;
950 }
951 }
952
David 'Digit' Turner318e4f22009-05-25 18:01:03 +0200953 /* Setup the kernel init options
954 */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800955 {
956 static char params[1024];
957 char *p = params, *end = p + sizeof(params);
958
David 'Digit' Turner062dd6a2011-03-01 14:50:07 +0100959 /* Don't worry about having a leading space here, this is handled
960 * by the core later. */
961
Jun Nakajima334ab472011-02-02 23:49:59 -0800962#ifdef TARGET_I386
963 p = bufprint(p, end, " androidboot.hardware=goldfish");
Jun Nakajimabac9add2011-02-08 22:10:52 -0800964 p = bufprint(p, end, " clocksource=pit");
Jun Nakajima334ab472011-02-02 23:49:59 -0800965#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800966
967 if (opts->shell || opts->logcat) {
968 p = bufprint(p, end, " androidboot.console=ttyS%d", shell_serial );
969 }
970
971 if (opts->trace) {
972 p = bufprint(p, end, " android.tracing=1");
973 }
974
975 if (!opts->no_jni) {
976 p = bufprint(p, end, " android.checkjni=1");
977 }
978
979 if (opts->no_boot_anim) {
980 p = bufprint( p, end, " android.bootanim=0" );
981 }
982
983 if (opts->logcat) {
984 char* q = bufprint(p, end, " androidboot.logcat=%s", opts->logcat);
985
986 if (q < end) {
987 /* replace any space by a comma ! */
988 {
989 int nn;
990 for (nn = 1; p[nn] != 0; nn++)
991 if (p[nn] == ' ' || p[nn] == '\t')
992 p[nn] = ',';
993 p += nn;
994 }
995 }
996 p = q;
997 }
998
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800999 if (opts->bootchart) {
1000 p = bufprint(p, end, " androidboot.bootchart=%s", opts->bootchart);
1001 }
1002
1003 if (p >= end) {
1004 fprintf(stderr, "### ERROR: kernel parameters too long\n");
1005 exit(1);
1006 }
1007
David 'Digit' Turner0b019492011-03-01 14:02:42 +01001008 hw->kernel_parameters = strdup(params);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001009 }
1010
Vladimir Chtchetkined81e6d12010-06-15 16:46:32 -07001011 if (opts->ports) {
1012 args[n++] = "-android-ports";
1013 args[n++] = opts->ports;
1014 }
1015
1016 if (opts->port) {
1017 args[n++] = "-android-port";
1018 args[n++] = opts->port;
1019 }
1020
1021 if (opts->report_console) {
1022 args[n++] = "-android-report-console";
1023 args[n++] = opts->report_console;
1024 }
1025
1026 if (opts->http_proxy) {
1027 args[n++] = "-http-proxy";
1028 args[n++] = opts->http_proxy;
1029 }
1030
Vladimir Chtchetkine43552dc2010-07-22 11:23:19 -07001031 if (opts->charmap) {
1032 args[n++] = "-charmap";
1033 args[n++] = opts->charmap;
1034 }
1035
Vladimir Chtchetkineb5365f32010-08-09 13:33:57 -07001036 if (opts->memcheck) {
1037 args[n++] = "-android-memcheck";
1038 args[n++] = opts->memcheck;
1039 }
1040
David 'Digit' Turner5377c5b2011-02-10 16:52:19 +01001041 /* physical memory is now in hw->hw_ramSize */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001042
David 'Digit' Turner53eb66d2011-03-01 14:58:23 +01001043 hw->avd_name = ASTRDUP(avdInfo_getName(avd));
David 'Digit' Turner6b8555c2011-02-17 04:28:19 +01001044
Dries Harnie40beab42010-05-15 17:04:47 +02001045 /* Set up the interfaces for inter-emulator networking */
1046 if (opts->shared_net_id) {
1047 unsigned int shared_net_id = atoi(opts->shared_net_id);
1048 char nic[37];
Dries Harnie40beab42010-05-15 17:04:47 +02001049
1050 args[n++] = "-net";
1051 args[n++] = "nic,vlan=0";
1052 args[n++] = "-net";
1053 args[n++] = "user,vlan=0";
Dries Harnie111d6f82010-06-09 21:42:18 +02001054
1055 args[n++] = "-net";
1056 snprintf(nic, sizeof nic, "nic,vlan=1,macaddr=52:54:00:12:34:%02x", shared_net_id);
1057 args[n++] = strdup(nic);
1058 args[n++] = "-net";
1059 args[n++] = "socket,vlan=1,mcast=230.0.0.10:1234";
Dries Harnie40beab42010-05-15 17:04:47 +02001060 }
1061
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001062 while(argc-- > 0) {
1063 args[n++] = *argv++;
1064 }
1065 args[n] = 0;
1066
David 'Digit' Turner26d41532011-03-01 15:03:07 +01001067 /* Generate a hardware-qemu.ini for this AVD. The real hardware
David 'Digit' Turner622f1532011-02-01 17:48:37 +01001068 * configuration is ususally stored in several files, e.g. the AVD's
1069 * config.ini plus the skin-specific hardware.ini.
1070 *
David 'Digit' Turner26d41532011-03-01 15:03:07 +01001071 * The new file will group all definitions and will be used to
David 'Digit' Turner622f1532011-02-01 17:48:37 +01001072 * launch the core with the -android-hw <file> option.
1073 */
1074 {
David 'Digit' Turner42074e52011-02-10 16:03:28 +01001075 const char* coreHwIniPath = avdInfo_getCoreHwIniPath(avd);
1076 IniFile* hwIni = iniFile_newFromMemory("", NULL);
David 'Digit' Turner622f1532011-02-01 17:48:37 +01001077 androidHwConfig_write(hw, hwIni);
David 'Digit' Turner26d41532011-03-01 15:03:07 +01001078
1079 if (filelock_create(coreHwIniPath) == NULL) {
1080 /* The AVD is already in use, we still support this as an
1081 * experimental feature. Use a temporary hardware-qemu.ini
1082 * file though to avoid overwriting the existing one. */
1083 TempFile* tempIni = tempfile_create();
1084 coreHwIniPath = tempfile_path(tempIni);
1085 }
1086
David 'Digit' Turner42074e52011-02-10 16:03:28 +01001087 if (iniFile_saveToFile(hwIni, coreHwIniPath) < 0) {
1088 derror("Could not write hardware.ini to %s: %s", coreHwIniPath, strerror(errno));
David 'Digit' Turner622f1532011-02-01 17:48:37 +01001089 exit(2);
1090 }
1091 args[n++] = "-android-hw";
David 'Digit' Turner42074e52011-02-10 16:03:28 +01001092 args[n++] = strdup(coreHwIniPath);
David 'Digit' Turner0a879bf2011-05-12 18:45:18 +02001093
1094 /* In verbose mode, dump the file's content */
1095 if (VERBOSE_CHECK(init)) {
1096 FILE* file = fopen(coreHwIniPath, "rt");
1097 if (file == NULL) {
1098 derror("Could not open hardware configuration file: %s\n",
1099 coreHwIniPath);
1100 } else {
1101 LineInput* input = lineInput_newFromStdFile(file);
1102 const char* line;
1103 printf("Content of hardware configuration file:\n");
1104 while ((line = lineInput_getLine(input)) != NULL) {
1105 printf(" %s\n", line);
1106 }
1107 printf(".\n");
1108 lineInput_free(input);
1109 fclose(file);
1110 }
1111 }
David 'Digit' Turner622f1532011-02-01 17:48:37 +01001112 }
1113
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001114 if(VERBOSE_CHECK(init)) {
1115 int i;
David 'Digit' Turner33361762011-01-19 22:11:03 +01001116 printf("QEMU options list:\n");
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001117 for(i = 0; i < n; i++) {
David 'Digit' Turner33361762011-01-19 22:11:03 +01001118 printf("emulator: argv[%02d] = \"%s\"\n", i, args[i]);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001119 }
David 'Digit' Turner33361762011-01-19 22:11:03 +01001120 /* Dump final command-line option to make debugging the core easier */
1121 printf("Concatenated QEMU options:\n");
1122 for (i = 0; i < n; i++) {
David 'Digit' Turner26722dd2011-02-24 16:40:20 +01001123 /* To make it easier to copy-paste the output to a command-line,
1124 * quote anything that contains spaces.
1125 */
1126 if (strchr(args[i], ' ') != NULL) {
1127 printf(" '%s'", args[i]);
1128 } else {
1129 printf(" %s", args[i]);
1130 }
David 'Digit' Turner33361762011-01-19 22:11:03 +01001131 }
1132 printf("\n");
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001133 }
David 'Digit' Turner74d7ace2011-02-02 13:21:03 +01001134
1135 /* Setup SDL UI just before calling the code */
1136 init_sdl_ui(skinConfig, skinPath, opts);
1137
David 'Digit' Turnerbdb6f2d2011-02-23 15:57:25 +01001138 if (attach_ui_to_core(opts) < 0) {
1139 derror("Can't attach to core!");
1140 exit(1);
1141 }
1142
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001143 return qemu_main(n, args);
1144}