blob: 9a763e5033223077e26d0d6d6e7cad21e0046f41 [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 {
Andrew Hsiehc7389bd2012-03-13 02:13:40 -0700148 snprintf(temp, sizeof temp, "(%" PRIu64 " bytes > %" PRIu64 " bytes)", imageBytes, defaultBytes);
David 'Digit' Turner40841b22011-03-01 14:04:00 +0100149 }
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
David 'Digit' Turner2ed457e2011-06-15 17:29:50 +0200172 int forceArmv7 = 0;
173
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800174 AndroidHwConfig* hw;
David 'Digit' Turnercd059b12009-08-28 19:36:27 +0200175 AvdInfo* avd;
David 'Digit' Turner74d7ace2011-02-02 13:21:03 +0100176 AConfig* skinConfig;
177 char* skinPath;
Vladimir Chtchetkine83ffd662011-02-11 12:40:59 -0800178 int inAndroidBuild;
Vladimir Chtchetkined4f5a3a2012-03-08 14:20:20 -0800179 uint64_t defaultPartitionSize = convertMBToBytes(128);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800180
181 AndroidOptions opts[1];
Vladimir Chtchetkineb25bf2a2010-09-08 11:09:23 -0700182 /* net.shared_net_ip boot property value. */
183 char boot_prop_ip[64];
184 boot_prop_ip[0] = '\0';
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800185
186 args[0] = argv[0];
187
188 if ( android_parse_options( &argc, &argv, opts ) < 0 ) {
189 exit(1);
190 }
191
David 'Digit' Turnerbdb6f2d2011-02-23 15:57:25 +0100192#ifdef _WIN32
193 socket_init();
194#endif
195
196 handle_ui_options(opts);
197
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800198 while (argc-- > 1) {
199 opt = (++argv)[0];
200
201 if(!strcmp(opt, "-qemu")) {
202 argc--;
203 argv++;
204 break;
205 }
206
207 if (!strcmp(opt, "-help")) {
208 emulator_help();
209 }
210
211 if (!strncmp(opt, "-help-",6)) {
212 STRALLOC_DEFINE(out);
213 opt += 6;
214
215 if (!strcmp(opt, "all")) {
216 android_help_all(out);
217 }
218 else if (android_help_for_option(opt, out) == 0) {
219 /* ok */
220 }
221 else if (android_help_for_topic(opt, out) == 0) {
222 /* ok */
223 }
224 if (out->n > 0) {
225 printf("\n%.*s", out->n, out->s);
226 exit(0);
227 }
228
229 fprintf(stderr, "unknown option: -help-%s\n", opt);
230 fprintf(stderr, "please use -help for a list of valid topics\n");
231 exit(1);
232 }
233
234 if (opt[0] == '-') {
235 fprintf(stderr, "unknown option: %s\n", opt);
236 fprintf(stderr, "please use -help for a list of valid options\n");
237 exit(1);
238 }
239
240 fprintf(stderr, "invalid command-line parameter: %s.\n", opt);
241 fprintf(stderr, "Hint: use '@foo' to launch a virtual device named 'foo'.\n");
242 fprintf(stderr, "please use -help for more information\n");
243 exit(1);
244 }
245
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800246 if (opts->version) {
247 printf("Android emulator version %s\n"
David 'Digit' Turner5f64b872011-02-28 23:23:05 +0100248 "Copyright (C) 2006-2011 The Android Open Source Project and many others.\n"
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800249 "This program is a derivative of the QEMU CPU emulator (www.qemu.org).\n\n",
250#if defined ANDROID_BUILD_ID
251 VERSION_STRING " (build_id " STRINGIFY(ANDROID_BUILD_ID) ")" );
252#else
253 VERSION_STRING);
254#endif
255 printf(" This software is licensed under the terms of the GNU General Public\n"
256 " License version 2, as published by the Free Software Foundation, and\n"
257 " may be copied, distributed, and modified under those terms.\n\n"
258 " This program is distributed in the hope that it will be useful,\n"
259 " but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
260 " MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
261 " GNU General Public License for more details.\n\n");
262
263 exit(0);
264 }
265
David 'Digit' Turner5f64b872011-02-28 23:23:05 +0100266 if (opts->snapshot_list) {
David 'Digit' Turnerd80a7862011-05-05 10:24:43 +0200267 if (opts->snapstorage == NULL) {
268 /* Need to find the default snapstorage */
269 avd = createAVD(opts, &inAndroidBuild);
270 opts->snapstorage = avdInfo_getSnapStoragePath(avd);
271 if (opts->snapstorage != NULL) {
272 D("autoconfig: -snapstorage %s", opts->snapstorage);
273 } else {
274 if (inAndroidBuild) {
275 derror("You must use the -snapstorage <file> option to specify a snapshot storage file!\n");
276 } else {
277 derror("This AVD doesn't have snapshotting enabled!\n");
278 }
279 exit(1);
280 }
281 }
David 'Digit' Turner5f64b872011-02-28 23:23:05 +0100282 snapshot_print_and_exit(opts->snapstorage);
283 }
284
David 'Digit' Turner25eb6552011-02-25 15:07:11 +0100285 sanitizeOptions(opts);
286
David 'Digit' Turnerbdb6f2d2011-02-23 15:57:25 +0100287 /* Initialization of UI started with -attach-core should work differently
288 * than initialization of UI that starts the core. In particular....
289 */
290
291 /* -charmap is incompatible with -attach-core, because particular
292 * charmap gets set up in the running core. */
David 'Digit' Turner74d7ace2011-02-02 13:21:03 +0100293 if (android_charmap_setup(opts->charmap)) {
294 exit(1);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800295 }
296
Vladimir Chtchetkine83ffd662011-02-11 12:40:59 -0800297 /* Parses options and builds an appropriate AVD. */
David 'Digit' Turner462564f2011-02-23 13:32:37 +0100298 avd = android_avdInfo = createAVD(opts, &inAndroidBuild);
David 'Digit' Turnercd059b12009-08-28 19:36:27 +0200299
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800300 /* get the skin from the virtual device configuration */
David 'Digit' Turner25eb6552011-02-25 15:07:11 +0100301 if (opts->skindir != NULL) {
302 if (opts->skin == NULL) {
303 /* NOTE: Normally handled by sanitizeOptions(), just be safe */
304 derror("The -skindir <path> option requires a -skin <name> option");
305 exit(2);
306 }
307 } else {
308 char* skinName;
309 char* skinDir;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800310
David 'Digit' Turner25eb6552011-02-25 15:07:11 +0100311 avdInfo_getSkinInfo(avd, &skinName, &skinDir);
312
313 if (opts->skin == NULL) {
314 opts->skin = skinName;
315 D("autoconfig: -skin %s", opts->skin);
316 } else {
317 AFREE(skinName);
318 }
319
320 opts->skindir = skinDir;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800321 D("autoconfig: -skindir %s", opts->skindir);
322 }
323
324 /* Read hardware configuration */
325 hw = android_hw;
David 'Digit' Turnerb64325d2011-03-22 16:07:01 +0100326 if (avdInfo_initHwConfig(avd, hw) < 0) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800327 derror("could not read hardware configuration ?");
328 exit(1);
329 }
330
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800331 if (opts->keyset) {
332 parse_keyset(opts->keyset, opts);
333 if (!android_keyset) {
334 fprintf(stderr,
335 "emulator: WARNING: could not find keyset file named '%s',"
336 " using defaults instead\n",
337 opts->keyset);
338 }
339 }
340 if (!android_keyset) {
341 parse_keyset("default", opts);
342 if (!android_keyset) {
343 android_keyset = skin_keyset_new_from_text( skin_keyset_get_default() );
344 if (!android_keyset) {
345 fprintf(stderr, "PANIC: default keyset file is corrupted !!\n" );
346 fprintf(stderr, "PANIC: please update the code in android/skin/keyset.c\n" );
347 exit(1);
348 }
349 if (!opts->keyset)
350 write_default_keyset();
351 }
352 }
353
Dries Harnie40beab42010-05-15 17:04:47 +0200354 if (opts->shared_net_id) {
355 char* end;
356 long shared_net_id = strtol(opts->shared_net_id, &end, 0);
357 if (end == NULL || *end || shared_net_id < 1 || shared_net_id > 255) {
358 fprintf(stderr, "option -shared-net-id must be an integer between 1 and 255\n");
359 exit(1);
360 }
Vladimir Chtchetkineb25bf2a2010-09-08 11:09:23 -0700361 snprintf(boot_prop_ip, sizeof(boot_prop_ip),
362 "net.shared_net_ip=10.1.2.%ld", shared_net_id);
Dries Harnie40beab42010-05-15 17:04:47 +0200363 }
364
365
David 'Digit' Turner755811e2011-02-07 13:38:25 +0100366 user_config_init();
David 'Digit' Turner2507cab2011-02-10 16:29:17 +0100367 parse_skin_files(opts->skindir, opts->skin, opts, hw,
David 'Digit' Turner74d7ace2011-02-02 13:21:03 +0100368 &skinConfig, &skinPath);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800369
David 'Digit' Turner092361e2011-03-01 13:14:18 +0100370 if (!opts->netspeed && skin_network_speed) {
371 D("skin network speed: '%s'", skin_network_speed);
372 if (strcmp(skin_network_speed, NETWORK_SPEED_DEFAULT) != 0) {
373 opts->netspeed = (char*)skin_network_speed;
374 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800375 }
David 'Digit' Turner092361e2011-03-01 13:14:18 +0100376 if (!opts->netdelay && skin_network_delay) {
377 D("skin network delay: '%s'", skin_network_delay);
378 if (strcmp(skin_network_delay, NETWORK_DELAY_DEFAULT) != 0) {
379 opts->netdelay = (char*)skin_network_delay;
380 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800381 }
382
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800383 if (opts->trace) {
David 'Digit' Turnercd059b12009-08-28 19:36:27 +0200384 char* tracePath = avdInfo_getTracePath(avd, opts->trace);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800385 int ret;
386
387 if (tracePath == NULL) {
388 derror( "bad -trace parameter" );
389 exit(1);
390 }
391 ret = path_mkdir_if_needed( tracePath, 0755 );
392 if (ret < 0) {
393 fprintf(stderr, "could not create directory '%s'\n", tmp);
394 exit(2);
395 }
396 opts->trace = tracePath;
397 }
398
Vladimir Chtchetkine33f89d02011-09-28 09:19:09 -0700399 /* Update CPU architecture for HW configs created from build dir. */
400 if (inAndroidBuild) {
401#if defined(TARGET_ARM)
402 free(android_hw->hw_cpu_arch);
403 android_hw->hw_cpu_arch = ASTRDUP("arm");
404#elif defined(TARGET_I386)
405 free(android_hw->hw_cpu_arch);
406 android_hw->hw_cpu_arch = ASTRDUP("x86");
407#endif
408 }
409
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800410 n = 1;
411 /* generate arguments for the underlying qemu main() */
David 'Digit' Turner238b4b02009-09-20 13:10:19 -0700412 {
David 'Digit' Turner0b019492011-03-01 14:02:42 +0100413 char* kernelFile = opts->kernel;
414 int kernelFileLen;
David 'Digit' Turner238b4b02009-09-20 13:10:19 -0700415
David 'Digit' Turner0b019492011-03-01 14:02:42 +0100416 if (kernelFile == NULL) {
417 kernelFile = avdInfo_getKernelPath(avd);
418 if (kernelFile == NULL) {
419 derror( "This AVD's configuration is missing a kernel file!!" );
420 exit(2);
421 }
422 D("autoconfig: -kernel %s", kernelFile);
423 }
424 if (!path_exists(kernelFile)) {
425 derror( "Invalid or missing kernel image file: %s", kernelFile );
426 exit(2);
427 }
428
429 hw->kernel_path = kernelFile;
David 'Digit' Turner238b4b02009-09-20 13:10:19 -0700430
431 /* If the kernel image name ends in "-armv7", then change the cpu
432 * type automatically. This is a poor man's approach to configuration
433 * management, but should allow us to get past building ARMv7
434 * system images with dex preopt pass without introducing too many
435 * changes to the emulator sources.
436 *
437 * XXX:
438 * A 'proper' change would require adding some sort of hardware-property
439 * to each AVD config file, then automatically determine its value for
440 * full Android builds (depending on some environment variable), plus
441 * some build system changes. I prefer not to do that for now for reasons
442 * of simplicity.
443 */
David 'Digit' Turner0b019492011-03-01 14:02:42 +0100444 kernelFileLen = strlen(kernelFile);
David 'Digit' Turner238b4b02009-09-20 13:10:19 -0700445 if (kernelFileLen > 6 && !memcmp(kernelFile + kernelFileLen - 6, "-armv7", 6)) {
David 'Digit' Turner2ed457e2011-06-15 17:29:50 +0200446 forceArmv7 = 1;
David 'Digit' Turner238b4b02009-09-20 13:10:19 -0700447 }
448 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800449
Vladimir Chtchetkineb25bf2a2010-09-08 11:09:23 -0700450 if (boot_prop_ip[0]) {
451 args[n++] = "-boot-property";
452 args[n++] = boot_prop_ip;
453 }
454
Vladimir Chtchetkine318f17a2010-08-27 09:09:45 -0700455 if (opts->tcpdump) {
456 args[n++] = "-tcpdump";
457 args[n++] = opts->tcpdump;
458 }
459
Vladimir Chtchetkinee1316862010-08-26 09:03:54 -0700460#ifdef CONFIG_NAND_LIMITS
461 if (opts->nand_limits) {
462 args[n++] = "-nand-limits";
463 args[n++] = opts->nand_limits;
464 }
465#endif
466
David 'Digit' Turner74d7ace2011-02-02 13:21:03 +0100467 if (opts->timezone) {
468 args[n++] = "-timezone";
469 args[n++] = opts->timezone;
470 }
471
Vladimir Chtchetkinee1316862010-08-26 09:03:54 -0700472 if (opts->netspeed) {
473 args[n++] = "-netspeed";
474 args[n++] = opts->netspeed;
475 }
476 if (opts->netdelay) {
477 args[n++] = "-netdelay";
478 args[n++] = opts->netdelay;
479 }
480 if (opts->netfast) {
481 args[n++] = "-netfast";
482 }
483
Vladimir Chtchetkineb2438402010-08-24 08:55:33 -0700484 if (opts->audio) {
485 args[n++] = "-audio";
486 args[n++] = opts->audio;
487 }
488
Vladimir Chtchetkineb2438402010-08-24 08:55:33 -0700489 if (opts->cpu_delay) {
490 args[n++] = "-cpu-delay";
491 args[n++] = opts->cpu_delay;
492 }
493
Vladimir Chtchetkine7fbf4972010-08-11 15:30:32 -0700494 if (opts->dns_server) {
495 args[n++] = "-dns-server";
496 args[n++] = opts->dns_server;
497 }
498
David 'Digit' Turner9ff69722011-09-13 12:32:52 +0200499 /* opts->ramdisk is never NULL (see createAVD) here */
500 if (opts->ramdisk) {
501 AFREE(hw->disk_ramdisk_path);
502 hw->disk_ramdisk_path = ASTRDUP(opts->ramdisk);
503 }
504 else if (!hw->disk_ramdisk_path[0]) {
505 hw->disk_ramdisk_path = avdInfo_getRamdiskPath(avd);
506 D("autoconfig: -ramdisk %s", hw->disk_ramdisk_path);
507 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800508
David 'Digit' Turner40841b22011-03-01 14:04:00 +0100509 /* -partition-size is used to specify the max size of both the system
510 * and data partition sizes.
511 */
512 if (opts->partition_size) {
513 char* end;
514 long sizeMB = strtol(opts->partition_size, &end, 0);
515 long minSizeMB = 10;
516 long maxSizeMB = LONG_MAX / ONE_MB;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800517
David 'Digit' Turner40841b22011-03-01 14:04:00 +0100518 if (sizeMB < 0 || *end != 0) {
519 derror( "-partition-size must be followed by a positive integer" );
520 exit(1);
521 }
522 if (sizeMB < minSizeMB || sizeMB > maxSizeMB) {
523 derror( "partition-size (%d) must be between %dMB and %dMB",
524 sizeMB, minSizeMB, maxSizeMB );
525 exit(1);
526 }
527 defaultPartitionSize = (uint64_t) sizeMB * ONE_MB;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800528 }
529
David 'Digit' Turner40841b22011-03-01 14:04:00 +0100530
531 /** SYSTEM PARTITION **/
532
533 if (opts->sysdir == NULL) {
534 if (avdInfo_inAndroidBuild(avd)) {
535 opts->sysdir = ASTRDUP(avdInfo_getContentPath(avd));
536 D("autoconfig: -sysdir %s", opts->sysdir);
537 }
538 }
539
540 if (opts->sysdir != NULL) {
541 if (!path_exists(opts->sysdir)) {
542 derror("Directory does not exist: %s", opts->sysdir);
543 exit(1);
544 }
545 }
546
547 {
548 char* rwImage = NULL;
549 char* initImage = NULL;
550
551 do {
552 if (opts->system == NULL) {
553 /* If -system is not used, try to find a runtime system image
554 * (i.e. system-qemu.img) in the content directory.
555 */
556 rwImage = avdInfo_getSystemImagePath(avd);
557 if (rwImage != NULL) {
558 break;
559 }
560 /* Otherwise, try to find the initial system image */
561 initImage = avdInfo_getSystemInitImagePath(avd);
562 if (initImage == NULL) {
563 derror("No initial system image for this configuration!");
564 exit(1);
565 }
566 break;
567 }
568
569 /* If -system <name> is used, use it to find the initial image */
David 'Digit' Turnerea283772011-07-07 04:40:27 +0200570 if (opts->sysdir != NULL && !path_exists(opts->system)) {
David 'Digit' Turner40841b22011-03-01 14:04:00 +0100571 initImage = _getFullFilePath(opts->sysdir, opts->system);
572 } else {
573 initImage = ASTRDUP(opts->system);
574 }
575 if (!path_exists(initImage)) {
576 derror("System image file doesn't exist: %s", initImage);
577 exit(1);
578 }
579
580 } while (0);
581
582 if (rwImage != NULL) {
583 /* Use the read/write image file directly */
584 hw->disk_systemPartition_path = rwImage;
585 hw->disk_systemPartition_initPath = NULL;
586 D("Using direct system image: %s", rwImage);
587 } else if (initImage != NULL) {
588 hw->disk_systemPartition_path = NULL;
589 hw->disk_systemPartition_initPath = initImage;
590 D("Using initial system image: %s", initImage);
591 }
592
593 /* Check the size of the system partition image.
594 * If we have an AVD, it must be smaller than
595 * the disk.systemPartition.size hardware property.
596 *
597 * Otherwise, we need to adjust the systemPartitionSize
598 * automatically, and print a warning.
599 *
600 */
601 const char* systemImage = hw->disk_systemPartition_path;
602 uint64_t systemBytes;
603
604 if (systemImage == NULL)
605 systemImage = hw->disk_systemPartition_initPath;
606
607 if (path_get_size(systemImage, &systemBytes) < 0) {
608 derror("Missing system image: %s", systemImage);
609 exit(1);
610 }
611
612 hw->disk_systemPartition_size =
613 _adjustPartitionSize("system", systemBytes, defaultPartitionSize,
614 avdInfo_inAndroidBuild(avd));
615 }
616
617 /** DATA PARTITION **/
618
David 'Digit' Turnerfd59c332011-03-01 00:48:52 +0100619 if (opts->datadir) {
620 if (!path_exists(opts->datadir)) {
621 derror("Invalid -datadir directory: %s", opts->datadir);
622 }
623 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800624
David 'Digit' Turnerfd59c332011-03-01 00:48:52 +0100625 {
626 char* dataImage = NULL;
627 char* initImage = NULL;
628
629 do {
630 if (!opts->data) {
631 dataImage = avdInfo_getDataImagePath(avd);
632 if (dataImage != NULL) {
633 D("autoconfig: -data %s", dataImage);
634 break;
635 }
636 dataImage = avdInfo_getDefaultDataImagePath(avd);
637 if (dataImage == NULL) {
638 derror("No data image path for this configuration!");
639 exit (1);
640 }
641 opts->wipe_data = 1;
642 break;
643 }
644
645 if (opts->datadir) {
646 dataImage = _getFullFilePath(opts->datadir, opts->data);
647 } else {
648 dataImage = ASTRDUP(opts->data);
649 }
650 } while (0);
651
652 if (opts->initdata != NULL) {
653 initImage = ASTRDUP(opts->initdata);
654 if (!path_exists(initImage)) {
655 derror("Invalid initial data image path: %s", initImage);
656 exit(1);
657 }
658 } else {
659 initImage = avdInfo_getDataInitImagePath(avd);
660 D("autoconfig: -initdata %s", initImage);
661 }
662
663 hw->disk_dataPartition_path = dataImage;
664 if (opts->wipe_data) {
665 hw->disk_dataPartition_initPath = initImage;
666 } else {
667 hw->disk_dataPartition_initPath = NULL;
668 }
669
Maciek Molerusf7584112011-06-15 22:26:35 +0200670 uint64_t defaultBytes =
671 hw->disk_dataPartition_size == 0 ?
672 defaultPartitionSize :
Vladimir Chtchetkined4f5a3a2012-03-08 14:20:20 -0800673 hw->disk_dataPartition_size;
David 'Digit' Turnerfd59c332011-03-01 00:48:52 +0100674 uint64_t dataBytes;
675 const char* dataPath = hw->disk_dataPartition_initPath;
676
677 if (dataPath == NULL)
678 dataPath = hw->disk_dataPartition_path;
679
680 path_get_size(dataPath, &dataBytes);
681
682 hw->disk_dataPartition_size =
683 _adjustPartitionSize("data", dataBytes, defaultBytes,
684 avdInfo_inAndroidBuild(avd));
685 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800686
David 'Digit' Turnerc480cca2011-02-25 16:43:34 +0100687 /** CACHE PARTITION **/
688
689 if (opts->no_cache) {
690 /* No cache partition at all */
691 hw->disk_cachePartition = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800692 }
David 'Digit' Turnerc480cca2011-02-25 16:43:34 +0100693 else if (!hw->disk_cachePartition) {
694 if (opts->cache) {
695 dwarning( "Emulated hardware doesn't support a cache partition. -cache option ignored!" );
696 opts->cache = NULL;
697 }
698 }
699 else
700 {
701 if (!opts->cache) {
702 /* Find the current cache partition file */
703 opts->cache = avdInfo_getCachePath(avd);
704 if (opts->cache == NULL) {
705 /* The file does not exists, we will force its creation
706 * if we are not in the Android build system. Otherwise,
707 * a temporary file will be used.
708 */
709 if (!avdInfo_inAndroidBuild(avd)) {
710 opts->cache = avdInfo_getDefaultCachePath(avd);
711 }
712 }
David 'Digit' Turner48a3c662011-03-01 14:03:20 +0100713 if (opts->cache) {
714 D("autoconfig: -cache %s", opts->cache);
715 }
David 'Digit' Turnerc480cca2011-02-25 16:43:34 +0100716 }
717
718 if (opts->cache) {
719 hw->disk_cachePartition_path = ASTRDUP(opts->cache);
720 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800721 }
722
David 'Digit' Turnerc480cca2011-02-25 16:43:34 +0100723 /** SD CARD PARTITION */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800724
David 'Digit' Turner48a3c662011-03-01 14:03:20 +0100725 if (!hw->hw_sdCard) {
726 /* No SD Card emulation, so -sdcard will be ignored */
727 if (opts->sdcard) {
728 dwarning( "Emulated hardware doesn't support SD Cards. -sdcard option ignored." );
729 opts->sdcard = NULL;
730 }
731 } else {
732 /* Auto-configure -sdcard if it is not available */
733 if (!opts->sdcard) {
734 do {
735 /* If -datadir <path> is used, look for a sdcard.img file here */
736 if (opts->datadir) {
737 bufprint(tmp, tmpend, "%s/%s", opts->datadir, "system.img");
738 if (path_exists(tmp)) {
739 opts->sdcard = strdup(tmp);
740 break;
741 }
742 }
743
744 /* Otherwise, look at the AVD's content */
745 opts->sdcard = avdInfo_getSdCardPath(avd);
746 if (opts->sdcard != NULL) {
747 break;
748 }
749
750 /* Nothing */
751 } while (0);
752
753 if (opts->sdcard) {
754 D("autoconfig: -sdcard %s", opts->sdcard);
755 }
756 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800757 }
758
759 if(opts->sdcard) {
760 uint64_t size;
761 if (path_get_size(opts->sdcard, &size) == 0) {
762 /* see if we have an sdcard image. get its size if it exists */
David 'Digit' Turner8b657e52009-12-01 13:38:21 -0800763 /* due to what looks like limitations of the MMC protocol, one has
764 * to use an SD Card image that is equal or larger than 9 MB
765 */
766 if (size < 9*1024*1024ULL) {
767 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 -0800768 } else {
David 'Digit' Turner48a3c662011-03-01 14:03:20 +0100769 hw->hw_sdCard_path = ASTRDUP(opts->sdcard);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800770 }
771 } else {
David 'Digit' Turner48a3c662011-03-01 14:03:20 +0100772 dwarning("no SD Card image at '%s'", opts->sdcard);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800773 }
774 }
775
David 'Digit' Turner48a3c662011-03-01 14:03:20 +0100776
777 /** SNAPSHOT STORAGE HANDLING */
778
David 'Digit' Turner5f64b872011-02-28 23:23:05 +0100779 /* Determine snapstorage path. -no-snapstorage disables all snapshotting
780 * support. This means you can't resume a snapshot at load, save it at
781 * exit, or even load/save them dynamically at runtime with the console.
782 */
783 if (opts->no_snapstorage) {
784
785 if (opts->snapshot) {
786 dwarning("ignoring -snapshot option due to the use of -no-snapstorage");
787 opts->snapshot = NULL;
788 }
789
790 if (opts->snapstorage) {
791 dwarning("ignoring -snapstorage option due to the use of -no-snapstorage");
792 opts->snapstorage = NULL;
793 }
794 }
795 else
796 {
Vladimir Chtchetkine873c3cb2012-03-14 12:46:51 -0700797 if (!opts->snapstorage && avdInfo_getSnapshotPresent(avd)) {
David 'Digit' Turner5f64b872011-02-28 23:23:05 +0100798 opts->snapstorage = avdInfo_getSnapStoragePath(avd);
799 if (opts->snapstorage != NULL) {
800 D("autoconfig: -snapstorage %s", opts->snapstorage);
Ot ten Thije353b3b12010-10-05 17:53:30 +0100801 }
802 }
803
David 'Digit' Turner5f64b872011-02-28 23:23:05 +0100804 if (opts->snapstorage && !path_exists(opts->snapstorage)) {
805 D("no image at '%s', state snapshots disabled", opts->snapstorage);
806 opts->snapstorage = NULL;
Ot ten Thije353b3b12010-10-05 17:53:30 +0100807 }
David 'Digit' Turner5f64b872011-02-28 23:23:05 +0100808 }
809
810 /* If we have a valid snapshot storage path */
811
812 if (opts->snapstorage) {
813
814 hw->disk_snapStorage_path = ASTRDUP(opts->snapstorage);
815
816 /* -no-snapshot is equivalent to using both -no-snapshot-load
817 * and -no-snapshot-save. You can still load/save snapshots dynamically
818 * from the console though.
819 */
820 if (opts->no_snapshot) {
821
822 opts->no_snapshot_load = 1;
823 opts->no_snapshot_save = 1;
824
825 if (opts->snapshot) {
826 dwarning("ignoring -snapshot option due to the use of -no-snapshot.");
827 }
828 }
829
830 if (!opts->no_snapshot_load || !opts->no_snapshot_save) {
831 if (opts->snapshot == NULL) {
832 opts->snapshot = "default-boot";
833 D("autoconfig: -snapshot %s", opts->snapshot);
834 }
835 }
836
837 /* We still use QEMU command-line options for the following since
838 * they can change from one invokation to the next and don't really
839 * correspond to the hardware configuration itself.
840 */
841 if (!opts->no_snapshot_load) {
842 args[n++] = "-loadvm";
843 args[n++] = ASTRDUP(opts->snapshot);
844 }
845
846 if (!opts->no_snapshot_save) {
847 args[n++] = "-savevm-on-exit";
848 args[n++] = ASTRDUP(opts->snapshot);
849 }
850
Tim Baverstock622b8f42010-12-07 11:36:59 +0000851 if (opts->no_snapshot_update_time) {
David 'Digit' Turnerbdb6f2d2011-02-23 15:57:25 +0100852 args[n++] = "-snapshot-no-time-update";
Tim Baverstock622b8f42010-12-07 11:36:59 +0000853 }
Ot ten Thijeae835ac2010-10-18 13:37:37 +0100854 }
Ot ten Thije353b3b12010-10-05 17:53:30 +0100855
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800856 if (!opts->logcat || opts->logcat[0] == 0) {
857 opts->logcat = getenv("ANDROID_LOG_TAGS");
858 if (opts->logcat && opts->logcat[0] == 0)
859 opts->logcat = NULL;
860 }
861
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800862 /* we always send the kernel messages from ttyS0 to android_kmsg */
David 'Digit' Turner062dd6a2011-03-01 14:50:07 +0100863 if (opts->show_kernel) {
864 args[n++] = "-show-kernel";
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800865 }
866
867 /* XXXX: TODO: implement -shell and -logcat through qemud instead */
868 if (!opts->shell_serial) {
869#ifdef _WIN32
870 opts->shell_serial = "con:";
871#else
872 opts->shell_serial = "stdio";
873#endif
874 }
875 else
876 opts->shell = 1;
877
878 if (opts->shell || opts->logcat) {
879 args[n++] = "-serial";
880 args[n++] = opts->shell_serial;
881 shell_serial = serial++;
882 }
883
David 'Digit' Turner062dd6a2011-03-01 14:50:07 +0100884 if (opts->radio) {
885 args[n++] = "-radio";
886 args[n++] = opts->radio;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800887 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800888
David 'Digit' Turner062dd6a2011-03-01 14:50:07 +0100889 if (opts->gps) {
890 args[n++] = "-gps";
891 args[n++] = opts->gps;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800892 }
893
894 if (opts->memory) {
895 char* end;
896 long ramSize = strtol(opts->memory, &end, 0);
897 if (ramSize < 0 || *end != 0) {
898 derror( "-memory must be followed by a positive integer" );
899 exit(1);
900 }
901 if (ramSize < 32 || ramSize > 4096) {
902 derror( "physical memory size must be between 32 and 4096 MB" );
903 exit(1);
904 }
David 'Digit' Turner5377c5b2011-02-10 16:52:19 +0100905 hw->hw_ramSize = ramSize;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800906 }
907 if (!opts->memory) {
David 'Digit' Turner3bbc9192011-01-19 22:18:02 +0100908 int ramSize = hw->hw_ramSize;
909 if (ramSize <= 0) {
910 /* Compute the default RAM size based on the size of screen.
911 * This is only used when the skin doesn't provide the ram
912 * size through its hardware.ini (i.e. legacy ones) or when
913 * in the full Android build system.
914 */
David 'Digit' Turner5377c5b2011-02-10 16:52:19 +0100915 int64_t pixels = hw->hw_lcd_width * hw->hw_lcd_height;
David 'Digit' Turner3bbc9192011-01-19 22:18:02 +0100916 /* The following thresholds are a bit liberal, but we
917 * essentially want to ensure the following mappings:
918 *
919 * 320x480 -> 96
920 * 800x600 -> 128
921 * 1024x768 -> 256
922 *
923 * These are just simple heuristics, they could change in
924 * the future.
925 */
926 if (pixels <= 250000)
927 ramSize = 96;
928 else if (pixels <= 500000)
929 ramSize = 128;
930 else
931 ramSize = 256;
932 }
David 'Digit' Turner5377c5b2011-02-10 16:52:19 +0100933 hw->hw_ramSize = ramSize;
934 }
935
936 D("Physical RAM size: %dMB\n", hw->hw_ramSize);
937
938 if (hw->vm_heapSize == 0) {
939 /* Compute the default heap size based on the RAM size.
940 * Essentially, we want to ensure the following liberal mappings:
941 *
942 * 96MB RAM -> 16MB heap
943 * 128MB RAM -> 24MB heap
944 * 256MB RAM -> 48MB heap
945 */
946 int ramSize = hw->hw_ramSize;
947 int heapSize;
948
949 if (ramSize < 100)
950 heapSize = 16;
951 else if (ramSize < 192)
952 heapSize = 24;
953 else
954 heapSize = 48;
955
956 hw->vm_heapSize = heapSize;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800957 }
958
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800959 if (opts->trace) {
960 args[n++] = "-trace";
961 args[n++] = opts->trace;
962 args[n++] = "-tracing";
963 args[n++] = "off";
964 }
965
Vladimir Chtchetkineb25bf2a2010-09-08 11:09:23 -0700966 /* Pass boot properties to the core. */
967 if (opts->prop != NULL) {
968 ParamList* pl = opts->prop;
969 for ( ; pl != NULL; pl = pl->next ) {
970 args[n++] = "-boot-property";
971 args[n++] = pl->param;
972 }
973 }
974
David 'Digit' Turner318e4f22009-05-25 18:01:03 +0200975 /* Setup the kernel init options
976 */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800977 {
978 static char params[1024];
979 char *p = params, *end = p + sizeof(params);
980
David 'Digit' Turner062dd6a2011-03-01 14:50:07 +0100981 /* Don't worry about having a leading space here, this is handled
982 * by the core later. */
983
Jun Nakajima334ab472011-02-02 23:49:59 -0800984#ifdef TARGET_I386
985 p = bufprint(p, end, " androidboot.hardware=goldfish");
Jun Nakajimabac9add2011-02-08 22:10:52 -0800986 p = bufprint(p, end, " clocksource=pit");
Jun Nakajima334ab472011-02-02 23:49:59 -0800987#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800988
989 if (opts->shell || opts->logcat) {
990 p = bufprint(p, end, " androidboot.console=ttyS%d", shell_serial );
991 }
992
993 if (opts->trace) {
994 p = bufprint(p, end, " android.tracing=1");
995 }
996
997 if (!opts->no_jni) {
998 p = bufprint(p, end, " android.checkjni=1");
999 }
1000
1001 if (opts->no_boot_anim) {
1002 p = bufprint( p, end, " android.bootanim=0" );
1003 }
1004
1005 if (opts->logcat) {
1006 char* q = bufprint(p, end, " androidboot.logcat=%s", opts->logcat);
1007
1008 if (q < end) {
1009 /* replace any space by a comma ! */
1010 {
1011 int nn;
1012 for (nn = 1; p[nn] != 0; nn++)
1013 if (p[nn] == ' ' || p[nn] == '\t')
1014 p[nn] = ',';
1015 p += nn;
1016 }
1017 }
1018 p = q;
1019 }
1020
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001021 if (opts->bootchart) {
1022 p = bufprint(p, end, " androidboot.bootchart=%s", opts->bootchart);
1023 }
1024
1025 if (p >= end) {
1026 fprintf(stderr, "### ERROR: kernel parameters too long\n");
1027 exit(1);
1028 }
1029
David 'Digit' Turner0b019492011-03-01 14:02:42 +01001030 hw->kernel_parameters = strdup(params);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001031 }
1032
Vladimir Chtchetkined81e6d12010-06-15 16:46:32 -07001033 if (opts->ports) {
1034 args[n++] = "-android-ports";
1035 args[n++] = opts->ports;
1036 }
1037
1038 if (opts->port) {
1039 args[n++] = "-android-port";
1040 args[n++] = opts->port;
1041 }
1042
1043 if (opts->report_console) {
1044 args[n++] = "-android-report-console";
1045 args[n++] = opts->report_console;
1046 }
1047
1048 if (opts->http_proxy) {
1049 args[n++] = "-http-proxy";
1050 args[n++] = opts->http_proxy;
1051 }
1052
Xavier Ducrohet72d56112011-08-11 18:47:27 -07001053 if (!opts->charmap) {
1054 /* Try to find a valid charmap name */
1055 char* charmap = avdInfo_getCharmapFile(avd, hw->hw_keyboard_charmap);
1056 if (charmap != NULL) {
1057 D("autoconfig: -charmap %s", charmap);
1058 opts->charmap = charmap;
1059 }
1060 }
1061
Vladimir Chtchetkine43552dc2010-07-22 11:23:19 -07001062 if (opts->charmap) {
Xavier Ducrohet72d56112011-08-11 18:47:27 -07001063 char charmap_name[AKEYCHARMAP_NAME_SIZE];
1064
1065 if (!path_exists(opts->charmap)) {
1066 derror("Charmap file does not exist: %s", opts->charmap);
1067 exit(1);
1068 }
1069 /* We need to store the charmap name in the hardware configuration.
1070 * However, the charmap file itself is only used by the UI component
1071 * and doesn't need to be set to the emulation engine.
1072 */
1073 kcm_extract_charmap_name(opts->charmap, charmap_name,
1074 sizeof(charmap_name));
1075 AFREE(hw->hw_keyboard_charmap);
1076 hw->hw_keyboard_charmap = ASTRDUP(charmap_name);
Vladimir Chtchetkine43552dc2010-07-22 11:23:19 -07001077 }
1078
Vladimir Chtchetkineb5365f32010-08-09 13:33:57 -07001079 if (opts->memcheck) {
1080 args[n++] = "-android-memcheck";
1081 args[n++] = opts->memcheck;
1082 }
1083
David Turner9da935d2011-09-12 21:27:56 +02001084 if (opts->gpu) {
1085 const char* gpu = opts->gpu;
Vladimir Chtchetkineae0d8132011-09-13 10:48:02 -07001086 if (!strcmp(gpu,"on") || !strcmp(gpu,"enable")) {
David Turner9da935d2011-09-12 21:27:56 +02001087 hw->hw_gpu_enabled = 1;
Vladimir Chtchetkineae0d8132011-09-13 10:48:02 -07001088 } else if (!strcmp(gpu,"off") || !strcmp(gpu,"disable")) {
David Turner9da935d2011-09-12 21:27:56 +02001089 hw->hw_gpu_enabled = 0;
1090 } else if (!strcmp(gpu,"auto")) {
1091 /* Nothing to do */
1092 } else {
1093 derror("Invalid value for -gpu <mode> parameter: %s\n", gpu);
1094 derror("Valid values are: on, off or auto\n");
1095 exit(1);
1096 }
1097 }
1098
Vladimir Chtchetkine9242b332012-02-10 08:29:22 -08001099 /* Quit emulator on condition that both, gpu and snapstorage are on. This is
1100 * a temporary solution preventing the emulator from crashing until GPU state
1101 * can be properly saved / resored in snapshot file. */
1102 if (hw->hw_gpu_enabled && opts->snapstorage && (!opts->no_snapshot_load ||
1103 !opts->no_snapshot_save)) {
1104 derror("Snapshots and gpu are mutually exclusive at this point. Please turn one of them off, and restart the emulator.");
1105 exit(1);
1106 }
1107
Vladimir Chtchetkine7485c292012-03-19 11:35:29 -07001108 /* Deal with camera emulation */
1109 if (opts->webcam_list) {
1110 /* List connected webcameras */
1111 args[n++] = "-list-webcam";
1112 }
1113
1114 if (opts->camera_back) {
1115 /* Validate parameter. */
1116 if (memcmp(opts->camera_back, "webcam", 6) &&
1117 strcmp(opts->camera_back, "emulated") &&
1118 strcmp(opts->camera_back, "none")) {
1119 derror("Invalid value for -camera-back <mode> parameter: %s\n"
1120 "Valid values are: 'emulated', 'webcam<N>', or 'none'\n",
1121 opts->camera_back);
Vladimir Chtchetkineae0d8132011-09-13 10:48:02 -07001122 exit(1);
1123 }
Vladimir Chtchetkine7485c292012-03-19 11:35:29 -07001124 hw->hw_camera_back = ASTRDUP(opts->camera_back);
Vladimir Chtchetkineae0d8132011-09-13 10:48:02 -07001125 }
1126
Vladimir Chtchetkine7485c292012-03-19 11:35:29 -07001127 if (opts->camera_front) {
1128 /* Validate parameter. */
1129 if (memcmp(opts->camera_front, "webcam", 6) &&
1130 strcmp(opts->camera_front, "emulated") &&
1131 strcmp(opts->camera_front, "none")) {
1132 derror("Invalid value for -camera-front <mode> parameter: %s\n"
1133 "Valid values are: 'emulated', 'webcam<N>', or 'none'\n",
1134 opts->camera_front);
1135 exit(1);
Vladimir Chtchetkineb8dcaff2011-09-17 11:15:47 -07001136 }
Vladimir Chtchetkine7485c292012-03-19 11:35:29 -07001137 hw->hw_camera_front = ASTRDUP(opts->camera_front);
Vladimir Chtchetkinef8675c22012-01-06 10:31:41 -08001138 }
1139
David 'Digit' Turner5377c5b2011-02-10 16:52:19 +01001140 /* physical memory is now in hw->hw_ramSize */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001141
David 'Digit' Turner53eb66d2011-03-01 14:58:23 +01001142 hw->avd_name = ASTRDUP(avdInfo_getName(avd));
David 'Digit' Turner6b8555c2011-02-17 04:28:19 +01001143
Dries Harnie40beab42010-05-15 17:04:47 +02001144 /* Set up the interfaces for inter-emulator networking */
1145 if (opts->shared_net_id) {
1146 unsigned int shared_net_id = atoi(opts->shared_net_id);
1147 char nic[37];
Dries Harnie40beab42010-05-15 17:04:47 +02001148
1149 args[n++] = "-net";
1150 args[n++] = "nic,vlan=0";
1151 args[n++] = "-net";
1152 args[n++] = "user,vlan=0";
Dries Harnie111d6f82010-06-09 21:42:18 +02001153
1154 args[n++] = "-net";
1155 snprintf(nic, sizeof nic, "nic,vlan=1,macaddr=52:54:00:12:34:%02x", shared_net_id);
1156 args[n++] = strdup(nic);
1157 args[n++] = "-net";
1158 args[n++] = "socket,vlan=1,mcast=230.0.0.10:1234";
Dries Harnie40beab42010-05-15 17:04:47 +02001159 }
1160
Vladimir Chtchetkine8dd31e82012-02-15 17:16:04 -08001161 /* Setup screen emulation */
1162 if (opts->screen) {
Vladimir Chtchetkine863d1012012-03-16 12:25:23 -07001163 if (strcmp(opts->screen, "touch") &&
1164 strcmp(opts->screen, "multi-touch") &&
1165 strcmp(opts->screen, "no-touch")) {
1166
1167 derror("Invalid value for -screen <mode> parameter: %s\n"
1168 "Valid values are: touch, multi-touch, or no-touch\n",
1169 opts->screen);
Vladimir Chtchetkine8dd31e82012-02-15 17:16:04 -08001170 exit(1);
1171 }
Vladimir Chtchetkine863d1012012-03-16 12:25:23 -07001172 hw->hw_screen = ASTRDUP(opts->screen);
Vladimir Chtchetkine8dd31e82012-02-15 17:16:04 -08001173 }
1174
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001175 while(argc-- > 0) {
1176 args[n++] = *argv++;
1177 }
1178 args[n] = 0;
1179
David 'Digit' Turner2ed457e2011-06-15 17:29:50 +02001180 /* If the target ABI is armeabi-v7a, we can auto-detect the cpu model
1181 * as a cortex-a8, instead of the default (arm926) which only emulates
1182 * an ARMv5TE CPU.
1183 */
1184 if (!forceArmv7 && hw->hw_cpu_model[0] == '\0')
1185 {
1186 char* abi = avdInfo_getTargetAbi(avd);
1187 if (abi != NULL) {
1188 if (!strcmp(abi, "armeabi-v7a")) {
1189 forceArmv7 = 1;
1190 }
1191 AFREE(abi);
1192 }
1193 }
1194
1195 if (forceArmv7 != 0) {
1196 AFREE(hw->hw_cpu_model);
1197 hw->hw_cpu_model = ASTRDUP("cortex-a8");
1198 D("Auto-config: -qemu -cpu %s", hw->hw_cpu_model);
1199 }
1200
David 'Digit' Turner26d41532011-03-01 15:03:07 +01001201 /* Generate a hardware-qemu.ini for this AVD. The real hardware
David 'Digit' Turner622f1532011-02-01 17:48:37 +01001202 * configuration is ususally stored in several files, e.g. the AVD's
1203 * config.ini plus the skin-specific hardware.ini.
1204 *
David 'Digit' Turner26d41532011-03-01 15:03:07 +01001205 * The new file will group all definitions and will be used to
David 'Digit' Turner622f1532011-02-01 17:48:37 +01001206 * launch the core with the -android-hw <file> option.
1207 */
1208 {
David 'Digit' Turner42074e52011-02-10 16:03:28 +01001209 const char* coreHwIniPath = avdInfo_getCoreHwIniPath(avd);
1210 IniFile* hwIni = iniFile_newFromMemory("", NULL);
David 'Digit' Turner622f1532011-02-01 17:48:37 +01001211 androidHwConfig_write(hw, hwIni);
David 'Digit' Turner26d41532011-03-01 15:03:07 +01001212
1213 if (filelock_create(coreHwIniPath) == NULL) {
1214 /* The AVD is already in use, we still support this as an
1215 * experimental feature. Use a temporary hardware-qemu.ini
1216 * file though to avoid overwriting the existing one. */
1217 TempFile* tempIni = tempfile_create();
1218 coreHwIniPath = tempfile_path(tempIni);
1219 }
1220
Vladimir Chtchetkinedb450d72012-01-12 13:37:40 -08001221 /* While saving HW config, ignore valueless entries. This will not break
1222 * anything, but will significantly simplify comparing the current HW
1223 * config with the one that has been associated with a snapshot (in case
1224 * VM starts from a snapshot for this instance of emulator). */
1225 if (iniFile_saveToFileClean(hwIni, coreHwIniPath) < 0) {
David 'Digit' Turner42074e52011-02-10 16:03:28 +01001226 derror("Could not write hardware.ini to %s: %s", coreHwIniPath, strerror(errno));
David 'Digit' Turner622f1532011-02-01 17:48:37 +01001227 exit(2);
1228 }
1229 args[n++] = "-android-hw";
David 'Digit' Turner42074e52011-02-10 16:03:28 +01001230 args[n++] = strdup(coreHwIniPath);
David 'Digit' Turner0a879bf2011-05-12 18:45:18 +02001231
1232 /* In verbose mode, dump the file's content */
1233 if (VERBOSE_CHECK(init)) {
1234 FILE* file = fopen(coreHwIniPath, "rt");
1235 if (file == NULL) {
1236 derror("Could not open hardware configuration file: %s\n",
1237 coreHwIniPath);
1238 } else {
1239 LineInput* input = lineInput_newFromStdFile(file);
1240 const char* line;
1241 printf("Content of hardware configuration file:\n");
1242 while ((line = lineInput_getLine(input)) != NULL) {
1243 printf(" %s\n", line);
1244 }
1245 printf(".\n");
1246 lineInput_free(input);
1247 fclose(file);
1248 }
1249 }
David 'Digit' Turner622f1532011-02-01 17:48:37 +01001250 }
1251
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001252 if(VERBOSE_CHECK(init)) {
1253 int i;
David 'Digit' Turner33361762011-01-19 22:11:03 +01001254 printf("QEMU options list:\n");
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001255 for(i = 0; i < n; i++) {
David 'Digit' Turner33361762011-01-19 22:11:03 +01001256 printf("emulator: argv[%02d] = \"%s\"\n", i, args[i]);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001257 }
David 'Digit' Turner33361762011-01-19 22:11:03 +01001258 /* Dump final command-line option to make debugging the core easier */
1259 printf("Concatenated QEMU options:\n");
1260 for (i = 0; i < n; i++) {
David 'Digit' Turner26722dd2011-02-24 16:40:20 +01001261 /* To make it easier to copy-paste the output to a command-line,
1262 * quote anything that contains spaces.
1263 */
1264 if (strchr(args[i], ' ') != NULL) {
1265 printf(" '%s'", args[i]);
1266 } else {
1267 printf(" %s", args[i]);
1268 }
David 'Digit' Turner33361762011-01-19 22:11:03 +01001269 }
1270 printf("\n");
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001271 }
David 'Digit' Turner74d7ace2011-02-02 13:21:03 +01001272
1273 /* Setup SDL UI just before calling the code */
1274 init_sdl_ui(skinConfig, skinPath, opts);
1275
David 'Digit' Turnerbdb6f2d2011-02-23 15:57:25 +01001276 if (attach_ui_to_core(opts) < 0) {
1277 derror("Can't attach to core!");
1278 exit(1);
1279 }
1280
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001281 return qemu_main(n, args);
1282}