blob: c557d95678744ffe6956e690292140ec83e7a965 [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' Turner9b3a4b02014-01-23 00:52:54 +010021#include "config.h"
David 'Digit' Turnercc330d42013-12-14 23:26:42 +010022#include "android/sockets.h"
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080023
24#include "android/android.h"
25#include "qemu-common.h"
David 'Digit' Turner34c48ff2013-12-15 00:25:03 +010026#include "sysemu/sysemu.h"
David 'Digit' Turner1c31e3e2013-12-14 20:07:17 +010027#include "ui/console.h"
David 'Digit' Turnerd4e803c2013-12-14 23:45:50 +010028#include "android/user-events.h"
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080029
30#include <SDL.h>
31#include <SDL_syswm.h>
32
33#include "math.h"
34
35#include "android/charmap.h"
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080036#include "android/utils/debug.h"
David 'Digit' Turner73dd5fc2014-02-04 12:50:55 +010037#include "android/config-file.h"
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080038#include "android/config/config.h"
39
David 'Digit' Turnerc6e0cae2014-03-07 23:08:30 +010040#include "android/kernel/kernel_utils.h"
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080041#include "android/user-config.h"
42#include "android/utils/bufprint.h"
David 'Digit' Turner26d41532011-03-01 15:03:07 +010043#include "android/utils/filelock.h"
David 'Digit' Turner0a879bf2011-05-12 18:45:18 +020044#include "android/utils/lineinput.h"
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080045#include "android/utils/path.h"
David 'Digit' Turner5ea91482014-02-13 18:02:56 +010046#include "android/utils/property_file.h"
David 'Digit' Turner622f1532011-02-01 17:48:37 +010047#include "android/utils/tempfile.h"
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080048
David 'Digit' Turnerf8456272011-02-02 12:34:14 +010049#include "android/main-common.h"
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080050#include "android/help.h"
David 'Digit' Turnerf0665422013-12-17 10:47:09 +010051#include "hw/android/goldfish/nand.h"
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080052
53#include "android/globals.h"
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080054
Xavier Ducrohetfc8ed802011-02-09 18:04:23 -080055#include "android/qemulator.h"
David 'Digit' Turner055ae422010-07-27 11:34:16 -070056#include "android/display.h"
Vladimir Chtchetkine01193622010-05-11 13:07:22 -070057
Ot ten Thijeae835ac2010-10-18 13:37:37 +010058#include "android/snapshot.h"
59
David 'Digit' Turnere3fdd072011-02-02 14:43:23 +010060#include "android/framebuffer.h"
David 'Digit' Turnerd413fa52013-12-14 23:35:20 +010061#include "android/iolooper.h"
David 'Digit' Turner055ae422010-07-27 11:34:16 -070062
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080063AndroidRotation android_framebuffer_rotation;
64
65#define STRINGIFY(x) _STRINGIFY(x)
66#define _STRINGIFY(x) #x
67
David 'Digit' Turnera383d022009-12-03 13:50:00 -080068#ifdef ANDROID_SDK_TOOLS_REVISION
69# define VERSION_STRING STRINGIFY(ANDROID_SDK_TOOLS_REVISION)".0"
70#else
71# define VERSION_STRING "standalone"
72#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080073
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080074#define D(...) do { if (VERBOSE_CHECK(init)) dprint(__VA_ARGS__); } while (0)
75
76extern int control_console_start( int port ); /* in control.c */
77
78extern int qemu_milli_needed;
79
80/* the default device DPI if none is specified by the skin
81 */
82#define DEFAULT_DEVICE_DPI 165
83
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080084int qemu_main(int argc, char **argv);
85
86/* this function dumps the QEMU help */
87extern void help( void );
88extern void emulator_help( void );
89
90#define VERBOSE_OPT(str,var) { str, &var }
91
92#define _VERBOSE_TAG(x,y) { #x, VERBOSE_##x, y },
93static const struct { const char* name; int flag; const char* text; }
94verbose_options[] = {
95 VERBOSE_TAG_LIST
96 { 0, 0, 0 }
97};
98
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080099void emulator_help( void )
100{
101 STRALLOC_DEFINE(out);
102 android_help_main(out);
103 printf( "%.*s", out->n, out->s );
104 stralloc_reset(out);
105 exit(1);
106}
107
David 'Digit' Turner40841b22011-03-01 14:04:00 +0100108/* TODO: Put in shared source file */
109static char*
110_getFullFilePath( const char* rootPath, const char* fileName )
111{
112 if (path_is_absolute(fileName)) {
113 return ASTRDUP(fileName);
114 } else {
115 char temp[PATH_MAX], *p=temp, *end=p+sizeof(temp);
116
117 p = bufprint(temp, end, "%s/%s", rootPath, fileName);
118 if (p >= end) {
119 return NULL;
120 }
121 return ASTRDUP(temp);
122 }
123}
124
125static uint64_t
126_adjustPartitionSize( const char* description,
127 uint64_t imageBytes,
128 uint64_t defaultBytes,
129 int inAndroidBuild )
130{
131 char temp[64];
132 unsigned imageMB;
133 unsigned defaultMB;
134
135 if (imageBytes <= defaultBytes)
136 return defaultBytes;
137
138 imageMB = convertBytesToMB(imageBytes);
139 defaultMB = convertBytesToMB(defaultBytes);
140
141 if (imageMB > defaultMB) {
142 snprintf(temp, sizeof temp, "(%d MB > %d MB)", imageMB, defaultMB);
143 } else {
Andrew Hsiehc7389bd2012-03-13 02:13:40 -0700144 snprintf(temp, sizeof temp, "(%" PRIu64 " bytes > %" PRIu64 " bytes)", imageBytes, defaultBytes);
David 'Digit' Turner40841b22011-03-01 14:04:00 +0100145 }
146
147 if (inAndroidBuild) {
148 dwarning("%s partition size adjusted to match image file %s\n", description, temp);
149 }
150
151 return convertMBToBytes(imageMB);
152}
153
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800154int main(int argc, char **argv)
155{
156 char tmp[MAX_PATH];
157 char* tmpend = tmp + sizeof(tmp);
158 char* args[128];
159 int n;
160 char* opt;
David 'Digit' Turner5e736932011-03-18 00:02:14 +0100161 /* The emulator always uses the first serial port for kernel messages
162 * and the second one for qemud. So start at the third if we need one
163 * for logcat or 'shell'
164 */
165 int serial = 2;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800166 int shell_serial = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800167
David 'Digit' Turner2ed457e2011-06-15 17:29:50 +0200168 int forceArmv7 = 0;
169
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800170 AndroidHwConfig* hw;
David 'Digit' Turnercd059b12009-08-28 19:36:27 +0200171 AvdInfo* avd;
David 'Digit' Turner74d7ace2011-02-02 13:21:03 +0100172 AConfig* skinConfig;
173 char* skinPath;
Vladimir Chtchetkine83ffd662011-02-11 12:40:59 -0800174 int inAndroidBuild;
Vladimir Chtchetkine88078b82012-04-19 12:24:38 -0700175 uint64_t defaultPartitionSize = convertMBToBytes(200);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800176
177 AndroidOptions opts[1];
Vladimir Chtchetkineb25bf2a2010-09-08 11:09:23 -0700178 /* net.shared_net_ip boot property value. */
179 char boot_prop_ip[64];
180 boot_prop_ip[0] = '\0';
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800181
182 args[0] = argv[0];
183
184 if ( android_parse_options( &argc, &argv, opts ) < 0 ) {
185 exit(1);
186 }
187
David 'Digit' Turnerbdb6f2d2011-02-23 15:57:25 +0100188#ifdef _WIN32
189 socket_init();
190#endif
191
192 handle_ui_options(opts);
193
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800194 while (argc-- > 1) {
195 opt = (++argv)[0];
196
197 if(!strcmp(opt, "-qemu")) {
198 argc--;
199 argv++;
200 break;
201 }
202
203 if (!strcmp(opt, "-help")) {
204 emulator_help();
205 }
206
207 if (!strncmp(opt, "-help-",6)) {
208 STRALLOC_DEFINE(out);
209 opt += 6;
210
211 if (!strcmp(opt, "all")) {
212 android_help_all(out);
213 }
214 else if (android_help_for_option(opt, out) == 0) {
215 /* ok */
216 }
217 else if (android_help_for_topic(opt, out) == 0) {
218 /* ok */
219 }
220 if (out->n > 0) {
221 printf("\n%.*s", out->n, out->s);
222 exit(0);
223 }
224
225 fprintf(stderr, "unknown option: -help-%s\n", opt);
226 fprintf(stderr, "please use -help for a list of valid topics\n");
227 exit(1);
228 }
229
230 if (opt[0] == '-') {
231 fprintf(stderr, "unknown option: %s\n", opt);
232 fprintf(stderr, "please use -help for a list of valid options\n");
233 exit(1);
234 }
235
236 fprintf(stderr, "invalid command-line parameter: %s.\n", opt);
237 fprintf(stderr, "Hint: use '@foo' to launch a virtual device named 'foo'.\n");
238 fprintf(stderr, "please use -help for more information\n");
239 exit(1);
240 }
241
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800242 if (opts->version) {
243 printf("Android emulator version %s\n"
David 'Digit' Turner5f64b872011-02-28 23:23:05 +0100244 "Copyright (C) 2006-2011 The Android Open Source Project and many others.\n"
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800245 "This program is a derivative of the QEMU CPU emulator (www.qemu.org).\n\n",
246#if defined ANDROID_BUILD_ID
247 VERSION_STRING " (build_id " STRINGIFY(ANDROID_BUILD_ID) ")" );
248#else
249 VERSION_STRING);
250#endif
251 printf(" This software is licensed under the terms of the GNU General Public\n"
252 " License version 2, as published by the Free Software Foundation, and\n"
253 " may be copied, distributed, and modified under those terms.\n\n"
254 " This program is distributed in the hope that it will be useful,\n"
255 " but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
256 " MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
257 " GNU General Public License for more details.\n\n");
258
259 exit(0);
260 }
261
David 'Digit' Turner5f64b872011-02-28 23:23:05 +0100262 if (opts->snapshot_list) {
David 'Digit' Turnerd80a7862011-05-05 10:24:43 +0200263 if (opts->snapstorage == NULL) {
264 /* Need to find the default snapstorage */
265 avd = createAVD(opts, &inAndroidBuild);
266 opts->snapstorage = avdInfo_getSnapStoragePath(avd);
267 if (opts->snapstorage != NULL) {
268 D("autoconfig: -snapstorage %s", opts->snapstorage);
269 } else {
270 if (inAndroidBuild) {
271 derror("You must use the -snapstorage <file> option to specify a snapshot storage file!\n");
272 } else {
273 derror("This AVD doesn't have snapshotting enabled!\n");
274 }
275 exit(1);
276 }
277 }
David 'Digit' Turner5f64b872011-02-28 23:23:05 +0100278 snapshot_print_and_exit(opts->snapstorage);
279 }
280
David 'Digit' Turner25eb6552011-02-25 15:07:11 +0100281 sanitizeOptions(opts);
282
David 'Digit' Turnerbdb6f2d2011-02-23 15:57:25 +0100283 /* Initialization of UI started with -attach-core should work differently
284 * than initialization of UI that starts the core. In particular....
285 */
286
287 /* -charmap is incompatible with -attach-core, because particular
288 * charmap gets set up in the running core. */
David 'Digit' Turner74d7ace2011-02-02 13:21:03 +0100289 if (android_charmap_setup(opts->charmap)) {
290 exit(1);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800291 }
292
Vladimir Chtchetkine83ffd662011-02-11 12:40:59 -0800293 /* Parses options and builds an appropriate AVD. */
David 'Digit' Turner462564f2011-02-23 13:32:37 +0100294 avd = android_avdInfo = createAVD(opts, &inAndroidBuild);
David 'Digit' Turnercd059b12009-08-28 19:36:27 +0200295
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800296 /* get the skin from the virtual device configuration */
David 'Digit' Turner25eb6552011-02-25 15:07:11 +0100297 if (opts->skindir != NULL) {
298 if (opts->skin == NULL) {
299 /* NOTE: Normally handled by sanitizeOptions(), just be safe */
300 derror("The -skindir <path> option requires a -skin <name> option");
301 exit(2);
302 }
303 } else {
304 char* skinName;
305 char* skinDir;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800306
David 'Digit' Turner25eb6552011-02-25 15:07:11 +0100307 avdInfo_getSkinInfo(avd, &skinName, &skinDir);
308
309 if (opts->skin == NULL) {
310 opts->skin = skinName;
311 D("autoconfig: -skin %s", opts->skin);
312 } else {
313 AFREE(skinName);
314 }
315
316 opts->skindir = skinDir;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800317 D("autoconfig: -skindir %s", opts->skindir);
Xavier Ducrohet689d1142012-04-19 12:54:08 -0700318
319 /* update the avd hw config from this new skin */
320 avdInfo_getSkinHardwareIni(avd, opts->skin, opts->skindir);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800321 }
322
Siva Velusamyd8999182012-10-08 18:02:30 -0700323 if (opts->dynamic_skin == 0) {
324 opts->dynamic_skin = avdInfo_shouldUseDynamicSkin(avd);
325 }
326
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800327 /* Read hardware configuration */
328 hw = android_hw;
David 'Digit' Turnerb64325d2011-03-22 16:07:01 +0100329 if (avdInfo_initHwConfig(avd, hw) < 0) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800330 derror("could not read hardware configuration ?");
331 exit(1);
332 }
333
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800334 if (opts->keyset) {
335 parse_keyset(opts->keyset, opts);
336 if (!android_keyset) {
337 fprintf(stderr,
338 "emulator: WARNING: could not find keyset file named '%s',"
339 " using defaults instead\n",
340 opts->keyset);
341 }
342 }
343 if (!android_keyset) {
344 parse_keyset("default", opts);
345 if (!android_keyset) {
346 android_keyset = skin_keyset_new_from_text( skin_keyset_get_default() );
347 if (!android_keyset) {
348 fprintf(stderr, "PANIC: default keyset file is corrupted !!\n" );
349 fprintf(stderr, "PANIC: please update the code in android/skin/keyset.c\n" );
350 exit(1);
351 }
352 if (!opts->keyset)
353 write_default_keyset();
354 }
355 }
356
Dries Harnie40beab42010-05-15 17:04:47 +0200357 if (opts->shared_net_id) {
358 char* end;
359 long shared_net_id = strtol(opts->shared_net_id, &end, 0);
360 if (end == NULL || *end || shared_net_id < 1 || shared_net_id > 255) {
361 fprintf(stderr, "option -shared-net-id must be an integer between 1 and 255\n");
362 exit(1);
363 }
Vladimir Chtchetkineb25bf2a2010-09-08 11:09:23 -0700364 snprintf(boot_prop_ip, sizeof(boot_prop_ip),
365 "net.shared_net_ip=10.1.2.%ld", shared_net_id);
Dries Harnie40beab42010-05-15 17:04:47 +0200366 }
367
368
David 'Digit' Turner755811e2011-02-07 13:38:25 +0100369 user_config_init();
David 'Digit' Turner2507cab2011-02-10 16:29:17 +0100370 parse_skin_files(opts->skindir, opts->skin, opts, hw,
David 'Digit' Turner74d7ace2011-02-02 13:21:03 +0100371 &skinConfig, &skinPath);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800372
David 'Digit' Turner092361e2011-03-01 13:14:18 +0100373 if (!opts->netspeed && skin_network_speed) {
374 D("skin network speed: '%s'", skin_network_speed);
375 if (strcmp(skin_network_speed, NETWORK_SPEED_DEFAULT) != 0) {
376 opts->netspeed = (char*)skin_network_speed;
377 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800378 }
David 'Digit' Turner092361e2011-03-01 13:14:18 +0100379 if (!opts->netdelay && skin_network_delay) {
380 D("skin network delay: '%s'", skin_network_delay);
381 if (strcmp(skin_network_delay, NETWORK_DELAY_DEFAULT) != 0) {
382 opts->netdelay = (char*)skin_network_delay;
383 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800384 }
385
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800386 if (opts->trace) {
David 'Digit' Turnercd059b12009-08-28 19:36:27 +0200387 char* tracePath = avdInfo_getTracePath(avd, opts->trace);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800388 int ret;
389
390 if (tracePath == NULL) {
391 derror( "bad -trace parameter" );
392 exit(1);
393 }
394 ret = path_mkdir_if_needed( tracePath, 0755 );
395 if (ret < 0) {
396 fprintf(stderr, "could not create directory '%s'\n", tmp);
397 exit(2);
398 }
399 opts->trace = tracePath;
400 }
401
Vladimir Chtchetkine33f89d02011-09-28 09:19:09 -0700402 /* Update CPU architecture for HW configs created from build dir. */
403 if (inAndroidBuild) {
404#if defined(TARGET_ARM)
405 free(android_hw->hw_cpu_arch);
406 android_hw->hw_cpu_arch = ASTRDUP("arm");
407#elif defined(TARGET_I386)
408 free(android_hw->hw_cpu_arch);
409 android_hw->hw_cpu_arch = ASTRDUP("x86");
Bhanu Chetlapalli741dc132012-05-08 17:16:03 -0700410#elif defined(TARGET_MIPS)
411 free(android_hw->hw_cpu_arch);
412 android_hw->hw_cpu_arch = ASTRDUP("mips");
Vladimir Chtchetkine33f89d02011-09-28 09:19:09 -0700413#endif
414 }
415
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800416 n = 1;
417 /* generate arguments for the underlying qemu main() */
David 'Digit' Turner238b4b02009-09-20 13:10:19 -0700418 {
David 'Digit' Turner0b019492011-03-01 14:02:42 +0100419 char* kernelFile = opts->kernel;
420 int kernelFileLen;
David 'Digit' Turner238b4b02009-09-20 13:10:19 -0700421
David 'Digit' Turner0b019492011-03-01 14:02:42 +0100422 if (kernelFile == NULL) {
423 kernelFile = avdInfo_getKernelPath(avd);
424 if (kernelFile == NULL) {
425 derror( "This AVD's configuration is missing a kernel file!!" );
426 exit(2);
427 }
428 D("autoconfig: -kernel %s", kernelFile);
429 }
430 if (!path_exists(kernelFile)) {
431 derror( "Invalid or missing kernel image file: %s", kernelFile );
432 exit(2);
433 }
434
435 hw->kernel_path = kernelFile;
David 'Digit' Turner238b4b02009-09-20 13:10:19 -0700436
437 /* If the kernel image name ends in "-armv7", then change the cpu
438 * type automatically. This is a poor man's approach to configuration
439 * management, but should allow us to get past building ARMv7
440 * system images with dex preopt pass without introducing too many
441 * changes to the emulator sources.
442 *
443 * XXX:
444 * A 'proper' change would require adding some sort of hardware-property
445 * to each AVD config file, then automatically determine its value for
446 * full Android builds (depending on some environment variable), plus
447 * some build system changes. I prefer not to do that for now for reasons
448 * of simplicity.
449 */
David 'Digit' Turner0b019492011-03-01 14:02:42 +0100450 kernelFileLen = strlen(kernelFile);
David 'Digit' Turner238b4b02009-09-20 13:10:19 -0700451 if (kernelFileLen > 6 && !memcmp(kernelFile + kernelFileLen - 6, "-armv7", 6)) {
David 'Digit' Turner2ed457e2011-06-15 17:29:50 +0200452 forceArmv7 = 1;
David 'Digit' Turner238b4b02009-09-20 13:10:19 -0700453 }
454 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800455
David 'Digit' Turnerc6e0cae2014-03-07 23:08:30 +0100456 // Auto-detect kernel device naming scheme if needed.
457 if (androidHwConfig_getKernelDeviceNaming(hw) < 0) {
458 KernelType kernelType;
459 const char* newDeviceNaming = "no";
460 if (!android_pathProbeKernelType(hw->kernel_path, &kernelType)) {
461 D("WARNING: Could not determine kernel device naming scheme. Assuming legacy\n"
462 "If this AVD doesn't boot, and uses a recent kernel (3.10 or above) try setting\n"
463 "'kernel.newDeviceNaming' to 'yes' in its configuration.\n");
464 } else if (kernelType == KERNEL_TYPE_3_10_OR_ABOVE) {
465 D("Auto-detect: Kernel image requires new device naming scheme.");
466 newDeviceNaming = "yes";
467 } else {
468 D("Auto-detect: Kernel image requires legacy device naming scheme.");
469 }
470 AFREE(hw->kernel_newDeviceNaming);
471 hw->kernel_newDeviceNaming = ASTRDUP(newDeviceNaming);
472 }
473
Vladimir Chtchetkineb25bf2a2010-09-08 11:09:23 -0700474 if (boot_prop_ip[0]) {
475 args[n++] = "-boot-property";
476 args[n++] = boot_prop_ip;
477 }
478
Vladimir Chtchetkine318f17a2010-08-27 09:09:45 -0700479 if (opts->tcpdump) {
480 args[n++] = "-tcpdump";
481 args[n++] = opts->tcpdump;
482 }
483
Vladimir Chtchetkinee1316862010-08-26 09:03:54 -0700484#ifdef CONFIG_NAND_LIMITS
485 if (opts->nand_limits) {
486 args[n++] = "-nand-limits";
487 args[n++] = opts->nand_limits;
488 }
489#endif
490
David 'Digit' Turner74d7ace2011-02-02 13:21:03 +0100491 if (opts->timezone) {
492 args[n++] = "-timezone";
493 args[n++] = opts->timezone;
494 }
495
Vladimir Chtchetkinee1316862010-08-26 09:03:54 -0700496 if (opts->netspeed) {
497 args[n++] = "-netspeed";
498 args[n++] = opts->netspeed;
499 }
500 if (opts->netdelay) {
501 args[n++] = "-netdelay";
502 args[n++] = opts->netdelay;
503 }
504 if (opts->netfast) {
505 args[n++] = "-netfast";
506 }
507
Vladimir Chtchetkineb2438402010-08-24 08:55:33 -0700508 if (opts->audio) {
509 args[n++] = "-audio";
510 args[n++] = opts->audio;
511 }
512
Vladimir Chtchetkineb2438402010-08-24 08:55:33 -0700513 if (opts->cpu_delay) {
514 args[n++] = "-cpu-delay";
515 args[n++] = opts->cpu_delay;
516 }
517
Vladimir Chtchetkine7fbf4972010-08-11 15:30:32 -0700518 if (opts->dns_server) {
519 args[n++] = "-dns-server";
520 args[n++] = opts->dns_server;
521 }
522
David 'Digit' Turner9ff69722011-09-13 12:32:52 +0200523 /* opts->ramdisk is never NULL (see createAVD) here */
524 if (opts->ramdisk) {
525 AFREE(hw->disk_ramdisk_path);
526 hw->disk_ramdisk_path = ASTRDUP(opts->ramdisk);
527 }
528 else if (!hw->disk_ramdisk_path[0]) {
529 hw->disk_ramdisk_path = avdInfo_getRamdiskPath(avd);
530 D("autoconfig: -ramdisk %s", hw->disk_ramdisk_path);
531 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800532
David 'Digit' Turner40841b22011-03-01 14:04:00 +0100533 /* -partition-size is used to specify the max size of both the system
534 * and data partition sizes.
535 */
536 if (opts->partition_size) {
537 char* end;
538 long sizeMB = strtol(opts->partition_size, &end, 0);
539 long minSizeMB = 10;
540 long maxSizeMB = LONG_MAX / ONE_MB;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800541
David 'Digit' Turner40841b22011-03-01 14:04:00 +0100542 if (sizeMB < 0 || *end != 0) {
543 derror( "-partition-size must be followed by a positive integer" );
544 exit(1);
545 }
546 if (sizeMB < minSizeMB || sizeMB > maxSizeMB) {
547 derror( "partition-size (%d) must be between %dMB and %dMB",
548 sizeMB, minSizeMB, maxSizeMB );
549 exit(1);
550 }
551 defaultPartitionSize = (uint64_t) sizeMB * ONE_MB;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800552 }
553
David 'Digit' Turner40841b22011-03-01 14:04:00 +0100554
555 /** SYSTEM PARTITION **/
556
557 if (opts->sysdir == NULL) {
558 if (avdInfo_inAndroidBuild(avd)) {
559 opts->sysdir = ASTRDUP(avdInfo_getContentPath(avd));
560 D("autoconfig: -sysdir %s", opts->sysdir);
561 }
562 }
563
564 if (opts->sysdir != NULL) {
565 if (!path_exists(opts->sysdir)) {
566 derror("Directory does not exist: %s", opts->sysdir);
567 exit(1);
568 }
569 }
570
571 {
572 char* rwImage = NULL;
573 char* initImage = NULL;
574
575 do {
576 if (opts->system == NULL) {
577 /* If -system is not used, try to find a runtime system image
578 * (i.e. system-qemu.img) in the content directory.
579 */
580 rwImage = avdInfo_getSystemImagePath(avd);
581 if (rwImage != NULL) {
582 break;
583 }
584 /* Otherwise, try to find the initial system image */
585 initImage = avdInfo_getSystemInitImagePath(avd);
586 if (initImage == NULL) {
587 derror("No initial system image for this configuration!");
588 exit(1);
589 }
590 break;
591 }
592
593 /* If -system <name> is used, use it to find the initial image */
David 'Digit' Turnerea283772011-07-07 04:40:27 +0200594 if (opts->sysdir != NULL && !path_exists(opts->system)) {
David 'Digit' Turner40841b22011-03-01 14:04:00 +0100595 initImage = _getFullFilePath(opts->sysdir, opts->system);
596 } else {
597 initImage = ASTRDUP(opts->system);
598 }
599 if (!path_exists(initImage)) {
600 derror("System image file doesn't exist: %s", initImage);
601 exit(1);
602 }
603
604 } while (0);
605
606 if (rwImage != NULL) {
607 /* Use the read/write image file directly */
608 hw->disk_systemPartition_path = rwImage;
609 hw->disk_systemPartition_initPath = NULL;
610 D("Using direct system image: %s", rwImage);
611 } else if (initImage != NULL) {
612 hw->disk_systemPartition_path = NULL;
613 hw->disk_systemPartition_initPath = initImage;
614 D("Using initial system image: %s", initImage);
615 }
616
617 /* Check the size of the system partition image.
618 * If we have an AVD, it must be smaller than
619 * the disk.systemPartition.size hardware property.
620 *
621 * Otherwise, we need to adjust the systemPartitionSize
622 * automatically, and print a warning.
623 *
624 */
625 const char* systemImage = hw->disk_systemPartition_path;
626 uint64_t systemBytes;
627
628 if (systemImage == NULL)
629 systemImage = hw->disk_systemPartition_initPath;
630
631 if (path_get_size(systemImage, &systemBytes) < 0) {
632 derror("Missing system image: %s", systemImage);
633 exit(1);
634 }
635
636 hw->disk_systemPartition_size =
637 _adjustPartitionSize("system", systemBytes, defaultPartitionSize,
638 avdInfo_inAndroidBuild(avd));
639 }
640
641 /** DATA PARTITION **/
642
David 'Digit' Turnerfd59c332011-03-01 00:48:52 +0100643 if (opts->datadir) {
644 if (!path_exists(opts->datadir)) {
645 derror("Invalid -datadir directory: %s", opts->datadir);
646 }
647 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800648
David 'Digit' Turnerfd59c332011-03-01 00:48:52 +0100649 {
650 char* dataImage = NULL;
651 char* initImage = NULL;
652
653 do {
654 if (!opts->data) {
655 dataImage = avdInfo_getDataImagePath(avd);
656 if (dataImage != NULL) {
657 D("autoconfig: -data %s", dataImage);
658 break;
659 }
660 dataImage = avdInfo_getDefaultDataImagePath(avd);
661 if (dataImage == NULL) {
662 derror("No data image path for this configuration!");
663 exit (1);
664 }
665 opts->wipe_data = 1;
666 break;
667 }
668
669 if (opts->datadir) {
670 dataImage = _getFullFilePath(opts->datadir, opts->data);
671 } else {
672 dataImage = ASTRDUP(opts->data);
673 }
674 } while (0);
675
676 if (opts->initdata != NULL) {
677 initImage = ASTRDUP(opts->initdata);
678 if (!path_exists(initImage)) {
679 derror("Invalid initial data image path: %s", initImage);
680 exit(1);
681 }
682 } else {
683 initImage = avdInfo_getDataInitImagePath(avd);
684 D("autoconfig: -initdata %s", initImage);
685 }
686
687 hw->disk_dataPartition_path = dataImage;
688 if (opts->wipe_data) {
689 hw->disk_dataPartition_initPath = initImage;
690 } else {
691 hw->disk_dataPartition_initPath = NULL;
692 }
693
Maciek Molerusf7584112011-06-15 22:26:35 +0200694 uint64_t defaultBytes =
695 hw->disk_dataPartition_size == 0 ?
696 defaultPartitionSize :
Vladimir Chtchetkined4f5a3a2012-03-08 14:20:20 -0800697 hw->disk_dataPartition_size;
David 'Digit' Turnerfd59c332011-03-01 00:48:52 +0100698 uint64_t dataBytes;
699 const char* dataPath = hw->disk_dataPartition_initPath;
700
701 if (dataPath == NULL)
702 dataPath = hw->disk_dataPartition_path;
703
704 path_get_size(dataPath, &dataBytes);
705
706 hw->disk_dataPartition_size =
707 _adjustPartitionSize("data", dataBytes, defaultBytes,
708 avdInfo_inAndroidBuild(avd));
709 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800710
David 'Digit' Turnerc480cca2011-02-25 16:43:34 +0100711 /** CACHE PARTITION **/
712
713 if (opts->no_cache) {
714 /* No cache partition at all */
715 hw->disk_cachePartition = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800716 }
David 'Digit' Turnerc480cca2011-02-25 16:43:34 +0100717 else if (!hw->disk_cachePartition) {
718 if (opts->cache) {
719 dwarning( "Emulated hardware doesn't support a cache partition. -cache option ignored!" );
720 opts->cache = NULL;
721 }
722 }
723 else
724 {
725 if (!opts->cache) {
726 /* Find the current cache partition file */
727 opts->cache = avdInfo_getCachePath(avd);
728 if (opts->cache == NULL) {
729 /* The file does not exists, we will force its creation
730 * if we are not in the Android build system. Otherwise,
731 * a temporary file will be used.
732 */
733 if (!avdInfo_inAndroidBuild(avd)) {
734 opts->cache = avdInfo_getDefaultCachePath(avd);
735 }
736 }
David 'Digit' Turner48a3c662011-03-01 14:03:20 +0100737 if (opts->cache) {
738 D("autoconfig: -cache %s", opts->cache);
739 }
David 'Digit' Turnerc480cca2011-02-25 16:43:34 +0100740 }
741
742 if (opts->cache) {
743 hw->disk_cachePartition_path = ASTRDUP(opts->cache);
744 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800745 }
746
Vladimir Chtchetkine6f50aa32012-04-26 08:20:18 -0700747 if (hw->disk_cachePartition_path && opts->cache_size) {
748 /* Set cache partition size per user options. */
749 char* end;
750 long sizeMB = strtol(opts->cache_size, &end, 0);
751
752 if (sizeMB < 0 || *end != 0) {
753 derror( "-cache-size must be followed by a positive integer" );
754 exit(1);
755 }
756 hw->disk_cachePartition_size = (uint64_t) sizeMB * ONE_MB;
757 }
758
David 'Digit' Turnerc480cca2011-02-25 16:43:34 +0100759 /** SD CARD PARTITION */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800760
David 'Digit' Turner48a3c662011-03-01 14:03:20 +0100761 if (!hw->hw_sdCard) {
762 /* No SD Card emulation, so -sdcard will be ignored */
763 if (opts->sdcard) {
764 dwarning( "Emulated hardware doesn't support SD Cards. -sdcard option ignored." );
765 opts->sdcard = NULL;
766 }
767 } else {
768 /* Auto-configure -sdcard if it is not available */
769 if (!opts->sdcard) {
770 do {
771 /* If -datadir <path> is used, look for a sdcard.img file here */
772 if (opts->datadir) {
773 bufprint(tmp, tmpend, "%s/%s", opts->datadir, "system.img");
774 if (path_exists(tmp)) {
775 opts->sdcard = strdup(tmp);
776 break;
777 }
778 }
779
780 /* Otherwise, look at the AVD's content */
781 opts->sdcard = avdInfo_getSdCardPath(avd);
782 if (opts->sdcard != NULL) {
783 break;
784 }
785
786 /* Nothing */
787 } while (0);
788
789 if (opts->sdcard) {
790 D("autoconfig: -sdcard %s", opts->sdcard);
791 }
792 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800793 }
794
795 if(opts->sdcard) {
796 uint64_t size;
797 if (path_get_size(opts->sdcard, &size) == 0) {
798 /* see if we have an sdcard image. get its size if it exists */
David 'Digit' Turner8b657e52009-12-01 13:38:21 -0800799 /* due to what looks like limitations of the MMC protocol, one has
800 * to use an SD Card image that is equal or larger than 9 MB
801 */
802 if (size < 9*1024*1024ULL) {
803 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 -0800804 } else {
David 'Digit' Turner48a3c662011-03-01 14:03:20 +0100805 hw->hw_sdCard_path = ASTRDUP(opts->sdcard);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800806 }
807 } else {
David 'Digit' Turner48a3c662011-03-01 14:03:20 +0100808 dwarning("no SD Card image at '%s'", opts->sdcard);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800809 }
810 }
811
David 'Digit' Turner48a3c662011-03-01 14:03:20 +0100812
813 /** SNAPSHOT STORAGE HANDLING */
814
David 'Digit' Turner5f64b872011-02-28 23:23:05 +0100815 /* Determine snapstorage path. -no-snapstorage disables all snapshotting
816 * support. This means you can't resume a snapshot at load, save it at
817 * exit, or even load/save them dynamically at runtime with the console.
818 */
819 if (opts->no_snapstorage) {
820
821 if (opts->snapshot) {
822 dwarning("ignoring -snapshot option due to the use of -no-snapstorage");
823 opts->snapshot = NULL;
824 }
825
826 if (opts->snapstorage) {
827 dwarning("ignoring -snapstorage option due to the use of -no-snapstorage");
828 opts->snapstorage = NULL;
829 }
830 }
831 else
832 {
Vladimir Chtchetkine873c3cb2012-03-14 12:46:51 -0700833 if (!opts->snapstorage && avdInfo_getSnapshotPresent(avd)) {
David 'Digit' Turner5f64b872011-02-28 23:23:05 +0100834 opts->snapstorage = avdInfo_getSnapStoragePath(avd);
835 if (opts->snapstorage != NULL) {
836 D("autoconfig: -snapstorage %s", opts->snapstorage);
Ot ten Thije353b3b12010-10-05 17:53:30 +0100837 }
838 }
839
David 'Digit' Turner5f64b872011-02-28 23:23:05 +0100840 if (opts->snapstorage && !path_exists(opts->snapstorage)) {
841 D("no image at '%s', state snapshots disabled", opts->snapstorage);
842 opts->snapstorage = NULL;
Ot ten Thije353b3b12010-10-05 17:53:30 +0100843 }
David 'Digit' Turner5f64b872011-02-28 23:23:05 +0100844 }
845
846 /* If we have a valid snapshot storage path */
847
848 if (opts->snapstorage) {
849
850 hw->disk_snapStorage_path = ASTRDUP(opts->snapstorage);
851
852 /* -no-snapshot is equivalent to using both -no-snapshot-load
853 * and -no-snapshot-save. You can still load/save snapshots dynamically
854 * from the console though.
855 */
856 if (opts->no_snapshot) {
857
858 opts->no_snapshot_load = 1;
859 opts->no_snapshot_save = 1;
860
861 if (opts->snapshot) {
862 dwarning("ignoring -snapshot option due to the use of -no-snapshot.");
863 }
864 }
865
866 if (!opts->no_snapshot_load || !opts->no_snapshot_save) {
867 if (opts->snapshot == NULL) {
868 opts->snapshot = "default-boot";
869 D("autoconfig: -snapshot %s", opts->snapshot);
870 }
871 }
872
873 /* We still use QEMU command-line options for the following since
874 * they can change from one invokation to the next and don't really
875 * correspond to the hardware configuration itself.
876 */
877 if (!opts->no_snapshot_load) {
878 args[n++] = "-loadvm";
879 args[n++] = ASTRDUP(opts->snapshot);
880 }
881
882 if (!opts->no_snapshot_save) {
883 args[n++] = "-savevm-on-exit";
884 args[n++] = ASTRDUP(opts->snapshot);
885 }
886
Tim Baverstock622b8f42010-12-07 11:36:59 +0000887 if (opts->no_snapshot_update_time) {
David 'Digit' Turnerbdb6f2d2011-02-23 15:57:25 +0100888 args[n++] = "-snapshot-no-time-update";
Tim Baverstock622b8f42010-12-07 11:36:59 +0000889 }
Ot ten Thijeae835ac2010-10-18 13:37:37 +0100890 }
Ot ten Thije353b3b12010-10-05 17:53:30 +0100891
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800892 if (!opts->logcat || opts->logcat[0] == 0) {
893 opts->logcat = getenv("ANDROID_LOG_TAGS");
894 if (opts->logcat && opts->logcat[0] == 0)
895 opts->logcat = NULL;
896 }
897
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800898 /* we always send the kernel messages from ttyS0 to android_kmsg */
David 'Digit' Turner062dd6a2011-03-01 14:50:07 +0100899 if (opts->show_kernel) {
900 args[n++] = "-show-kernel";
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800901 }
902
903 /* XXXX: TODO: implement -shell and -logcat through qemud instead */
904 if (!opts->shell_serial) {
905#ifdef _WIN32
906 opts->shell_serial = "con:";
907#else
908 opts->shell_serial = "stdio";
909#endif
910 }
911 else
912 opts->shell = 1;
913
914 if (opts->shell || opts->logcat) {
915 args[n++] = "-serial";
916 args[n++] = opts->shell_serial;
917 shell_serial = serial++;
918 }
919
David 'Digit' Turner062dd6a2011-03-01 14:50:07 +0100920 if (opts->radio) {
921 args[n++] = "-radio";
922 args[n++] = opts->radio;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800923 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800924
David 'Digit' Turner062dd6a2011-03-01 14:50:07 +0100925 if (opts->gps) {
926 args[n++] = "-gps";
927 args[n++] = opts->gps;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800928 }
929
Nick Kralevich185231a2013-10-07 13:54:31 -0700930 if (opts->selinux) {
931 if ((strcmp(opts->selinux, "permissive") != 0)
932 && (strcmp(opts->selinux, "disabled") != 0)) {
933 derror("-selinux must be \"disabled\" or \"permissive\"");
934 exit(1);
935 }
936 }
937
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800938 if (opts->memory) {
939 char* end;
940 long ramSize = strtol(opts->memory, &end, 0);
941 if (ramSize < 0 || *end != 0) {
942 derror( "-memory must be followed by a positive integer" );
943 exit(1);
944 }
945 if (ramSize < 32 || ramSize > 4096) {
946 derror( "physical memory size must be between 32 and 4096 MB" );
947 exit(1);
948 }
David 'Digit' Turner5377c5b2011-02-10 16:52:19 +0100949 hw->hw_ramSize = ramSize;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800950 }
951 if (!opts->memory) {
David 'Digit' Turner3bbc9192011-01-19 22:18:02 +0100952 int ramSize = hw->hw_ramSize;
953 if (ramSize <= 0) {
954 /* Compute the default RAM size based on the size of screen.
955 * This is only used when the skin doesn't provide the ram
956 * size through its hardware.ini (i.e. legacy ones) or when
957 * in the full Android build system.
958 */
David 'Digit' Turner5377c5b2011-02-10 16:52:19 +0100959 int64_t pixels = hw->hw_lcd_width * hw->hw_lcd_height;
David 'Digit' Turner3bbc9192011-01-19 22:18:02 +0100960 /* The following thresholds are a bit liberal, but we
961 * essentially want to ensure the following mappings:
962 *
963 * 320x480 -> 96
964 * 800x600 -> 128
965 * 1024x768 -> 256
966 *
967 * These are just simple heuristics, they could change in
968 * the future.
969 */
970 if (pixels <= 250000)
971 ramSize = 96;
972 else if (pixels <= 500000)
973 ramSize = 128;
974 else
975 ramSize = 256;
976 }
David 'Digit' Turner5377c5b2011-02-10 16:52:19 +0100977 hw->hw_ramSize = ramSize;
978 }
979
980 D("Physical RAM size: %dMB\n", hw->hw_ramSize);
981
982 if (hw->vm_heapSize == 0) {
983 /* Compute the default heap size based on the RAM size.
984 * Essentially, we want to ensure the following liberal mappings:
985 *
986 * 96MB RAM -> 16MB heap
987 * 128MB RAM -> 24MB heap
988 * 256MB RAM -> 48MB heap
989 */
990 int ramSize = hw->hw_ramSize;
991 int heapSize;
992
993 if (ramSize < 100)
994 heapSize = 16;
995 else if (ramSize < 192)
996 heapSize = 24;
997 else
998 heapSize = 48;
999
1000 hw->vm_heapSize = heapSize;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001001 }
1002
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001003 if (opts->trace) {
1004 args[n++] = "-trace";
1005 args[n++] = opts->trace;
1006 args[n++] = "-tracing";
1007 args[n++] = "off";
1008 }
1009
David 'Digit' Turnerc0052462014-02-25 18:39:29 +01001010 /* Pass boot properties to the core. First, those from boot.prop,
David 'Digit' Turner5ea91482014-02-13 18:02:56 +01001011 * then those from the command-line */
1012 const FileData* bootProperties = avdInfo_getBootProperties(avd);
1013 if (!fileData_isEmpty(bootProperties)) {
1014 PropertyFileIterator iter[1];
1015 propertyFileIterator_init(iter,
1016 bootProperties->data,
1017 bootProperties->size);
1018 while (propertyFileIterator_next(iter)) {
1019 char temp[MAX_PROPERTY_NAME_LEN + MAX_PROPERTY_VALUE_LEN + 2];
1020 snprintf(temp, sizeof temp, "%s=%s", iter->name, iter->value);
1021 args[n++] = "-boot-property";
1022 args[n++] = ASTRDUP(temp);
1023 }
1024 }
David 'Digit' Turnerc0052462014-02-25 18:39:29 +01001025
Vladimir Chtchetkineb25bf2a2010-09-08 11:09:23 -07001026 if (opts->prop != NULL) {
1027 ParamList* pl = opts->prop;
1028 for ( ; pl != NULL; pl = pl->next ) {
1029 args[n++] = "-boot-property";
1030 args[n++] = pl->param;
1031 }
1032 }
1033
David 'Digit' Turner318e4f22009-05-25 18:01:03 +02001034 /* Setup the kernel init options
1035 */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001036 {
1037 static char params[1024];
1038 char *p = params, *end = p + sizeof(params);
1039
David 'Digit' Turner062dd6a2011-03-01 14:50:07 +01001040 /* Don't worry about having a leading space here, this is handled
1041 * by the core later. */
1042
Jun Nakajima334ab472011-02-02 23:49:59 -08001043#ifdef TARGET_I386
1044 p = bufprint(p, end, " androidboot.hardware=goldfish");
Jun Nakajimabac9add2011-02-08 22:10:52 -08001045 p = bufprint(p, end, " clocksource=pit");
Jun Nakajima334ab472011-02-02 23:49:59 -08001046#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001047
1048 if (opts->shell || opts->logcat) {
David 'Digit' Turnerc6e0cae2014-03-07 23:08:30 +01001049 p = bufprint(p, end, " androidboot.console=%s%d",
1050 androidHwConfig_getKernelSerialPrefix(android_hw),
1051 shell_serial );
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001052 }
1053
1054 if (opts->trace) {
1055 p = bufprint(p, end, " android.tracing=1");
1056 }
1057
1058 if (!opts->no_jni) {
1059 p = bufprint(p, end, " android.checkjni=1");
1060 }
1061
1062 if (opts->no_boot_anim) {
1063 p = bufprint( p, end, " android.bootanim=0" );
1064 }
1065
1066 if (opts->logcat) {
1067 char* q = bufprint(p, end, " androidboot.logcat=%s", opts->logcat);
1068
1069 if (q < end) {
1070 /* replace any space by a comma ! */
1071 {
1072 int nn;
1073 for (nn = 1; p[nn] != 0; nn++)
1074 if (p[nn] == ' ' || p[nn] == '\t')
1075 p[nn] = ',';
1076 p += nn;
1077 }
1078 }
1079 p = q;
1080 }
1081
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001082 if (opts->bootchart) {
1083 p = bufprint(p, end, " androidboot.bootchart=%s", opts->bootchart);
1084 }
1085
Nick Kralevich185231a2013-10-07 13:54:31 -07001086 if (opts->selinux) {
1087 p = bufprint(p, end, " androidboot.selinux=%s", opts->selinux);
1088 }
1089
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001090 if (p >= end) {
1091 fprintf(stderr, "### ERROR: kernel parameters too long\n");
1092 exit(1);
1093 }
1094
David 'Digit' Turner0b019492011-03-01 14:02:42 +01001095 hw->kernel_parameters = strdup(params);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001096 }
1097
Vladimir Chtchetkined81e6d12010-06-15 16:46:32 -07001098 if (opts->ports) {
1099 args[n++] = "-android-ports";
1100 args[n++] = opts->ports;
1101 }
1102
1103 if (opts->port) {
1104 args[n++] = "-android-port";
1105 args[n++] = opts->port;
1106 }
1107
1108 if (opts->report_console) {
1109 args[n++] = "-android-report-console";
1110 args[n++] = opts->report_console;
1111 }
1112
1113 if (opts->http_proxy) {
1114 args[n++] = "-http-proxy";
1115 args[n++] = opts->http_proxy;
1116 }
1117
Xavier Ducrohet72d56112011-08-11 18:47:27 -07001118 if (!opts->charmap) {
1119 /* Try to find a valid charmap name */
1120 char* charmap = avdInfo_getCharmapFile(avd, hw->hw_keyboard_charmap);
1121 if (charmap != NULL) {
1122 D("autoconfig: -charmap %s", charmap);
1123 opts->charmap = charmap;
1124 }
1125 }
1126
Vladimir Chtchetkine43552dc2010-07-22 11:23:19 -07001127 if (opts->charmap) {
Xavier Ducrohet72d56112011-08-11 18:47:27 -07001128 char charmap_name[AKEYCHARMAP_NAME_SIZE];
1129
1130 if (!path_exists(opts->charmap)) {
1131 derror("Charmap file does not exist: %s", opts->charmap);
1132 exit(1);
1133 }
1134 /* We need to store the charmap name in the hardware configuration.
1135 * However, the charmap file itself is only used by the UI component
1136 * and doesn't need to be set to the emulation engine.
1137 */
1138 kcm_extract_charmap_name(opts->charmap, charmap_name,
1139 sizeof(charmap_name));
1140 AFREE(hw->hw_keyboard_charmap);
1141 hw->hw_keyboard_charmap = ASTRDUP(charmap_name);
Vladimir Chtchetkine43552dc2010-07-22 11:23:19 -07001142 }
1143
Vladimir Chtchetkineb5365f32010-08-09 13:33:57 -07001144 if (opts->memcheck) {
1145 args[n++] = "-android-memcheck";
1146 args[n++] = opts->memcheck;
1147 }
1148
David Turner9da935d2011-09-12 21:27:56 +02001149 if (opts->gpu) {
1150 const char* gpu = opts->gpu;
Vladimir Chtchetkineae0d8132011-09-13 10:48:02 -07001151 if (!strcmp(gpu,"on") || !strcmp(gpu,"enable")) {
David Turner9da935d2011-09-12 21:27:56 +02001152 hw->hw_gpu_enabled = 1;
Vladimir Chtchetkineae0d8132011-09-13 10:48:02 -07001153 } else if (!strcmp(gpu,"off") || !strcmp(gpu,"disable")) {
David Turner9da935d2011-09-12 21:27:56 +02001154 hw->hw_gpu_enabled = 0;
1155 } else if (!strcmp(gpu,"auto")) {
1156 /* Nothing to do */
1157 } else {
1158 derror("Invalid value for -gpu <mode> parameter: %s\n", gpu);
1159 derror("Valid values are: on, off or auto\n");
1160 exit(1);
1161 }
1162 }
1163
Vladimir Chtchetkine9242b332012-02-10 08:29:22 -08001164 /* Quit emulator on condition that both, gpu and snapstorage are on. This is
1165 * a temporary solution preventing the emulator from crashing until GPU state
1166 * can be properly saved / resored in snapshot file. */
1167 if (hw->hw_gpu_enabled && opts->snapstorage && (!opts->no_snapshot_load ||
1168 !opts->no_snapshot_save)) {
1169 derror("Snapshots and gpu are mutually exclusive at this point. Please turn one of them off, and restart the emulator.");
1170 exit(1);
1171 }
1172
Vladimir Chtchetkine7485c292012-03-19 11:35:29 -07001173 /* Deal with camera emulation */
1174 if (opts->webcam_list) {
1175 /* List connected webcameras */
1176 args[n++] = "-list-webcam";
1177 }
1178
1179 if (opts->camera_back) {
1180 /* Validate parameter. */
1181 if (memcmp(opts->camera_back, "webcam", 6) &&
1182 strcmp(opts->camera_back, "emulated") &&
1183 strcmp(opts->camera_back, "none")) {
1184 derror("Invalid value for -camera-back <mode> parameter: %s\n"
1185 "Valid values are: 'emulated', 'webcam<N>', or 'none'\n",
1186 opts->camera_back);
Vladimir Chtchetkineae0d8132011-09-13 10:48:02 -07001187 exit(1);
1188 }
Vladimir Chtchetkine7485c292012-03-19 11:35:29 -07001189 hw->hw_camera_back = ASTRDUP(opts->camera_back);
Vladimir Chtchetkineae0d8132011-09-13 10:48:02 -07001190 }
1191
Vladimir Chtchetkine7485c292012-03-19 11:35:29 -07001192 if (opts->camera_front) {
1193 /* Validate parameter. */
1194 if (memcmp(opts->camera_front, "webcam", 6) &&
1195 strcmp(opts->camera_front, "emulated") &&
1196 strcmp(opts->camera_front, "none")) {
1197 derror("Invalid value for -camera-front <mode> parameter: %s\n"
1198 "Valid values are: 'emulated', 'webcam<N>', or 'none'\n",
1199 opts->camera_front);
1200 exit(1);
Vladimir Chtchetkineb8dcaff2011-09-17 11:15:47 -07001201 }
Vladimir Chtchetkine7485c292012-03-19 11:35:29 -07001202 hw->hw_camera_front = ASTRDUP(opts->camera_front);
Vladimir Chtchetkinef8675c22012-01-06 10:31:41 -08001203 }
1204
David 'Digit' Turner5377c5b2011-02-10 16:52:19 +01001205 /* physical memory is now in hw->hw_ramSize */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001206
David 'Digit' Turner53eb66d2011-03-01 14:58:23 +01001207 hw->avd_name = ASTRDUP(avdInfo_getName(avd));
David 'Digit' Turner6b8555c2011-02-17 04:28:19 +01001208
Dries Harnie40beab42010-05-15 17:04:47 +02001209 /* Set up the interfaces for inter-emulator networking */
1210 if (opts->shared_net_id) {
1211 unsigned int shared_net_id = atoi(opts->shared_net_id);
1212 char nic[37];
Dries Harnie40beab42010-05-15 17:04:47 +02001213
1214 args[n++] = "-net";
1215 args[n++] = "nic,vlan=0";
1216 args[n++] = "-net";
1217 args[n++] = "user,vlan=0";
Dries Harnie111d6f82010-06-09 21:42:18 +02001218
1219 args[n++] = "-net";
1220 snprintf(nic, sizeof nic, "nic,vlan=1,macaddr=52:54:00:12:34:%02x", shared_net_id);
1221 args[n++] = strdup(nic);
1222 args[n++] = "-net";
1223 args[n++] = "socket,vlan=1,mcast=230.0.0.10:1234";
Dries Harnie40beab42010-05-15 17:04:47 +02001224 }
1225
Vladimir Chtchetkine8dd31e82012-02-15 17:16:04 -08001226 /* Setup screen emulation */
1227 if (opts->screen) {
Vladimir Chtchetkine863d1012012-03-16 12:25:23 -07001228 if (strcmp(opts->screen, "touch") &&
1229 strcmp(opts->screen, "multi-touch") &&
1230 strcmp(opts->screen, "no-touch")) {
1231
1232 derror("Invalid value for -screen <mode> parameter: %s\n"
1233 "Valid values are: touch, multi-touch, or no-touch\n",
1234 opts->screen);
Vladimir Chtchetkine8dd31e82012-02-15 17:16:04 -08001235 exit(1);
1236 }
Vladimir Chtchetkine863d1012012-03-16 12:25:23 -07001237 hw->hw_screen = ASTRDUP(opts->screen);
Vladimir Chtchetkine8dd31e82012-02-15 17:16:04 -08001238 }
1239
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001240 while(argc-- > 0) {
1241 args[n++] = *argv++;
1242 }
1243 args[n] = 0;
1244
David 'Digit' Turner2ed457e2011-06-15 17:29:50 +02001245 /* If the target ABI is armeabi-v7a, we can auto-detect the cpu model
1246 * as a cortex-a8, instead of the default (arm926) which only emulates
1247 * an ARMv5TE CPU.
1248 */
1249 if (!forceArmv7 && hw->hw_cpu_model[0] == '\0')
1250 {
1251 char* abi = avdInfo_getTargetAbi(avd);
1252 if (abi != NULL) {
1253 if (!strcmp(abi, "armeabi-v7a")) {
1254 forceArmv7 = 1;
1255 }
1256 AFREE(abi);
1257 }
1258 }
1259
1260 if (forceArmv7 != 0) {
1261 AFREE(hw->hw_cpu_model);
1262 hw->hw_cpu_model = ASTRDUP("cortex-a8");
1263 D("Auto-config: -qemu -cpu %s", hw->hw_cpu_model);
1264 }
1265
David 'Digit' Turner26d41532011-03-01 15:03:07 +01001266 /* Generate a hardware-qemu.ini for this AVD. The real hardware
David 'Digit' Turner622f1532011-02-01 17:48:37 +01001267 * configuration is ususally stored in several files, e.g. the AVD's
1268 * config.ini plus the skin-specific hardware.ini.
1269 *
David 'Digit' Turner26d41532011-03-01 15:03:07 +01001270 * The new file will group all definitions and will be used to
David 'Digit' Turner622f1532011-02-01 17:48:37 +01001271 * launch the core with the -android-hw <file> option.
1272 */
1273 {
David 'Digit' Turner42074e52011-02-10 16:03:28 +01001274 const char* coreHwIniPath = avdInfo_getCoreHwIniPath(avd);
1275 IniFile* hwIni = iniFile_newFromMemory("", NULL);
David 'Digit' Turner622f1532011-02-01 17:48:37 +01001276 androidHwConfig_write(hw, hwIni);
David 'Digit' Turner26d41532011-03-01 15:03:07 +01001277
1278 if (filelock_create(coreHwIniPath) == NULL) {
1279 /* The AVD is already in use, we still support this as an
1280 * experimental feature. Use a temporary hardware-qemu.ini
1281 * file though to avoid overwriting the existing one. */
1282 TempFile* tempIni = tempfile_create();
1283 coreHwIniPath = tempfile_path(tempIni);
1284 }
1285
Vladimir Chtchetkinedb450d72012-01-12 13:37:40 -08001286 /* While saving HW config, ignore valueless entries. This will not break
1287 * anything, but will significantly simplify comparing the current HW
1288 * config with the one that has been associated with a snapshot (in case
1289 * VM starts from a snapshot for this instance of emulator). */
1290 if (iniFile_saveToFileClean(hwIni, coreHwIniPath) < 0) {
David 'Digit' Turner42074e52011-02-10 16:03:28 +01001291 derror("Could not write hardware.ini to %s: %s", coreHwIniPath, strerror(errno));
David 'Digit' Turner622f1532011-02-01 17:48:37 +01001292 exit(2);
1293 }
1294 args[n++] = "-android-hw";
David 'Digit' Turner42074e52011-02-10 16:03:28 +01001295 args[n++] = strdup(coreHwIniPath);
David 'Digit' Turner0a879bf2011-05-12 18:45:18 +02001296
1297 /* In verbose mode, dump the file's content */
1298 if (VERBOSE_CHECK(init)) {
1299 FILE* file = fopen(coreHwIniPath, "rt");
1300 if (file == NULL) {
1301 derror("Could not open hardware configuration file: %s\n",
1302 coreHwIniPath);
1303 } else {
1304 LineInput* input = lineInput_newFromStdFile(file);
1305 const char* line;
1306 printf("Content of hardware configuration file:\n");
1307 while ((line = lineInput_getLine(input)) != NULL) {
1308 printf(" %s\n", line);
1309 }
1310 printf(".\n");
1311 lineInput_free(input);
1312 fclose(file);
1313 }
1314 }
David 'Digit' Turner622f1532011-02-01 17:48:37 +01001315 }
1316
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001317 if(VERBOSE_CHECK(init)) {
1318 int i;
David 'Digit' Turner33361762011-01-19 22:11:03 +01001319 printf("QEMU options list:\n");
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001320 for(i = 0; i < n; i++) {
David 'Digit' Turner33361762011-01-19 22:11:03 +01001321 printf("emulator: argv[%02d] = \"%s\"\n", i, args[i]);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001322 }
David 'Digit' Turner33361762011-01-19 22:11:03 +01001323 /* Dump final command-line option to make debugging the core easier */
1324 printf("Concatenated QEMU options:\n");
1325 for (i = 0; i < n; i++) {
David 'Digit' Turner26722dd2011-02-24 16:40:20 +01001326 /* To make it easier to copy-paste the output to a command-line,
1327 * quote anything that contains spaces.
1328 */
1329 if (strchr(args[i], ' ') != NULL) {
1330 printf(" '%s'", args[i]);
1331 } else {
1332 printf(" %s", args[i]);
1333 }
David 'Digit' Turner33361762011-01-19 22:11:03 +01001334 }
1335 printf("\n");
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001336 }
David 'Digit' Turner74d7ace2011-02-02 13:21:03 +01001337
1338 /* Setup SDL UI just before calling the code */
1339 init_sdl_ui(skinConfig, skinPath, opts);
1340
David 'Digit' Turnerbdb6f2d2011-02-23 15:57:25 +01001341 if (attach_ui_to_core(opts) < 0) {
1342 derror("Can't attach to core!");
1343 exit(1);
1344 }
1345
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001346 return qemu_main(n, args);
1347}