blob: 363c9234db629cb2d6498e58c21ab3d1c478d9b9 [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
81/* the default device DPI if none is specified by the skin
82 */
83#define DEFAULT_DEVICE_DPI 165
84
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080085int qemu_main(int argc, char **argv);
86
87/* this function dumps the QEMU help */
88extern void help( void );
89extern void emulator_help( void );
90
91#define VERBOSE_OPT(str,var) { str, &var }
92
93#define _VERBOSE_TAG(x,y) { #x, VERBOSE_##x, y },
94static const struct { const char* name; int flag; const char* text; }
95verbose_options[] = {
96 VERBOSE_TAG_LIST
97 { 0, 0, 0 }
98};
99
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800100void emulator_help( void )
101{
102 STRALLOC_DEFINE(out);
103 android_help_main(out);
104 printf( "%.*s", out->n, out->s );
105 stralloc_reset(out);
106 exit(1);
107}
108
David 'Digit' Turner40841b22011-03-01 14:04:00 +0100109/* TODO: Put in shared source file */
110static char*
111_getFullFilePath( const char* rootPath, const char* fileName )
112{
113 if (path_is_absolute(fileName)) {
114 return ASTRDUP(fileName);
115 } else {
116 char temp[PATH_MAX], *p=temp, *end=p+sizeof(temp);
117
118 p = bufprint(temp, end, "%s/%s", rootPath, fileName);
119 if (p >= end) {
120 return NULL;
121 }
122 return ASTRDUP(temp);
123 }
124}
125
126static uint64_t
127_adjustPartitionSize( const char* description,
128 uint64_t imageBytes,
129 uint64_t defaultBytes,
130 int inAndroidBuild )
131{
132 char temp[64];
133 unsigned imageMB;
134 unsigned defaultMB;
135
136 if (imageBytes <= defaultBytes)
137 return defaultBytes;
138
139 imageMB = convertBytesToMB(imageBytes);
140 defaultMB = convertBytesToMB(defaultBytes);
141
142 if (imageMB > defaultMB) {
143 snprintf(temp, sizeof temp, "(%d MB > %d MB)", imageMB, defaultMB);
144 } else {
Andrew Hsiehc7389bd2012-03-13 02:13:40 -0700145 snprintf(temp, sizeof temp, "(%" PRIu64 " bytes > %" PRIu64 " bytes)", imageBytes, defaultBytes);
David 'Digit' Turner40841b22011-03-01 14:04:00 +0100146 }
147
148 if (inAndroidBuild) {
149 dwarning("%s partition size adjusted to match image file %s\n", description, temp);
150 }
151
152 return convertMBToBytes(imageMB);
153}
154
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800155int main(int argc, char **argv)
156{
157 char tmp[MAX_PATH];
158 char* tmpend = tmp + sizeof(tmp);
159 char* args[128];
160 int n;
161 char* opt;
David 'Digit' Turner5e736932011-03-18 00:02:14 +0100162 /* The emulator always uses the first serial port for kernel messages
163 * and the second one for qemud. So start at the third if we need one
164 * for logcat or 'shell'
165 */
166 int serial = 2;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800167 int shell_serial = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800168
David 'Digit' Turner2ed457e2011-06-15 17:29:50 +0200169 int forceArmv7 = 0;
170
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800171 AndroidHwConfig* hw;
David 'Digit' Turnercd059b12009-08-28 19:36:27 +0200172 AvdInfo* avd;
David 'Digit' Turner74d7ace2011-02-02 13:21:03 +0100173 AConfig* skinConfig;
174 char* skinPath;
Vladimir Chtchetkine83ffd662011-02-11 12:40:59 -0800175 int inAndroidBuild;
Vladimir Chtchetkine88078b82012-04-19 12:24:38 -0700176 uint64_t defaultPartitionSize = convertMBToBytes(200);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800177
178 AndroidOptions opts[1];
Vladimir Chtchetkineb25bf2a2010-09-08 11:09:23 -0700179 /* net.shared_net_ip boot property value. */
180 char boot_prop_ip[64];
181 boot_prop_ip[0] = '\0';
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800182
183 args[0] = argv[0];
184
185 if ( android_parse_options( &argc, &argv, opts ) < 0 ) {
186 exit(1);
187 }
188
David 'Digit' Turnerbdb6f2d2011-02-23 15:57:25 +0100189#ifdef _WIN32
190 socket_init();
191#endif
192
193 handle_ui_options(opts);
194
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800195 while (argc-- > 1) {
196 opt = (++argv)[0];
197
198 if(!strcmp(opt, "-qemu")) {
199 argc--;
200 argv++;
201 break;
202 }
203
204 if (!strcmp(opt, "-help")) {
205 emulator_help();
206 }
207
208 if (!strncmp(opt, "-help-",6)) {
209 STRALLOC_DEFINE(out);
210 opt += 6;
211
212 if (!strcmp(opt, "all")) {
213 android_help_all(out);
214 }
215 else if (android_help_for_option(opt, out) == 0) {
216 /* ok */
217 }
218 else if (android_help_for_topic(opt, out) == 0) {
219 /* ok */
220 }
221 if (out->n > 0) {
222 printf("\n%.*s", out->n, out->s);
223 exit(0);
224 }
225
226 fprintf(stderr, "unknown option: -help-%s\n", opt);
227 fprintf(stderr, "please use -help for a list of valid topics\n");
228 exit(1);
229 }
230
231 if (opt[0] == '-') {
232 fprintf(stderr, "unknown option: %s\n", opt);
233 fprintf(stderr, "please use -help for a list of valid options\n");
234 exit(1);
235 }
236
237 fprintf(stderr, "invalid command-line parameter: %s.\n", opt);
238 fprintf(stderr, "Hint: use '@foo' to launch a virtual device named 'foo'.\n");
239 fprintf(stderr, "please use -help for more information\n");
240 exit(1);
241 }
242
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800243 if (opts->version) {
244 printf("Android emulator version %s\n"
David 'Digit' Turner5f64b872011-02-28 23:23:05 +0100245 "Copyright (C) 2006-2011 The Android Open Source Project and many others.\n"
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800246 "This program is a derivative of the QEMU CPU emulator (www.qemu.org).\n\n",
247#if defined ANDROID_BUILD_ID
248 VERSION_STRING " (build_id " STRINGIFY(ANDROID_BUILD_ID) ")" );
249#else
250 VERSION_STRING);
251#endif
252 printf(" This software is licensed under the terms of the GNU General Public\n"
253 " License version 2, as published by the Free Software Foundation, and\n"
254 " may be copied, distributed, and modified under those terms.\n\n"
255 " This program is distributed in the hope that it will be useful,\n"
256 " but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
257 " MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
258 " GNU General Public License for more details.\n\n");
259
260 exit(0);
261 }
262
David 'Digit' Turner5f64b872011-02-28 23:23:05 +0100263 if (opts->snapshot_list) {
David 'Digit' Turnerd80a7862011-05-05 10:24:43 +0200264 if (opts->snapstorage == NULL) {
265 /* Need to find the default snapstorage */
266 avd = createAVD(opts, &inAndroidBuild);
267 opts->snapstorage = avdInfo_getSnapStoragePath(avd);
268 if (opts->snapstorage != NULL) {
269 D("autoconfig: -snapstorage %s", opts->snapstorage);
270 } else {
271 if (inAndroidBuild) {
272 derror("You must use the -snapstorage <file> option to specify a snapshot storage file!\n");
273 } else {
274 derror("This AVD doesn't have snapshotting enabled!\n");
275 }
276 exit(1);
277 }
278 }
David 'Digit' Turner5f64b872011-02-28 23:23:05 +0100279 snapshot_print_and_exit(opts->snapstorage);
280 }
281
David 'Digit' Turner25eb6552011-02-25 15:07:11 +0100282 sanitizeOptions(opts);
283
David 'Digit' Turnerbdb6f2d2011-02-23 15:57:25 +0100284 /* Initialization of UI started with -attach-core should work differently
285 * than initialization of UI that starts the core. In particular....
286 */
287
288 /* -charmap is incompatible with -attach-core, because particular
289 * charmap gets set up in the running core. */
David 'Digit' Turner74d7ace2011-02-02 13:21:03 +0100290 if (android_charmap_setup(opts->charmap)) {
291 exit(1);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800292 }
293
Vladimir Chtchetkine83ffd662011-02-11 12:40:59 -0800294 /* Parses options and builds an appropriate AVD. */
David 'Digit' Turner462564f2011-02-23 13:32:37 +0100295 avd = android_avdInfo = createAVD(opts, &inAndroidBuild);
David 'Digit' Turnercd059b12009-08-28 19:36:27 +0200296
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800297 /* get the skin from the virtual device configuration */
David 'Digit' Turner25eb6552011-02-25 15:07:11 +0100298 if (opts->skindir != NULL) {
299 if (opts->skin == NULL) {
300 /* NOTE: Normally handled by sanitizeOptions(), just be safe */
301 derror("The -skindir <path> option requires a -skin <name> option");
302 exit(2);
303 }
304 } else {
305 char* skinName;
306 char* skinDir;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800307
David 'Digit' Turner25eb6552011-02-25 15:07:11 +0100308 avdInfo_getSkinInfo(avd, &skinName, &skinDir);
309
310 if (opts->skin == NULL) {
311 opts->skin = skinName;
312 D("autoconfig: -skin %s", opts->skin);
313 } else {
314 AFREE(skinName);
315 }
316
317 opts->skindir = skinDir;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800318 D("autoconfig: -skindir %s", opts->skindir);
Xavier Ducrohet689d1142012-04-19 12:54:08 -0700319
320 /* update the avd hw config from this new skin */
321 avdInfo_getSkinHardwareIni(avd, opts->skin, opts->skindir);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800322 }
323
Siva Velusamyd8999182012-10-08 18:02:30 -0700324 if (opts->dynamic_skin == 0) {
325 opts->dynamic_skin = avdInfo_shouldUseDynamicSkin(avd);
326 }
327
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800328 /* Read hardware configuration */
329 hw = android_hw;
David 'Digit' Turnerb64325d2011-03-22 16:07:01 +0100330 if (avdInfo_initHwConfig(avd, hw) < 0) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800331 derror("could not read hardware configuration ?");
332 exit(1);
333 }
334
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800335 if (opts->keyset) {
336 parse_keyset(opts->keyset, opts);
337 if (!android_keyset) {
338 fprintf(stderr,
339 "emulator: WARNING: could not find keyset file named '%s',"
340 " using defaults instead\n",
341 opts->keyset);
342 }
343 }
344 if (!android_keyset) {
345 parse_keyset("default", opts);
346 if (!android_keyset) {
347 android_keyset = skin_keyset_new_from_text( skin_keyset_get_default() );
348 if (!android_keyset) {
349 fprintf(stderr, "PANIC: default keyset file is corrupted !!\n" );
350 fprintf(stderr, "PANIC: please update the code in android/skin/keyset.c\n" );
351 exit(1);
352 }
353 if (!opts->keyset)
354 write_default_keyset();
355 }
356 }
357
Dries Harnie40beab42010-05-15 17:04:47 +0200358 if (opts->shared_net_id) {
359 char* end;
360 long shared_net_id = strtol(opts->shared_net_id, &end, 0);
361 if (end == NULL || *end || shared_net_id < 1 || shared_net_id > 255) {
362 fprintf(stderr, "option -shared-net-id must be an integer between 1 and 255\n");
363 exit(1);
364 }
Vladimir Chtchetkineb25bf2a2010-09-08 11:09:23 -0700365 snprintf(boot_prop_ip, sizeof(boot_prop_ip),
366 "net.shared_net_ip=10.1.2.%ld", shared_net_id);
Dries Harnie40beab42010-05-15 17:04:47 +0200367 }
368
369
David 'Digit' Turner755811e2011-02-07 13:38:25 +0100370 user_config_init();
David 'Digit' Turner2507cab2011-02-10 16:29:17 +0100371 parse_skin_files(opts->skindir, opts->skin, opts, hw,
David 'Digit' Turner74d7ace2011-02-02 13:21:03 +0100372 &skinConfig, &skinPath);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800373
David 'Digit' Turner092361e2011-03-01 13:14:18 +0100374 if (!opts->netspeed && skin_network_speed) {
375 D("skin network speed: '%s'", skin_network_speed);
376 if (strcmp(skin_network_speed, NETWORK_SPEED_DEFAULT) != 0) {
377 opts->netspeed = (char*)skin_network_speed;
378 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800379 }
David 'Digit' Turner092361e2011-03-01 13:14:18 +0100380 if (!opts->netdelay && skin_network_delay) {
381 D("skin network delay: '%s'", skin_network_delay);
382 if (strcmp(skin_network_delay, NETWORK_DELAY_DEFAULT) != 0) {
383 opts->netdelay = (char*)skin_network_delay;
384 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800385 }
386
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800387 if (opts->trace) {
David 'Digit' Turnercd059b12009-08-28 19:36:27 +0200388 char* tracePath = avdInfo_getTracePath(avd, opts->trace);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800389 int ret;
390
391 if (tracePath == NULL) {
392 derror( "bad -trace parameter" );
393 exit(1);
394 }
395 ret = path_mkdir_if_needed( tracePath, 0755 );
396 if (ret < 0) {
397 fprintf(stderr, "could not create directory '%s'\n", tmp);
398 exit(2);
399 }
400 opts->trace = tracePath;
401 }
402
Vladimir Chtchetkine33f89d02011-09-28 09:19:09 -0700403 /* Update CPU architecture for HW configs created from build dir. */
404 if (inAndroidBuild) {
405#if defined(TARGET_ARM)
406 free(android_hw->hw_cpu_arch);
407 android_hw->hw_cpu_arch = ASTRDUP("arm");
408#elif defined(TARGET_I386)
409 free(android_hw->hw_cpu_arch);
410 android_hw->hw_cpu_arch = ASTRDUP("x86");
Bhanu Chetlapalli741dc132012-05-08 17:16:03 -0700411#elif defined(TARGET_MIPS)
412 free(android_hw->hw_cpu_arch);
413 android_hw->hw_cpu_arch = ASTRDUP("mips");
Vladimir Chtchetkine33f89d02011-09-28 09:19:09 -0700414#endif
415 }
416
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800417 n = 1;
418 /* generate arguments for the underlying qemu main() */
David 'Digit' Turner238b4b02009-09-20 13:10:19 -0700419 {
David 'Digit' Turner0b019492011-03-01 14:02:42 +0100420 char* kernelFile = opts->kernel;
421 int kernelFileLen;
David 'Digit' Turner238b4b02009-09-20 13:10:19 -0700422
David 'Digit' Turner0b019492011-03-01 14:02:42 +0100423 if (kernelFile == NULL) {
424 kernelFile = avdInfo_getKernelPath(avd);
425 if (kernelFile == NULL) {
426 derror( "This AVD's configuration is missing a kernel file!!" );
427 exit(2);
428 }
429 D("autoconfig: -kernel %s", kernelFile);
430 }
431 if (!path_exists(kernelFile)) {
432 derror( "Invalid or missing kernel image file: %s", kernelFile );
433 exit(2);
434 }
435
436 hw->kernel_path = kernelFile;
David 'Digit' Turner238b4b02009-09-20 13:10:19 -0700437
438 /* If the kernel image name ends in "-armv7", then change the cpu
439 * type automatically. This is a poor man's approach to configuration
440 * management, but should allow us to get past building ARMv7
441 * system images with dex preopt pass without introducing too many
442 * changes to the emulator sources.
443 *
444 * XXX:
445 * A 'proper' change would require adding some sort of hardware-property
446 * to each AVD config file, then automatically determine its value for
447 * full Android builds (depending on some environment variable), plus
448 * some build system changes. I prefer not to do that for now for reasons
449 * of simplicity.
450 */
David 'Digit' Turner0b019492011-03-01 14:02:42 +0100451 kernelFileLen = strlen(kernelFile);
David 'Digit' Turner238b4b02009-09-20 13:10:19 -0700452 if (kernelFileLen > 6 && !memcmp(kernelFile + kernelFileLen - 6, "-armv7", 6)) {
David 'Digit' Turner2ed457e2011-06-15 17:29:50 +0200453 forceArmv7 = 1;
David 'Digit' Turner238b4b02009-09-20 13:10:19 -0700454 }
455 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800456
David 'Digit' Turnercc5804c2014-06-12 19:26:27 +0200457 KernelType kernelType = KERNEL_TYPE_LEGACY;
458 if (!android_pathProbeKernelType(hw->kernel_path, &kernelType)) {
459 D("WARNING: Could not determine kernel device naming scheme. Assuming legacy\n"
460 "If this AVD doesn't boot, and uses a recent kernel (3.10 or above) try setting\n"
461 "'kernel.newDeviceNaming' to 'yes' in its configuration.\n");
462 }
463
David 'Digit' Turnerc6e0cae2014-03-07 23:08:30 +0100464 // Auto-detect kernel device naming scheme if needed.
465 if (androidHwConfig_getKernelDeviceNaming(hw) < 0) {
David 'Digit' Turnerc6e0cae2014-03-07 23:08:30 +0100466 const char* newDeviceNaming = "no";
David 'Digit' Turnercc5804c2014-06-12 19:26:27 +0200467 if (kernelType == KERNEL_TYPE_3_10_OR_ABOVE) {
David 'Digit' Turnerc6e0cae2014-03-07 23:08:30 +0100468 D("Auto-detect: Kernel image requires new device naming scheme.");
469 newDeviceNaming = "yes";
470 } else {
471 D("Auto-detect: Kernel image requires legacy device naming scheme.");
472 }
473 AFREE(hw->kernel_newDeviceNaming);
474 hw->kernel_newDeviceNaming = ASTRDUP(newDeviceNaming);
475 }
476
David 'Digit' Turnercc5804c2014-06-12 19:26:27 +0200477 // Auto-detect YAFFS2 partition support if needed.
478 if (androidHwConfig_getKernelYaffs2Support(hw) < 0) {
479 const char* newYaffs2Support = "no";
480 if (kernelType == KERNEL_TYPE_3_10_OR_ABOVE) {
481 D("Auto-detect: Kernel does not support YAFFS2 partitions.");
482 } else {
483 D("Auto-detect: Kernel does support YAFFS2 partitions.");
484 newYaffs2Support = "yes";
485 }
486 AFREE(hw->kernel_supportsYaffs2);
487 hw->kernel_supportsYaffs2 = ASTRDUP(newYaffs2Support);
488 }
489
Vladimir Chtchetkineb25bf2a2010-09-08 11:09:23 -0700490 if (boot_prop_ip[0]) {
491 args[n++] = "-boot-property";
492 args[n++] = boot_prop_ip;
493 }
494
Vladimir Chtchetkine318f17a2010-08-27 09:09:45 -0700495 if (opts->tcpdump) {
496 args[n++] = "-tcpdump";
497 args[n++] = opts->tcpdump;
498 }
499
Vladimir Chtchetkinee1316862010-08-26 09:03:54 -0700500#ifdef CONFIG_NAND_LIMITS
501 if (opts->nand_limits) {
502 args[n++] = "-nand-limits";
503 args[n++] = opts->nand_limits;
504 }
505#endif
506
David 'Digit' Turner74d7ace2011-02-02 13:21:03 +0100507 if (opts->timezone) {
508 args[n++] = "-timezone";
509 args[n++] = opts->timezone;
510 }
511
Vladimir Chtchetkinee1316862010-08-26 09:03:54 -0700512 if (opts->netspeed) {
513 args[n++] = "-netspeed";
514 args[n++] = opts->netspeed;
515 }
516 if (opts->netdelay) {
517 args[n++] = "-netdelay";
518 args[n++] = opts->netdelay;
519 }
520 if (opts->netfast) {
521 args[n++] = "-netfast";
522 }
523
Vladimir Chtchetkineb2438402010-08-24 08:55:33 -0700524 if (opts->audio) {
525 args[n++] = "-audio";
526 args[n++] = opts->audio;
527 }
528
Vladimir Chtchetkineb2438402010-08-24 08:55:33 -0700529 if (opts->cpu_delay) {
530 args[n++] = "-cpu-delay";
531 args[n++] = opts->cpu_delay;
532 }
533
Vladimir Chtchetkine7fbf4972010-08-11 15:30:32 -0700534 if (opts->dns_server) {
535 args[n++] = "-dns-server";
536 args[n++] = opts->dns_server;
537 }
538
David 'Digit' Turner9ff69722011-09-13 12:32:52 +0200539 /* opts->ramdisk is never NULL (see createAVD) here */
540 if (opts->ramdisk) {
541 AFREE(hw->disk_ramdisk_path);
542 hw->disk_ramdisk_path = ASTRDUP(opts->ramdisk);
543 }
544 else if (!hw->disk_ramdisk_path[0]) {
545 hw->disk_ramdisk_path = avdInfo_getRamdiskPath(avd);
546 D("autoconfig: -ramdisk %s", hw->disk_ramdisk_path);
547 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800548
David 'Digit' Turner40841b22011-03-01 14:04:00 +0100549 /* -partition-size is used to specify the max size of both the system
550 * and data partition sizes.
551 */
552 if (opts->partition_size) {
553 char* end;
554 long sizeMB = strtol(opts->partition_size, &end, 0);
555 long minSizeMB = 10;
556 long maxSizeMB = LONG_MAX / ONE_MB;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800557
David 'Digit' Turner40841b22011-03-01 14:04:00 +0100558 if (sizeMB < 0 || *end != 0) {
559 derror( "-partition-size must be followed by a positive integer" );
560 exit(1);
561 }
562 if (sizeMB < minSizeMB || sizeMB > maxSizeMB) {
563 derror( "partition-size (%d) must be between %dMB and %dMB",
564 sizeMB, minSizeMB, maxSizeMB );
565 exit(1);
566 }
567 defaultPartitionSize = (uint64_t) sizeMB * ONE_MB;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800568 }
569
David 'Digit' Turner40841b22011-03-01 14:04:00 +0100570
571 /** SYSTEM PARTITION **/
572
573 if (opts->sysdir == NULL) {
574 if (avdInfo_inAndroidBuild(avd)) {
575 opts->sysdir = ASTRDUP(avdInfo_getContentPath(avd));
576 D("autoconfig: -sysdir %s", opts->sysdir);
577 }
578 }
579
580 if (opts->sysdir != NULL) {
581 if (!path_exists(opts->sysdir)) {
582 derror("Directory does not exist: %s", opts->sysdir);
583 exit(1);
584 }
585 }
586
587 {
588 char* rwImage = NULL;
589 char* initImage = NULL;
590
591 do {
592 if (opts->system == NULL) {
593 /* If -system is not used, try to find a runtime system image
594 * (i.e. system-qemu.img) in the content directory.
595 */
596 rwImage = avdInfo_getSystemImagePath(avd);
597 if (rwImage != NULL) {
598 break;
599 }
600 /* Otherwise, try to find the initial system image */
601 initImage = avdInfo_getSystemInitImagePath(avd);
602 if (initImage == NULL) {
603 derror("No initial system image for this configuration!");
604 exit(1);
605 }
606 break;
607 }
608
609 /* If -system <name> is used, use it to find the initial image */
David 'Digit' Turnerea283772011-07-07 04:40:27 +0200610 if (opts->sysdir != NULL && !path_exists(opts->system)) {
David 'Digit' Turner40841b22011-03-01 14:04:00 +0100611 initImage = _getFullFilePath(opts->sysdir, opts->system);
612 } else {
613 initImage = ASTRDUP(opts->system);
614 }
615 if (!path_exists(initImage)) {
616 derror("System image file doesn't exist: %s", initImage);
617 exit(1);
618 }
619
620 } while (0);
621
622 if (rwImage != NULL) {
623 /* Use the read/write image file directly */
624 hw->disk_systemPartition_path = rwImage;
625 hw->disk_systemPartition_initPath = NULL;
626 D("Using direct system image: %s", rwImage);
627 } else if (initImage != NULL) {
628 hw->disk_systemPartition_path = NULL;
629 hw->disk_systemPartition_initPath = initImage;
630 D("Using initial system image: %s", initImage);
631 }
632
633 /* Check the size of the system partition image.
634 * If we have an AVD, it must be smaller than
635 * the disk.systemPartition.size hardware property.
636 *
637 * Otherwise, we need to adjust the systemPartitionSize
638 * automatically, and print a warning.
639 *
640 */
641 const char* systemImage = hw->disk_systemPartition_path;
642 uint64_t systemBytes;
643
644 if (systemImage == NULL)
645 systemImage = hw->disk_systemPartition_initPath;
646
647 if (path_get_size(systemImage, &systemBytes) < 0) {
648 derror("Missing system image: %s", systemImage);
649 exit(1);
650 }
651
652 hw->disk_systemPartition_size =
653 _adjustPartitionSize("system", systemBytes, defaultPartitionSize,
654 avdInfo_inAndroidBuild(avd));
655 }
656
657 /** DATA PARTITION **/
658
David 'Digit' Turnerfd59c332011-03-01 00:48:52 +0100659 if (opts->datadir) {
660 if (!path_exists(opts->datadir)) {
661 derror("Invalid -datadir directory: %s", opts->datadir);
662 }
663 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800664
David 'Digit' Turnerfd59c332011-03-01 00:48:52 +0100665 {
666 char* dataImage = NULL;
667 char* initImage = NULL;
668
669 do {
670 if (!opts->data) {
671 dataImage = avdInfo_getDataImagePath(avd);
672 if (dataImage != NULL) {
673 D("autoconfig: -data %s", dataImage);
674 break;
675 }
676 dataImage = avdInfo_getDefaultDataImagePath(avd);
677 if (dataImage == NULL) {
678 derror("No data image path for this configuration!");
679 exit (1);
680 }
681 opts->wipe_data = 1;
682 break;
683 }
684
685 if (opts->datadir) {
686 dataImage = _getFullFilePath(opts->datadir, opts->data);
687 } else {
688 dataImage = ASTRDUP(opts->data);
689 }
690 } while (0);
691
692 if (opts->initdata != NULL) {
693 initImage = ASTRDUP(opts->initdata);
694 if (!path_exists(initImage)) {
695 derror("Invalid initial data image path: %s", initImage);
696 exit(1);
697 }
698 } else {
699 initImage = avdInfo_getDataInitImagePath(avd);
700 D("autoconfig: -initdata %s", initImage);
701 }
702
703 hw->disk_dataPartition_path = dataImage;
704 if (opts->wipe_data) {
705 hw->disk_dataPartition_initPath = initImage;
706 } else {
707 hw->disk_dataPartition_initPath = NULL;
708 }
709
Maciek Molerusf7584112011-06-15 22:26:35 +0200710 uint64_t defaultBytes =
711 hw->disk_dataPartition_size == 0 ?
712 defaultPartitionSize :
Vladimir Chtchetkined4f5a3a2012-03-08 14:20:20 -0800713 hw->disk_dataPartition_size;
David 'Digit' Turnerfd59c332011-03-01 00:48:52 +0100714 uint64_t dataBytes;
715 const char* dataPath = hw->disk_dataPartition_initPath;
716
717 if (dataPath == NULL)
718 dataPath = hw->disk_dataPartition_path;
719
720 path_get_size(dataPath, &dataBytes);
721
722 hw->disk_dataPartition_size =
723 _adjustPartitionSize("data", dataBytes, defaultBytes,
724 avdInfo_inAndroidBuild(avd));
725 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800726
David 'Digit' Turnerc480cca2011-02-25 16:43:34 +0100727 /** CACHE PARTITION **/
728
729 if (opts->no_cache) {
730 /* No cache partition at all */
731 hw->disk_cachePartition = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800732 }
David 'Digit' Turnerc480cca2011-02-25 16:43:34 +0100733 else if (!hw->disk_cachePartition) {
734 if (opts->cache) {
735 dwarning( "Emulated hardware doesn't support a cache partition. -cache option ignored!" );
736 opts->cache = NULL;
737 }
738 }
739 else
740 {
741 if (!opts->cache) {
742 /* Find the current cache partition file */
743 opts->cache = avdInfo_getCachePath(avd);
744 if (opts->cache == NULL) {
745 /* The file does not exists, we will force its creation
746 * if we are not in the Android build system. Otherwise,
747 * a temporary file will be used.
748 */
749 if (!avdInfo_inAndroidBuild(avd)) {
750 opts->cache = avdInfo_getDefaultCachePath(avd);
751 }
752 }
David 'Digit' Turner48a3c662011-03-01 14:03:20 +0100753 if (opts->cache) {
754 D("autoconfig: -cache %s", opts->cache);
755 }
David 'Digit' Turnerc480cca2011-02-25 16:43:34 +0100756 }
757
758 if (opts->cache) {
759 hw->disk_cachePartition_path = ASTRDUP(opts->cache);
760 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800761 }
762
Vladimir Chtchetkine6f50aa32012-04-26 08:20:18 -0700763 if (hw->disk_cachePartition_path && opts->cache_size) {
764 /* Set cache partition size per user options. */
765 char* end;
766 long sizeMB = strtol(opts->cache_size, &end, 0);
767
768 if (sizeMB < 0 || *end != 0) {
769 derror( "-cache-size must be followed by a positive integer" );
770 exit(1);
771 }
772 hw->disk_cachePartition_size = (uint64_t) sizeMB * ONE_MB;
773 }
774
David 'Digit' Turnerc480cca2011-02-25 16:43:34 +0100775 /** SD CARD PARTITION */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800776
David 'Digit' Turner48a3c662011-03-01 14:03:20 +0100777 if (!hw->hw_sdCard) {
778 /* No SD Card emulation, so -sdcard will be ignored */
779 if (opts->sdcard) {
780 dwarning( "Emulated hardware doesn't support SD Cards. -sdcard option ignored." );
781 opts->sdcard = NULL;
782 }
783 } else {
784 /* Auto-configure -sdcard if it is not available */
785 if (!opts->sdcard) {
786 do {
787 /* If -datadir <path> is used, look for a sdcard.img file here */
788 if (opts->datadir) {
789 bufprint(tmp, tmpend, "%s/%s", opts->datadir, "system.img");
790 if (path_exists(tmp)) {
791 opts->sdcard = strdup(tmp);
792 break;
793 }
794 }
795
796 /* Otherwise, look at the AVD's content */
797 opts->sdcard = avdInfo_getSdCardPath(avd);
798 if (opts->sdcard != NULL) {
799 break;
800 }
801
802 /* Nothing */
803 } while (0);
804
805 if (opts->sdcard) {
806 D("autoconfig: -sdcard %s", opts->sdcard);
807 }
808 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800809 }
810
811 if(opts->sdcard) {
812 uint64_t size;
813 if (path_get_size(opts->sdcard, &size) == 0) {
814 /* see if we have an sdcard image. get its size if it exists */
David 'Digit' Turner8b657e52009-12-01 13:38:21 -0800815 /* due to what looks like limitations of the MMC protocol, one has
816 * to use an SD Card image that is equal or larger than 9 MB
817 */
818 if (size < 9*1024*1024ULL) {
819 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 -0800820 } else {
David 'Digit' Turner48a3c662011-03-01 14:03:20 +0100821 hw->hw_sdCard_path = ASTRDUP(opts->sdcard);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800822 }
823 } else {
David 'Digit' Turner48a3c662011-03-01 14:03:20 +0100824 dwarning("no SD Card image at '%s'", opts->sdcard);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800825 }
826 }
827
David 'Digit' Turner48a3c662011-03-01 14:03:20 +0100828
829 /** SNAPSHOT STORAGE HANDLING */
830
David 'Digit' Turner5f64b872011-02-28 23:23:05 +0100831 /* Determine snapstorage path. -no-snapstorage disables all snapshotting
832 * support. This means you can't resume a snapshot at load, save it at
833 * exit, or even load/save them dynamically at runtime with the console.
834 */
835 if (opts->no_snapstorage) {
836
837 if (opts->snapshot) {
838 dwarning("ignoring -snapshot option due to the use of -no-snapstorage");
839 opts->snapshot = NULL;
840 }
841
842 if (opts->snapstorage) {
843 dwarning("ignoring -snapstorage option due to the use of -no-snapstorage");
844 opts->snapstorage = NULL;
845 }
846 }
847 else
848 {
Vladimir Chtchetkine873c3cb2012-03-14 12:46:51 -0700849 if (!opts->snapstorage && avdInfo_getSnapshotPresent(avd)) {
David 'Digit' Turner5f64b872011-02-28 23:23:05 +0100850 opts->snapstorage = avdInfo_getSnapStoragePath(avd);
851 if (opts->snapstorage != NULL) {
852 D("autoconfig: -snapstorage %s", opts->snapstorage);
Ot ten Thije353b3b12010-10-05 17:53:30 +0100853 }
854 }
855
David 'Digit' Turner5f64b872011-02-28 23:23:05 +0100856 if (opts->snapstorage && !path_exists(opts->snapstorage)) {
857 D("no image at '%s', state snapshots disabled", opts->snapstorage);
858 opts->snapstorage = NULL;
Ot ten Thije353b3b12010-10-05 17:53:30 +0100859 }
David 'Digit' Turner5f64b872011-02-28 23:23:05 +0100860 }
861
862 /* If we have a valid snapshot storage path */
863
864 if (opts->snapstorage) {
865
866 hw->disk_snapStorage_path = ASTRDUP(opts->snapstorage);
867
868 /* -no-snapshot is equivalent to using both -no-snapshot-load
869 * and -no-snapshot-save. You can still load/save snapshots dynamically
870 * from the console though.
871 */
872 if (opts->no_snapshot) {
873
874 opts->no_snapshot_load = 1;
875 opts->no_snapshot_save = 1;
876
877 if (opts->snapshot) {
878 dwarning("ignoring -snapshot option due to the use of -no-snapshot.");
879 }
880 }
881
882 if (!opts->no_snapshot_load || !opts->no_snapshot_save) {
883 if (opts->snapshot == NULL) {
884 opts->snapshot = "default-boot";
885 D("autoconfig: -snapshot %s", opts->snapshot);
886 }
887 }
888
889 /* We still use QEMU command-line options for the following since
890 * they can change from one invokation to the next and don't really
891 * correspond to the hardware configuration itself.
892 */
893 if (!opts->no_snapshot_load) {
894 args[n++] = "-loadvm";
895 args[n++] = ASTRDUP(opts->snapshot);
896 }
897
898 if (!opts->no_snapshot_save) {
899 args[n++] = "-savevm-on-exit";
900 args[n++] = ASTRDUP(opts->snapshot);
901 }
902
Tim Baverstock622b8f42010-12-07 11:36:59 +0000903 if (opts->no_snapshot_update_time) {
David 'Digit' Turnerbdb6f2d2011-02-23 15:57:25 +0100904 args[n++] = "-snapshot-no-time-update";
Tim Baverstock622b8f42010-12-07 11:36:59 +0000905 }
Ot ten Thijeae835ac2010-10-18 13:37:37 +0100906 }
Ot ten Thije353b3b12010-10-05 17:53:30 +0100907
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800908 if (!opts->logcat || opts->logcat[0] == 0) {
909 opts->logcat = getenv("ANDROID_LOG_TAGS");
910 if (opts->logcat && opts->logcat[0] == 0)
911 opts->logcat = NULL;
912 }
913
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800914 /* we always send the kernel messages from ttyS0 to android_kmsg */
David 'Digit' Turner062dd6a2011-03-01 14:50:07 +0100915 if (opts->show_kernel) {
916 args[n++] = "-show-kernel";
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800917 }
918
919 /* XXXX: TODO: implement -shell and -logcat through qemud instead */
920 if (!opts->shell_serial) {
921#ifdef _WIN32
922 opts->shell_serial = "con:";
923#else
924 opts->shell_serial = "stdio";
925#endif
926 }
927 else
928 opts->shell = 1;
929
930 if (opts->shell || opts->logcat) {
931 args[n++] = "-serial";
932 args[n++] = opts->shell_serial;
933 shell_serial = serial++;
934 }
935
David 'Digit' Turner062dd6a2011-03-01 14:50:07 +0100936 if (opts->radio) {
937 args[n++] = "-radio";
938 args[n++] = opts->radio;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800939 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800940
David 'Digit' Turner062dd6a2011-03-01 14:50:07 +0100941 if (opts->gps) {
942 args[n++] = "-gps";
943 args[n++] = opts->gps;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800944 }
945
Nick Kralevich185231a2013-10-07 13:54:31 -0700946 if (opts->selinux) {
947 if ((strcmp(opts->selinux, "permissive") != 0)
948 && (strcmp(opts->selinux, "disabled") != 0)) {
949 derror("-selinux must be \"disabled\" or \"permissive\"");
950 exit(1);
951 }
952 }
953
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800954 if (opts->memory) {
955 char* end;
956 long ramSize = strtol(opts->memory, &end, 0);
957 if (ramSize < 0 || *end != 0) {
958 derror( "-memory must be followed by a positive integer" );
959 exit(1);
960 }
961 if (ramSize < 32 || ramSize > 4096) {
962 derror( "physical memory size must be between 32 and 4096 MB" );
963 exit(1);
964 }
David 'Digit' Turner5377c5b2011-02-10 16:52:19 +0100965 hw->hw_ramSize = ramSize;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800966 }
967 if (!opts->memory) {
David 'Digit' Turner3bbc9192011-01-19 22:18:02 +0100968 int ramSize = hw->hw_ramSize;
969 if (ramSize <= 0) {
970 /* Compute the default RAM size based on the size of screen.
971 * This is only used when the skin doesn't provide the ram
972 * size through its hardware.ini (i.e. legacy ones) or when
973 * in the full Android build system.
974 */
David 'Digit' Turner5377c5b2011-02-10 16:52:19 +0100975 int64_t pixels = hw->hw_lcd_width * hw->hw_lcd_height;
David 'Digit' Turner3bbc9192011-01-19 22:18:02 +0100976 /* The following thresholds are a bit liberal, but we
977 * essentially want to ensure the following mappings:
978 *
979 * 320x480 -> 96
980 * 800x600 -> 128
981 * 1024x768 -> 256
982 *
983 * These are just simple heuristics, they could change in
984 * the future.
985 */
986 if (pixels <= 250000)
987 ramSize = 96;
988 else if (pixels <= 500000)
989 ramSize = 128;
990 else
991 ramSize = 256;
992 }
David 'Digit' Turner5377c5b2011-02-10 16:52:19 +0100993 hw->hw_ramSize = ramSize;
994 }
995
996 D("Physical RAM size: %dMB\n", hw->hw_ramSize);
997
998 if (hw->vm_heapSize == 0) {
999 /* Compute the default heap size based on the RAM size.
1000 * Essentially, we want to ensure the following liberal mappings:
1001 *
1002 * 96MB RAM -> 16MB heap
1003 * 128MB RAM -> 24MB heap
1004 * 256MB RAM -> 48MB heap
1005 */
1006 int ramSize = hw->hw_ramSize;
1007 int heapSize;
1008
1009 if (ramSize < 100)
1010 heapSize = 16;
1011 else if (ramSize < 192)
1012 heapSize = 24;
1013 else
1014 heapSize = 48;
1015
1016 hw->vm_heapSize = heapSize;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001017 }
1018
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001019 if (opts->trace) {
1020 args[n++] = "-trace";
1021 args[n++] = opts->trace;
1022 args[n++] = "-tracing";
1023 args[n++] = "off";
1024 }
1025
David 'Digit' Turnerc0052462014-02-25 18:39:29 +01001026 /* Pass boot properties to the core. First, those from boot.prop,
David 'Digit' Turner5ea91482014-02-13 18:02:56 +01001027 * then those from the command-line */
1028 const FileData* bootProperties = avdInfo_getBootProperties(avd);
1029 if (!fileData_isEmpty(bootProperties)) {
1030 PropertyFileIterator iter[1];
1031 propertyFileIterator_init(iter,
1032 bootProperties->data,
1033 bootProperties->size);
1034 while (propertyFileIterator_next(iter)) {
1035 char temp[MAX_PROPERTY_NAME_LEN + MAX_PROPERTY_VALUE_LEN + 2];
1036 snprintf(temp, sizeof temp, "%s=%s", iter->name, iter->value);
1037 args[n++] = "-boot-property";
1038 args[n++] = ASTRDUP(temp);
1039 }
1040 }
David 'Digit' Turnerc0052462014-02-25 18:39:29 +01001041
Vladimir Chtchetkineb25bf2a2010-09-08 11:09:23 -07001042 if (opts->prop != NULL) {
1043 ParamList* pl = opts->prop;
1044 for ( ; pl != NULL; pl = pl->next ) {
1045 args[n++] = "-boot-property";
1046 args[n++] = pl->param;
1047 }
1048 }
1049
David 'Digit' Turner318e4f22009-05-25 18:01:03 +02001050 /* Setup the kernel init options
1051 */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001052 {
1053 static char params[1024];
1054 char *p = params, *end = p + sizeof(params);
1055
David 'Digit' Turner062dd6a2011-03-01 14:50:07 +01001056 /* Don't worry about having a leading space here, this is handled
1057 * by the core later. */
1058
Jun Nakajima334ab472011-02-02 23:49:59 -08001059#ifdef TARGET_I386
1060 p = bufprint(p, end, " androidboot.hardware=goldfish");
Jun Nakajimabac9add2011-02-08 22:10:52 -08001061 p = bufprint(p, end, " clocksource=pit");
Jun Nakajima334ab472011-02-02 23:49:59 -08001062#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001063
1064 if (opts->shell || opts->logcat) {
David 'Digit' Turnerc6e0cae2014-03-07 23:08:30 +01001065 p = bufprint(p, end, " androidboot.console=%s%d",
1066 androidHwConfig_getKernelSerialPrefix(android_hw),
1067 shell_serial );
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001068 }
1069
1070 if (opts->trace) {
1071 p = bufprint(p, end, " android.tracing=1");
1072 }
1073
1074 if (!opts->no_jni) {
1075 p = bufprint(p, end, " android.checkjni=1");
1076 }
1077
1078 if (opts->no_boot_anim) {
1079 p = bufprint( p, end, " android.bootanim=0" );
1080 }
1081
1082 if (opts->logcat) {
1083 char* q = bufprint(p, end, " androidboot.logcat=%s", opts->logcat);
1084
1085 if (q < end) {
1086 /* replace any space by a comma ! */
1087 {
1088 int nn;
1089 for (nn = 1; p[nn] != 0; nn++)
1090 if (p[nn] == ' ' || p[nn] == '\t')
1091 p[nn] = ',';
1092 p += nn;
1093 }
1094 }
1095 p = q;
1096 }
1097
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001098 if (opts->bootchart) {
1099 p = bufprint(p, end, " androidboot.bootchart=%s", opts->bootchart);
1100 }
1101
Nick Kralevich185231a2013-10-07 13:54:31 -07001102 if (opts->selinux) {
1103 p = bufprint(p, end, " androidboot.selinux=%s", opts->selinux);
1104 }
1105
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001106 if (p >= end) {
1107 fprintf(stderr, "### ERROR: kernel parameters too long\n");
1108 exit(1);
1109 }
1110
David 'Digit' Turner0b019492011-03-01 14:02:42 +01001111 hw->kernel_parameters = strdup(params);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001112 }
1113
Vladimir Chtchetkined81e6d12010-06-15 16:46:32 -07001114 if (opts->ports) {
1115 args[n++] = "-android-ports";
1116 args[n++] = opts->ports;
1117 }
1118
1119 if (opts->port) {
1120 args[n++] = "-android-port";
1121 args[n++] = opts->port;
1122 }
1123
1124 if (opts->report_console) {
1125 args[n++] = "-android-report-console";
1126 args[n++] = opts->report_console;
1127 }
1128
1129 if (opts->http_proxy) {
1130 args[n++] = "-http-proxy";
1131 args[n++] = opts->http_proxy;
1132 }
1133
Xavier Ducrohet72d56112011-08-11 18:47:27 -07001134 if (!opts->charmap) {
1135 /* Try to find a valid charmap name */
1136 char* charmap = avdInfo_getCharmapFile(avd, hw->hw_keyboard_charmap);
1137 if (charmap != NULL) {
1138 D("autoconfig: -charmap %s", charmap);
1139 opts->charmap = charmap;
1140 }
1141 }
1142
Vladimir Chtchetkine43552dc2010-07-22 11:23:19 -07001143 if (opts->charmap) {
Xavier Ducrohet72d56112011-08-11 18:47:27 -07001144 char charmap_name[AKEYCHARMAP_NAME_SIZE];
1145
1146 if (!path_exists(opts->charmap)) {
1147 derror("Charmap file does not exist: %s", opts->charmap);
1148 exit(1);
1149 }
1150 /* We need to store the charmap name in the hardware configuration.
1151 * However, the charmap file itself is only used by the UI component
1152 * and doesn't need to be set to the emulation engine.
1153 */
1154 kcm_extract_charmap_name(opts->charmap, charmap_name,
1155 sizeof(charmap_name));
1156 AFREE(hw->hw_keyboard_charmap);
1157 hw->hw_keyboard_charmap = ASTRDUP(charmap_name);
Vladimir Chtchetkine43552dc2010-07-22 11:23:19 -07001158 }
1159
Vladimir Chtchetkineb5365f32010-08-09 13:33:57 -07001160 if (opts->memcheck) {
1161 args[n++] = "-android-memcheck";
1162 args[n++] = opts->memcheck;
1163 }
1164
David Turner9da935d2011-09-12 21:27:56 +02001165 if (opts->gpu) {
1166 const char* gpu = opts->gpu;
Vladimir Chtchetkineae0d8132011-09-13 10:48:02 -07001167 if (!strcmp(gpu,"on") || !strcmp(gpu,"enable")) {
David Turner9da935d2011-09-12 21:27:56 +02001168 hw->hw_gpu_enabled = 1;
Vladimir Chtchetkineae0d8132011-09-13 10:48:02 -07001169 } else if (!strcmp(gpu,"off") || !strcmp(gpu,"disable")) {
David Turner9da935d2011-09-12 21:27:56 +02001170 hw->hw_gpu_enabled = 0;
1171 } else if (!strcmp(gpu,"auto")) {
1172 /* Nothing to do */
1173 } else {
1174 derror("Invalid value for -gpu <mode> parameter: %s\n", gpu);
1175 derror("Valid values are: on, off or auto\n");
1176 exit(1);
1177 }
1178 }
1179
Vladimir Chtchetkine9242b332012-02-10 08:29:22 -08001180 /* Quit emulator on condition that both, gpu and snapstorage are on. This is
1181 * a temporary solution preventing the emulator from crashing until GPU state
1182 * can be properly saved / resored in snapshot file. */
1183 if (hw->hw_gpu_enabled && opts->snapstorage && (!opts->no_snapshot_load ||
1184 !opts->no_snapshot_save)) {
1185 derror("Snapshots and gpu are mutually exclusive at this point. Please turn one of them off, and restart the emulator.");
1186 exit(1);
1187 }
1188
Vladimir Chtchetkine7485c292012-03-19 11:35:29 -07001189 /* Deal with camera emulation */
1190 if (opts->webcam_list) {
1191 /* List connected webcameras */
1192 args[n++] = "-list-webcam";
1193 }
1194
1195 if (opts->camera_back) {
1196 /* Validate parameter. */
1197 if (memcmp(opts->camera_back, "webcam", 6) &&
1198 strcmp(opts->camera_back, "emulated") &&
1199 strcmp(opts->camera_back, "none")) {
1200 derror("Invalid value for -camera-back <mode> parameter: %s\n"
1201 "Valid values are: 'emulated', 'webcam<N>', or 'none'\n",
1202 opts->camera_back);
Vladimir Chtchetkineae0d8132011-09-13 10:48:02 -07001203 exit(1);
1204 }
Vladimir Chtchetkine7485c292012-03-19 11:35:29 -07001205 hw->hw_camera_back = ASTRDUP(opts->camera_back);
Vladimir Chtchetkineae0d8132011-09-13 10:48:02 -07001206 }
1207
Vladimir Chtchetkine7485c292012-03-19 11:35:29 -07001208 if (opts->camera_front) {
1209 /* Validate parameter. */
1210 if (memcmp(opts->camera_front, "webcam", 6) &&
1211 strcmp(opts->camera_front, "emulated") &&
1212 strcmp(opts->camera_front, "none")) {
1213 derror("Invalid value for -camera-front <mode> parameter: %s\n"
1214 "Valid values are: 'emulated', 'webcam<N>', or 'none'\n",
1215 opts->camera_front);
1216 exit(1);
Vladimir Chtchetkineb8dcaff2011-09-17 11:15:47 -07001217 }
Vladimir Chtchetkine7485c292012-03-19 11:35:29 -07001218 hw->hw_camera_front = ASTRDUP(opts->camera_front);
Vladimir Chtchetkinef8675c22012-01-06 10:31:41 -08001219 }
1220
David 'Digit' Turner5377c5b2011-02-10 16:52:19 +01001221 /* physical memory is now in hw->hw_ramSize */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001222
David 'Digit' Turner53eb66d2011-03-01 14:58:23 +01001223 hw->avd_name = ASTRDUP(avdInfo_getName(avd));
David 'Digit' Turner6b8555c2011-02-17 04:28:19 +01001224
Dries Harnie40beab42010-05-15 17:04:47 +02001225 /* Set up the interfaces for inter-emulator networking */
1226 if (opts->shared_net_id) {
1227 unsigned int shared_net_id = atoi(opts->shared_net_id);
1228 char nic[37];
Dries Harnie40beab42010-05-15 17:04:47 +02001229
1230 args[n++] = "-net";
1231 args[n++] = "nic,vlan=0";
1232 args[n++] = "-net";
1233 args[n++] = "user,vlan=0";
Dries Harnie111d6f82010-06-09 21:42:18 +02001234
1235 args[n++] = "-net";
1236 snprintf(nic, sizeof nic, "nic,vlan=1,macaddr=52:54:00:12:34:%02x", shared_net_id);
1237 args[n++] = strdup(nic);
1238 args[n++] = "-net";
1239 args[n++] = "socket,vlan=1,mcast=230.0.0.10:1234";
Dries Harnie40beab42010-05-15 17:04:47 +02001240 }
1241
David 'Digit' Turner045bdbe2014-04-28 22:26:52 +02001242 /* Handle CPU acceleration options. */
1243 if (opts->no_accel) {
1244 if (opts->accel) {
1245 if (strcmp(opts->accel, "off") != 0) {
1246 derror("You cannot use -no-accel and '-accel %s' at the same time",
1247 opts->accel);
1248 exit(1);
1249 }
1250 } else {
1251 AFREE(opts->accel);
1252 opts->accel = ASTRDUP("off");
1253 }
1254 }
1255
1256 enum {
1257 ACCEL_OFF = 0,
1258 ACCEL_ON = 1,
1259 ACCEL_AUTO = 2,
1260 } accel_mode = ACCEL_AUTO;
1261
1262 if (opts->accel) {
1263 if (!strcmp(opts->accel, "off")) {
1264 accel_mode = ACCEL_OFF;
1265 } else if (!strcmp(opts->accel, "on")) {
1266 accel_mode = ACCEL_ON;
1267 } else if (!strcmp(opts->accel, "auto")) {
1268 accel_mode = ACCEL_AUTO;
1269 } else {
1270 derror("Invalid '-accel %s' parameter, valid values are: on off auto\n",
1271 opts->accel);
1272 exit(1);
1273 }
1274 }
1275
1276#if defined(TARGET_I386) || defined(TARGET_X86_64)
1277 char* accel_status = NULL;
1278 bool accel_ok = android_hasCpuAcceleration(&accel_status);
1279
1280#ifdef __linux__
1281 static const char kEnableAccelerator[] = "-enable-kvm";
1282 static const char kDisableAccelerator[] = "-disable-kvm";
1283#else
1284 static const char kEnableAccelerator[] = "-enable-hax";
1285 static const char kDisableAccelerator[] = "-disable-hax";
1286#endif
1287
1288 // Dump CPU acceleration status.
1289 if (VERBOSE_CHECK(init)) {
1290 const char* accel_str = "DISABLED";
1291 if (accel_ok) {
1292 if (accel_mode == ACCEL_OFF) {
1293 accel_str = "working, but disabled by user";
1294 } else {
1295 accel_str = "working";
1296 }
1297 }
1298 dprint("CPU Acceleration: %s", accel_str);
1299 dprint("CPU Acceleration status: %s", accel_status);
1300 }
1301
1302 // CPU acceleration only works for x86 and x86_64 system images.
1303 if (accel_mode == ACCEL_OFF && accel_ok) {
1304 args[n++] = ASTRDUP(kDisableAccelerator);
1305 } else if (accel_mode == ACCEL_ON) {
1306 if (!accel_ok) {
1307 derror("CPU acceleration not supported on this machine!");
1308 derror("Reason: %s", accel_status);
1309 exit(1);
1310 }
1311 args[n++] = ASTRDUP(kEnableAccelerator);
1312 } else {
1313 args[n++] = accel_ok ? ASTRDUP(kEnableAccelerator)
1314 : ASTRDUP(kDisableAccelerator);
1315 }
1316
1317 AFREE(accel_status);
1318#else
1319 (void)accel_mode;
1320
1321 if (VERBOSE_CHECK(init)) {
1322 dwarning("CPU acceleration only works with x86/x86_64 "
1323 "system images.");
1324 }
1325#endif
1326
Vladimir Chtchetkine8dd31e82012-02-15 17:16:04 -08001327 /* Setup screen emulation */
1328 if (opts->screen) {
Vladimir Chtchetkine863d1012012-03-16 12:25:23 -07001329 if (strcmp(opts->screen, "touch") &&
1330 strcmp(opts->screen, "multi-touch") &&
1331 strcmp(opts->screen, "no-touch")) {
1332
1333 derror("Invalid value for -screen <mode> parameter: %s\n"
1334 "Valid values are: touch, multi-touch, or no-touch\n",
1335 opts->screen);
Vladimir Chtchetkine8dd31e82012-02-15 17:16:04 -08001336 exit(1);
1337 }
Vladimir Chtchetkine863d1012012-03-16 12:25:23 -07001338 hw->hw_screen = ASTRDUP(opts->screen);
Vladimir Chtchetkine8dd31e82012-02-15 17:16:04 -08001339 }
1340
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001341 while(argc-- > 0) {
1342 args[n++] = *argv++;
1343 }
1344 args[n] = 0;
1345
David 'Digit' Turner2ed457e2011-06-15 17:29:50 +02001346 /* If the target ABI is armeabi-v7a, we can auto-detect the cpu model
1347 * as a cortex-a8, instead of the default (arm926) which only emulates
1348 * an ARMv5TE CPU.
1349 */
1350 if (!forceArmv7 && hw->hw_cpu_model[0] == '\0')
1351 {
1352 char* abi = avdInfo_getTargetAbi(avd);
1353 if (abi != NULL) {
1354 if (!strcmp(abi, "armeabi-v7a")) {
1355 forceArmv7 = 1;
1356 }
1357 AFREE(abi);
1358 }
1359 }
1360
1361 if (forceArmv7 != 0) {
1362 AFREE(hw->hw_cpu_model);
1363 hw->hw_cpu_model = ASTRDUP("cortex-a8");
1364 D("Auto-config: -qemu -cpu %s", hw->hw_cpu_model);
1365 }
1366
David 'Digit' Turner7666d5f2014-04-01 15:29:14 +02001367 /* If the target architecture is 'x86', ensure that the 'qemu32'
1368 * CPU model is used. Otherwise, the default (which is now 'qemu64')
1369 * will result in a failure to boot with some kernels under
1370 * un-accelerated emulation.
1371 */
1372 if (hw->hw_cpu_model[0] == '\0') {
1373 char* arch = avdInfo_getTargetCpuArch(avd);
1374 D("Target arch = '%s'", arch ? arch : "NULL");
1375 if (arch != NULL && !strcmp(arch, "x86")) {
1376 AFREE(hw->hw_cpu_model);
1377 hw->hw_cpu_model = ASTRDUP("qemu32");
1378 D("Auto-config: -qemu -cpu %s", hw->hw_cpu_model);
1379 }
1380 AFREE(arch);
1381 }
1382
David 'Digit' Turner26d41532011-03-01 15:03:07 +01001383 /* Generate a hardware-qemu.ini for this AVD. The real hardware
David 'Digit' Turner622f1532011-02-01 17:48:37 +01001384 * configuration is ususally stored in several files, e.g. the AVD's
1385 * config.ini plus the skin-specific hardware.ini.
1386 *
David 'Digit' Turner26d41532011-03-01 15:03:07 +01001387 * The new file will group all definitions and will be used to
David 'Digit' Turner622f1532011-02-01 17:48:37 +01001388 * launch the core with the -android-hw <file> option.
1389 */
1390 {
David 'Digit' Turner42074e52011-02-10 16:03:28 +01001391 const char* coreHwIniPath = avdInfo_getCoreHwIniPath(avd);
1392 IniFile* hwIni = iniFile_newFromMemory("", NULL);
David 'Digit' Turner622f1532011-02-01 17:48:37 +01001393 androidHwConfig_write(hw, hwIni);
David 'Digit' Turner26d41532011-03-01 15:03:07 +01001394
1395 if (filelock_create(coreHwIniPath) == NULL) {
1396 /* The AVD is already in use, we still support this as an
1397 * experimental feature. Use a temporary hardware-qemu.ini
1398 * file though to avoid overwriting the existing one. */
1399 TempFile* tempIni = tempfile_create();
1400 coreHwIniPath = tempfile_path(tempIni);
1401 }
1402
Vladimir Chtchetkinedb450d72012-01-12 13:37:40 -08001403 /* While saving HW config, ignore valueless entries. This will not break
1404 * anything, but will significantly simplify comparing the current HW
1405 * config with the one that has been associated with a snapshot (in case
1406 * VM starts from a snapshot for this instance of emulator). */
1407 if (iniFile_saveToFileClean(hwIni, coreHwIniPath) < 0) {
David 'Digit' Turner42074e52011-02-10 16:03:28 +01001408 derror("Could not write hardware.ini to %s: %s", coreHwIniPath, strerror(errno));
David 'Digit' Turner622f1532011-02-01 17:48:37 +01001409 exit(2);
1410 }
1411 args[n++] = "-android-hw";
David 'Digit' Turner42074e52011-02-10 16:03:28 +01001412 args[n++] = strdup(coreHwIniPath);
David 'Digit' Turner0a879bf2011-05-12 18:45:18 +02001413
1414 /* In verbose mode, dump the file's content */
1415 if (VERBOSE_CHECK(init)) {
1416 FILE* file = fopen(coreHwIniPath, "rt");
1417 if (file == NULL) {
1418 derror("Could not open hardware configuration file: %s\n",
1419 coreHwIniPath);
1420 } else {
1421 LineInput* input = lineInput_newFromStdFile(file);
1422 const char* line;
1423 printf("Content of hardware configuration file:\n");
1424 while ((line = lineInput_getLine(input)) != NULL) {
1425 printf(" %s\n", line);
1426 }
1427 printf(".\n");
1428 lineInput_free(input);
1429 fclose(file);
1430 }
1431 }
David 'Digit' Turner622f1532011-02-01 17:48:37 +01001432 }
1433
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001434 if(VERBOSE_CHECK(init)) {
1435 int i;
David 'Digit' Turner33361762011-01-19 22:11:03 +01001436 printf("QEMU options list:\n");
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001437 for(i = 0; i < n; i++) {
David 'Digit' Turner33361762011-01-19 22:11:03 +01001438 printf("emulator: argv[%02d] = \"%s\"\n", i, args[i]);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001439 }
David 'Digit' Turner33361762011-01-19 22:11:03 +01001440 /* Dump final command-line option to make debugging the core easier */
1441 printf("Concatenated QEMU options:\n");
1442 for (i = 0; i < n; i++) {
David 'Digit' Turner26722dd2011-02-24 16:40:20 +01001443 /* To make it easier to copy-paste the output to a command-line,
1444 * quote anything that contains spaces.
1445 */
1446 if (strchr(args[i], ' ') != NULL) {
1447 printf(" '%s'", args[i]);
1448 } else {
1449 printf(" %s", args[i]);
1450 }
David 'Digit' Turner33361762011-01-19 22:11:03 +01001451 }
1452 printf("\n");
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001453 }
David 'Digit' Turner74d7ace2011-02-02 13:21:03 +01001454
1455 /* Setup SDL UI just before calling the code */
1456 init_sdl_ui(skinConfig, skinPath, opts);
1457
David 'Digit' Turnerbdb6f2d2011-02-23 15:57:25 +01001458 if (attach_ui_to_core(opts) < 0) {
1459 derror("Can't attach to core!");
1460 exit(1);
1461 }
1462
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001463 return qemu_main(n, args);
1464}