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