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 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* 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 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 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 #elif defined(TARGET_MIPS) 411 free(android_hw->hw_cpu_arch); 412 android_hw->hw_cpu_arch = ASTRDUP("mips"); 413 #endif 414 } 415 416 n = 1; 417 /* generate arguments for the underlying qemu main() */ 418 { 419 char* kernelFile = opts->kernel; 420 int kernelFileLen; 421 422 if (kernelFile == NULL) { 423 kernelFile = avdInfo_getKernelPath(avd); 424 if (kernelFile == NULL) { 425 derror( "This AVD's configuration is missing a kernel file!!" ); 426 exit(2); 427 } 428 D("autoconfig: -kernel %s", kernelFile); 429 } 430 if (!path_exists(kernelFile)) { 431 derror( "Invalid or missing kernel image file: %s", kernelFile ); 432 exit(2); 433 } 434 435 hw->kernel_path = kernelFile; 436 437 /* If the kernel image name ends in "-armv7", then change the cpu 438 * type automatically. This is a poor man's approach to configuration 439 * management, but should allow us to get past building ARMv7 440 * system images with dex preopt pass without introducing too many 441 * changes to the emulator sources. 442 * 443 * XXX: 444 * A 'proper' change would require adding some sort of hardware-property 445 * to each AVD config file, then automatically determine its value for 446 * full Android builds (depending on some environment variable), plus 447 * some build system changes. I prefer not to do that for now for reasons 448 * of simplicity. 449 */ 450 kernelFileLen = strlen(kernelFile); 451 if (kernelFileLen > 6 && !memcmp(kernelFile + kernelFileLen - 6, "-armv7", 6)) { 452 forceArmv7 = 1; 453 } 454 } 455 456 if (boot_prop_ip[0]) { 457 args[n++] = "-boot-property"; 458 args[n++] = boot_prop_ip; 459 } 460 461 if (opts->tcpdump) { 462 args[n++] = "-tcpdump"; 463 args[n++] = opts->tcpdump; 464 } 465 466 #ifdef CONFIG_NAND_LIMITS 467 if (opts->nand_limits) { 468 args[n++] = "-nand-limits"; 469 args[n++] = opts->nand_limits; 470 } 471 #endif 472 473 if (opts->timezone) { 474 args[n++] = "-timezone"; 475 args[n++] = opts->timezone; 476 } 477 478 if (opts->netspeed) { 479 args[n++] = "-netspeed"; 480 args[n++] = opts->netspeed; 481 } 482 if (opts->netdelay) { 483 args[n++] = "-netdelay"; 484 args[n++] = opts->netdelay; 485 } 486 if (opts->netfast) { 487 args[n++] = "-netfast"; 488 } 489 490 if (opts->audio) { 491 args[n++] = "-audio"; 492 args[n++] = opts->audio; 493 } 494 495 if (opts->cpu_delay) { 496 args[n++] = "-cpu-delay"; 497 args[n++] = opts->cpu_delay; 498 } 499 500 if (opts->dns_server) { 501 args[n++] = "-dns-server"; 502 args[n++] = opts->dns_server; 503 } 504 505 /* opts->ramdisk is never NULL (see createAVD) here */ 506 if (opts->ramdisk) { 507 AFREE(hw->disk_ramdisk_path); 508 hw->disk_ramdisk_path = ASTRDUP(opts->ramdisk); 509 } 510 else if (!hw->disk_ramdisk_path[0]) { 511 hw->disk_ramdisk_path = avdInfo_getRamdiskPath(avd); 512 D("autoconfig: -ramdisk %s", hw->disk_ramdisk_path); 513 } 514 515 /* -partition-size is used to specify the max size of both the system 516 * and data partition sizes. 517 */ 518 if (opts->partition_size) { 519 char* end; 520 long sizeMB = strtol(opts->partition_size, &end, 0); 521 long minSizeMB = 10; 522 long maxSizeMB = LONG_MAX / ONE_MB; 523 524 if (sizeMB < 0 || *end != 0) { 525 derror( "-partition-size must be followed by a positive integer" ); 526 exit(1); 527 } 528 if (sizeMB < minSizeMB || sizeMB > maxSizeMB) { 529 derror( "partition-size (%d) must be between %dMB and %dMB", 530 sizeMB, minSizeMB, maxSizeMB ); 531 exit(1); 532 } 533 defaultPartitionSize = (uint64_t) sizeMB * ONE_MB; 534 } 535 536 537 /** SYSTEM PARTITION **/ 538 539 if (opts->sysdir == NULL) { 540 if (avdInfo_inAndroidBuild(avd)) { 541 opts->sysdir = ASTRDUP(avdInfo_getContentPath(avd)); 542 D("autoconfig: -sysdir %s", opts->sysdir); 543 } 544 } 545 546 if (opts->sysdir != NULL) { 547 if (!path_exists(opts->sysdir)) { 548 derror("Directory does not exist: %s", opts->sysdir); 549 exit(1); 550 } 551 } 552 553 { 554 char* rwImage = NULL; 555 char* initImage = NULL; 556 557 do { 558 if (opts->system == NULL) { 559 /* If -system is not used, try to find a runtime system image 560 * (i.e. system-qemu.img) in the content directory. 561 */ 562 rwImage = avdInfo_getSystemImagePath(avd); 563 if (rwImage != NULL) { 564 break; 565 } 566 /* Otherwise, try to find the initial system image */ 567 initImage = avdInfo_getSystemInitImagePath(avd); 568 if (initImage == NULL) { 569 derror("No initial system image for this configuration!"); 570 exit(1); 571 } 572 break; 573 } 574 575 /* If -system <name> is used, use it to find the initial image */ 576 if (opts->sysdir != NULL && !path_exists(opts->system)) { 577 initImage = _getFullFilePath(opts->sysdir, opts->system); 578 } else { 579 initImage = ASTRDUP(opts->system); 580 } 581 if (!path_exists(initImage)) { 582 derror("System image file doesn't exist: %s", initImage); 583 exit(1); 584 } 585 586 } while (0); 587 588 if (rwImage != NULL) { 589 /* Use the read/write image file directly */ 590 hw->disk_systemPartition_path = rwImage; 591 hw->disk_systemPartition_initPath = NULL; 592 D("Using direct system image: %s", rwImage); 593 } else if (initImage != NULL) { 594 hw->disk_systemPartition_path = NULL; 595 hw->disk_systemPartition_initPath = initImage; 596 D("Using initial system image: %s", initImage); 597 } 598 599 /* Check the size of the system partition image. 600 * If we have an AVD, it must be smaller than 601 * the disk.systemPartition.size hardware property. 602 * 603 * Otherwise, we need to adjust the systemPartitionSize 604 * automatically, and print a warning. 605 * 606 */ 607 const char* systemImage = hw->disk_systemPartition_path; 608 uint64_t systemBytes; 609 610 if (systemImage == NULL) 611 systemImage = hw->disk_systemPartition_initPath; 612 613 if (path_get_size(systemImage, &systemBytes) < 0) { 614 derror("Missing system image: %s", systemImage); 615 exit(1); 616 } 617 618 hw->disk_systemPartition_size = 619 _adjustPartitionSize("system", systemBytes, defaultPartitionSize, 620 avdInfo_inAndroidBuild(avd)); 621 } 622 623 /** DATA PARTITION **/ 624 625 if (opts->datadir) { 626 if (!path_exists(opts->datadir)) { 627 derror("Invalid -datadir directory: %s", opts->datadir); 628 } 629 } 630 631 { 632 char* dataImage = NULL; 633 char* initImage = NULL; 634 635 do { 636 if (!opts->data) { 637 dataImage = avdInfo_getDataImagePath(avd); 638 if (dataImage != NULL) { 639 D("autoconfig: -data %s", dataImage); 640 break; 641 } 642 dataImage = avdInfo_getDefaultDataImagePath(avd); 643 if (dataImage == NULL) { 644 derror("No data image path for this configuration!"); 645 exit (1); 646 } 647 opts->wipe_data = 1; 648 break; 649 } 650 651 if (opts->datadir) { 652 dataImage = _getFullFilePath(opts->datadir, opts->data); 653 } else { 654 dataImage = ASTRDUP(opts->data); 655 } 656 } while (0); 657 658 if (opts->initdata != NULL) { 659 initImage = ASTRDUP(opts->initdata); 660 if (!path_exists(initImage)) { 661 derror("Invalid initial data image path: %s", initImage); 662 exit(1); 663 } 664 } else { 665 initImage = avdInfo_getDataInitImagePath(avd); 666 D("autoconfig: -initdata %s", initImage); 667 } 668 669 hw->disk_dataPartition_path = dataImage; 670 if (opts->wipe_data) { 671 hw->disk_dataPartition_initPath = initImage; 672 } else { 673 hw->disk_dataPartition_initPath = NULL; 674 } 675 676 uint64_t defaultBytes = 677 hw->disk_dataPartition_size == 0 ? 678 defaultPartitionSize : 679 hw->disk_dataPartition_size; 680 uint64_t dataBytes; 681 const char* dataPath = hw->disk_dataPartition_initPath; 682 683 if (dataPath == NULL) 684 dataPath = hw->disk_dataPartition_path; 685 686 path_get_size(dataPath, &dataBytes); 687 688 hw->disk_dataPartition_size = 689 _adjustPartitionSize("data", dataBytes, defaultBytes, 690 avdInfo_inAndroidBuild(avd)); 691 } 692 693 /** CACHE PARTITION **/ 694 695 if (opts->no_cache) { 696 /* No cache partition at all */ 697 hw->disk_cachePartition = 0; 698 } 699 else if (!hw->disk_cachePartition) { 700 if (opts->cache) { 701 dwarning( "Emulated hardware doesn't support a cache partition. -cache option ignored!" ); 702 opts->cache = NULL; 703 } 704 } 705 else 706 { 707 if (!opts->cache) { 708 /* Find the current cache partition file */ 709 opts->cache = avdInfo_getCachePath(avd); 710 if (opts->cache == NULL) { 711 /* The file does not exists, we will force its creation 712 * if we are not in the Android build system. Otherwise, 713 * a temporary file will be used. 714 */ 715 if (!avdInfo_inAndroidBuild(avd)) { 716 opts->cache = avdInfo_getDefaultCachePath(avd); 717 } 718 } 719 if (opts->cache) { 720 D("autoconfig: -cache %s", opts->cache); 721 } 722 } 723 724 if (opts->cache) { 725 hw->disk_cachePartition_path = ASTRDUP(opts->cache); 726 } 727 } 728 729 if (hw->disk_cachePartition_path && opts->cache_size) { 730 /* Set cache partition size per user options. */ 731 char* end; 732 long sizeMB = strtol(opts->cache_size, &end, 0); 733 734 if (sizeMB < 0 || *end != 0) { 735 derror( "-cache-size must be followed by a positive integer" ); 736 exit(1); 737 } 738 hw->disk_cachePartition_size = (uint64_t) sizeMB * ONE_MB; 739 } 740 741 /** SD CARD PARTITION */ 742 743 if (!hw->hw_sdCard) { 744 /* No SD Card emulation, so -sdcard will be ignored */ 745 if (opts->sdcard) { 746 dwarning( "Emulated hardware doesn't support SD Cards. -sdcard option ignored." ); 747 opts->sdcard = NULL; 748 } 749 } else { 750 /* Auto-configure -sdcard if it is not available */ 751 if (!opts->sdcard) { 752 do { 753 /* If -datadir <path> is used, look for a sdcard.img file here */ 754 if (opts->datadir) { 755 bufprint(tmp, tmpend, "%s/%s", opts->datadir, "system.img"); 756 if (path_exists(tmp)) { 757 opts->sdcard = strdup(tmp); 758 break; 759 } 760 } 761 762 /* Otherwise, look at the AVD's content */ 763 opts->sdcard = avdInfo_getSdCardPath(avd); 764 if (opts->sdcard != NULL) { 765 break; 766 } 767 768 /* Nothing */ 769 } while (0); 770 771 if (opts->sdcard) { 772 D("autoconfig: -sdcard %s", opts->sdcard); 773 } 774 } 775 } 776 777 if(opts->sdcard) { 778 uint64_t size; 779 if (path_get_size(opts->sdcard, &size) == 0) { 780 /* see if we have an sdcard image. get its size if it exists */ 781 /* due to what looks like limitations of the MMC protocol, one has 782 * to use an SD Card image that is equal or larger than 9 MB 783 */ 784 if (size < 9*1024*1024ULL) { 785 fprintf(stderr, "### WARNING: SD Card files must be at least 9MB, ignoring '%s'\n", opts->sdcard); 786 } else { 787 hw->hw_sdCard_path = ASTRDUP(opts->sdcard); 788 } 789 } else { 790 dwarning("no SD Card image at '%s'", opts->sdcard); 791 } 792 } 793 794 795 /** SNAPSHOT STORAGE HANDLING */ 796 797 /* Determine snapstorage path. -no-snapstorage disables all snapshotting 798 * support. This means you can't resume a snapshot at load, save it at 799 * exit, or even load/save them dynamically at runtime with the console. 800 */ 801 if (opts->no_snapstorage) { 802 803 if (opts->snapshot) { 804 dwarning("ignoring -snapshot option due to the use of -no-snapstorage"); 805 opts->snapshot = NULL; 806 } 807 808 if (opts->snapstorage) { 809 dwarning("ignoring -snapstorage option due to the use of -no-snapstorage"); 810 opts->snapstorage = NULL; 811 } 812 } 813 else 814 { 815 if (!opts->snapstorage && avdInfo_getSnapshotPresent(avd)) { 816 opts->snapstorage = avdInfo_getSnapStoragePath(avd); 817 if (opts->snapstorage != NULL) { 818 D("autoconfig: -snapstorage %s", opts->snapstorage); 819 } 820 } 821 822 if (opts->snapstorage && !path_exists(opts->snapstorage)) { 823 D("no image at '%s', state snapshots disabled", opts->snapstorage); 824 opts->snapstorage = NULL; 825 } 826 } 827 828 /* If we have a valid snapshot storage path */ 829 830 if (opts->snapstorage) { 831 832 hw->disk_snapStorage_path = ASTRDUP(opts->snapstorage); 833 834 /* -no-snapshot is equivalent to using both -no-snapshot-load 835 * and -no-snapshot-save. You can still load/save snapshots dynamically 836 * from the console though. 837 */ 838 if (opts->no_snapshot) { 839 840 opts->no_snapshot_load = 1; 841 opts->no_snapshot_save = 1; 842 843 if (opts->snapshot) { 844 dwarning("ignoring -snapshot option due to the use of -no-snapshot."); 845 } 846 } 847 848 if (!opts->no_snapshot_load || !opts->no_snapshot_save) { 849 if (opts->snapshot == NULL) { 850 opts->snapshot = "default-boot"; 851 D("autoconfig: -snapshot %s", opts->snapshot); 852 } 853 } 854 855 /* We still use QEMU command-line options for the following since 856 * they can change from one invokation to the next and don't really 857 * correspond to the hardware configuration itself. 858 */ 859 if (!opts->no_snapshot_load) { 860 args[n++] = "-loadvm"; 861 args[n++] = ASTRDUP(opts->snapshot); 862 } 863 864 if (!opts->no_snapshot_save) { 865 args[n++] = "-savevm-on-exit"; 866 args[n++] = ASTRDUP(opts->snapshot); 867 } 868 869 if (opts->no_snapshot_update_time) { 870 args[n++] = "-snapshot-no-time-update"; 871 } 872 } 873 874 if (!opts->logcat || opts->logcat[0] == 0) { 875 opts->logcat = getenv("ANDROID_LOG_TAGS"); 876 if (opts->logcat && opts->logcat[0] == 0) 877 opts->logcat = NULL; 878 } 879 880 /* we always send the kernel messages from ttyS0 to android_kmsg */ 881 if (opts->show_kernel) { 882 args[n++] = "-show-kernel"; 883 } 884 885 /* XXXX: TODO: implement -shell and -logcat through qemud instead */ 886 if (!opts->shell_serial) { 887 #ifdef _WIN32 888 opts->shell_serial = "con:"; 889 #else 890 opts->shell_serial = "stdio"; 891 #endif 892 } 893 else 894 opts->shell = 1; 895 896 if (opts->shell || opts->logcat) { 897 args[n++] = "-serial"; 898 args[n++] = opts->shell_serial; 899 shell_serial = serial++; 900 } 901 902 if (opts->radio) { 903 args[n++] = "-radio"; 904 args[n++] = opts->radio; 905 } 906 907 if (opts->gps) { 908 args[n++] = "-gps"; 909 args[n++] = opts->gps; 910 } 911 912 if (opts->memory) { 913 char* end; 914 long ramSize = strtol(opts->memory, &end, 0); 915 if (ramSize < 0 || *end != 0) { 916 derror( "-memory must be followed by a positive integer" ); 917 exit(1); 918 } 919 if (ramSize < 32 || ramSize > 4096) { 920 derror( "physical memory size must be between 32 and 4096 MB" ); 921 exit(1); 922 } 923 hw->hw_ramSize = ramSize; 924 } 925 if (!opts->memory) { 926 int ramSize = hw->hw_ramSize; 927 if (ramSize <= 0) { 928 /* Compute the default RAM size based on the size of screen. 929 * This is only used when the skin doesn't provide the ram 930 * size through its hardware.ini (i.e. legacy ones) or when 931 * in the full Android build system. 932 */ 933 int64_t pixels = hw->hw_lcd_width * hw->hw_lcd_height; 934 /* The following thresholds are a bit liberal, but we 935 * essentially want to ensure the following mappings: 936 * 937 * 320x480 -> 96 938 * 800x600 -> 128 939 * 1024x768 -> 256 940 * 941 * These are just simple heuristics, they could change in 942 * the future. 943 */ 944 if (pixels <= 250000) 945 ramSize = 96; 946 else if (pixels <= 500000) 947 ramSize = 128; 948 else 949 ramSize = 256; 950 } 951 hw->hw_ramSize = ramSize; 952 } 953 954 D("Physical RAM size: %dMB\n", hw->hw_ramSize); 955 956 if (hw->vm_heapSize == 0) { 957 /* Compute the default heap size based on the RAM size. 958 * Essentially, we want to ensure the following liberal mappings: 959 * 960 * 96MB RAM -> 16MB heap 961 * 128MB RAM -> 24MB heap 962 * 256MB RAM -> 48MB heap 963 */ 964 int ramSize = hw->hw_ramSize; 965 int heapSize; 966 967 if (ramSize < 100) 968 heapSize = 16; 969 else if (ramSize < 192) 970 heapSize = 24; 971 else 972 heapSize = 48; 973 974 hw->vm_heapSize = heapSize; 975 } 976 977 if (opts->trace) { 978 args[n++] = "-trace"; 979 args[n++] = opts->trace; 980 args[n++] = "-tracing"; 981 args[n++] = "off"; 982 } 983 984 /* Pass boot properties to the core. */ 985 if (opts->prop != NULL) { 986 ParamList* pl = opts->prop; 987 for ( ; pl != NULL; pl = pl->next ) { 988 args[n++] = "-boot-property"; 989 args[n++] = pl->param; 990 } 991 } 992 993 /* Setup the kernel init options 994 */ 995 { 996 static char params[1024]; 997 char *p = params, *end = p + sizeof(params); 998 999 /* Don't worry about having a leading space here, this is handled 1000 * by the core later. */ 1001 1002 #ifdef TARGET_I386 1003 p = bufprint(p, end, " androidboot.hardware=goldfish"); 1004 p = bufprint(p, end, " clocksource=pit"); 1005 #endif 1006 1007 if (opts->shell || opts->logcat) { 1008 p = bufprint(p, end, " androidboot.console=ttyS%d", shell_serial ); 1009 } 1010 1011 if (opts->trace) { 1012 p = bufprint(p, end, " android.tracing=1"); 1013 } 1014 1015 if (!opts->no_jni) { 1016 p = bufprint(p, end, " android.checkjni=1"); 1017 } 1018 1019 if (opts->no_boot_anim) { 1020 p = bufprint( p, end, " android.bootanim=0" ); 1021 } 1022 1023 if (opts->logcat) { 1024 char* q = bufprint(p, end, " androidboot.logcat=%s", opts->logcat); 1025 1026 if (q < end) { 1027 /* replace any space by a comma ! */ 1028 { 1029 int nn; 1030 for (nn = 1; p[nn] != 0; nn++) 1031 if (p[nn] == ' ' || p[nn] == '\t') 1032 p[nn] = ','; 1033 p += nn; 1034 } 1035 } 1036 p = q; 1037 } 1038 1039 if (opts->bootchart) { 1040 p = bufprint(p, end, " androidboot.bootchart=%s", opts->bootchart); 1041 } 1042 1043 if (p >= end) { 1044 fprintf(stderr, "### ERROR: kernel parameters too long\n"); 1045 exit(1); 1046 } 1047 1048 hw->kernel_parameters = strdup(params); 1049 } 1050 1051 if (opts->ports) { 1052 args[n++] = "-android-ports"; 1053 args[n++] = opts->ports; 1054 } 1055 1056 if (opts->port) { 1057 args[n++] = "-android-port"; 1058 args[n++] = opts->port; 1059 } 1060 1061 if (opts->report_console) { 1062 args[n++] = "-android-report-console"; 1063 args[n++] = opts->report_console; 1064 } 1065 1066 if (opts->http_proxy) { 1067 args[n++] = "-http-proxy"; 1068 args[n++] = opts->http_proxy; 1069 } 1070 1071 if (!opts->charmap) { 1072 /* Try to find a valid charmap name */ 1073 char* charmap = avdInfo_getCharmapFile(avd, hw->hw_keyboard_charmap); 1074 if (charmap != NULL) { 1075 D("autoconfig: -charmap %s", charmap); 1076 opts->charmap = charmap; 1077 } 1078 } 1079 1080 if (opts->charmap) { 1081 char charmap_name[AKEYCHARMAP_NAME_SIZE]; 1082 1083 if (!path_exists(opts->charmap)) { 1084 derror("Charmap file does not exist: %s", opts->charmap); 1085 exit(1); 1086 } 1087 /* We need to store the charmap name in the hardware configuration. 1088 * However, the charmap file itself is only used by the UI component 1089 * and doesn't need to be set to the emulation engine. 1090 */ 1091 kcm_extract_charmap_name(opts->charmap, charmap_name, 1092 sizeof(charmap_name)); 1093 AFREE(hw->hw_keyboard_charmap); 1094 hw->hw_keyboard_charmap = ASTRDUP(charmap_name); 1095 } 1096 1097 if (opts->memcheck) { 1098 args[n++] = "-android-memcheck"; 1099 args[n++] = opts->memcheck; 1100 } 1101 1102 if (opts->gpu) { 1103 const char* gpu = opts->gpu; 1104 if (!strcmp(gpu,"on") || !strcmp(gpu,"enable")) { 1105 hw->hw_gpu_enabled = 1; 1106 } else if (!strcmp(gpu,"off") || !strcmp(gpu,"disable")) { 1107 hw->hw_gpu_enabled = 0; 1108 } else if (!strcmp(gpu,"auto")) { 1109 /* Nothing to do */ 1110 } else { 1111 derror("Invalid value for -gpu <mode> parameter: %s\n", gpu); 1112 derror("Valid values are: on, off or auto\n"); 1113 exit(1); 1114 } 1115 } 1116 1117 /* Quit emulator on condition that both, gpu and snapstorage are on. This is 1118 * a temporary solution preventing the emulator from crashing until GPU state 1119 * can be properly saved / resored in snapshot file. */ 1120 if (hw->hw_gpu_enabled && opts->snapstorage && (!opts->no_snapshot_load || 1121 !opts->no_snapshot_save)) { 1122 derror("Snapshots and gpu are mutually exclusive at this point. Please turn one of them off, and restart the emulator."); 1123 exit(1); 1124 } 1125 1126 /* Deal with camera emulation */ 1127 if (opts->webcam_list) { 1128 /* List connected webcameras */ 1129 args[n++] = "-list-webcam"; 1130 } 1131 1132 if (opts->camera_back) { 1133 /* Validate parameter. */ 1134 if (memcmp(opts->camera_back, "webcam", 6) && 1135 strcmp(opts->camera_back, "emulated") && 1136 strcmp(opts->camera_back, "none")) { 1137 derror("Invalid value for -camera-back <mode> parameter: %s\n" 1138 "Valid values are: 'emulated', 'webcam<N>', or 'none'\n", 1139 opts->camera_back); 1140 exit(1); 1141 } 1142 hw->hw_camera_back = ASTRDUP(opts->camera_back); 1143 } 1144 1145 if (opts->camera_front) { 1146 /* Validate parameter. */ 1147 if (memcmp(opts->camera_front, "webcam", 6) && 1148 strcmp(opts->camera_front, "emulated") && 1149 strcmp(opts->camera_front, "none")) { 1150 derror("Invalid value for -camera-front <mode> parameter: %s\n" 1151 "Valid values are: 'emulated', 'webcam<N>', or 'none'\n", 1152 opts->camera_front); 1153 exit(1); 1154 } 1155 hw->hw_camera_front = ASTRDUP(opts->camera_front); 1156 } 1157 1158 /* physical memory is now in hw->hw_ramSize */ 1159 1160 hw->avd_name = ASTRDUP(avdInfo_getName(avd)); 1161 1162 /* Set up the interfaces for inter-emulator networking */ 1163 if (opts->shared_net_id) { 1164 unsigned int shared_net_id = atoi(opts->shared_net_id); 1165 char nic[37]; 1166 1167 args[n++] = "-net"; 1168 args[n++] = "nic,vlan=0"; 1169 args[n++] = "-net"; 1170 args[n++] = "user,vlan=0"; 1171 1172 args[n++] = "-net"; 1173 snprintf(nic, sizeof nic, "nic,vlan=1,macaddr=52:54:00:12:34:%02x", shared_net_id); 1174 args[n++] = strdup(nic); 1175 args[n++] = "-net"; 1176 args[n++] = "socket,vlan=1,mcast=230.0.0.10:1234"; 1177 } 1178 1179 /* Setup screen emulation */ 1180 if (opts->screen) { 1181 if (strcmp(opts->screen, "touch") && 1182 strcmp(opts->screen, "multi-touch") && 1183 strcmp(opts->screen, "no-touch")) { 1184 1185 derror("Invalid value for -screen <mode> parameter: %s\n" 1186 "Valid values are: touch, multi-touch, or no-touch\n", 1187 opts->screen); 1188 exit(1); 1189 } 1190 hw->hw_screen = ASTRDUP(opts->screen); 1191 } 1192 1193 while(argc-- > 0) { 1194 args[n++] = *argv++; 1195 } 1196 args[n] = 0; 1197 1198 /* If the target ABI is armeabi-v7a, we can auto-detect the cpu model 1199 * as a cortex-a8, instead of the default (arm926) which only emulates 1200 * an ARMv5TE CPU. 1201 */ 1202 if (!forceArmv7 && hw->hw_cpu_model[0] == '\0') 1203 { 1204 char* abi = avdInfo_getTargetAbi(avd); 1205 if (abi != NULL) { 1206 if (!strcmp(abi, "armeabi-v7a")) { 1207 forceArmv7 = 1; 1208 } 1209 AFREE(abi); 1210 } 1211 } 1212 1213 if (forceArmv7 != 0) { 1214 AFREE(hw->hw_cpu_model); 1215 hw->hw_cpu_model = ASTRDUP("cortex-a8"); 1216 D("Auto-config: -qemu -cpu %s", hw->hw_cpu_model); 1217 } 1218 1219 /* Generate a hardware-qemu.ini for this AVD. The real hardware 1220 * configuration is ususally stored in several files, e.g. the AVD's 1221 * config.ini plus the skin-specific hardware.ini. 1222 * 1223 * The new file will group all definitions and will be used to 1224 * launch the core with the -android-hw <file> option. 1225 */ 1226 { 1227 const char* coreHwIniPath = avdInfo_getCoreHwIniPath(avd); 1228 IniFile* hwIni = iniFile_newFromMemory("", NULL); 1229 androidHwConfig_write(hw, hwIni); 1230 1231 if (filelock_create(coreHwIniPath) == NULL) { 1232 /* The AVD is already in use, we still support this as an 1233 * experimental feature. Use a temporary hardware-qemu.ini 1234 * file though to avoid overwriting the existing one. */ 1235 TempFile* tempIni = tempfile_create(); 1236 coreHwIniPath = tempfile_path(tempIni); 1237 } 1238 1239 /* While saving HW config, ignore valueless entries. This will not break 1240 * anything, but will significantly simplify comparing the current HW 1241 * config with the one that has been associated with a snapshot (in case 1242 * VM starts from a snapshot for this instance of emulator). */ 1243 if (iniFile_saveToFileClean(hwIni, coreHwIniPath) < 0) { 1244 derror("Could not write hardware.ini to %s: %s", coreHwIniPath, strerror(errno)); 1245 exit(2); 1246 } 1247 args[n++] = "-android-hw"; 1248 args[n++] = strdup(coreHwIniPath); 1249 1250 /* In verbose mode, dump the file's content */ 1251 if (VERBOSE_CHECK(init)) { 1252 FILE* file = fopen(coreHwIniPath, "rt"); 1253 if (file == NULL) { 1254 derror("Could not open hardware configuration file: %s\n", 1255 coreHwIniPath); 1256 } else { 1257 LineInput* input = lineInput_newFromStdFile(file); 1258 const char* line; 1259 printf("Content of hardware configuration file:\n"); 1260 while ((line = lineInput_getLine(input)) != NULL) { 1261 printf(" %s\n", line); 1262 } 1263 printf(".\n"); 1264 lineInput_free(input); 1265 fclose(file); 1266 } 1267 } 1268 } 1269 1270 if(VERBOSE_CHECK(init)) { 1271 int i; 1272 printf("QEMU options list:\n"); 1273 for(i = 0; i < n; i++) { 1274 printf("emulator: argv[%02d] = \"%s\"\n", i, args[i]); 1275 } 1276 /* Dump final command-line option to make debugging the core easier */ 1277 printf("Concatenated QEMU options:\n"); 1278 for (i = 0; i < n; i++) { 1279 /* To make it easier to copy-paste the output to a command-line, 1280 * quote anything that contains spaces. 1281 */ 1282 if (strchr(args[i], ' ') != NULL) { 1283 printf(" '%s'", args[i]); 1284 } else { 1285 printf(" %s", args[i]); 1286 } 1287 } 1288 printf("\n"); 1289 } 1290 1291 /* Setup SDL UI just before calling the code */ 1292 init_sdl_ui(skinConfig, skinPath, opts); 1293 1294 if (attach_ui_to_core(opts) < 0) { 1295 derror("Can't attach to core!"); 1296 exit(1); 1297 } 1298 1299 return qemu_main(n, args); 1300 } 1301