blob: f2a55d39c43e4b5075415ea9a49ea4af63bb7e48 [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
David 'Digit' Turnercc330d42013-12-14 23:26:42 +010021#include "android/sockets.h"
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080022
23#include "android/android.h"
24#include "qemu-common.h"
David 'Digit' Turner34c48ff2013-12-15 00:25:03 +010025#include "sysemu/sysemu.h"
David 'Digit' Turner1c31e3e2013-12-14 20:07:17 +010026#include "ui/console.h"
David 'Digit' Turnerd4e803c2013-12-14 23:45:50 +010027#include "android/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"
David 'Digit' Turner73dd5fc2014-02-04 12:50:55 +010036#include "android/config-file.h"
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080037#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"
David 'Digit' Turnerf0665422013-12-17 10:47:09 +010048#include "hw/android/goldfish/nand.h"
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080049
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"
David 'Digit' Turnerd413fa52013-12-14 23:35:20 +010058#include "android/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
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080086int qemu_main(int argc, char **argv);
87
88/* this function dumps the QEMU help */
89extern void help( void );
90extern void emulator_help( void );
91
92#define VERBOSE_OPT(str,var) { str, &var }
93
94#define _VERBOSE_TAG(x,y) { #x, VERBOSE_##x, y },
95static const struct { const char* name; int flag; const char* text; }
96verbose_options[] = {
97 VERBOSE_TAG_LIST
98 { 0, 0, 0 }
99};
100
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800101void emulator_help( void )
102{
103 STRALLOC_DEFINE(out);
104 android_help_main(out);
105 printf( "%.*s", out->n, out->s );
106 stralloc_reset(out);
107 exit(1);
108}
109
David 'Digit' Turner40841b22011-03-01 14:04:00 +0100110/* TODO: Put in shared source file */
111static char*
112_getFullFilePath( const char* rootPath, const char* fileName )
113{
114 if (path_is_absolute(fileName)) {
115 return ASTRDUP(fileName);
116 } else {
117 char temp[PATH_MAX], *p=temp, *end=p+sizeof(temp);
118
119 p = bufprint(temp, end, "%s/%s", rootPath, fileName);
120 if (p >= end) {
121 return NULL;
122 }
123 return ASTRDUP(temp);
124 }
125}
126
127static uint64_t
128_adjustPartitionSize( const char* description,
129 uint64_t imageBytes,
130 uint64_t defaultBytes,
131 int inAndroidBuild )
132{
133 char temp[64];
134 unsigned imageMB;
135 unsigned defaultMB;
136
137 if (imageBytes <= defaultBytes)
138 return defaultBytes;
139
140 imageMB = convertBytesToMB(imageBytes);
141 defaultMB = convertBytesToMB(defaultBytes);
142
143 if (imageMB > defaultMB) {
144 snprintf(temp, sizeof temp, "(%d MB > %d MB)", imageMB, defaultMB);
145 } else {
Andrew Hsiehc7389bd2012-03-13 02:13:40 -0700146 snprintf(temp, sizeof temp, "(%" PRIu64 " bytes > %" PRIu64 " bytes)", imageBytes, defaultBytes);
David 'Digit' Turner40841b22011-03-01 14:04:00 +0100147 }
148
149 if (inAndroidBuild) {
150 dwarning("%s partition size adjusted to match image file %s\n", description, temp);
151 }
152
153 return convertMBToBytes(imageMB);
154}
155
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800156int main(int argc, char **argv)
157{
158 char tmp[MAX_PATH];
159 char* tmpend = tmp + sizeof(tmp);
160 char* args[128];
161 int n;
162 char* opt;
David 'Digit' Turner5e736932011-03-18 00:02:14 +0100163 /* The emulator always uses the first serial port for kernel messages
164 * and the second one for qemud. So start at the third if we need one
165 * for logcat or 'shell'
166 */
167 int serial = 2;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800168 int shell_serial = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800169
David 'Digit' Turner2ed457e2011-06-15 17:29:50 +0200170 int forceArmv7 = 0;
171
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800172 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;
Vladimir Chtchetkine88078b82012-04-19 12:24:38 -0700177 uint64_t defaultPartitionSize = convertMBToBytes(200);
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);
Xavier Ducrohet689d1142012-04-19 12:54:08 -0700320
321 /* update the avd hw config from this new skin */
322 avdInfo_getSkinHardwareIni(avd, opts->skin, opts->skindir);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800323 }
324
Siva Velusamyd8999182012-10-08 18:02:30 -0700325 if (opts->dynamic_skin == 0) {
326 opts->dynamic_skin = avdInfo_shouldUseDynamicSkin(avd);
327 }
328
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800329 /* Read hardware configuration */
330 hw = android_hw;
David 'Digit' Turnerb64325d2011-03-22 16:07:01 +0100331 if (avdInfo_initHwConfig(avd, hw) < 0) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800332 derror("could not read hardware configuration ?");
333 exit(1);
334 }
335
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800336 if (opts->keyset) {
337 parse_keyset(opts->keyset, opts);
338 if (!android_keyset) {
339 fprintf(stderr,
340 "emulator: WARNING: could not find keyset file named '%s',"
341 " using defaults instead\n",
342 opts->keyset);
343 }
344 }
345 if (!android_keyset) {
346 parse_keyset("default", opts);
347 if (!android_keyset) {
348 android_keyset = skin_keyset_new_from_text( skin_keyset_get_default() );
349 if (!android_keyset) {
350 fprintf(stderr, "PANIC: default keyset file is corrupted !!\n" );
351 fprintf(stderr, "PANIC: please update the code in android/skin/keyset.c\n" );
352 exit(1);
353 }
354 if (!opts->keyset)
355 write_default_keyset();
356 }
357 }
358
Dries Harnie40beab42010-05-15 17:04:47 +0200359 if (opts->shared_net_id) {
360 char* end;
361 long shared_net_id = strtol(opts->shared_net_id, &end, 0);
362 if (end == NULL || *end || shared_net_id < 1 || shared_net_id > 255) {
363 fprintf(stderr, "option -shared-net-id must be an integer between 1 and 255\n");
364 exit(1);
365 }
Vladimir Chtchetkineb25bf2a2010-09-08 11:09:23 -0700366 snprintf(boot_prop_ip, sizeof(boot_prop_ip),
367 "net.shared_net_ip=10.1.2.%ld", shared_net_id);
Dries Harnie40beab42010-05-15 17:04:47 +0200368 }
369
370
David 'Digit' Turner755811e2011-02-07 13:38:25 +0100371 user_config_init();
David 'Digit' Turner2507cab2011-02-10 16:29:17 +0100372 parse_skin_files(opts->skindir, opts->skin, opts, hw,
David 'Digit' Turner74d7ace2011-02-02 13:21:03 +0100373 &skinConfig, &skinPath);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800374
David 'Digit' Turner092361e2011-03-01 13:14:18 +0100375 if (!opts->netspeed && skin_network_speed) {
376 D("skin network speed: '%s'", skin_network_speed);
377 if (strcmp(skin_network_speed, NETWORK_SPEED_DEFAULT) != 0) {
378 opts->netspeed = (char*)skin_network_speed;
379 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800380 }
David 'Digit' Turner092361e2011-03-01 13:14:18 +0100381 if (!opts->netdelay && skin_network_delay) {
382 D("skin network delay: '%s'", skin_network_delay);
383 if (strcmp(skin_network_delay, NETWORK_DELAY_DEFAULT) != 0) {
384 opts->netdelay = (char*)skin_network_delay;
385 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800386 }
387
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800388 if (opts->trace) {
David 'Digit' Turnercd059b12009-08-28 19:36:27 +0200389 char* tracePath = avdInfo_getTracePath(avd, opts->trace);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800390 int ret;
391
392 if (tracePath == NULL) {
393 derror( "bad -trace parameter" );
394 exit(1);
395 }
396 ret = path_mkdir_if_needed( tracePath, 0755 );
397 if (ret < 0) {
398 fprintf(stderr, "could not create directory '%s'\n", tmp);
399 exit(2);
400 }
401 opts->trace = tracePath;
402 }
403
Vladimir Chtchetkine33f89d02011-09-28 09:19:09 -0700404 /* Update CPU architecture for HW configs created from build dir. */
405 if (inAndroidBuild) {
406#if defined(TARGET_ARM)
407 free(android_hw->hw_cpu_arch);
408 android_hw->hw_cpu_arch = ASTRDUP("arm");
409#elif defined(TARGET_I386)
410 free(android_hw->hw_cpu_arch);
411 android_hw->hw_cpu_arch = ASTRDUP("x86");
Bhanu Chetlapalli741dc132012-05-08 17:16:03 -0700412#elif defined(TARGET_MIPS)
413 free(android_hw->hw_cpu_arch);
414 android_hw->hw_cpu_arch = ASTRDUP("mips");
Vladimir Chtchetkine33f89d02011-09-28 09:19:09 -0700415#endif
416 }
417
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800418 n = 1;
419 /* generate arguments for the underlying qemu main() */
David 'Digit' Turner238b4b02009-09-20 13:10:19 -0700420 {
David 'Digit' Turner0b019492011-03-01 14:02:42 +0100421 char* kernelFile = opts->kernel;
422 int kernelFileLen;
David 'Digit' Turner238b4b02009-09-20 13:10:19 -0700423
David 'Digit' Turner0b019492011-03-01 14:02:42 +0100424 if (kernelFile == NULL) {
425 kernelFile = avdInfo_getKernelPath(avd);
426 if (kernelFile == NULL) {
427 derror( "This AVD's configuration is missing a kernel file!!" );
428 exit(2);
429 }
430 D("autoconfig: -kernel %s", kernelFile);
431 }
432 if (!path_exists(kernelFile)) {
433 derror( "Invalid or missing kernel image file: %s", kernelFile );
434 exit(2);
435 }
436
437 hw->kernel_path = kernelFile;
David 'Digit' Turner238b4b02009-09-20 13:10:19 -0700438
439 /* If the kernel image name ends in "-armv7", then change the cpu
440 * type automatically. This is a poor man's approach to configuration
441 * management, but should allow us to get past building ARMv7
442 * system images with dex preopt pass without introducing too many
443 * changes to the emulator sources.
444 *
445 * XXX:
446 * A 'proper' change would require adding some sort of hardware-property
447 * to each AVD config file, then automatically determine its value for
448 * full Android builds (depending on some environment variable), plus
449 * some build system changes. I prefer not to do that for now for reasons
450 * of simplicity.
451 */
David 'Digit' Turner0b019492011-03-01 14:02:42 +0100452 kernelFileLen = strlen(kernelFile);
David 'Digit' Turner238b4b02009-09-20 13:10:19 -0700453 if (kernelFileLen > 6 && !memcmp(kernelFile + kernelFileLen - 6, "-armv7", 6)) {
David 'Digit' Turner2ed457e2011-06-15 17:29:50 +0200454 forceArmv7 = 1;
David 'Digit' Turner238b4b02009-09-20 13:10:19 -0700455 }
456 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800457
Vladimir Chtchetkineb25bf2a2010-09-08 11:09:23 -0700458 if (boot_prop_ip[0]) {
459 args[n++] = "-boot-property";
460 args[n++] = boot_prop_ip;
461 }
462
Vladimir Chtchetkine318f17a2010-08-27 09:09:45 -0700463 if (opts->tcpdump) {
464 args[n++] = "-tcpdump";
465 args[n++] = opts->tcpdump;
466 }
467
Vladimir Chtchetkinee1316862010-08-26 09:03:54 -0700468#ifdef CONFIG_NAND_LIMITS
469 if (opts->nand_limits) {
470 args[n++] = "-nand-limits";
471 args[n++] = opts->nand_limits;
472 }
473#endif
474
David 'Digit' Turner74d7ace2011-02-02 13:21:03 +0100475 if (opts->timezone) {
476 args[n++] = "-timezone";
477 args[n++] = opts->timezone;
478 }
479
Vladimir Chtchetkinee1316862010-08-26 09:03:54 -0700480 if (opts->netspeed) {
481 args[n++] = "-netspeed";
482 args[n++] = opts->netspeed;
483 }
484 if (opts->netdelay) {
485 args[n++] = "-netdelay";
486 args[n++] = opts->netdelay;
487 }
488 if (opts->netfast) {
489 args[n++] = "-netfast";
490 }
491
Vladimir Chtchetkineb2438402010-08-24 08:55:33 -0700492 if (opts->audio) {
493 args[n++] = "-audio";
494 args[n++] = opts->audio;
495 }
496
Vladimir Chtchetkineb2438402010-08-24 08:55:33 -0700497 if (opts->cpu_delay) {
498 args[n++] = "-cpu-delay";
499 args[n++] = opts->cpu_delay;
500 }
501
Vladimir Chtchetkine7fbf4972010-08-11 15:30:32 -0700502 if (opts->dns_server) {
503 args[n++] = "-dns-server";
504 args[n++] = opts->dns_server;
505 }
506
David 'Digit' Turner9ff69722011-09-13 12:32:52 +0200507 /* opts->ramdisk is never NULL (see createAVD) here */
508 if (opts->ramdisk) {
509 AFREE(hw->disk_ramdisk_path);
510 hw->disk_ramdisk_path = ASTRDUP(opts->ramdisk);
511 }
512 else if (!hw->disk_ramdisk_path[0]) {
513 hw->disk_ramdisk_path = avdInfo_getRamdiskPath(avd);
514 D("autoconfig: -ramdisk %s", hw->disk_ramdisk_path);
515 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800516
David 'Digit' Turner40841b22011-03-01 14:04:00 +0100517 /* -partition-size is used to specify the max size of both the system
518 * and data partition sizes.
519 */
520 if (opts->partition_size) {
521 char* end;
522 long sizeMB = strtol(opts->partition_size, &end, 0);
523 long minSizeMB = 10;
524 long maxSizeMB = LONG_MAX / ONE_MB;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800525
David 'Digit' Turner40841b22011-03-01 14:04:00 +0100526 if (sizeMB < 0 || *end != 0) {
527 derror( "-partition-size must be followed by a positive integer" );
528 exit(1);
529 }
530 if (sizeMB < minSizeMB || sizeMB > maxSizeMB) {
531 derror( "partition-size (%d) must be between %dMB and %dMB",
532 sizeMB, minSizeMB, maxSizeMB );
533 exit(1);
534 }
535 defaultPartitionSize = (uint64_t) sizeMB * ONE_MB;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800536 }
537
David 'Digit' Turner40841b22011-03-01 14:04:00 +0100538
539 /** SYSTEM PARTITION **/
540
541 if (opts->sysdir == NULL) {
542 if (avdInfo_inAndroidBuild(avd)) {
543 opts->sysdir = ASTRDUP(avdInfo_getContentPath(avd));
544 D("autoconfig: -sysdir %s", opts->sysdir);
545 }
546 }
547
548 if (opts->sysdir != NULL) {
549 if (!path_exists(opts->sysdir)) {
550 derror("Directory does not exist: %s", opts->sysdir);
551 exit(1);
552 }
553 }
554
555 {
556 char* rwImage = NULL;
557 char* initImage = NULL;
558
559 do {
560 if (opts->system == NULL) {
561 /* If -system is not used, try to find a runtime system image
562 * (i.e. system-qemu.img) in the content directory.
563 */
564 rwImage = avdInfo_getSystemImagePath(avd);
565 if (rwImage != NULL) {
566 break;
567 }
568 /* Otherwise, try to find the initial system image */
569 initImage = avdInfo_getSystemInitImagePath(avd);
570 if (initImage == NULL) {
571 derror("No initial system image for this configuration!");
572 exit(1);
573 }
574 break;
575 }
576
577 /* If -system <name> is used, use it to find the initial image */
David 'Digit' Turnerea283772011-07-07 04:40:27 +0200578 if (opts->sysdir != NULL && !path_exists(opts->system)) {
David 'Digit' Turner40841b22011-03-01 14:04:00 +0100579 initImage = _getFullFilePath(opts->sysdir, opts->system);
580 } else {
581 initImage = ASTRDUP(opts->system);
582 }
583 if (!path_exists(initImage)) {
584 derror("System image file doesn't exist: %s", initImage);
585 exit(1);
586 }
587
588 } while (0);
589
590 if (rwImage != NULL) {
591 /* Use the read/write image file directly */
592 hw->disk_systemPartition_path = rwImage;
593 hw->disk_systemPartition_initPath = NULL;
594 D("Using direct system image: %s", rwImage);
595 } else if (initImage != NULL) {
596 hw->disk_systemPartition_path = NULL;
597 hw->disk_systemPartition_initPath = initImage;
598 D("Using initial system image: %s", initImage);
599 }
600
601 /* Check the size of the system partition image.
602 * If we have an AVD, it must be smaller than
603 * the disk.systemPartition.size hardware property.
604 *
605 * Otherwise, we need to adjust the systemPartitionSize
606 * automatically, and print a warning.
607 *
608 */
609 const char* systemImage = hw->disk_systemPartition_path;
610 uint64_t systemBytes;
611
612 if (systemImage == NULL)
613 systemImage = hw->disk_systemPartition_initPath;
614
615 if (path_get_size(systemImage, &systemBytes) < 0) {
616 derror("Missing system image: %s", systemImage);
617 exit(1);
618 }
619
620 hw->disk_systemPartition_size =
621 _adjustPartitionSize("system", systemBytes, defaultPartitionSize,
622 avdInfo_inAndroidBuild(avd));
623 }
624
625 /** DATA PARTITION **/
626
David 'Digit' Turnerfd59c332011-03-01 00:48:52 +0100627 if (opts->datadir) {
628 if (!path_exists(opts->datadir)) {
629 derror("Invalid -datadir directory: %s", opts->datadir);
630 }
631 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800632
David 'Digit' Turnerfd59c332011-03-01 00:48:52 +0100633 {
634 char* dataImage = NULL;
635 char* initImage = NULL;
636
637 do {
638 if (!opts->data) {
639 dataImage = avdInfo_getDataImagePath(avd);
640 if (dataImage != NULL) {
641 D("autoconfig: -data %s", dataImage);
642 break;
643 }
644 dataImage = avdInfo_getDefaultDataImagePath(avd);
645 if (dataImage == NULL) {
646 derror("No data image path for this configuration!");
647 exit (1);
648 }
649 opts->wipe_data = 1;
650 break;
651 }
652
653 if (opts->datadir) {
654 dataImage = _getFullFilePath(opts->datadir, opts->data);
655 } else {
656 dataImage = ASTRDUP(opts->data);
657 }
658 } while (0);
659
660 if (opts->initdata != NULL) {
661 initImage = ASTRDUP(opts->initdata);
662 if (!path_exists(initImage)) {
663 derror("Invalid initial data image path: %s", initImage);
664 exit(1);
665 }
666 } else {
667 initImage = avdInfo_getDataInitImagePath(avd);
668 D("autoconfig: -initdata %s", initImage);
669 }
670
671 hw->disk_dataPartition_path = dataImage;
672 if (opts->wipe_data) {
673 hw->disk_dataPartition_initPath = initImage;
674 } else {
675 hw->disk_dataPartition_initPath = NULL;
676 }
677
Maciek Molerusf7584112011-06-15 22:26:35 +0200678 uint64_t defaultBytes =
679 hw->disk_dataPartition_size == 0 ?
680 defaultPartitionSize :
Vladimir Chtchetkined4f5a3a2012-03-08 14:20:20 -0800681 hw->disk_dataPartition_size;
David 'Digit' Turnerfd59c332011-03-01 00:48:52 +0100682 uint64_t dataBytes;
683 const char* dataPath = hw->disk_dataPartition_initPath;
684
685 if (dataPath == NULL)
686 dataPath = hw->disk_dataPartition_path;
687
688 path_get_size(dataPath, &dataBytes);
689
690 hw->disk_dataPartition_size =
691 _adjustPartitionSize("data", dataBytes, defaultBytes,
692 avdInfo_inAndroidBuild(avd));
693 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800694
David 'Digit' Turnerc480cca2011-02-25 16:43:34 +0100695 /** CACHE PARTITION **/
696
697 if (opts->no_cache) {
698 /* No cache partition at all */
699 hw->disk_cachePartition = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800700 }
David 'Digit' Turnerc480cca2011-02-25 16:43:34 +0100701 else if (!hw->disk_cachePartition) {
702 if (opts->cache) {
703 dwarning( "Emulated hardware doesn't support a cache partition. -cache option ignored!" );
704 opts->cache = NULL;
705 }
706 }
707 else
708 {
709 if (!opts->cache) {
710 /* Find the current cache partition file */
711 opts->cache = avdInfo_getCachePath(avd);
712 if (opts->cache == NULL) {
713 /* The file does not exists, we will force its creation
714 * if we are not in the Android build system. Otherwise,
715 * a temporary file will be used.
716 */
717 if (!avdInfo_inAndroidBuild(avd)) {
718 opts->cache = avdInfo_getDefaultCachePath(avd);
719 }
720 }
David 'Digit' Turner48a3c662011-03-01 14:03:20 +0100721 if (opts->cache) {
722 D("autoconfig: -cache %s", opts->cache);
723 }
David 'Digit' Turnerc480cca2011-02-25 16:43:34 +0100724 }
725
726 if (opts->cache) {
727 hw->disk_cachePartition_path = ASTRDUP(opts->cache);
728 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800729 }
730
Vladimir Chtchetkine6f50aa32012-04-26 08:20:18 -0700731 if (hw->disk_cachePartition_path && opts->cache_size) {
732 /* Set cache partition size per user options. */
733 char* end;
734 long sizeMB = strtol(opts->cache_size, &end, 0);
735
736 if (sizeMB < 0 || *end != 0) {
737 derror( "-cache-size must be followed by a positive integer" );
738 exit(1);
739 }
740 hw->disk_cachePartition_size = (uint64_t) sizeMB * ONE_MB;
741 }
742
David 'Digit' Turnerc480cca2011-02-25 16:43:34 +0100743 /** SD CARD PARTITION */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800744
David 'Digit' Turner48a3c662011-03-01 14:03:20 +0100745 if (!hw->hw_sdCard) {
746 /* No SD Card emulation, so -sdcard will be ignored */
747 if (opts->sdcard) {
748 dwarning( "Emulated hardware doesn't support SD Cards. -sdcard option ignored." );
749 opts->sdcard = NULL;
750 }
751 } else {
752 /* Auto-configure -sdcard if it is not available */
753 if (!opts->sdcard) {
754 do {
755 /* If -datadir <path> is used, look for a sdcard.img file here */
756 if (opts->datadir) {
757 bufprint(tmp, tmpend, "%s/%s", opts->datadir, "system.img");
758 if (path_exists(tmp)) {
759 opts->sdcard = strdup(tmp);
760 break;
761 }
762 }
763
764 /* Otherwise, look at the AVD's content */
765 opts->sdcard = avdInfo_getSdCardPath(avd);
766 if (opts->sdcard != NULL) {
767 break;
768 }
769
770 /* Nothing */
771 } while (0);
772
773 if (opts->sdcard) {
774 D("autoconfig: -sdcard %s", opts->sdcard);
775 }
776 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800777 }
778
779 if(opts->sdcard) {
780 uint64_t size;
781 if (path_get_size(opts->sdcard, &size) == 0) {
782 /* see if we have an sdcard image. get its size if it exists */
David 'Digit' Turner8b657e52009-12-01 13:38:21 -0800783 /* due to what looks like limitations of the MMC protocol, one has
784 * to use an SD Card image that is equal or larger than 9 MB
785 */
786 if (size < 9*1024*1024ULL) {
787 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 -0800788 } else {
David 'Digit' Turner48a3c662011-03-01 14:03:20 +0100789 hw->hw_sdCard_path = ASTRDUP(opts->sdcard);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800790 }
791 } else {
David 'Digit' Turner48a3c662011-03-01 14:03:20 +0100792 dwarning("no SD Card image at '%s'", opts->sdcard);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800793 }
794 }
795
David 'Digit' Turner48a3c662011-03-01 14:03:20 +0100796
797 /** SNAPSHOT STORAGE HANDLING */
798
David 'Digit' Turner5f64b872011-02-28 23:23:05 +0100799 /* Determine snapstorage path. -no-snapstorage disables all snapshotting
800 * support. This means you can't resume a snapshot at load, save it at
801 * exit, or even load/save them dynamically at runtime with the console.
802 */
803 if (opts->no_snapstorage) {
804
805 if (opts->snapshot) {
806 dwarning("ignoring -snapshot option due to the use of -no-snapstorage");
807 opts->snapshot = NULL;
808 }
809
810 if (opts->snapstorage) {
811 dwarning("ignoring -snapstorage option due to the use of -no-snapstorage");
812 opts->snapstorage = NULL;
813 }
814 }
815 else
816 {
Vladimir Chtchetkine873c3cb2012-03-14 12:46:51 -0700817 if (!opts->snapstorage && avdInfo_getSnapshotPresent(avd)) {
David 'Digit' Turner5f64b872011-02-28 23:23:05 +0100818 opts->snapstorage = avdInfo_getSnapStoragePath(avd);
819 if (opts->snapstorage != NULL) {
820 D("autoconfig: -snapstorage %s", opts->snapstorage);
Ot ten Thije353b3b12010-10-05 17:53:30 +0100821 }
822 }
823
David 'Digit' Turner5f64b872011-02-28 23:23:05 +0100824 if (opts->snapstorage && !path_exists(opts->snapstorage)) {
825 D("no image at '%s', state snapshots disabled", opts->snapstorage);
826 opts->snapstorage = NULL;
Ot ten Thije353b3b12010-10-05 17:53:30 +0100827 }
David 'Digit' Turner5f64b872011-02-28 23:23:05 +0100828 }
829
830 /* If we have a valid snapshot storage path */
831
832 if (opts->snapstorage) {
833
834 hw->disk_snapStorage_path = ASTRDUP(opts->snapstorage);
835
836 /* -no-snapshot is equivalent to using both -no-snapshot-load
837 * and -no-snapshot-save. You can still load/save snapshots dynamically
838 * from the console though.
839 */
840 if (opts->no_snapshot) {
841
842 opts->no_snapshot_load = 1;
843 opts->no_snapshot_save = 1;
844
845 if (opts->snapshot) {
846 dwarning("ignoring -snapshot option due to the use of -no-snapshot.");
847 }
848 }
849
850 if (!opts->no_snapshot_load || !opts->no_snapshot_save) {
851 if (opts->snapshot == NULL) {
852 opts->snapshot = "default-boot";
853 D("autoconfig: -snapshot %s", opts->snapshot);
854 }
855 }
856
857 /* We still use QEMU command-line options for the following since
858 * they can change from one invokation to the next and don't really
859 * correspond to the hardware configuration itself.
860 */
861 if (!opts->no_snapshot_load) {
862 args[n++] = "-loadvm";
863 args[n++] = ASTRDUP(opts->snapshot);
864 }
865
866 if (!opts->no_snapshot_save) {
867 args[n++] = "-savevm-on-exit";
868 args[n++] = ASTRDUP(opts->snapshot);
869 }
870
Tim Baverstock622b8f42010-12-07 11:36:59 +0000871 if (opts->no_snapshot_update_time) {
David 'Digit' Turnerbdb6f2d2011-02-23 15:57:25 +0100872 args[n++] = "-snapshot-no-time-update";
Tim Baverstock622b8f42010-12-07 11:36:59 +0000873 }
Ot ten Thijeae835ac2010-10-18 13:37:37 +0100874 }
Ot ten Thije353b3b12010-10-05 17:53:30 +0100875
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800876 if (!opts->logcat || opts->logcat[0] == 0) {
877 opts->logcat = getenv("ANDROID_LOG_TAGS");
878 if (opts->logcat && opts->logcat[0] == 0)
879 opts->logcat = NULL;
880 }
881
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800882 /* we always send the kernel messages from ttyS0 to android_kmsg */
David 'Digit' Turner062dd6a2011-03-01 14:50:07 +0100883 if (opts->show_kernel) {
884 args[n++] = "-show-kernel";
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800885 }
886
887 /* XXXX: TODO: implement -shell and -logcat through qemud instead */
888 if (!opts->shell_serial) {
889#ifdef _WIN32
890 opts->shell_serial = "con:";
891#else
892 opts->shell_serial = "stdio";
893#endif
894 }
895 else
896 opts->shell = 1;
897
898 if (opts->shell || opts->logcat) {
899 args[n++] = "-serial";
900 args[n++] = opts->shell_serial;
901 shell_serial = serial++;
902 }
903
David 'Digit' Turner062dd6a2011-03-01 14:50:07 +0100904 if (opts->radio) {
905 args[n++] = "-radio";
906 args[n++] = opts->radio;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800907 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800908
David 'Digit' Turner062dd6a2011-03-01 14:50:07 +0100909 if (opts->gps) {
910 args[n++] = "-gps";
911 args[n++] = opts->gps;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800912 }
913
Nick Kralevich185231a2013-10-07 13:54:31 -0700914 if (opts->selinux) {
915 if ((strcmp(opts->selinux, "permissive") != 0)
916 && (strcmp(opts->selinux, "disabled") != 0)) {
917 derror("-selinux must be \"disabled\" or \"permissive\"");
918 exit(1);
919 }
920 }
921
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800922 if (opts->memory) {
923 char* end;
924 long ramSize = strtol(opts->memory, &end, 0);
925 if (ramSize < 0 || *end != 0) {
926 derror( "-memory must be followed by a positive integer" );
927 exit(1);
928 }
929 if (ramSize < 32 || ramSize > 4096) {
930 derror( "physical memory size must be between 32 and 4096 MB" );
931 exit(1);
932 }
David 'Digit' Turner5377c5b2011-02-10 16:52:19 +0100933 hw->hw_ramSize = ramSize;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800934 }
935 if (!opts->memory) {
David 'Digit' Turner3bbc9192011-01-19 22:18:02 +0100936 int ramSize = hw->hw_ramSize;
937 if (ramSize <= 0) {
938 /* Compute the default RAM size based on the size of screen.
939 * This is only used when the skin doesn't provide the ram
940 * size through its hardware.ini (i.e. legacy ones) or when
941 * in the full Android build system.
942 */
David 'Digit' Turner5377c5b2011-02-10 16:52:19 +0100943 int64_t pixels = hw->hw_lcd_width * hw->hw_lcd_height;
David 'Digit' Turner3bbc9192011-01-19 22:18:02 +0100944 /* The following thresholds are a bit liberal, but we
945 * essentially want to ensure the following mappings:
946 *
947 * 320x480 -> 96
948 * 800x600 -> 128
949 * 1024x768 -> 256
950 *
951 * These are just simple heuristics, they could change in
952 * the future.
953 */
954 if (pixels <= 250000)
955 ramSize = 96;
956 else if (pixels <= 500000)
957 ramSize = 128;
958 else
959 ramSize = 256;
960 }
David 'Digit' Turner5377c5b2011-02-10 16:52:19 +0100961 hw->hw_ramSize = ramSize;
962 }
963
964 D("Physical RAM size: %dMB\n", hw->hw_ramSize);
965
966 if (hw->vm_heapSize == 0) {
967 /* Compute the default heap size based on the RAM size.
968 * Essentially, we want to ensure the following liberal mappings:
969 *
970 * 96MB RAM -> 16MB heap
971 * 128MB RAM -> 24MB heap
972 * 256MB RAM -> 48MB heap
973 */
974 int ramSize = hw->hw_ramSize;
975 int heapSize;
976
977 if (ramSize < 100)
978 heapSize = 16;
979 else if (ramSize < 192)
980 heapSize = 24;
981 else
982 heapSize = 48;
983
984 hw->vm_heapSize = heapSize;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800985 }
986
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800987 if (opts->trace) {
988 args[n++] = "-trace";
989 args[n++] = opts->trace;
990 args[n++] = "-tracing";
991 args[n++] = "off";
992 }
993
Vladimir Chtchetkineb25bf2a2010-09-08 11:09:23 -0700994 /* Pass boot properties to the core. */
995 if (opts->prop != NULL) {
996 ParamList* pl = opts->prop;
997 for ( ; pl != NULL; pl = pl->next ) {
998 args[n++] = "-boot-property";
999 args[n++] = pl->param;
1000 }
1001 }
1002
David 'Digit' Turner318e4f22009-05-25 18:01:03 +02001003 /* Setup the kernel init options
1004 */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001005 {
1006 static char params[1024];
1007 char *p = params, *end = p + sizeof(params);
1008
David 'Digit' Turner062dd6a2011-03-01 14:50:07 +01001009 /* Don't worry about having a leading space here, this is handled
1010 * by the core later. */
1011
Jun Nakajima334ab472011-02-02 23:49:59 -08001012#ifdef TARGET_I386
1013 p = bufprint(p, end, " androidboot.hardware=goldfish");
Jun Nakajimabac9add2011-02-08 22:10:52 -08001014 p = bufprint(p, end, " clocksource=pit");
Jun Nakajima334ab472011-02-02 23:49:59 -08001015#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001016
1017 if (opts->shell || opts->logcat) {
1018 p = bufprint(p, end, " androidboot.console=ttyS%d", shell_serial );
1019 }
1020
1021 if (opts->trace) {
1022 p = bufprint(p, end, " android.tracing=1");
1023 }
1024
1025 if (!opts->no_jni) {
1026 p = bufprint(p, end, " android.checkjni=1");
1027 }
1028
1029 if (opts->no_boot_anim) {
1030 p = bufprint( p, end, " android.bootanim=0" );
1031 }
1032
1033 if (opts->logcat) {
1034 char* q = bufprint(p, end, " androidboot.logcat=%s", opts->logcat);
1035
1036 if (q < end) {
1037 /* replace any space by a comma ! */
1038 {
1039 int nn;
1040 for (nn = 1; p[nn] != 0; nn++)
1041 if (p[nn] == ' ' || p[nn] == '\t')
1042 p[nn] = ',';
1043 p += nn;
1044 }
1045 }
1046 p = q;
1047 }
1048
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001049 if (opts->bootchart) {
1050 p = bufprint(p, end, " androidboot.bootchart=%s", opts->bootchart);
1051 }
1052
Nick Kralevich185231a2013-10-07 13:54:31 -07001053 if (opts->selinux) {
1054 p = bufprint(p, end, " androidboot.selinux=%s", opts->selinux);
1055 }
1056
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001057 if (p >= end) {
1058 fprintf(stderr, "### ERROR: kernel parameters too long\n");
1059 exit(1);
1060 }
1061
David 'Digit' Turner0b019492011-03-01 14:02:42 +01001062 hw->kernel_parameters = strdup(params);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001063 }
1064
Vladimir Chtchetkined81e6d12010-06-15 16:46:32 -07001065 if (opts->ports) {
1066 args[n++] = "-android-ports";
1067 args[n++] = opts->ports;
1068 }
1069
1070 if (opts->port) {
1071 args[n++] = "-android-port";
1072 args[n++] = opts->port;
1073 }
1074
1075 if (opts->report_console) {
1076 args[n++] = "-android-report-console";
1077 args[n++] = opts->report_console;
1078 }
1079
1080 if (opts->http_proxy) {
1081 args[n++] = "-http-proxy";
1082 args[n++] = opts->http_proxy;
1083 }
1084
Xavier Ducrohet72d56112011-08-11 18:47:27 -07001085 if (!opts->charmap) {
1086 /* Try to find a valid charmap name */
1087 char* charmap = avdInfo_getCharmapFile(avd, hw->hw_keyboard_charmap);
1088 if (charmap != NULL) {
1089 D("autoconfig: -charmap %s", charmap);
1090 opts->charmap = charmap;
1091 }
1092 }
1093
Vladimir Chtchetkine43552dc2010-07-22 11:23:19 -07001094 if (opts->charmap) {
Xavier Ducrohet72d56112011-08-11 18:47:27 -07001095 char charmap_name[AKEYCHARMAP_NAME_SIZE];
1096
1097 if (!path_exists(opts->charmap)) {
1098 derror("Charmap file does not exist: %s", opts->charmap);
1099 exit(1);
1100 }
1101 /* We need to store the charmap name in the hardware configuration.
1102 * However, the charmap file itself is only used by the UI component
1103 * and doesn't need to be set to the emulation engine.
1104 */
1105 kcm_extract_charmap_name(opts->charmap, charmap_name,
1106 sizeof(charmap_name));
1107 AFREE(hw->hw_keyboard_charmap);
1108 hw->hw_keyboard_charmap = ASTRDUP(charmap_name);
Vladimir Chtchetkine43552dc2010-07-22 11:23:19 -07001109 }
1110
Vladimir Chtchetkineb5365f32010-08-09 13:33:57 -07001111 if (opts->memcheck) {
1112 args[n++] = "-android-memcheck";
1113 args[n++] = opts->memcheck;
1114 }
1115
David Turner9da935d2011-09-12 21:27:56 +02001116 if (opts->gpu) {
1117 const char* gpu = opts->gpu;
Vladimir Chtchetkineae0d8132011-09-13 10:48:02 -07001118 if (!strcmp(gpu,"on") || !strcmp(gpu,"enable")) {
David Turner9da935d2011-09-12 21:27:56 +02001119 hw->hw_gpu_enabled = 1;
Vladimir Chtchetkineae0d8132011-09-13 10:48:02 -07001120 } else if (!strcmp(gpu,"off") || !strcmp(gpu,"disable")) {
David Turner9da935d2011-09-12 21:27:56 +02001121 hw->hw_gpu_enabled = 0;
1122 } else if (!strcmp(gpu,"auto")) {
1123 /* Nothing to do */
1124 } else {
1125 derror("Invalid value for -gpu <mode> parameter: %s\n", gpu);
1126 derror("Valid values are: on, off or auto\n");
1127 exit(1);
1128 }
1129 }
1130
Vladimir Chtchetkine9242b332012-02-10 08:29:22 -08001131 /* Quit emulator on condition that both, gpu and snapstorage are on. This is
1132 * a temporary solution preventing the emulator from crashing until GPU state
1133 * can be properly saved / resored in snapshot file. */
1134 if (hw->hw_gpu_enabled && opts->snapstorage && (!opts->no_snapshot_load ||
1135 !opts->no_snapshot_save)) {
1136 derror("Snapshots and gpu are mutually exclusive at this point. Please turn one of them off, and restart the emulator.");
1137 exit(1);
1138 }
1139
Vladimir Chtchetkine7485c292012-03-19 11:35:29 -07001140 /* Deal with camera emulation */
1141 if (opts->webcam_list) {
1142 /* List connected webcameras */
1143 args[n++] = "-list-webcam";
1144 }
1145
1146 if (opts->camera_back) {
1147 /* Validate parameter. */
1148 if (memcmp(opts->camera_back, "webcam", 6) &&
1149 strcmp(opts->camera_back, "emulated") &&
1150 strcmp(opts->camera_back, "none")) {
1151 derror("Invalid value for -camera-back <mode> parameter: %s\n"
1152 "Valid values are: 'emulated', 'webcam<N>', or 'none'\n",
1153 opts->camera_back);
Vladimir Chtchetkineae0d8132011-09-13 10:48:02 -07001154 exit(1);
1155 }
Vladimir Chtchetkine7485c292012-03-19 11:35:29 -07001156 hw->hw_camera_back = ASTRDUP(opts->camera_back);
Vladimir Chtchetkineae0d8132011-09-13 10:48:02 -07001157 }
1158
Vladimir Chtchetkine7485c292012-03-19 11:35:29 -07001159 if (opts->camera_front) {
1160 /* Validate parameter. */
1161 if (memcmp(opts->camera_front, "webcam", 6) &&
1162 strcmp(opts->camera_front, "emulated") &&
1163 strcmp(opts->camera_front, "none")) {
1164 derror("Invalid value for -camera-front <mode> parameter: %s\n"
1165 "Valid values are: 'emulated', 'webcam<N>', or 'none'\n",
1166 opts->camera_front);
1167 exit(1);
Vladimir Chtchetkineb8dcaff2011-09-17 11:15:47 -07001168 }
Vladimir Chtchetkine7485c292012-03-19 11:35:29 -07001169 hw->hw_camera_front = ASTRDUP(opts->camera_front);
Vladimir Chtchetkinef8675c22012-01-06 10:31:41 -08001170 }
1171
David 'Digit' Turner5377c5b2011-02-10 16:52:19 +01001172 /* physical memory is now in hw->hw_ramSize */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001173
David 'Digit' Turner53eb66d2011-03-01 14:58:23 +01001174 hw->avd_name = ASTRDUP(avdInfo_getName(avd));
David 'Digit' Turner6b8555c2011-02-17 04:28:19 +01001175
Dries Harnie40beab42010-05-15 17:04:47 +02001176 /* Set up the interfaces for inter-emulator networking */
1177 if (opts->shared_net_id) {
1178 unsigned int shared_net_id = atoi(opts->shared_net_id);
1179 char nic[37];
Dries Harnie40beab42010-05-15 17:04:47 +02001180
1181 args[n++] = "-net";
1182 args[n++] = "nic,vlan=0";
1183 args[n++] = "-net";
1184 args[n++] = "user,vlan=0";
Dries Harnie111d6f82010-06-09 21:42:18 +02001185
1186 args[n++] = "-net";
1187 snprintf(nic, sizeof nic, "nic,vlan=1,macaddr=52:54:00:12:34:%02x", shared_net_id);
1188 args[n++] = strdup(nic);
1189 args[n++] = "-net";
1190 args[n++] = "socket,vlan=1,mcast=230.0.0.10:1234";
Dries Harnie40beab42010-05-15 17:04:47 +02001191 }
1192
Vladimir Chtchetkine8dd31e82012-02-15 17:16:04 -08001193 /* Setup screen emulation */
1194 if (opts->screen) {
Vladimir Chtchetkine863d1012012-03-16 12:25:23 -07001195 if (strcmp(opts->screen, "touch") &&
1196 strcmp(opts->screen, "multi-touch") &&
1197 strcmp(opts->screen, "no-touch")) {
1198
1199 derror("Invalid value for -screen <mode> parameter: %s\n"
1200 "Valid values are: touch, multi-touch, or no-touch\n",
1201 opts->screen);
Vladimir Chtchetkine8dd31e82012-02-15 17:16:04 -08001202 exit(1);
1203 }
Vladimir Chtchetkine863d1012012-03-16 12:25:23 -07001204 hw->hw_screen = ASTRDUP(opts->screen);
Vladimir Chtchetkine8dd31e82012-02-15 17:16:04 -08001205 }
1206
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001207 while(argc-- > 0) {
1208 args[n++] = *argv++;
1209 }
1210 args[n] = 0;
1211
David 'Digit' Turner2ed457e2011-06-15 17:29:50 +02001212 /* If the target ABI is armeabi-v7a, we can auto-detect the cpu model
1213 * as a cortex-a8, instead of the default (arm926) which only emulates
1214 * an ARMv5TE CPU.
1215 */
1216 if (!forceArmv7 && hw->hw_cpu_model[0] == '\0')
1217 {
1218 char* abi = avdInfo_getTargetAbi(avd);
1219 if (abi != NULL) {
1220 if (!strcmp(abi, "armeabi-v7a")) {
1221 forceArmv7 = 1;
1222 }
1223 AFREE(abi);
1224 }
1225 }
1226
1227 if (forceArmv7 != 0) {
1228 AFREE(hw->hw_cpu_model);
1229 hw->hw_cpu_model = ASTRDUP("cortex-a8");
1230 D("Auto-config: -qemu -cpu %s", hw->hw_cpu_model);
1231 }
1232
David 'Digit' Turner26d41532011-03-01 15:03:07 +01001233 /* Generate a hardware-qemu.ini for this AVD. The real hardware
David 'Digit' Turner622f1532011-02-01 17:48:37 +01001234 * configuration is ususally stored in several files, e.g. the AVD's
1235 * config.ini plus the skin-specific hardware.ini.
1236 *
David 'Digit' Turner26d41532011-03-01 15:03:07 +01001237 * The new file will group all definitions and will be used to
David 'Digit' Turner622f1532011-02-01 17:48:37 +01001238 * launch the core with the -android-hw <file> option.
1239 */
1240 {
David 'Digit' Turner42074e52011-02-10 16:03:28 +01001241 const char* coreHwIniPath = avdInfo_getCoreHwIniPath(avd);
1242 IniFile* hwIni = iniFile_newFromMemory("", NULL);
David 'Digit' Turner622f1532011-02-01 17:48:37 +01001243 androidHwConfig_write(hw, hwIni);
David 'Digit' Turner26d41532011-03-01 15:03:07 +01001244
1245 if (filelock_create(coreHwIniPath) == NULL) {
1246 /* The AVD is already in use, we still support this as an
1247 * experimental feature. Use a temporary hardware-qemu.ini
1248 * file though to avoid overwriting the existing one. */
1249 TempFile* tempIni = tempfile_create();
1250 coreHwIniPath = tempfile_path(tempIni);
1251 }
1252
Vladimir Chtchetkinedb450d72012-01-12 13:37:40 -08001253 /* While saving HW config, ignore valueless entries. This will not break
1254 * anything, but will significantly simplify comparing the current HW
1255 * config with the one that has been associated with a snapshot (in case
1256 * VM starts from a snapshot for this instance of emulator). */
1257 if (iniFile_saveToFileClean(hwIni, coreHwIniPath) < 0) {
David 'Digit' Turner42074e52011-02-10 16:03:28 +01001258 derror("Could not write hardware.ini to %s: %s", coreHwIniPath, strerror(errno));
David 'Digit' Turner622f1532011-02-01 17:48:37 +01001259 exit(2);
1260 }
1261 args[n++] = "-android-hw";
David 'Digit' Turner42074e52011-02-10 16:03:28 +01001262 args[n++] = strdup(coreHwIniPath);
David 'Digit' Turner0a879bf2011-05-12 18:45:18 +02001263
1264 /* In verbose mode, dump the file's content */
1265 if (VERBOSE_CHECK(init)) {
1266 FILE* file = fopen(coreHwIniPath, "rt");
1267 if (file == NULL) {
1268 derror("Could not open hardware configuration file: %s\n",
1269 coreHwIniPath);
1270 } else {
1271 LineInput* input = lineInput_newFromStdFile(file);
1272 const char* line;
1273 printf("Content of hardware configuration file:\n");
1274 while ((line = lineInput_getLine(input)) != NULL) {
1275 printf(" %s\n", line);
1276 }
1277 printf(".\n");
1278 lineInput_free(input);
1279 fclose(file);
1280 }
1281 }
David 'Digit' Turner622f1532011-02-01 17:48:37 +01001282 }
1283
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001284 if(VERBOSE_CHECK(init)) {
1285 int i;
David 'Digit' Turner33361762011-01-19 22:11:03 +01001286 printf("QEMU options list:\n");
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001287 for(i = 0; i < n; i++) {
David 'Digit' Turner33361762011-01-19 22:11:03 +01001288 printf("emulator: argv[%02d] = \"%s\"\n", i, args[i]);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001289 }
David 'Digit' Turner33361762011-01-19 22:11:03 +01001290 /* Dump final command-line option to make debugging the core easier */
1291 printf("Concatenated QEMU options:\n");
1292 for (i = 0; i < n; i++) {
David 'Digit' Turner26722dd2011-02-24 16:40:20 +01001293 /* To make it easier to copy-paste the output to a command-line,
1294 * quote anything that contains spaces.
1295 */
1296 if (strchr(args[i], ' ') != NULL) {
1297 printf(" '%s'", args[i]);
1298 } else {
1299 printf(" %s", args[i]);
1300 }
David 'Digit' Turner33361762011-01-19 22:11:03 +01001301 }
1302 printf("\n");
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001303 }
David 'Digit' Turner74d7ace2011-02-02 13:21:03 +01001304
1305 /* Setup SDL UI just before calling the code */
1306 init_sdl_ui(skinConfig, skinPath, opts);
1307
David 'Digit' Turnerbdb6f2d2011-02-23 15:57:25 +01001308 if (attach_ui_to_core(opts) < 0) {
1309 derror("Can't attach to core!");
1310 exit(1);
1311 }
1312
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001313 return qemu_main(n, args);
1314}