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