blob: b1a3053fb6441e7a3226f5fe470ae56caec6de14 [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"
David 'Digit' Turner045bdbe2014-04-28 22:26:52 +020039#include "android/cpu_accelerator.h"
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080040
David 'Digit' Turnerc6e0cae2014-03-07 23:08:30 +010041#include "android/kernel/kernel_utils.h"
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080042#include "android/user-config.h"
43#include "android/utils/bufprint.h"
David 'Digit' Turner26d41532011-03-01 15:03:07 +010044#include "android/utils/filelock.h"
David 'Digit' Turner0a879bf2011-05-12 18:45:18 +020045#include "android/utils/lineinput.h"
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080046#include "android/utils/path.h"
David 'Digit' Turner5ea91482014-02-13 18:02:56 +010047#include "android/utils/property_file.h"
David 'Digit' Turner622f1532011-02-01 17:48:37 +010048#include "android/utils/tempfile.h"
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080049
David 'Digit' Turnerf8456272011-02-02 12:34:14 +010050#include "android/main-common.h"
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080051#include "android/help.h"
David 'Digit' Turnerf0665422013-12-17 10:47:09 +010052#include "hw/android/goldfish/nand.h"
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080053
54#include "android/globals.h"
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080055
Xavier Ducrohetfc8ed802011-02-09 18:04:23 -080056#include "android/qemulator.h"
David 'Digit' Turner055ae422010-07-27 11:34:16 -070057#include "android/display.h"
Vladimir Chtchetkine01193622010-05-11 13:07:22 -070058
Ot ten Thijeae835ac2010-10-18 13:37:37 +010059#include "android/snapshot.h"
60
David 'Digit' Turnere3fdd072011-02-02 14:43:23 +010061#include "android/framebuffer.h"
David 'Digit' Turnerd413fa52013-12-14 23:35:20 +010062#include "android/iolooper.h"
David 'Digit' Turner055ae422010-07-27 11:34:16 -070063
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080064AndroidRotation android_framebuffer_rotation;
65
66#define STRINGIFY(x) _STRINGIFY(x)
67#define _STRINGIFY(x) #x
68
David 'Digit' Turnera383d022009-12-03 13:50:00 -080069#ifdef ANDROID_SDK_TOOLS_REVISION
70# define VERSION_STRING STRINGIFY(ANDROID_SDK_TOOLS_REVISION)".0"
71#else
72# define VERSION_STRING "standalone"
73#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080074
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080075#define D(...) do { if (VERBOSE_CHECK(init)) dprint(__VA_ARGS__); } while (0)
76
77extern int control_console_start( int port ); /* in control.c */
78
79extern int qemu_milli_needed;
80
David 'Digit' Turnerb72ae032014-06-18 19:23:20 +020081extern bool android_op_wipe_data;
82
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080083/* the default device DPI if none is specified by the skin
84 */
85#define DEFAULT_DEVICE_DPI 165
86
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080087int qemu_main(int argc, char **argv);
88
89/* this function dumps the QEMU help */
90extern void help( void );
91extern void emulator_help( void );
92
93#define VERBOSE_OPT(str,var) { str, &var }
94
95#define _VERBOSE_TAG(x,y) { #x, VERBOSE_##x, y },
96static const struct { const char* name; int flag; const char* text; }
97verbose_options[] = {
98 VERBOSE_TAG_LIST
99 { 0, 0, 0 }
100};
101
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800102void emulator_help( void )
103{
104 STRALLOC_DEFINE(out);
105 android_help_main(out);
106 printf( "%.*s", out->n, out->s );
107 stralloc_reset(out);
108 exit(1);
109}
110
David 'Digit' Turner40841b22011-03-01 14:04:00 +0100111/* TODO: Put in shared source file */
112static char*
113_getFullFilePath( const char* rootPath, const char* fileName )
114{
115 if (path_is_absolute(fileName)) {
116 return ASTRDUP(fileName);
117 } else {
118 char temp[PATH_MAX], *p=temp, *end=p+sizeof(temp);
119
120 p = bufprint(temp, end, "%s/%s", rootPath, fileName);
121 if (p >= end) {
122 return NULL;
123 }
124 return ASTRDUP(temp);
125 }
126}
127
128static uint64_t
129_adjustPartitionSize( const char* description,
130 uint64_t imageBytes,
131 uint64_t defaultBytes,
132 int inAndroidBuild )
133{
134 char temp[64];
135 unsigned imageMB;
136 unsigned defaultMB;
137
138 if (imageBytes <= defaultBytes)
139 return defaultBytes;
140
141 imageMB = convertBytesToMB(imageBytes);
142 defaultMB = convertBytesToMB(defaultBytes);
143
144 if (imageMB > defaultMB) {
145 snprintf(temp, sizeof temp, "(%d MB > %d MB)", imageMB, defaultMB);
146 } else {
Andrew Hsiehc7389bd2012-03-13 02:13:40 -0700147 snprintf(temp, sizeof temp, "(%" PRIu64 " bytes > %" PRIu64 " bytes)", imageBytes, defaultBytes);
David 'Digit' Turner40841b22011-03-01 14:04:00 +0100148 }
149
150 if (inAndroidBuild) {
151 dwarning("%s partition size adjusted to match image file %s\n", description, temp);
152 }
153
154 return convertMBToBytes(imageMB);
155}
156
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800157int main(int argc, char **argv)
158{
159 char tmp[MAX_PATH];
160 char* tmpend = tmp + sizeof(tmp);
161 char* args[128];
162 int n;
163 char* opt;
David 'Digit' Turner5e736932011-03-18 00:02:14 +0100164 /* The emulator always uses the first serial port for kernel messages
165 * and the second one for qemud. So start at the third if we need one
166 * for logcat or 'shell'
167 */
168 int serial = 2;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800169 int shell_serial = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800170
David 'Digit' Turner2ed457e2011-06-15 17:29:50 +0200171 int forceArmv7 = 0;
172
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800173 AndroidHwConfig* hw;
David 'Digit' Turnercd059b12009-08-28 19:36:27 +0200174 AvdInfo* avd;
David 'Digit' Turner74d7ace2011-02-02 13:21:03 +0100175 AConfig* skinConfig;
176 char* skinPath;
Vladimir Chtchetkine83ffd662011-02-11 12:40:59 -0800177 int inAndroidBuild;
Vladimir Chtchetkine88078b82012-04-19 12:24:38 -0700178 uint64_t defaultPartitionSize = convertMBToBytes(200);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800179
180 AndroidOptions opts[1];
Vladimir Chtchetkineb25bf2a2010-09-08 11:09:23 -0700181 /* net.shared_net_ip boot property value. */
182 char boot_prop_ip[64];
183 boot_prop_ip[0] = '\0';
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800184
185 args[0] = argv[0];
186
187 if ( android_parse_options( &argc, &argv, opts ) < 0 ) {
188 exit(1);
189 }
190
David 'Digit' Turnerbdb6f2d2011-02-23 15:57:25 +0100191#ifdef _WIN32
192 socket_init();
193#endif
194
195 handle_ui_options(opts);
196
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800197 while (argc-- > 1) {
198 opt = (++argv)[0];
199
200 if(!strcmp(opt, "-qemu")) {
201 argc--;
202 argv++;
203 break;
204 }
205
206 if (!strcmp(opt, "-help")) {
207 emulator_help();
208 }
209
210 if (!strncmp(opt, "-help-",6)) {
211 STRALLOC_DEFINE(out);
212 opt += 6;
213
214 if (!strcmp(opt, "all")) {
215 android_help_all(out);
216 }
217 else if (android_help_for_option(opt, out) == 0) {
218 /* ok */
219 }
220 else if (android_help_for_topic(opt, out) == 0) {
221 /* ok */
222 }
223 if (out->n > 0) {
224 printf("\n%.*s", out->n, out->s);
225 exit(0);
226 }
227
228 fprintf(stderr, "unknown option: -help-%s\n", opt);
229 fprintf(stderr, "please use -help for a list of valid topics\n");
230 exit(1);
231 }
232
233 if (opt[0] == '-') {
234 fprintf(stderr, "unknown option: %s\n", opt);
235 fprintf(stderr, "please use -help for a list of valid options\n");
236 exit(1);
237 }
238
239 fprintf(stderr, "invalid command-line parameter: %s.\n", opt);
240 fprintf(stderr, "Hint: use '@foo' to launch a virtual device named 'foo'.\n");
241 fprintf(stderr, "please use -help for more information\n");
242 exit(1);
243 }
244
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800245 if (opts->version) {
246 printf("Android emulator version %s\n"
David 'Digit' Turner5f64b872011-02-28 23:23:05 +0100247 "Copyright (C) 2006-2011 The Android Open Source Project and many others.\n"
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800248 "This program is a derivative of the QEMU CPU emulator (www.qemu.org).\n\n",
249#if defined ANDROID_BUILD_ID
250 VERSION_STRING " (build_id " STRINGIFY(ANDROID_BUILD_ID) ")" );
251#else
252 VERSION_STRING);
253#endif
254 printf(" This software is licensed under the terms of the GNU General Public\n"
255 " License version 2, as published by the Free Software Foundation, and\n"
256 " may be copied, distributed, and modified under those terms.\n\n"
257 " This program is distributed in the hope that it will be useful,\n"
258 " but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
259 " MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
260 " GNU General Public License for more details.\n\n");
261
262 exit(0);
263 }
264
David 'Digit' Turner5f64b872011-02-28 23:23:05 +0100265 if (opts->snapshot_list) {
David 'Digit' Turnerd80a7862011-05-05 10:24:43 +0200266 if (opts->snapstorage == NULL) {
267 /* Need to find the default snapstorage */
268 avd = createAVD(opts, &inAndroidBuild);
269 opts->snapstorage = avdInfo_getSnapStoragePath(avd);
270 if (opts->snapstorage != NULL) {
271 D("autoconfig: -snapstorage %s", opts->snapstorage);
272 } else {
273 if (inAndroidBuild) {
274 derror("You must use the -snapstorage <file> option to specify a snapshot storage file!\n");
275 } else {
276 derror("This AVD doesn't have snapshotting enabled!\n");
277 }
278 exit(1);
279 }
280 }
David 'Digit' Turner5f64b872011-02-28 23:23:05 +0100281 snapshot_print_and_exit(opts->snapstorage);
282 }
283
David 'Digit' Turner25eb6552011-02-25 15:07:11 +0100284 sanitizeOptions(opts);
285
David 'Digit' Turnerbdb6f2d2011-02-23 15:57:25 +0100286 /* Initialization of UI started with -attach-core should work differently
287 * than initialization of UI that starts the core. In particular....
288 */
289
290 /* -charmap is incompatible with -attach-core, because particular
291 * charmap gets set up in the running core. */
David 'Digit' Turner74d7ace2011-02-02 13:21:03 +0100292 if (android_charmap_setup(opts->charmap)) {
293 exit(1);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800294 }
295
Vladimir Chtchetkine83ffd662011-02-11 12:40:59 -0800296 /* Parses options and builds an appropriate AVD. */
David 'Digit' Turner462564f2011-02-23 13:32:37 +0100297 avd = android_avdInfo = createAVD(opts, &inAndroidBuild);
David 'Digit' Turnercd059b12009-08-28 19:36:27 +0200298
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800299 /* get the skin from the virtual device configuration */
David 'Digit' Turner25eb6552011-02-25 15:07:11 +0100300 if (opts->skindir != NULL) {
301 if (opts->skin == NULL) {
302 /* NOTE: Normally handled by sanitizeOptions(), just be safe */
303 derror("The -skindir <path> option requires a -skin <name> option");
304 exit(2);
305 }
306 } else {
307 char* skinName;
308 char* skinDir;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800309
David 'Digit' Turner25eb6552011-02-25 15:07:11 +0100310 avdInfo_getSkinInfo(avd, &skinName, &skinDir);
311
312 if (opts->skin == NULL) {
313 opts->skin = skinName;
314 D("autoconfig: -skin %s", opts->skin);
315 } else {
316 AFREE(skinName);
317 }
318
319 opts->skindir = skinDir;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800320 D("autoconfig: -skindir %s", opts->skindir);
Xavier Ducrohet689d1142012-04-19 12:54:08 -0700321
322 /* update the avd hw config from this new skin */
323 avdInfo_getSkinHardwareIni(avd, opts->skin, opts->skindir);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800324 }
325
Siva Velusamyd8999182012-10-08 18:02:30 -0700326 if (opts->dynamic_skin == 0) {
327 opts->dynamic_skin = avdInfo_shouldUseDynamicSkin(avd);
328 }
329
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800330 /* Read hardware configuration */
331 hw = android_hw;
David 'Digit' Turnerb64325d2011-03-22 16:07:01 +0100332 if (avdInfo_initHwConfig(avd, hw) < 0) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800333 derror("could not read hardware configuration ?");
334 exit(1);
335 }
336
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800337 if (opts->keyset) {
338 parse_keyset(opts->keyset, opts);
339 if (!android_keyset) {
340 fprintf(stderr,
341 "emulator: WARNING: could not find keyset file named '%s',"
342 " using defaults instead\n",
343 opts->keyset);
344 }
345 }
346 if (!android_keyset) {
347 parse_keyset("default", opts);
348 if (!android_keyset) {
349 android_keyset = skin_keyset_new_from_text( skin_keyset_get_default() );
350 if (!android_keyset) {
351 fprintf(stderr, "PANIC: default keyset file is corrupted !!\n" );
352 fprintf(stderr, "PANIC: please update the code in android/skin/keyset.c\n" );
353 exit(1);
354 }
355 if (!opts->keyset)
356 write_default_keyset();
357 }
358 }
359
Dries Harnie40beab42010-05-15 17:04:47 +0200360 if (opts->shared_net_id) {
361 char* end;
362 long shared_net_id = strtol(opts->shared_net_id, &end, 0);
363 if (end == NULL || *end || shared_net_id < 1 || shared_net_id > 255) {
364 fprintf(stderr, "option -shared-net-id must be an integer between 1 and 255\n");
365 exit(1);
366 }
Vladimir Chtchetkineb25bf2a2010-09-08 11:09:23 -0700367 snprintf(boot_prop_ip, sizeof(boot_prop_ip),
368 "net.shared_net_ip=10.1.2.%ld", shared_net_id);
Dries Harnie40beab42010-05-15 17:04:47 +0200369 }
370
371
David 'Digit' Turner755811e2011-02-07 13:38:25 +0100372 user_config_init();
David 'Digit' Turner2507cab2011-02-10 16:29:17 +0100373 parse_skin_files(opts->skindir, opts->skin, opts, hw,
David 'Digit' Turner74d7ace2011-02-02 13:21:03 +0100374 &skinConfig, &skinPath);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800375
David 'Digit' Turner092361e2011-03-01 13:14:18 +0100376 if (!opts->netspeed && skin_network_speed) {
377 D("skin network speed: '%s'", skin_network_speed);
378 if (strcmp(skin_network_speed, NETWORK_SPEED_DEFAULT) != 0) {
379 opts->netspeed = (char*)skin_network_speed;
380 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800381 }
David 'Digit' Turner092361e2011-03-01 13:14:18 +0100382 if (!opts->netdelay && skin_network_delay) {
383 D("skin network delay: '%s'", skin_network_delay);
384 if (strcmp(skin_network_delay, NETWORK_DELAY_DEFAULT) != 0) {
385 opts->netdelay = (char*)skin_network_delay;
386 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800387 }
388
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800389 if (opts->trace) {
David 'Digit' Turnercd059b12009-08-28 19:36:27 +0200390 char* tracePath = avdInfo_getTracePath(avd, opts->trace);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800391 int ret;
392
393 if (tracePath == NULL) {
394 derror( "bad -trace parameter" );
395 exit(1);
396 }
397 ret = path_mkdir_if_needed( tracePath, 0755 );
398 if (ret < 0) {
399 fprintf(stderr, "could not create directory '%s'\n", tmp);
400 exit(2);
401 }
402 opts->trace = tracePath;
403 }
404
Vladimir Chtchetkine33f89d02011-09-28 09:19:09 -0700405 /* Update CPU architecture for HW configs created from build dir. */
406 if (inAndroidBuild) {
407#if defined(TARGET_ARM)
David 'Digit' Turnerc5f12b92014-07-11 13:59:57 +0200408 reassign_string(&android_hw->hw_cpu_arch, "arm");
Vladimir Chtchetkine33f89d02011-09-28 09:19:09 -0700409#elif defined(TARGET_I386)
David 'Digit' Turnerc5f12b92014-07-11 13:59:57 +0200410 reassign_string(&android_hw->hw_cpu_arch, "x86");
Bhanu Chetlapalli741dc132012-05-08 17:16:03 -0700411#elif defined(TARGET_MIPS)
David 'Digit' Turnerc5f12b92014-07-11 13:59:57 +0200412 reassign_string(&android_hw->hw_cpu_arch, "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' Turnercc5804c2014-06-12 19:26:27 +0200456 KernelType kernelType = KERNEL_TYPE_LEGACY;
457 if (!android_pathProbeKernelType(hw->kernel_path, &kernelType)) {
458 D("WARNING: Could not determine kernel device naming scheme. Assuming legacy\n"
459 "If this AVD doesn't boot, and uses a recent kernel (3.10 or above) try setting\n"
460 "'kernel.newDeviceNaming' to 'yes' in its configuration.\n");
461 }
462
David 'Digit' Turnerc6e0cae2014-03-07 23:08:30 +0100463 // Auto-detect kernel device naming scheme if needed.
464 if (androidHwConfig_getKernelDeviceNaming(hw) < 0) {
David 'Digit' Turnerc6e0cae2014-03-07 23:08:30 +0100465 const char* newDeviceNaming = "no";
David 'Digit' Turnercc5804c2014-06-12 19:26:27 +0200466 if (kernelType == KERNEL_TYPE_3_10_OR_ABOVE) {
David 'Digit' Turnerc6e0cae2014-03-07 23:08:30 +0100467 D("Auto-detect: Kernel image requires new device naming scheme.");
468 newDeviceNaming = "yes";
469 } else {
470 D("Auto-detect: Kernel image requires legacy device naming scheme.");
471 }
David 'Digit' Turnerc5f12b92014-07-11 13:59:57 +0200472 reassign_string(&hw->kernel_newDeviceNaming, newDeviceNaming);
David 'Digit' Turnerc6e0cae2014-03-07 23:08:30 +0100473 }
474
David 'Digit' Turnercc5804c2014-06-12 19:26:27 +0200475 // Auto-detect YAFFS2 partition support if needed.
476 if (androidHwConfig_getKernelYaffs2Support(hw) < 0) {
David 'Digit' Turner9cab7532014-06-19 02:41:55 +0200477 // Essentially, anything before API level 20 supports Yaffs2
David 'Digit' Turnercc5804c2014-06-12 19:26:27 +0200478 const char* newYaffs2Support = "no";
David 'Digit' Turner9cab7532014-06-19 02:41:55 +0200479 if (avdInfo_getApiLevel(avd) < 20) {
David 'Digit' Turnercc5804c2014-06-12 19:26:27 +0200480 newYaffs2Support = "yes";
David 'Digit' Turner9cab7532014-06-19 02:41:55 +0200481 D("Auto-detect: Kernel does support YAFFS2 partitions.");
482 } else {
483 D("Auto-detect: Kernel does not support YAFFS2 partitions.");
David 'Digit' Turnercc5804c2014-06-12 19:26:27 +0200484 }
David 'Digit' Turnerc5f12b92014-07-11 13:59:57 +0200485 reassign_string(&hw->kernel_supportsYaffs2, newYaffs2Support);
David 'Digit' Turnercc5804c2014-06-12 19:26:27 +0200486 }
487
Vladimir Chtchetkineb25bf2a2010-09-08 11:09:23 -0700488 if (boot_prop_ip[0]) {
489 args[n++] = "-boot-property";
490 args[n++] = boot_prop_ip;
491 }
492
Vladimir Chtchetkine318f17a2010-08-27 09:09:45 -0700493 if (opts->tcpdump) {
494 args[n++] = "-tcpdump";
495 args[n++] = opts->tcpdump;
496 }
497
Vladimir Chtchetkinee1316862010-08-26 09:03:54 -0700498#ifdef CONFIG_NAND_LIMITS
499 if (opts->nand_limits) {
500 args[n++] = "-nand-limits";
501 args[n++] = opts->nand_limits;
502 }
503#endif
504
David 'Digit' Turner74d7ace2011-02-02 13:21:03 +0100505 if (opts->timezone) {
506 args[n++] = "-timezone";
507 args[n++] = opts->timezone;
508 }
509
Vladimir Chtchetkinee1316862010-08-26 09:03:54 -0700510 if (opts->netspeed) {
511 args[n++] = "-netspeed";
512 args[n++] = opts->netspeed;
513 }
514 if (opts->netdelay) {
515 args[n++] = "-netdelay";
516 args[n++] = opts->netdelay;
517 }
518 if (opts->netfast) {
519 args[n++] = "-netfast";
520 }
521
Vladimir Chtchetkineb2438402010-08-24 08:55:33 -0700522 if (opts->audio) {
523 args[n++] = "-audio";
524 args[n++] = opts->audio;
525 }
526
Vladimir Chtchetkineb2438402010-08-24 08:55:33 -0700527 if (opts->cpu_delay) {
528 args[n++] = "-cpu-delay";
529 args[n++] = opts->cpu_delay;
530 }
531
Vladimir Chtchetkine7fbf4972010-08-11 15:30:32 -0700532 if (opts->dns_server) {
533 args[n++] = "-dns-server";
534 args[n++] = opts->dns_server;
535 }
536
David 'Digit' Turner9ff69722011-09-13 12:32:52 +0200537 /* opts->ramdisk is never NULL (see createAVD) here */
538 if (opts->ramdisk) {
David 'Digit' Turnerc5f12b92014-07-11 13:59:57 +0200539 reassign_string(&hw->disk_ramdisk_path, opts->ramdisk);
David 'Digit' Turner9ff69722011-09-13 12:32:52 +0200540 }
541 else if (!hw->disk_ramdisk_path[0]) {
542 hw->disk_ramdisk_path = avdInfo_getRamdiskPath(avd);
543 D("autoconfig: -ramdisk %s", hw->disk_ramdisk_path);
544 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800545
David 'Digit' Turner40841b22011-03-01 14:04:00 +0100546 /* -partition-size is used to specify the max size of both the system
547 * and data partition sizes.
548 */
549 if (opts->partition_size) {
550 char* end;
551 long sizeMB = strtol(opts->partition_size, &end, 0);
552 long minSizeMB = 10;
553 long maxSizeMB = LONG_MAX / ONE_MB;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800554
David 'Digit' Turner40841b22011-03-01 14:04:00 +0100555 if (sizeMB < 0 || *end != 0) {
556 derror( "-partition-size must be followed by a positive integer" );
557 exit(1);
558 }
559 if (sizeMB < minSizeMB || sizeMB > maxSizeMB) {
560 derror( "partition-size (%d) must be between %dMB and %dMB",
561 sizeMB, minSizeMB, maxSizeMB );
562 exit(1);
563 }
564 defaultPartitionSize = (uint64_t) sizeMB * ONE_MB;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800565 }
566
David 'Digit' Turner40841b22011-03-01 14:04:00 +0100567
568 /** SYSTEM PARTITION **/
569
570 if (opts->sysdir == NULL) {
571 if (avdInfo_inAndroidBuild(avd)) {
572 opts->sysdir = ASTRDUP(avdInfo_getContentPath(avd));
573 D("autoconfig: -sysdir %s", opts->sysdir);
574 }
575 }
576
577 if (opts->sysdir != NULL) {
578 if (!path_exists(opts->sysdir)) {
579 derror("Directory does not exist: %s", opts->sysdir);
580 exit(1);
581 }
582 }
583
584 {
585 char* rwImage = NULL;
586 char* initImage = NULL;
587
588 do {
589 if (opts->system == NULL) {
590 /* If -system is not used, try to find a runtime system image
591 * (i.e. system-qemu.img) in the content directory.
592 */
593 rwImage = avdInfo_getSystemImagePath(avd);
594 if (rwImage != NULL) {
595 break;
596 }
597 /* Otherwise, try to find the initial system image */
598 initImage = avdInfo_getSystemInitImagePath(avd);
599 if (initImage == NULL) {
600 derror("No initial system image for this configuration!");
601 exit(1);
602 }
603 break;
604 }
605
606 /* If -system <name> is used, use it to find the initial image */
David 'Digit' Turnerea283772011-07-07 04:40:27 +0200607 if (opts->sysdir != NULL && !path_exists(opts->system)) {
David 'Digit' Turner40841b22011-03-01 14:04:00 +0100608 initImage = _getFullFilePath(opts->sysdir, opts->system);
609 } else {
610 initImage = ASTRDUP(opts->system);
611 }
612 if (!path_exists(initImage)) {
613 derror("System image file doesn't exist: %s", initImage);
614 exit(1);
615 }
616
617 } while (0);
618
619 if (rwImage != NULL) {
620 /* Use the read/write image file directly */
621 hw->disk_systemPartition_path = rwImage;
622 hw->disk_systemPartition_initPath = NULL;
623 D("Using direct system image: %s", rwImage);
624 } else if (initImage != NULL) {
625 hw->disk_systemPartition_path = NULL;
626 hw->disk_systemPartition_initPath = initImage;
627 D("Using initial system image: %s", initImage);
628 }
629
630 /* Check the size of the system partition image.
631 * If we have an AVD, it must be smaller than
632 * the disk.systemPartition.size hardware property.
633 *
634 * Otherwise, we need to adjust the systemPartitionSize
635 * automatically, and print a warning.
636 *
637 */
638 const char* systemImage = hw->disk_systemPartition_path;
639 uint64_t systemBytes;
640
641 if (systemImage == NULL)
642 systemImage = hw->disk_systemPartition_initPath;
643
644 if (path_get_size(systemImage, &systemBytes) < 0) {
645 derror("Missing system image: %s", systemImage);
646 exit(1);
647 }
648
649 hw->disk_systemPartition_size =
650 _adjustPartitionSize("system", systemBytes, defaultPartitionSize,
651 avdInfo_inAndroidBuild(avd));
652 }
653
654 /** DATA PARTITION **/
655
David 'Digit' Turnerfd59c332011-03-01 00:48:52 +0100656 if (opts->datadir) {
657 if (!path_exists(opts->datadir)) {
658 derror("Invalid -datadir directory: %s", opts->datadir);
659 }
660 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800661
David 'Digit' Turnerfd59c332011-03-01 00:48:52 +0100662 {
663 char* dataImage = NULL;
664 char* initImage = NULL;
665
666 do {
667 if (!opts->data) {
668 dataImage = avdInfo_getDataImagePath(avd);
669 if (dataImage != NULL) {
670 D("autoconfig: -data %s", dataImage);
671 break;
672 }
673 dataImage = avdInfo_getDefaultDataImagePath(avd);
674 if (dataImage == NULL) {
675 derror("No data image path for this configuration!");
676 exit (1);
677 }
678 opts->wipe_data = 1;
679 break;
680 }
681
682 if (opts->datadir) {
683 dataImage = _getFullFilePath(opts->datadir, opts->data);
684 } else {
685 dataImage = ASTRDUP(opts->data);
686 }
687 } while (0);
688
689 if (opts->initdata != NULL) {
690 initImage = ASTRDUP(opts->initdata);
691 if (!path_exists(initImage)) {
692 derror("Invalid initial data image path: %s", initImage);
693 exit(1);
694 }
695 } else {
696 initImage = avdInfo_getDataInitImagePath(avd);
697 D("autoconfig: -initdata %s", initImage);
698 }
699
700 hw->disk_dataPartition_path = dataImage;
701 if (opts->wipe_data) {
702 hw->disk_dataPartition_initPath = initImage;
703 } else {
704 hw->disk_dataPartition_initPath = NULL;
705 }
David 'Digit' Turnerb72ae032014-06-18 19:23:20 +0200706 android_op_wipe_data = opts->wipe_data;
David 'Digit' Turnerfd59c332011-03-01 00:48:52 +0100707
Maciek Molerusf7584112011-06-15 22:26:35 +0200708 uint64_t defaultBytes =
709 hw->disk_dataPartition_size == 0 ?
710 defaultPartitionSize :
Vladimir Chtchetkined4f5a3a2012-03-08 14:20:20 -0800711 hw->disk_dataPartition_size;
David 'Digit' Turnerfd59c332011-03-01 00:48:52 +0100712 uint64_t dataBytes;
713 const char* dataPath = hw->disk_dataPartition_initPath;
714
715 if (dataPath == NULL)
716 dataPath = hw->disk_dataPartition_path;
717
718 path_get_size(dataPath, &dataBytes);
719
720 hw->disk_dataPartition_size =
721 _adjustPartitionSize("data", dataBytes, defaultBytes,
722 avdInfo_inAndroidBuild(avd));
723 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800724
David 'Digit' Turnerc480cca2011-02-25 16:43:34 +0100725 /** CACHE PARTITION **/
726
727 if (opts->no_cache) {
728 /* No cache partition at all */
729 hw->disk_cachePartition = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800730 }
David 'Digit' Turnerc480cca2011-02-25 16:43:34 +0100731 else if (!hw->disk_cachePartition) {
732 if (opts->cache) {
733 dwarning( "Emulated hardware doesn't support a cache partition. -cache option ignored!" );
734 opts->cache = NULL;
735 }
736 }
737 else
738 {
739 if (!opts->cache) {
740 /* Find the current cache partition file */
741 opts->cache = avdInfo_getCachePath(avd);
742 if (opts->cache == NULL) {
743 /* The file does not exists, we will force its creation
744 * if we are not in the Android build system. Otherwise,
745 * a temporary file will be used.
746 */
747 if (!avdInfo_inAndroidBuild(avd)) {
748 opts->cache = avdInfo_getDefaultCachePath(avd);
749 }
750 }
David 'Digit' Turner48a3c662011-03-01 14:03:20 +0100751 if (opts->cache) {
752 D("autoconfig: -cache %s", opts->cache);
753 }
David 'Digit' Turnerc480cca2011-02-25 16:43:34 +0100754 }
755
756 if (opts->cache) {
757 hw->disk_cachePartition_path = ASTRDUP(opts->cache);
758 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800759 }
760
Vladimir Chtchetkine6f50aa32012-04-26 08:20:18 -0700761 if (hw->disk_cachePartition_path && opts->cache_size) {
762 /* Set cache partition size per user options. */
763 char* end;
764 long sizeMB = strtol(opts->cache_size, &end, 0);
765
766 if (sizeMB < 0 || *end != 0) {
767 derror( "-cache-size must be followed by a positive integer" );
768 exit(1);
769 }
770 hw->disk_cachePartition_size = (uint64_t) sizeMB * ONE_MB;
771 }
772
David 'Digit' Turnerc480cca2011-02-25 16:43:34 +0100773 /** SD CARD PARTITION */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800774
David 'Digit' Turner48a3c662011-03-01 14:03:20 +0100775 if (!hw->hw_sdCard) {
776 /* No SD Card emulation, so -sdcard will be ignored */
777 if (opts->sdcard) {
778 dwarning( "Emulated hardware doesn't support SD Cards. -sdcard option ignored." );
779 opts->sdcard = NULL;
780 }
781 } else {
782 /* Auto-configure -sdcard if it is not available */
783 if (!opts->sdcard) {
784 do {
785 /* If -datadir <path> is used, look for a sdcard.img file here */
786 if (opts->datadir) {
787 bufprint(tmp, tmpend, "%s/%s", opts->datadir, "system.img");
788 if (path_exists(tmp)) {
789 opts->sdcard = strdup(tmp);
790 break;
791 }
792 }
793
794 /* Otherwise, look at the AVD's content */
795 opts->sdcard = avdInfo_getSdCardPath(avd);
796 if (opts->sdcard != NULL) {
797 break;
798 }
799
800 /* Nothing */
801 } while (0);
802
803 if (opts->sdcard) {
804 D("autoconfig: -sdcard %s", opts->sdcard);
805 }
806 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800807 }
808
809 if(opts->sdcard) {
810 uint64_t size;
811 if (path_get_size(opts->sdcard, &size) == 0) {
812 /* see if we have an sdcard image. get its size if it exists */
David 'Digit' Turner8b657e52009-12-01 13:38:21 -0800813 /* due to what looks like limitations of the MMC protocol, one has
814 * to use an SD Card image that is equal or larger than 9 MB
815 */
816 if (size < 9*1024*1024ULL) {
817 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 -0800818 } else {
David 'Digit' Turner48a3c662011-03-01 14:03:20 +0100819 hw->hw_sdCard_path = ASTRDUP(opts->sdcard);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800820 }
821 } else {
David 'Digit' Turner48a3c662011-03-01 14:03:20 +0100822 dwarning("no SD Card image at '%s'", opts->sdcard);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800823 }
824 }
825
David 'Digit' Turner48a3c662011-03-01 14:03:20 +0100826
827 /** SNAPSHOT STORAGE HANDLING */
828
David 'Digit' Turner5f64b872011-02-28 23:23:05 +0100829 /* Determine snapstorage path. -no-snapstorage disables all snapshotting
830 * support. This means you can't resume a snapshot at load, save it at
831 * exit, or even load/save them dynamically at runtime with the console.
832 */
833 if (opts->no_snapstorage) {
834
835 if (opts->snapshot) {
836 dwarning("ignoring -snapshot option due to the use of -no-snapstorage");
837 opts->snapshot = NULL;
838 }
839
840 if (opts->snapstorage) {
841 dwarning("ignoring -snapstorage option due to the use of -no-snapstorage");
842 opts->snapstorage = NULL;
843 }
844 }
845 else
846 {
Vladimir Chtchetkine873c3cb2012-03-14 12:46:51 -0700847 if (!opts->snapstorage && avdInfo_getSnapshotPresent(avd)) {
David 'Digit' Turner5f64b872011-02-28 23:23:05 +0100848 opts->snapstorage = avdInfo_getSnapStoragePath(avd);
849 if (opts->snapstorage != NULL) {
850 D("autoconfig: -snapstorage %s", opts->snapstorage);
Ot ten Thije353b3b12010-10-05 17:53:30 +0100851 }
852 }
853
David 'Digit' Turner5f64b872011-02-28 23:23:05 +0100854 if (opts->snapstorage && !path_exists(opts->snapstorage)) {
855 D("no image at '%s', state snapshots disabled", opts->snapstorage);
856 opts->snapstorage = NULL;
Ot ten Thije353b3b12010-10-05 17:53:30 +0100857 }
David 'Digit' Turner5f64b872011-02-28 23:23:05 +0100858 }
859
860 /* If we have a valid snapshot storage path */
861
862 if (opts->snapstorage) {
863
864 hw->disk_snapStorage_path = ASTRDUP(opts->snapstorage);
865
866 /* -no-snapshot is equivalent to using both -no-snapshot-load
867 * and -no-snapshot-save. You can still load/save snapshots dynamically
868 * from the console though.
869 */
870 if (opts->no_snapshot) {
871
872 opts->no_snapshot_load = 1;
873 opts->no_snapshot_save = 1;
874
875 if (opts->snapshot) {
876 dwarning("ignoring -snapshot option due to the use of -no-snapshot.");
877 }
878 }
879
880 if (!opts->no_snapshot_load || !opts->no_snapshot_save) {
881 if (opts->snapshot == NULL) {
882 opts->snapshot = "default-boot";
883 D("autoconfig: -snapshot %s", opts->snapshot);
884 }
885 }
886
887 /* We still use QEMU command-line options for the following since
888 * they can change from one invokation to the next and don't really
889 * correspond to the hardware configuration itself.
890 */
891 if (!opts->no_snapshot_load) {
892 args[n++] = "-loadvm";
893 args[n++] = ASTRDUP(opts->snapshot);
894 }
895
896 if (!opts->no_snapshot_save) {
897 args[n++] = "-savevm-on-exit";
898 args[n++] = ASTRDUP(opts->snapshot);
899 }
900
Tim Baverstock622b8f42010-12-07 11:36:59 +0000901 if (opts->no_snapshot_update_time) {
David 'Digit' Turnerbdb6f2d2011-02-23 15:57:25 +0100902 args[n++] = "-snapshot-no-time-update";
Tim Baverstock622b8f42010-12-07 11:36:59 +0000903 }
Ot ten Thijeae835ac2010-10-18 13:37:37 +0100904 }
Ot ten Thije353b3b12010-10-05 17:53:30 +0100905
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800906 if (!opts->logcat || opts->logcat[0] == 0) {
907 opts->logcat = getenv("ANDROID_LOG_TAGS");
908 if (opts->logcat && opts->logcat[0] == 0)
909 opts->logcat = NULL;
910 }
911
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800912 /* we always send the kernel messages from ttyS0 to android_kmsg */
David 'Digit' Turner062dd6a2011-03-01 14:50:07 +0100913 if (opts->show_kernel) {
914 args[n++] = "-show-kernel";
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800915 }
916
917 /* XXXX: TODO: implement -shell and -logcat through qemud instead */
918 if (!opts->shell_serial) {
919#ifdef _WIN32
920 opts->shell_serial = "con:";
921#else
922 opts->shell_serial = "stdio";
923#endif
924 }
925 else
926 opts->shell = 1;
927
928 if (opts->shell || opts->logcat) {
929 args[n++] = "-serial";
930 args[n++] = opts->shell_serial;
931 shell_serial = serial++;
932 }
933
David 'Digit' Turner062dd6a2011-03-01 14:50:07 +0100934 if (opts->radio) {
935 args[n++] = "-radio";
936 args[n++] = opts->radio;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800937 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800938
David 'Digit' Turner062dd6a2011-03-01 14:50:07 +0100939 if (opts->gps) {
940 args[n++] = "-gps";
941 args[n++] = opts->gps;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800942 }
943
Nick Kralevich185231a2013-10-07 13:54:31 -0700944 if (opts->selinux) {
945 if ((strcmp(opts->selinux, "permissive") != 0)
946 && (strcmp(opts->selinux, "disabled") != 0)) {
947 derror("-selinux must be \"disabled\" or \"permissive\"");
948 exit(1);
949 }
950 }
951
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800952 if (opts->memory) {
953 char* end;
954 long ramSize = strtol(opts->memory, &end, 0);
955 if (ramSize < 0 || *end != 0) {
956 derror( "-memory must be followed by a positive integer" );
957 exit(1);
958 }
959 if (ramSize < 32 || ramSize > 4096) {
960 derror( "physical memory size must be between 32 and 4096 MB" );
961 exit(1);
962 }
David 'Digit' Turner5377c5b2011-02-10 16:52:19 +0100963 hw->hw_ramSize = ramSize;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800964 }
965 if (!opts->memory) {
David 'Digit' Turner3bbc9192011-01-19 22:18:02 +0100966 int ramSize = hw->hw_ramSize;
967 if (ramSize <= 0) {
968 /* Compute the default RAM size based on the size of screen.
969 * This is only used when the skin doesn't provide the ram
970 * size through its hardware.ini (i.e. legacy ones) or when
971 * in the full Android build system.
972 */
David 'Digit' Turner5377c5b2011-02-10 16:52:19 +0100973 int64_t pixels = hw->hw_lcd_width * hw->hw_lcd_height;
David 'Digit' Turner3bbc9192011-01-19 22:18:02 +0100974 /* The following thresholds are a bit liberal, but we
975 * essentially want to ensure the following mappings:
976 *
977 * 320x480 -> 96
978 * 800x600 -> 128
979 * 1024x768 -> 256
980 *
981 * These are just simple heuristics, they could change in
982 * the future.
983 */
984 if (pixels <= 250000)
985 ramSize = 96;
986 else if (pixels <= 500000)
987 ramSize = 128;
988 else
989 ramSize = 256;
990 }
David 'Digit' Turner5377c5b2011-02-10 16:52:19 +0100991 hw->hw_ramSize = ramSize;
992 }
993
994 D("Physical RAM size: %dMB\n", hw->hw_ramSize);
995
996 if (hw->vm_heapSize == 0) {
997 /* Compute the default heap size based on the RAM size.
998 * Essentially, we want to ensure the following liberal mappings:
999 *
1000 * 96MB RAM -> 16MB heap
1001 * 128MB RAM -> 24MB heap
1002 * 256MB RAM -> 48MB heap
1003 */
1004 int ramSize = hw->hw_ramSize;
1005 int heapSize;
1006
1007 if (ramSize < 100)
1008 heapSize = 16;
1009 else if (ramSize < 192)
1010 heapSize = 24;
1011 else
1012 heapSize = 48;
1013
1014 hw->vm_heapSize = heapSize;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001015 }
1016
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001017 if (opts->trace) {
1018 args[n++] = "-trace";
1019 args[n++] = opts->trace;
1020 args[n++] = "-tracing";
1021 args[n++] = "off";
1022 }
1023
David 'Digit' Turnerc0052462014-02-25 18:39:29 +01001024 /* Pass boot properties to the core. First, those from boot.prop,
David 'Digit' Turner5ea91482014-02-13 18:02:56 +01001025 * then those from the command-line */
1026 const FileData* bootProperties = avdInfo_getBootProperties(avd);
1027 if (!fileData_isEmpty(bootProperties)) {
1028 PropertyFileIterator iter[1];
1029 propertyFileIterator_init(iter,
1030 bootProperties->data,
1031 bootProperties->size);
1032 while (propertyFileIterator_next(iter)) {
1033 char temp[MAX_PROPERTY_NAME_LEN + MAX_PROPERTY_VALUE_LEN + 2];
1034 snprintf(temp, sizeof temp, "%s=%s", iter->name, iter->value);
1035 args[n++] = "-boot-property";
1036 args[n++] = ASTRDUP(temp);
1037 }
1038 }
David 'Digit' Turnerc0052462014-02-25 18:39:29 +01001039
Vladimir Chtchetkineb25bf2a2010-09-08 11:09:23 -07001040 if (opts->prop != NULL) {
1041 ParamList* pl = opts->prop;
1042 for ( ; pl != NULL; pl = pl->next ) {
1043 args[n++] = "-boot-property";
1044 args[n++] = pl->param;
1045 }
1046 }
1047
David 'Digit' Turner318e4f22009-05-25 18:01:03 +02001048 /* Setup the kernel init options
1049 */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001050 {
1051 static char params[1024];
1052 char *p = params, *end = p + sizeof(params);
1053
David 'Digit' Turner062dd6a2011-03-01 14:50:07 +01001054 /* Don't worry about having a leading space here, this is handled
1055 * by the core later. */
1056
Jun Nakajima334ab472011-02-02 23:49:59 -08001057#ifdef TARGET_I386
1058 p = bufprint(p, end, " androidboot.hardware=goldfish");
Jun Nakajimabac9add2011-02-08 22:10:52 -08001059 p = bufprint(p, end, " clocksource=pit");
Jun Nakajima334ab472011-02-02 23:49:59 -08001060#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001061
1062 if (opts->shell || opts->logcat) {
David 'Digit' Turnerc6e0cae2014-03-07 23:08:30 +01001063 p = bufprint(p, end, " androidboot.console=%s%d",
1064 androidHwConfig_getKernelSerialPrefix(android_hw),
1065 shell_serial );
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001066 }
1067
1068 if (opts->trace) {
1069 p = bufprint(p, end, " android.tracing=1");
1070 }
1071
1072 if (!opts->no_jni) {
1073 p = bufprint(p, end, " android.checkjni=1");
1074 }
1075
1076 if (opts->no_boot_anim) {
1077 p = bufprint( p, end, " android.bootanim=0" );
1078 }
1079
1080 if (opts->logcat) {
1081 char* q = bufprint(p, end, " androidboot.logcat=%s", opts->logcat);
1082
1083 if (q < end) {
1084 /* replace any space by a comma ! */
1085 {
1086 int nn;
1087 for (nn = 1; p[nn] != 0; nn++)
1088 if (p[nn] == ' ' || p[nn] == '\t')
1089 p[nn] = ',';
1090 p += nn;
1091 }
1092 }
1093 p = q;
1094 }
1095
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001096 if (opts->bootchart) {
1097 p = bufprint(p, end, " androidboot.bootchart=%s", opts->bootchart);
1098 }
1099
Nick Kralevich185231a2013-10-07 13:54:31 -07001100 if (opts->selinux) {
1101 p = bufprint(p, end, " androidboot.selinux=%s", opts->selinux);
1102 }
1103
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001104 if (p >= end) {
1105 fprintf(stderr, "### ERROR: kernel parameters too long\n");
1106 exit(1);
1107 }
1108
David 'Digit' Turner0b019492011-03-01 14:02:42 +01001109 hw->kernel_parameters = strdup(params);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001110 }
1111
Vladimir Chtchetkined81e6d12010-06-15 16:46:32 -07001112 if (opts->ports) {
1113 args[n++] = "-android-ports";
1114 args[n++] = opts->ports;
1115 }
1116
1117 if (opts->port) {
1118 args[n++] = "-android-port";
1119 args[n++] = opts->port;
1120 }
1121
1122 if (opts->report_console) {
1123 args[n++] = "-android-report-console";
1124 args[n++] = opts->report_console;
1125 }
1126
1127 if (opts->http_proxy) {
1128 args[n++] = "-http-proxy";
1129 args[n++] = opts->http_proxy;
1130 }
1131
Xavier Ducrohet72d56112011-08-11 18:47:27 -07001132 if (!opts->charmap) {
1133 /* Try to find a valid charmap name */
1134 char* charmap = avdInfo_getCharmapFile(avd, hw->hw_keyboard_charmap);
1135 if (charmap != NULL) {
1136 D("autoconfig: -charmap %s", charmap);
1137 opts->charmap = charmap;
1138 }
1139 }
1140
Vladimir Chtchetkine43552dc2010-07-22 11:23:19 -07001141 if (opts->charmap) {
Xavier Ducrohet72d56112011-08-11 18:47:27 -07001142 char charmap_name[AKEYCHARMAP_NAME_SIZE];
1143
1144 if (!path_exists(opts->charmap)) {
1145 derror("Charmap file does not exist: %s", opts->charmap);
1146 exit(1);
1147 }
1148 /* We need to store the charmap name in the hardware configuration.
1149 * However, the charmap file itself is only used by the UI component
1150 * and doesn't need to be set to the emulation engine.
1151 */
1152 kcm_extract_charmap_name(opts->charmap, charmap_name,
1153 sizeof(charmap_name));
David 'Digit' Turnerc5f12b92014-07-11 13:59:57 +02001154 reassign_string(&hw->hw_keyboard_charmap, charmap_name);
Vladimir Chtchetkine43552dc2010-07-22 11:23:19 -07001155 }
1156
David Turner9da935d2011-09-12 21:27:56 +02001157 if (opts->gpu) {
1158 const char* gpu = opts->gpu;
Vladimir Chtchetkineae0d8132011-09-13 10:48:02 -07001159 if (!strcmp(gpu,"on") || !strcmp(gpu,"enable")) {
David Turner9da935d2011-09-12 21:27:56 +02001160 hw->hw_gpu_enabled = 1;
Vladimir Chtchetkineae0d8132011-09-13 10:48:02 -07001161 } else if (!strcmp(gpu,"off") || !strcmp(gpu,"disable")) {
David Turner9da935d2011-09-12 21:27:56 +02001162 hw->hw_gpu_enabled = 0;
1163 } else if (!strcmp(gpu,"auto")) {
1164 /* Nothing to do */
1165 } else {
1166 derror("Invalid value for -gpu <mode> parameter: %s\n", gpu);
1167 derror("Valid values are: on, off or auto\n");
1168 exit(1);
1169 }
1170 }
1171
Vladimir Chtchetkine9242b332012-02-10 08:29:22 -08001172 /* Quit emulator on condition that both, gpu and snapstorage are on. This is
1173 * a temporary solution preventing the emulator from crashing until GPU state
1174 * can be properly saved / resored in snapshot file. */
1175 if (hw->hw_gpu_enabled && opts->snapstorage && (!opts->no_snapshot_load ||
1176 !opts->no_snapshot_save)) {
1177 derror("Snapshots and gpu are mutually exclusive at this point. Please turn one of them off, and restart the emulator.");
1178 exit(1);
1179 }
1180
Vladimir Chtchetkine7485c292012-03-19 11:35:29 -07001181 /* Deal with camera emulation */
1182 if (opts->webcam_list) {
1183 /* List connected webcameras */
1184 args[n++] = "-list-webcam";
1185 }
1186
1187 if (opts->camera_back) {
1188 /* Validate parameter. */
1189 if (memcmp(opts->camera_back, "webcam", 6) &&
1190 strcmp(opts->camera_back, "emulated") &&
1191 strcmp(opts->camera_back, "none")) {
1192 derror("Invalid value for -camera-back <mode> parameter: %s\n"
1193 "Valid values are: 'emulated', 'webcam<N>', or 'none'\n",
1194 opts->camera_back);
Vladimir Chtchetkineae0d8132011-09-13 10:48:02 -07001195 exit(1);
1196 }
Vladimir Chtchetkine7485c292012-03-19 11:35:29 -07001197 hw->hw_camera_back = ASTRDUP(opts->camera_back);
Vladimir Chtchetkineae0d8132011-09-13 10:48:02 -07001198 }
1199
Vladimir Chtchetkine7485c292012-03-19 11:35:29 -07001200 if (opts->camera_front) {
1201 /* Validate parameter. */
1202 if (memcmp(opts->camera_front, "webcam", 6) &&
1203 strcmp(opts->camera_front, "emulated") &&
1204 strcmp(opts->camera_front, "none")) {
1205 derror("Invalid value for -camera-front <mode> parameter: %s\n"
1206 "Valid values are: 'emulated', 'webcam<N>', or 'none'\n",
1207 opts->camera_front);
1208 exit(1);
Vladimir Chtchetkineb8dcaff2011-09-17 11:15:47 -07001209 }
Vladimir Chtchetkine7485c292012-03-19 11:35:29 -07001210 hw->hw_camera_front = ASTRDUP(opts->camera_front);
Vladimir Chtchetkinef8675c22012-01-06 10:31:41 -08001211 }
1212
David 'Digit' Turner5377c5b2011-02-10 16:52:19 +01001213 /* physical memory is now in hw->hw_ramSize */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001214
David 'Digit' Turner53eb66d2011-03-01 14:58:23 +01001215 hw->avd_name = ASTRDUP(avdInfo_getName(avd));
David 'Digit' Turner6b8555c2011-02-17 04:28:19 +01001216
Dries Harnie40beab42010-05-15 17:04:47 +02001217 /* Set up the interfaces for inter-emulator networking */
1218 if (opts->shared_net_id) {
1219 unsigned int shared_net_id = atoi(opts->shared_net_id);
1220 char nic[37];
Dries Harnie40beab42010-05-15 17:04:47 +02001221
1222 args[n++] = "-net";
1223 args[n++] = "nic,vlan=0";
1224 args[n++] = "-net";
1225 args[n++] = "user,vlan=0";
Dries Harnie111d6f82010-06-09 21:42:18 +02001226
1227 args[n++] = "-net";
1228 snprintf(nic, sizeof nic, "nic,vlan=1,macaddr=52:54:00:12:34:%02x", shared_net_id);
1229 args[n++] = strdup(nic);
1230 args[n++] = "-net";
1231 args[n++] = "socket,vlan=1,mcast=230.0.0.10:1234";
Dries Harnie40beab42010-05-15 17:04:47 +02001232 }
1233
David 'Digit' Turner045bdbe2014-04-28 22:26:52 +02001234 /* Handle CPU acceleration options. */
1235 if (opts->no_accel) {
1236 if (opts->accel) {
1237 if (strcmp(opts->accel, "off") != 0) {
1238 derror("You cannot use -no-accel and '-accel %s' at the same time",
1239 opts->accel);
1240 exit(1);
1241 }
1242 } else {
David 'Digit' Turnerc5f12b92014-07-11 13:59:57 +02001243 reassign_string(&opts->accel, "off");
David 'Digit' Turner045bdbe2014-04-28 22:26:52 +02001244 }
1245 }
1246
1247 enum {
1248 ACCEL_OFF = 0,
1249 ACCEL_ON = 1,
1250 ACCEL_AUTO = 2,
1251 } accel_mode = ACCEL_AUTO;
1252
1253 if (opts->accel) {
1254 if (!strcmp(opts->accel, "off")) {
1255 accel_mode = ACCEL_OFF;
1256 } else if (!strcmp(opts->accel, "on")) {
1257 accel_mode = ACCEL_ON;
1258 } else if (!strcmp(opts->accel, "auto")) {
1259 accel_mode = ACCEL_AUTO;
1260 } else {
1261 derror("Invalid '-accel %s' parameter, valid values are: on off auto\n",
1262 opts->accel);
1263 exit(1);
1264 }
1265 }
1266
1267#if defined(TARGET_I386) || defined(TARGET_X86_64)
1268 char* accel_status = NULL;
1269 bool accel_ok = android_hasCpuAcceleration(&accel_status);
1270
1271#ifdef __linux__
David 'Digit' Turner4a889872014-06-25 19:04:34 +02001272 static const char kAccelerator[] = "KVM";
David 'Digit' Turner045bdbe2014-04-28 22:26:52 +02001273 static const char kEnableAccelerator[] = "-enable-kvm";
1274 static const char kDisableAccelerator[] = "-disable-kvm";
1275#else
David 'Digit' Turner4a889872014-06-25 19:04:34 +02001276 static const char kAccelerator[] = "Intel HAXM";
David 'Digit' Turner045bdbe2014-04-28 22:26:52 +02001277 static const char kEnableAccelerator[] = "-enable-hax";
1278 static const char kDisableAccelerator[] = "-disable-hax";
1279#endif
1280
1281 // Dump CPU acceleration status.
1282 if (VERBOSE_CHECK(init)) {
1283 const char* accel_str = "DISABLED";
1284 if (accel_ok) {
1285 if (accel_mode == ACCEL_OFF) {
1286 accel_str = "working, but disabled by user";
1287 } else {
1288 accel_str = "working";
1289 }
1290 }
1291 dprint("CPU Acceleration: %s", accel_str);
1292 dprint("CPU Acceleration status: %s", accel_status);
1293 }
1294
David 'Digit' Turner4a889872014-06-25 19:04:34 +02001295 // Special case: x86_64 emulation currently requires hardware
1296 // acceleration, so refuse to start in 'auto' mode if it is not
1297 // available.
1298 {
1299 char* abi = avdInfo_getTargetAbi(avd);
1300 if (!strcmp(abi, "x86_64")) {
1301 if (!accel_ok && accel_mode != ACCEL_OFF) {
1302 derror("x86_64 emulation currently requires hardware acceleration!\n"
1303 "Please ensure %s is properly installed and usable.\n"
1304 "CPU acceleration status: %s",
1305 kAccelerator, accel_status);
1306 exit(1);
1307 }
1308 else if (accel_mode == ACCEL_OFF) {
1309 // '-no-accel' of '-accel off' was used explicitly. Warn about
1310 // the issue but do not exit.
1311 dwarning("x86_64 emulation may not work without hardware acceleration!");
1312 }
1313 }
1314 AFREE(abi);
1315 }
1316
David 'Digit' Turner045bdbe2014-04-28 22:26:52 +02001317 // CPU acceleration only works for x86 and x86_64 system images.
1318 if (accel_mode == ACCEL_OFF && accel_ok) {
1319 args[n++] = ASTRDUP(kDisableAccelerator);
1320 } else if (accel_mode == ACCEL_ON) {
1321 if (!accel_ok) {
1322 derror("CPU acceleration not supported on this machine!");
1323 derror("Reason: %s", accel_status);
1324 exit(1);
1325 }
1326 args[n++] = ASTRDUP(kEnableAccelerator);
1327 } else {
1328 args[n++] = accel_ok ? ASTRDUP(kEnableAccelerator)
1329 : ASTRDUP(kDisableAccelerator);
1330 }
1331
1332 AFREE(accel_status);
1333#else
1334 (void)accel_mode;
1335
1336 if (VERBOSE_CHECK(init)) {
1337 dwarning("CPU acceleration only works with x86/x86_64 "
1338 "system images.");
1339 }
1340#endif
1341
Vladimir Chtchetkine8dd31e82012-02-15 17:16:04 -08001342 /* Setup screen emulation */
1343 if (opts->screen) {
Vladimir Chtchetkine863d1012012-03-16 12:25:23 -07001344 if (strcmp(opts->screen, "touch") &&
1345 strcmp(opts->screen, "multi-touch") &&
1346 strcmp(opts->screen, "no-touch")) {
1347
1348 derror("Invalid value for -screen <mode> parameter: %s\n"
1349 "Valid values are: touch, multi-touch, or no-touch\n",
1350 opts->screen);
Vladimir Chtchetkine8dd31e82012-02-15 17:16:04 -08001351 exit(1);
1352 }
Vladimir Chtchetkine863d1012012-03-16 12:25:23 -07001353 hw->hw_screen = ASTRDUP(opts->screen);
Vladimir Chtchetkine8dd31e82012-02-15 17:16:04 -08001354 }
1355
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001356 while(argc-- > 0) {
1357 args[n++] = *argv++;
1358 }
1359 args[n] = 0;
1360
David 'Digit' Turner2ed457e2011-06-15 17:29:50 +02001361 /* If the target ABI is armeabi-v7a, we can auto-detect the cpu model
1362 * as a cortex-a8, instead of the default (arm926) which only emulates
1363 * an ARMv5TE CPU.
1364 */
1365 if (!forceArmv7 && hw->hw_cpu_model[0] == '\0')
1366 {
1367 char* abi = avdInfo_getTargetAbi(avd);
1368 if (abi != NULL) {
1369 if (!strcmp(abi, "armeabi-v7a")) {
1370 forceArmv7 = 1;
1371 }
1372 AFREE(abi);
1373 }
1374 }
1375
1376 if (forceArmv7 != 0) {
David 'Digit' Turnerc5f12b92014-07-11 13:59:57 +02001377 reassign_string(&hw->hw_cpu_model, "cortex-a8");
David 'Digit' Turner2ed457e2011-06-15 17:29:50 +02001378 D("Auto-config: -qemu -cpu %s", hw->hw_cpu_model);
1379 }
1380
David 'Digit' Turner7666d5f2014-04-01 15:29:14 +02001381 /* If the target architecture is 'x86', ensure that the 'qemu32'
1382 * CPU model is used. Otherwise, the default (which is now 'qemu64')
1383 * will result in a failure to boot with some kernels under
1384 * un-accelerated emulation.
1385 */
1386 if (hw->hw_cpu_model[0] == '\0') {
1387 char* arch = avdInfo_getTargetCpuArch(avd);
1388 D("Target arch = '%s'", arch ? arch : "NULL");
1389 if (arch != NULL && !strcmp(arch, "x86")) {
David 'Digit' Turnerc5f12b92014-07-11 13:59:57 +02001390 reassign_string(&hw->hw_cpu_model, "qemu32");
David 'Digit' Turner7666d5f2014-04-01 15:29:14 +02001391 D("Auto-config: -qemu -cpu %s", hw->hw_cpu_model);
1392 }
1393 AFREE(arch);
1394 }
1395
David 'Digit' Turner26d41532011-03-01 15:03:07 +01001396 /* Generate a hardware-qemu.ini for this AVD. The real hardware
David 'Digit' Turner622f1532011-02-01 17:48:37 +01001397 * configuration is ususally stored in several files, e.g. the AVD's
1398 * config.ini plus the skin-specific hardware.ini.
1399 *
David 'Digit' Turner26d41532011-03-01 15:03:07 +01001400 * The new file will group all definitions and will be used to
David 'Digit' Turner622f1532011-02-01 17:48:37 +01001401 * launch the core with the -android-hw <file> option.
1402 */
1403 {
David 'Digit' Turner42074e52011-02-10 16:03:28 +01001404 const char* coreHwIniPath = avdInfo_getCoreHwIniPath(avd);
1405 IniFile* hwIni = iniFile_newFromMemory("", NULL);
David 'Digit' Turner622f1532011-02-01 17:48:37 +01001406 androidHwConfig_write(hw, hwIni);
David 'Digit' Turner26d41532011-03-01 15:03:07 +01001407
1408 if (filelock_create(coreHwIniPath) == NULL) {
1409 /* The AVD is already in use, we still support this as an
1410 * experimental feature. Use a temporary hardware-qemu.ini
1411 * file though to avoid overwriting the existing one. */
1412 TempFile* tempIni = tempfile_create();
1413 coreHwIniPath = tempfile_path(tempIni);
1414 }
1415
Vladimir Chtchetkinedb450d72012-01-12 13:37:40 -08001416 /* While saving HW config, ignore valueless entries. This will not break
1417 * anything, but will significantly simplify comparing the current HW
1418 * config with the one that has been associated with a snapshot (in case
1419 * VM starts from a snapshot for this instance of emulator). */
1420 if (iniFile_saveToFileClean(hwIni, coreHwIniPath) < 0) {
David 'Digit' Turner42074e52011-02-10 16:03:28 +01001421 derror("Could not write hardware.ini to %s: %s", coreHwIniPath, strerror(errno));
David 'Digit' Turner622f1532011-02-01 17:48:37 +01001422 exit(2);
1423 }
1424 args[n++] = "-android-hw";
David 'Digit' Turner42074e52011-02-10 16:03:28 +01001425 args[n++] = strdup(coreHwIniPath);
David 'Digit' Turner0a879bf2011-05-12 18:45:18 +02001426
1427 /* In verbose mode, dump the file's content */
1428 if (VERBOSE_CHECK(init)) {
1429 FILE* file = fopen(coreHwIniPath, "rt");
1430 if (file == NULL) {
1431 derror("Could not open hardware configuration file: %s\n",
1432 coreHwIniPath);
1433 } else {
1434 LineInput* input = lineInput_newFromStdFile(file);
1435 const char* line;
1436 printf("Content of hardware configuration file:\n");
1437 while ((line = lineInput_getLine(input)) != NULL) {
1438 printf(" %s\n", line);
1439 }
1440 printf(".\n");
1441 lineInput_free(input);
1442 fclose(file);
1443 }
1444 }
David 'Digit' Turner622f1532011-02-01 17:48:37 +01001445 }
1446
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001447 if(VERBOSE_CHECK(init)) {
1448 int i;
David 'Digit' Turner33361762011-01-19 22:11:03 +01001449 printf("QEMU options list:\n");
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001450 for(i = 0; i < n; i++) {
David 'Digit' Turner33361762011-01-19 22:11:03 +01001451 printf("emulator: argv[%02d] = \"%s\"\n", i, args[i]);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001452 }
David 'Digit' Turner33361762011-01-19 22:11:03 +01001453 /* Dump final command-line option to make debugging the core easier */
1454 printf("Concatenated QEMU options:\n");
1455 for (i = 0; i < n; i++) {
David 'Digit' Turner26722dd2011-02-24 16:40:20 +01001456 /* To make it easier to copy-paste the output to a command-line,
1457 * quote anything that contains spaces.
1458 */
1459 if (strchr(args[i], ' ') != NULL) {
1460 printf(" '%s'", args[i]);
1461 } else {
1462 printf(" %s", args[i]);
1463 }
David 'Digit' Turner33361762011-01-19 22:11:03 +01001464 }
1465 printf("\n");
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001466 }
David 'Digit' Turner74d7ace2011-02-02 13:21:03 +01001467
1468 /* Setup SDL UI just before calling the code */
1469 init_sdl_ui(skinConfig, skinPath, opts);
1470
David 'Digit' Turnerbdb6f2d2011-02-23 15:57:25 +01001471 if (attach_ui_to_core(opts) < 0) {
1472 derror("Can't attach to core!");
1473 exit(1);
1474 }
1475
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001476 return qemu_main(n, args);
1477}