1 /* 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
20
21 #include "sockets.h"
22
23 #include "android/android.h"
24 #include "qemu-common.h"
25 #include "sysemu.h"
26 #include "console.h"
27 #include "user-events.h"
28
29 #include <SDL.h>
30 #include <SDL_syswm.h>
31
32 #include "math.h"
33
34 #include "android/charmap.h"
35 #include "android/utils/debug.h"
36 #include "android/config.h"
37 #include "android/config/config.h"
38
39 #include "android/user-config.h"
40 #include "android/utils/bufprint.h"
41 #include "android/utils/filelock.h"
42 #include "android/utils/lineinput.h"
43 #include "android/utils/path.h"
44 #include "android/utils/tempfile.h"
45
46 #include "android/main-common.h"
47 #include "android/help.h"
48 #include "hw/goldfish_nand.h"
49
50 #include "android/globals.h"
51
52 #include "android/qemulator.h"
53 #include "android/display.h"
54
55 #include "android/snapshot.h"
56
57 #include "android/framebuffer.h"
58 #include "iolooper.h"
59
60 AndroidRotation android_framebuffer_rotation;
61
62 #define STRINGIFY(x) _STRINGIFY(x)
63 #define _STRINGIFY(x) #x
64
65 #ifdef ANDROID_SDK_TOOLS_REVISION
66 # define VERSION_STRING STRINGIFY(ANDROID_SDK_TOOLS_REVISION)".0"
67 #else
68 # define VERSION_STRING "standalone"
69 #endif
70
71 #define D(...) do { if (VERBOSE_CHECK(init)) dprint(__VA_ARGS__); } while (0)
72
73 extern int control_console_start( int port ); /* in control.c */
74
75 extern int qemu_milli_needed;
76
77 /* the default device DPI if none is specified by the skin
78 */
79 #define DEFAULT_DEVICE_DPI 165
80
81 #ifdef CONFIG_TRACE
82 extern void start_tracing(void);
83 extern void stop_tracing(void);
84 #endif
85
86 unsigned long android_verbose;
87
88 int qemu_main(int argc, char **argv);
89
90 /* this function dumps the QEMU help */
91 extern void help( void );
92 extern void emulator_help( void );
93
94 #define VERBOSE_OPT(str,var) { str, &var }
95
96 #define _VERBOSE_TAG(x,y) { #x, VERBOSE_##x, y },
97 static const struct { const char* name; int flag; const char* text; }
98 verbose_options[] = {
99 VERBOSE_TAG_LIST
100 { 0, 0, 0 }
101 };
102
emulator_help(void)103 void emulator_help( void )
104 {
105 STRALLOC_DEFINE(out);
106 android_help_main(out);
107 printf( "%.*s", out->n, out->s );
108 stralloc_reset(out);
109 exit(1);
110 }
111
112 /* TODO: Put in shared source file */
113 static char*
_getFullFilePath(const char * rootPath,const char * fileName)114 _getFullFilePath( const char* rootPath, const char* fileName )
115 {
116 if (path_is_absolute(fileName)) {
117 return ASTRDUP(fileName);
118 } else {
119 char temp[PATH_MAX], *p=temp, *end=p+sizeof(temp);
120
121 p = bufprint(temp, end, "%s/%s", rootPath, fileName);
122 if (p >= end) {
123 return NULL;
124 }
125 return ASTRDUP(temp);
126 }
127 }
128
129 static uint64_t
_adjustPartitionSize(const char * description,uint64_t imageBytes,uint64_t defaultBytes,int inAndroidBuild)130 _adjustPartitionSize( const char* description,
131 uint64_t imageBytes,
132 uint64_t defaultBytes,
133 int inAndroidBuild )
134 {
135 char temp[64];
136 unsigned imageMB;
137 unsigned defaultMB;
138
139 if (imageBytes <= defaultBytes)
140 return defaultBytes;
141
142 imageMB = convertBytesToMB(imageBytes);
143 defaultMB = convertBytesToMB(defaultBytes);
144
145 if (imageMB > defaultMB) {
146 snprintf(temp, sizeof temp, "(%d MB > %d MB)", imageMB, defaultMB);
147 } else {
148 snprintf(temp, sizeof temp, "(%" PRIu64 " bytes > %" PRIu64 " bytes)", imageBytes, defaultBytes);
149 }
150
151 if (inAndroidBuild) {
152 dwarning("%s partition size adjusted to match image file %s\n", description, temp);
153 }
154
155 return convertMBToBytes(imageMB);
156 }
157
main(int argc,char ** argv)158 int main(int argc, char **argv)
159 {
160 char tmp[MAX_PATH];
161 char* tmpend = tmp + sizeof(tmp);
162 char* args[128];
163 int n;
164 char* opt;
165 /* The emulator always uses the first serial port for kernel messages
166 * and the second one for qemud. So start at the third if we need one
167 * for logcat or 'shell'
168 */
169 int serial = 2;
170 int shell_serial = 0;
171
172 int forceArmv7 = 0;
173
174 AndroidHwConfig* hw;
175 AvdInfo* avd;
176 AConfig* skinConfig;
177 char* skinPath;
178 int inAndroidBuild;
179 uint64_t defaultPartitionSize = convertMBToBytes(200);
180
181 AndroidOptions opts[1];
182 /* net.shared_net_ip boot property value. */
183 char boot_prop_ip[64];
184 boot_prop_ip[0] = '\0';
185
186 args[0] = argv[0];
187
188 if ( android_parse_options( &argc, &argv, opts ) < 0 ) {
189 exit(1);
190 }
191
192 #ifdef _WIN32
193 socket_init();
194 #endif
195
196 handle_ui_options(opts);
197
198 while (argc-- > 1) {
199 opt = (++argv)[0];
200
201 if(!strcmp(opt, "-qemu")) {
202 argc--;
203 argv++;
204 break;
205 }
206
207 if (!strcmp(opt, "-help")) {
208 emulator_help();
209 }
210
211 if (!strncmp(opt, "-help-",6)) {
212 STRALLOC_DEFINE(out);
213 opt += 6;
214
215 if (!strcmp(opt, "all")) {
216 android_help_all(out);
217 }
218 else if (android_help_for_option(opt, out) == 0) {
219 /* ok */
220 }
221 else if (android_help_for_topic(opt, out) == 0) {
222 /* ok */
223 }
224 if (out->n > 0) {
225 printf("\n%.*s", out->n, out->s);
226 exit(0);
227 }
228
229 fprintf(stderr, "unknown option: -help-%s\n", opt);
230 fprintf(stderr, "please use -help for a list of valid topics\n");
231 exit(1);
232 }
233
234 if (opt[0] == '-') {
235 fprintf(stderr, "unknown option: %s\n", opt);
236 fprintf(stderr, "please use -help for a list of valid options\n");
237 exit(1);
238 }
239
240 fprintf(stderr, "invalid command-line parameter: %s.\n", opt);
241 fprintf(stderr, "Hint: use '@foo' to launch a virtual device named 'foo'.\n");
242 fprintf(stderr, "please use -help for more information\n");
243 exit(1);
244 }
245
246 if (opts->version) {
247 printf("Android emulator version %s\n"
248 "Copyright (C) 2006-2011 The Android Open Source Project and many others.\n"
249 "This program is a derivative of the QEMU CPU emulator (www.qemu.org).\n\n",
250 #if defined ANDROID_BUILD_ID
251 VERSION_STRING " (build_id " STRINGIFY(ANDROID_BUILD_ID) ")" );
252 #else
253 VERSION_STRING);
254 #endif
255 printf(" This software is licensed under the terms of the GNU General Public\n"
256 " License version 2, as published by the Free Software Foundation, and\n"
257 " may be copied, distributed, and modified under those terms.\n\n"
258 " This program is distributed in the hope that it will be useful,\n"
259 " but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
260 " MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
261 " GNU General Public License for more details.\n\n");
262
263 exit(0);
264 }
265
266 if (opts->snapshot_list) {
267 if (opts->snapstorage == NULL) {
268 /* Need to find the default snapstorage */
269 avd = createAVD(opts, &inAndroidBuild);
270 opts->snapstorage = avdInfo_getSnapStoragePath(avd);
271 if (opts->snapstorage != NULL) {
272 D("autoconfig: -snapstorage %s", opts->snapstorage);
273 } else {
274 if (inAndroidBuild) {
275 derror("You must use the -snapstorage <file> option to specify a snapshot storage file!\n");
276 } else {
277 derror("This AVD doesn't have snapshotting enabled!\n");
278 }
279 exit(1);
280 }
281 }
282 snapshot_print_and_exit(opts->snapstorage);
283 }
284
285 sanitizeOptions(opts);
286
287 /* Initialization of UI started with -attach-core should work differently
288 * than initialization of UI that starts the core. In particular....
289 */
290
291 /* -charmap is incompatible with -attach-core, because particular
292 * charmap gets set up in the running core. */
293 if (android_charmap_setup(opts->charmap)) {
294 exit(1);
295 }
296
297 /* Parses options and builds an appropriate AVD. */
298 avd = android_avdInfo = createAVD(opts, &inAndroidBuild);
299
300 /* get the skin from the virtual device configuration */
301 if (opts->skindir != NULL) {
302 if (opts->skin == NULL) {
303 /* NOTE: Normally handled by sanitizeOptions(), just be safe */
304 derror("The -skindir <path> option requires a -skin <name> option");
305 exit(2);
306 }
307 } else {
308 char* skinName;
309 char* skinDir;
310
311 avdInfo_getSkinInfo(avd, &skinName, &skinDir);
312
313 if (opts->skin == NULL) {
314 opts->skin = skinName;
315 D("autoconfig: -skin %s", opts->skin);
316 } else {
317 AFREE(skinName);
318 }
319
320 opts->skindir = skinDir;
321 D("autoconfig: -skindir %s", opts->skindir);
322
323 /* update the avd hw config from this new skin */
324 avdInfo_getSkinHardwareIni(avd, opts->skin, opts->skindir);
325 }
326
327 /* Read hardware configuration */
328 hw = android_hw;
329 if (avdInfo_initHwConfig(avd, hw) < 0) {
330 derror("could not read hardware configuration ?");
331 exit(1);
332 }
333
334 if (opts->keyset) {
335 parse_keyset(opts->keyset, opts);
336 if (!android_keyset) {
337 fprintf(stderr,
338 "emulator: WARNING: could not find keyset file named '%s',"
339 " using defaults instead\n",
340 opts->keyset);
341 }
342 }
343 if (!android_keyset) {
344 parse_keyset("default", opts);
345 if (!android_keyset) {
346 android_keyset = skin_keyset_new_from_text( skin_keyset_get_default() );
347 if (!android_keyset) {
348 fprintf(stderr, "PANIC: default keyset file is corrupted !!\n" );
349 fprintf(stderr, "PANIC: please update the code in android/skin/keyset.c\n" );
350 exit(1);
351 }
352 if (!opts->keyset)
353 write_default_keyset();
354 }
355 }
356
357 if (opts->shared_net_id) {
358 char* end;
359 long shared_net_id = strtol(opts->shared_net_id, &end, 0);
360 if (end == NULL || *end || shared_net_id < 1 || shared_net_id > 255) {
361 fprintf(stderr, "option -shared-net-id must be an integer between 1 and 255\n");
362 exit(1);
363 }
364 snprintf(boot_prop_ip, sizeof(boot_prop_ip),
365 "net.shared_net_ip=10.1.2.%ld", shared_net_id);
366 }
367
368
369 user_config_init();
370 parse_skin_files(opts->skindir, opts->skin, opts, hw,
371 &skinConfig, &skinPath);
372
373 if (!opts->netspeed && skin_network_speed) {
374 D("skin network speed: '%s'", skin_network_speed);
375 if (strcmp(skin_network_speed, NETWORK_SPEED_DEFAULT) != 0) {
376 opts->netspeed = (char*)skin_network_speed;
377 }
378 }
379 if (!opts->netdelay && skin_network_delay) {
380 D("skin network delay: '%s'", skin_network_delay);
381 if (strcmp(skin_network_delay, NETWORK_DELAY_DEFAULT) != 0) {
382 opts->netdelay = (char*)skin_network_delay;
383 }
384 }
385
386 if (opts->trace) {
387 char* tracePath = avdInfo_getTracePath(avd, opts->trace);
388 int ret;
389
390 if (tracePath == NULL) {
391 derror( "bad -trace parameter" );
392 exit(1);
393 }
394 ret = path_mkdir_if_needed( tracePath, 0755 );
395 if (ret < 0) {
396 fprintf(stderr, "could not create directory '%s'\n", tmp);
397 exit(2);
398 }
399 opts->trace = tracePath;
400 }
401
402 /* Update CPU architecture for HW configs created from build dir. */
403 if (inAndroidBuild) {
404 #if defined(TARGET_ARM)
405 free(android_hw->hw_cpu_arch);
406 android_hw->hw_cpu_arch = ASTRDUP("arm");
407 #elif defined(TARGET_I386)
408 free(android_hw->hw_cpu_arch);
409 android_hw->hw_cpu_arch = ASTRDUP("x86");
410 #endif
411 }
412
413 n = 1;
414 /* generate arguments for the underlying qemu main() */
415 {
416 char* kernelFile = opts->kernel;
417 int kernelFileLen;
418
419 if (kernelFile == NULL) {
420 kernelFile = avdInfo_getKernelPath(avd);
421 if (kernelFile == NULL) {
422 derror( "This AVD's configuration is missing a kernel file!!" );
423 exit(2);
424 }
425 D("autoconfig: -kernel %s", kernelFile);
426 }
427 if (!path_exists(kernelFile)) {
428 derror( "Invalid or missing kernel image file: %s", kernelFile );
429 exit(2);
430 }
431
432 hw->kernel_path = kernelFile;
433
434 /* If the kernel image name ends in "-armv7", then change the cpu
435 * type automatically. This is a poor man's approach to configuration
436 * management, but should allow us to get past building ARMv7
437 * system images with dex preopt pass without introducing too many
438 * changes to the emulator sources.
439 *
440 * XXX:
441 * A 'proper' change would require adding some sort of hardware-property
442 * to each AVD config file, then automatically determine its value for
443 * full Android builds (depending on some environment variable), plus
444 * some build system changes. I prefer not to do that for now for reasons
445 * of simplicity.
446 */
447 kernelFileLen = strlen(kernelFile);
448 if (kernelFileLen > 6 && !memcmp(kernelFile + kernelFileLen - 6, "-armv7", 6)) {
449 forceArmv7 = 1;
450 }
451 }
452
453 if (boot_prop_ip[0]) {
454 args[n++] = "-boot-property";
455 args[n++] = boot_prop_ip;
456 }
457
458 if (opts->tcpdump) {
459 args[n++] = "-tcpdump";
460 args[n++] = opts->tcpdump;
461 }
462
463 #ifdef CONFIG_NAND_LIMITS
464 if (opts->nand_limits) {
465 args[n++] = "-nand-limits";
466 args[n++] = opts->nand_limits;
467 }
468 #endif
469
470 if (opts->timezone) {
471 args[n++] = "-timezone";
472 args[n++] = opts->timezone;
473 }
474
475 if (opts->netspeed) {
476 args[n++] = "-netspeed";
477 args[n++] = opts->netspeed;
478 }
479 if (opts->netdelay) {
480 args[n++] = "-netdelay";
481 args[n++] = opts->netdelay;
482 }
483 if (opts->netfast) {
484 args[n++] = "-netfast";
485 }
486
487 if (opts->audio) {
488 args[n++] = "-audio";
489 args[n++] = opts->audio;
490 }
491
492 if (opts->cpu_delay) {
493 args[n++] = "-cpu-delay";
494 args[n++] = opts->cpu_delay;
495 }
496
497 if (opts->dns_server) {
498 args[n++] = "-dns-server";
499 args[n++] = opts->dns_server;
500 }
501
502 /* opts->ramdisk is never NULL (see createAVD) here */
503 if (opts->ramdisk) {
504 AFREE(hw->disk_ramdisk_path);
505 hw->disk_ramdisk_path = ASTRDUP(opts->ramdisk);
506 }
507 else if (!hw->disk_ramdisk_path[0]) {
508 hw->disk_ramdisk_path = avdInfo_getRamdiskPath(avd);
509 D("autoconfig: -ramdisk %s", hw->disk_ramdisk_path);
510 }
511
512 /* -partition-size is used to specify the max size of both the system
513 * and data partition sizes.
514 */
515 if (opts->partition_size) {
516 char* end;
517 long sizeMB = strtol(opts->partition_size, &end, 0);
518 long minSizeMB = 10;
519 long maxSizeMB = LONG_MAX / ONE_MB;
520
521 if (sizeMB < 0 || *end != 0) {
522 derror( "-partition-size must be followed by a positive integer" );
523 exit(1);
524 }
525 if (sizeMB < minSizeMB || sizeMB > maxSizeMB) {
526 derror( "partition-size (%d) must be between %dMB and %dMB",
527 sizeMB, minSizeMB, maxSizeMB );
528 exit(1);
529 }
530 defaultPartitionSize = (uint64_t) sizeMB * ONE_MB;
531 }
532
533
534 /** SYSTEM PARTITION **/
535
536 if (opts->sysdir == NULL) {
537 if (avdInfo_inAndroidBuild(avd)) {
538 opts->sysdir = ASTRDUP(avdInfo_getContentPath(avd));
539 D("autoconfig: -sysdir %s", opts->sysdir);
540 }
541 }
542
543 if (opts->sysdir != NULL) {
544 if (!path_exists(opts->sysdir)) {
545 derror("Directory does not exist: %s", opts->sysdir);
546 exit(1);
547 }
548 }
549
550 {
551 char* rwImage = NULL;
552 char* initImage = NULL;
553
554 do {
555 if (opts->system == NULL) {
556 /* If -system is not used, try to find a runtime system image
557 * (i.e. system-qemu.img) in the content directory.
558 */
559 rwImage = avdInfo_getSystemImagePath(avd);
560 if (rwImage != NULL) {
561 break;
562 }
563 /* Otherwise, try to find the initial system image */
564 initImage = avdInfo_getSystemInitImagePath(avd);
565 if (initImage == NULL) {
566 derror("No initial system image for this configuration!");
567 exit(1);
568 }
569 break;
570 }
571
572 /* If -system <name> is used, use it to find the initial image */
573 if (opts->sysdir != NULL && !path_exists(opts->system)) {
574 initImage = _getFullFilePath(opts->sysdir, opts->system);
575 } else {
576 initImage = ASTRDUP(opts->system);
577 }
578 if (!path_exists(initImage)) {
579 derror("System image file doesn't exist: %s", initImage);
580 exit(1);
581 }
582
583 } while (0);
584
585 if (rwImage != NULL) {
586 /* Use the read/write image file directly */
587 hw->disk_systemPartition_path = rwImage;
588 hw->disk_systemPartition_initPath = NULL;
589 D("Using direct system image: %s", rwImage);
590 } else if (initImage != NULL) {
591 hw->disk_systemPartition_path = NULL;
592 hw->disk_systemPartition_initPath = initImage;
593 D("Using initial system image: %s", initImage);
594 }
595
596 /* Check the size of the system partition image.
597 * If we have an AVD, it must be smaller than
598 * the disk.systemPartition.size hardware property.
599 *
600 * Otherwise, we need to adjust the systemPartitionSize
601 * automatically, and print a warning.
602 *
603 */
604 const char* systemImage = hw->disk_systemPartition_path;
605 uint64_t systemBytes;
606
607 if (systemImage == NULL)
608 systemImage = hw->disk_systemPartition_initPath;
609
610 if (path_get_size(systemImage, &systemBytes) < 0) {
611 derror("Missing system image: %s", systemImage);
612 exit(1);
613 }
614
615 hw->disk_systemPartition_size =
616 _adjustPartitionSize("system", systemBytes, defaultPartitionSize,
617 avdInfo_inAndroidBuild(avd));
618 }
619
620 /** DATA PARTITION **/
621
622 if (opts->datadir) {
623 if (!path_exists(opts->datadir)) {
624 derror("Invalid -datadir directory: %s", opts->datadir);
625 }
626 }
627
628 {
629 char* dataImage = NULL;
630 char* initImage = NULL;
631
632 do {
633 if (!opts->data) {
634 dataImage = avdInfo_getDataImagePath(avd);
635 if (dataImage != NULL) {
636 D("autoconfig: -data %s", dataImage);
637 break;
638 }
639 dataImage = avdInfo_getDefaultDataImagePath(avd);
640 if (dataImage == NULL) {
641 derror("No data image path for this configuration!");
642 exit (1);
643 }
644 opts->wipe_data = 1;
645 break;
646 }
647
648 if (opts->datadir) {
649 dataImage = _getFullFilePath(opts->datadir, opts->data);
650 } else {
651 dataImage = ASTRDUP(opts->data);
652 }
653 } while (0);
654
655 if (opts->initdata != NULL) {
656 initImage = ASTRDUP(opts->initdata);
657 if (!path_exists(initImage)) {
658 derror("Invalid initial data image path: %s", initImage);
659 exit(1);
660 }
661 } else {
662 initImage = avdInfo_getDataInitImagePath(avd);
663 D("autoconfig: -initdata %s", initImage);
664 }
665
666 hw->disk_dataPartition_path = dataImage;
667 if (opts->wipe_data) {
668 hw->disk_dataPartition_initPath = initImage;
669 } else {
670 hw->disk_dataPartition_initPath = NULL;
671 }
672
673 uint64_t defaultBytes =
674 hw->disk_dataPartition_size == 0 ?
675 defaultPartitionSize :
676 hw->disk_dataPartition_size;
677 uint64_t dataBytes;
678 const char* dataPath = hw->disk_dataPartition_initPath;
679
680 if (dataPath == NULL)
681 dataPath = hw->disk_dataPartition_path;
682
683 path_get_size(dataPath, &dataBytes);
684
685 hw->disk_dataPartition_size =
686 _adjustPartitionSize("data", dataBytes, defaultBytes,
687 avdInfo_inAndroidBuild(avd));
688 }
689
690 /** CACHE PARTITION **/
691
692 if (opts->no_cache) {
693 /* No cache partition at all */
694 hw->disk_cachePartition = 0;
695 }
696 else if (!hw->disk_cachePartition) {
697 if (opts->cache) {
698 dwarning( "Emulated hardware doesn't support a cache partition. -cache option ignored!" );
699 opts->cache = NULL;
700 }
701 }
702 else
703 {
704 if (!opts->cache) {
705 /* Find the current cache partition file */
706 opts->cache = avdInfo_getCachePath(avd);
707 if (opts->cache == NULL) {
708 /* The file does not exists, we will force its creation
709 * if we are not in the Android build system. Otherwise,
710 * a temporary file will be used.
711 */
712 if (!avdInfo_inAndroidBuild(avd)) {
713 opts->cache = avdInfo_getDefaultCachePath(avd);
714 }
715 }
716 if (opts->cache) {
717 D("autoconfig: -cache %s", opts->cache);
718 }
719 }
720
721 if (opts->cache) {
722 hw->disk_cachePartition_path = ASTRDUP(opts->cache);
723 }
724 }
725
726 /** SD CARD PARTITION */
727
728 if (!hw->hw_sdCard) {
729 /* No SD Card emulation, so -sdcard will be ignored */
730 if (opts->sdcard) {
731 dwarning( "Emulated hardware doesn't support SD Cards. -sdcard option ignored." );
732 opts->sdcard = NULL;
733 }
734 } else {
735 /* Auto-configure -sdcard if it is not available */
736 if (!opts->sdcard) {
737 do {
738 /* If -datadir <path> is used, look for a sdcard.img file here */
739 if (opts->datadir) {
740 bufprint(tmp, tmpend, "%s/%s", opts->datadir, "system.img");
741 if (path_exists(tmp)) {
742 opts->sdcard = strdup(tmp);
743 break;
744 }
745 }
746
747 /* Otherwise, look at the AVD's content */
748 opts->sdcard = avdInfo_getSdCardPath(avd);
749 if (opts->sdcard != NULL) {
750 break;
751 }
752
753 /* Nothing */
754 } while (0);
755
756 if (opts->sdcard) {
757 D("autoconfig: -sdcard %s", opts->sdcard);
758 }
759 }
760 }
761
762 if(opts->sdcard) {
763 uint64_t size;
764 if (path_get_size(opts->sdcard, &size) == 0) {
765 /* see if we have an sdcard image. get its size if it exists */
766 /* due to what looks like limitations of the MMC protocol, one has
767 * to use an SD Card image that is equal or larger than 9 MB
768 */
769 if (size < 9*1024*1024ULL) {
770 fprintf(stderr, "### WARNING: SD Card files must be at least 9MB, ignoring '%s'\n", opts->sdcard);
771 } else {
772 hw->hw_sdCard_path = ASTRDUP(opts->sdcard);
773 }
774 } else {
775 dwarning("no SD Card image at '%s'", opts->sdcard);
776 }
777 }
778
779
780 /** SNAPSHOT STORAGE HANDLING */
781
782 /* Determine snapstorage path. -no-snapstorage disables all snapshotting
783 * support. This means you can't resume a snapshot at load, save it at
784 * exit, or even load/save them dynamically at runtime with the console.
785 */
786 if (opts->no_snapstorage) {
787
788 if (opts->snapshot) {
789 dwarning("ignoring -snapshot option due to the use of -no-snapstorage");
790 opts->snapshot = NULL;
791 }
792
793 if (opts->snapstorage) {
794 dwarning("ignoring -snapstorage option due to the use of -no-snapstorage");
795 opts->snapstorage = NULL;
796 }
797 }
798 else
799 {
800 if (!opts->snapstorage && avdInfo_getSnapshotPresent(avd)) {
801 opts->snapstorage = avdInfo_getSnapStoragePath(avd);
802 if (opts->snapstorage != NULL) {
803 D("autoconfig: -snapstorage %s", opts->snapstorage);
804 }
805 }
806
807 if (opts->snapstorage && !path_exists(opts->snapstorage)) {
808 D("no image at '%s', state snapshots disabled", opts->snapstorage);
809 opts->snapstorage = NULL;
810 }
811 }
812
813 /* If we have a valid snapshot storage path */
814
815 if (opts->snapstorage) {
816
817 hw->disk_snapStorage_path = ASTRDUP(opts->snapstorage);
818
819 /* -no-snapshot is equivalent to using both -no-snapshot-load
820 * and -no-snapshot-save. You can still load/save snapshots dynamically
821 * from the console though.
822 */
823 if (opts->no_snapshot) {
824
825 opts->no_snapshot_load = 1;
826 opts->no_snapshot_save = 1;
827
828 if (opts->snapshot) {
829 dwarning("ignoring -snapshot option due to the use of -no-snapshot.");
830 }
831 }
832
833 if (!opts->no_snapshot_load || !opts->no_snapshot_save) {
834 if (opts->snapshot == NULL) {
835 opts->snapshot = "default-boot";
836 D("autoconfig: -snapshot %s", opts->snapshot);
837 }
838 }
839
840 /* We still use QEMU command-line options for the following since
841 * they can change from one invokation to the next and don't really
842 * correspond to the hardware configuration itself.
843 */
844 if (!opts->no_snapshot_load) {
845 args[n++] = "-loadvm";
846 args[n++] = ASTRDUP(opts->snapshot);
847 }
848
849 if (!opts->no_snapshot_save) {
850 args[n++] = "-savevm-on-exit";
851 args[n++] = ASTRDUP(opts->snapshot);
852 }
853
854 if (opts->no_snapshot_update_time) {
855 args[n++] = "-snapshot-no-time-update";
856 }
857 }
858
859 if (!opts->logcat || opts->logcat[0] == 0) {
860 opts->logcat = getenv("ANDROID_LOG_TAGS");
861 if (opts->logcat && opts->logcat[0] == 0)
862 opts->logcat = NULL;
863 }
864
865 /* we always send the kernel messages from ttyS0 to android_kmsg */
866 if (opts->show_kernel) {
867 args[n++] = "-show-kernel";
868 }
869
870 /* XXXX: TODO: implement -shell and -logcat through qemud instead */
871 if (!opts->shell_serial) {
872 #ifdef _WIN32
873 opts->shell_serial = "con:";
874 #else
875 opts->shell_serial = "stdio";
876 #endif
877 }
878 else
879 opts->shell = 1;
880
881 if (opts->shell || opts->logcat) {
882 args[n++] = "-serial";
883 args[n++] = opts->shell_serial;
884 shell_serial = serial++;
885 }
886
887 if (opts->radio) {
888 args[n++] = "-radio";
889 args[n++] = opts->radio;
890 }
891
892 if (opts->gps) {
893 args[n++] = "-gps";
894 args[n++] = opts->gps;
895 }
896
897 if (opts->memory) {
898 char* end;
899 long ramSize = strtol(opts->memory, &end, 0);
900 if (ramSize < 0 || *end != 0) {
901 derror( "-memory must be followed by a positive integer" );
902 exit(1);
903 }
904 if (ramSize < 32 || ramSize > 4096) {
905 derror( "physical memory size must be between 32 and 4096 MB" );
906 exit(1);
907 }
908 hw->hw_ramSize = ramSize;
909 }
910 if (!opts->memory) {
911 int ramSize = hw->hw_ramSize;
912 if (ramSize <= 0) {
913 /* Compute the default RAM size based on the size of screen.
914 * This is only used when the skin doesn't provide the ram
915 * size through its hardware.ini (i.e. legacy ones) or when
916 * in the full Android build system.
917 */
918 int64_t pixels = hw->hw_lcd_width * hw->hw_lcd_height;
919 /* The following thresholds are a bit liberal, but we
920 * essentially want to ensure the following mappings:
921 *
922 * 320x480 -> 96
923 * 800x600 -> 128
924 * 1024x768 -> 256
925 *
926 * These are just simple heuristics, they could change in
927 * the future.
928 */
929 if (pixels <= 250000)
930 ramSize = 96;
931 else if (pixels <= 500000)
932 ramSize = 128;
933 else
934 ramSize = 256;
935 }
936 hw->hw_ramSize = ramSize;
937 }
938
939 D("Physical RAM size: %dMB\n", hw->hw_ramSize);
940
941 if (hw->vm_heapSize == 0) {
942 /* Compute the default heap size based on the RAM size.
943 * Essentially, we want to ensure the following liberal mappings:
944 *
945 * 96MB RAM -> 16MB heap
946 * 128MB RAM -> 24MB heap
947 * 256MB RAM -> 48MB heap
948 */
949 int ramSize = hw->hw_ramSize;
950 int heapSize;
951
952 if (ramSize < 100)
953 heapSize = 16;
954 else if (ramSize < 192)
955 heapSize = 24;
956 else
957 heapSize = 48;
958
959 hw->vm_heapSize = heapSize;
960 }
961
962 if (opts->trace) {
963 args[n++] = "-trace";
964 args[n++] = opts->trace;
965 args[n++] = "-tracing";
966 args[n++] = "off";
967 }
968
969 /* Pass boot properties to the core. */
970 if (opts->prop != NULL) {
971 ParamList* pl = opts->prop;
972 for ( ; pl != NULL; pl = pl->next ) {
973 args[n++] = "-boot-property";
974 args[n++] = pl->param;
975 }
976 }
977
978 /* Setup the kernel init options
979 */
980 {
981 static char params[1024];
982 char *p = params, *end = p + sizeof(params);
983
984 /* Don't worry about having a leading space here, this is handled
985 * by the core later. */
986
987 #ifdef TARGET_I386
988 p = bufprint(p, end, " androidboot.hardware=goldfish");
989 p = bufprint(p, end, " clocksource=pit");
990 #endif
991
992 if (opts->shell || opts->logcat) {
993 p = bufprint(p, end, " androidboot.console=ttyS%d", shell_serial );
994 }
995
996 if (opts->trace) {
997 p = bufprint(p, end, " android.tracing=1");
998 }
999
1000 if (!opts->no_jni) {
1001 p = bufprint(p, end, " android.checkjni=1");
1002 }
1003
1004 if (opts->no_boot_anim) {
1005 p = bufprint( p, end, " android.bootanim=0" );
1006 }
1007
1008 if (opts->logcat) {
1009 char* q = bufprint(p, end, " androidboot.logcat=%s", opts->logcat);
1010
1011 if (q < end) {
1012 /* replace any space by a comma ! */
1013 {
1014 int nn;
1015 for (nn = 1; p[nn] != 0; nn++)
1016 if (p[nn] == ' ' || p[nn] == '\t')
1017 p[nn] = ',';
1018 p += nn;
1019 }
1020 }
1021 p = q;
1022 }
1023
1024 if (opts->bootchart) {
1025 p = bufprint(p, end, " androidboot.bootchart=%s", opts->bootchart);
1026 }
1027
1028 if (p >= end) {
1029 fprintf(stderr, "### ERROR: kernel parameters too long\n");
1030 exit(1);
1031 }
1032
1033 hw->kernel_parameters = strdup(params);
1034 }
1035
1036 if (opts->ports) {
1037 args[n++] = "-android-ports";
1038 args[n++] = opts->ports;
1039 }
1040
1041 if (opts->port) {
1042 args[n++] = "-android-port";
1043 args[n++] = opts->port;
1044 }
1045
1046 if (opts->report_console) {
1047 args[n++] = "-android-report-console";
1048 args[n++] = opts->report_console;
1049 }
1050
1051 if (opts->http_proxy) {
1052 args[n++] = "-http-proxy";
1053 args[n++] = opts->http_proxy;
1054 }
1055
1056 if (!opts->charmap) {
1057 /* Try to find a valid charmap name */
1058 char* charmap = avdInfo_getCharmapFile(avd, hw->hw_keyboard_charmap);
1059 if (charmap != NULL) {
1060 D("autoconfig: -charmap %s", charmap);
1061 opts->charmap = charmap;
1062 }
1063 }
1064
1065 if (opts->charmap) {
1066 char charmap_name[AKEYCHARMAP_NAME_SIZE];
1067
1068 if (!path_exists(opts->charmap)) {
1069 derror("Charmap file does not exist: %s", opts->charmap);
1070 exit(1);
1071 }
1072 /* We need to store the charmap name in the hardware configuration.
1073 * However, the charmap file itself is only used by the UI component
1074 * and doesn't need to be set to the emulation engine.
1075 */
1076 kcm_extract_charmap_name(opts->charmap, charmap_name,
1077 sizeof(charmap_name));
1078 AFREE(hw->hw_keyboard_charmap);
1079 hw->hw_keyboard_charmap = ASTRDUP(charmap_name);
1080 }
1081
1082 if (opts->memcheck) {
1083 args[n++] = "-android-memcheck";
1084 args[n++] = opts->memcheck;
1085 }
1086
1087 if (opts->gpu) {
1088 const char* gpu = opts->gpu;
1089 if (!strcmp(gpu,"on") || !strcmp(gpu,"enable")) {
1090 hw->hw_gpu_enabled = 1;
1091 } else if (!strcmp(gpu,"off") || !strcmp(gpu,"disable")) {
1092 hw->hw_gpu_enabled = 0;
1093 } else if (!strcmp(gpu,"auto")) {
1094 /* Nothing to do */
1095 } else {
1096 derror("Invalid value for -gpu <mode> parameter: %s\n", gpu);
1097 derror("Valid values are: on, off or auto\n");
1098 exit(1);
1099 }
1100 }
1101
1102 /* Quit emulator on condition that both, gpu and snapstorage are on. This is
1103 * a temporary solution preventing the emulator from crashing until GPU state
1104 * can be properly saved / resored in snapshot file. */
1105 if (hw->hw_gpu_enabled && opts->snapstorage && (!opts->no_snapshot_load ||
1106 !opts->no_snapshot_save)) {
1107 derror("Snapshots and gpu are mutually exclusive at this point. Please turn one of them off, and restart the emulator.");
1108 exit(1);
1109 }
1110
1111 /* Deal with camera emulation */
1112 if (opts->webcam_list) {
1113 /* List connected webcameras */
1114 args[n++] = "-list-webcam";
1115 }
1116
1117 if (opts->camera_back) {
1118 /* Validate parameter. */
1119 if (memcmp(opts->camera_back, "webcam", 6) &&
1120 strcmp(opts->camera_back, "emulated") &&
1121 strcmp(opts->camera_back, "none")) {
1122 derror("Invalid value for -camera-back <mode> parameter: %s\n"
1123 "Valid values are: 'emulated', 'webcam<N>', or 'none'\n",
1124 opts->camera_back);
1125 exit(1);
1126 }
1127 hw->hw_camera_back = ASTRDUP(opts->camera_back);
1128 }
1129
1130 if (opts->camera_front) {
1131 /* Validate parameter. */
1132 if (memcmp(opts->camera_front, "webcam", 6) &&
1133 strcmp(opts->camera_front, "emulated") &&
1134 strcmp(opts->camera_front, "none")) {
1135 derror("Invalid value for -camera-front <mode> parameter: %s\n"
1136 "Valid values are: 'emulated', 'webcam<N>', or 'none'\n",
1137 opts->camera_front);
1138 exit(1);
1139 }
1140 hw->hw_camera_front = ASTRDUP(opts->camera_front);
1141 }
1142
1143 /* physical memory is now in hw->hw_ramSize */
1144
1145 hw->avd_name = ASTRDUP(avdInfo_getName(avd));
1146
1147 /* Set up the interfaces for inter-emulator networking */
1148 if (opts->shared_net_id) {
1149 unsigned int shared_net_id = atoi(opts->shared_net_id);
1150 char nic[37];
1151
1152 args[n++] = "-net";
1153 args[n++] = "nic,vlan=0";
1154 args[n++] = "-net";
1155 args[n++] = "user,vlan=0";
1156
1157 args[n++] = "-net";
1158 snprintf(nic, sizeof nic, "nic,vlan=1,macaddr=52:54:00:12:34:%02x", shared_net_id);
1159 args[n++] = strdup(nic);
1160 args[n++] = "-net";
1161 args[n++] = "socket,vlan=1,mcast=230.0.0.10:1234";
1162 }
1163
1164 /* Setup screen emulation */
1165 if (opts->screen) {
1166 if (strcmp(opts->screen, "touch") &&
1167 strcmp(opts->screen, "multi-touch") &&
1168 strcmp(opts->screen, "no-touch")) {
1169
1170 derror("Invalid value for -screen <mode> parameter: %s\n"
1171 "Valid values are: touch, multi-touch, or no-touch\n",
1172 opts->screen);
1173 exit(1);
1174 }
1175 hw->hw_screen = ASTRDUP(opts->screen);
1176 }
1177
1178 while(argc-- > 0) {
1179 args[n++] = *argv++;
1180 }
1181 args[n] = 0;
1182
1183 /* If the target ABI is armeabi-v7a, we can auto-detect the cpu model
1184 * as a cortex-a8, instead of the default (arm926) which only emulates
1185 * an ARMv5TE CPU.
1186 */
1187 if (!forceArmv7 && hw->hw_cpu_model[0] == '\0')
1188 {
1189 char* abi = avdInfo_getTargetAbi(avd);
1190 if (abi != NULL) {
1191 if (!strcmp(abi, "armeabi-v7a")) {
1192 forceArmv7 = 1;
1193 }
1194 AFREE(abi);
1195 }
1196 }
1197
1198 if (forceArmv7 != 0) {
1199 AFREE(hw->hw_cpu_model);
1200 hw->hw_cpu_model = ASTRDUP("cortex-a8");
1201 D("Auto-config: -qemu -cpu %s", hw->hw_cpu_model);
1202 }
1203
1204 /* Generate a hardware-qemu.ini for this AVD. The real hardware
1205 * configuration is ususally stored in several files, e.g. the AVD's
1206 * config.ini plus the skin-specific hardware.ini.
1207 *
1208 * The new file will group all definitions and will be used to
1209 * launch the core with the -android-hw <file> option.
1210 */
1211 {
1212 const char* coreHwIniPath = avdInfo_getCoreHwIniPath(avd);
1213 IniFile* hwIni = iniFile_newFromMemory("", NULL);
1214 androidHwConfig_write(hw, hwIni);
1215
1216 if (filelock_create(coreHwIniPath) == NULL) {
1217 /* The AVD is already in use, we still support this as an
1218 * experimental feature. Use a temporary hardware-qemu.ini
1219 * file though to avoid overwriting the existing one. */
1220 TempFile* tempIni = tempfile_create();
1221 coreHwIniPath = tempfile_path(tempIni);
1222 }
1223
1224 /* While saving HW config, ignore valueless entries. This will not break
1225 * anything, but will significantly simplify comparing the current HW
1226 * config with the one that has been associated with a snapshot (in case
1227 * VM starts from a snapshot for this instance of emulator). */
1228 if (iniFile_saveToFileClean(hwIni, coreHwIniPath) < 0) {
1229 derror("Could not write hardware.ini to %s: %s", coreHwIniPath, strerror(errno));
1230 exit(2);
1231 }
1232 args[n++] = "-android-hw";
1233 args[n++] = strdup(coreHwIniPath);
1234
1235 /* In verbose mode, dump the file's content */
1236 if (VERBOSE_CHECK(init)) {
1237 FILE* file = fopen(coreHwIniPath, "rt");
1238 if (file == NULL) {
1239 derror("Could not open hardware configuration file: %s\n",
1240 coreHwIniPath);
1241 } else {
1242 LineInput* input = lineInput_newFromStdFile(file);
1243 const char* line;
1244 printf("Content of hardware configuration file:\n");
1245 while ((line = lineInput_getLine(input)) != NULL) {
1246 printf(" %s\n", line);
1247 }
1248 printf(".\n");
1249 lineInput_free(input);
1250 fclose(file);
1251 }
1252 }
1253 }
1254
1255 if(VERBOSE_CHECK(init)) {
1256 int i;
1257 printf("QEMU options list:\n");
1258 for(i = 0; i < n; i++) {
1259 printf("emulator: argv[%02d] = \"%s\"\n", i, args[i]);
1260 }
1261 /* Dump final command-line option to make debugging the core easier */
1262 printf("Concatenated QEMU options:\n");
1263 for (i = 0; i < n; i++) {
1264 /* To make it easier to copy-paste the output to a command-line,
1265 * quote anything that contains spaces.
1266 */
1267 if (strchr(args[i], ' ') != NULL) {
1268 printf(" '%s'", args[i]);
1269 } else {
1270 printf(" %s", args[i]);
1271 }
1272 }
1273 printf("\n");
1274 }
1275
1276 /* Setup SDL UI just before calling the code */
1277 init_sdl_ui(skinConfig, skinPath, opts);
1278
1279 if (attach_ui_to_core(opts) < 0) {
1280 derror("Can't attach to core!");
1281 exit(1);
1282 }
1283
1284 return qemu_main(n, args);
1285 }
1286