• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright (C) 2006-2008 The Android Open Source Project
2 **
3 ** This software is licensed under the terms of the GNU General Public
4 ** License version 2, as published by the Free Software Foundation, and
5 ** may be copied, distributed, and modified under those terms.
6 **
7 ** This program is distributed in the hope that it will be useful,
8 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
9 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10 ** GNU General Public License for more details.
11 */
12 
13 #include <signal.h>
14 #include <unistd.h>
15 #include <string.h>
16 #include <sys/time.h>
17 #ifdef _WIN32
18 #include <process.h>
19 #endif
20 
21 #include "sockets.h"
22 
23 #include "android/android.h"
24 #include "qemu-common.h"
25 #include "sysemu.h"
26 #include "console.h"
27 #include "user-events.h"
28 
29 #include <SDL.h>
30 #include <SDL_syswm.h>
31 
32 #include "math.h"
33 
34 #include "android/charmap.h"
35 #include "android/utils/debug.h"
36 #include "android/config.h"
37 #include "android/config/config.h"
38 
39 #include "android/user-config.h"
40 #include "android/utils/bufprint.h"
41 #include "android/utils/filelock.h"
42 #include "android/utils/lineinput.h"
43 #include "android/utils/path.h"
44 #include "android/utils/tempfile.h"
45 
46 #include "android/main-common.h"
47 #include "android/help.h"
48 #include "hw/goldfish_nand.h"
49 
50 #include "android/globals.h"
51 
52 #include "android/qemulator.h"
53 #include "android/display.h"
54 
55 #include "android/snapshot.h"
56 
57 #include "android/framebuffer.h"
58 #include "iolooper.h"
59 
60 AndroidRotation  android_framebuffer_rotation;
61 
62 #define  STRINGIFY(x)   _STRINGIFY(x)
63 #define  _STRINGIFY(x)  #x
64 
65 #ifdef ANDROID_SDK_TOOLS_REVISION
66 #  define  VERSION_STRING  STRINGIFY(ANDROID_SDK_TOOLS_REVISION)".0"
67 #else
68 #  define  VERSION_STRING  "standalone"
69 #endif
70 
71 #define  D(...)  do {  if (VERBOSE_CHECK(init)) dprint(__VA_ARGS__); } while (0)
72 
73 extern int  control_console_start( int  port );  /* in control.c */
74 
75 extern int qemu_milli_needed;
76 
77 /* the default device DPI if none is specified by the skin
78  */
79 #define  DEFAULT_DEVICE_DPI  165
80 
81 #ifdef CONFIG_TRACE
82 extern void  start_tracing(void);
83 extern void  stop_tracing(void);
84 #endif
85 
86 unsigned long   android_verbose;
87 
88 int qemu_main(int argc, char **argv);
89 
90 /* this function dumps the QEMU help */
91 extern void  help( void );
92 extern void  emulator_help( void );
93 
94 #define  VERBOSE_OPT(str,var)   { str, &var }
95 
96 #define  _VERBOSE_TAG(x,y)   { #x, VERBOSE_##x, y },
97 static const struct { const char*  name; int  flag; const char*  text; }
98 verbose_options[] = {
99     VERBOSE_TAG_LIST
100     { 0, 0, 0 }
101 };
102 
emulator_help(void)103 void emulator_help( void )
104 {
105     STRALLOC_DEFINE(out);
106     android_help_main(out);
107     printf( "%.*s", out->n, out->s );
108     stralloc_reset(out);
109     exit(1);
110 }
111 
112 /* TODO: Put in shared source file */
113 static char*
_getFullFilePath(const char * rootPath,const char * fileName)114 _getFullFilePath( const char* rootPath, const char* fileName )
115 {
116     if (path_is_absolute(fileName)) {
117         return ASTRDUP(fileName);
118     } else {
119         char temp[PATH_MAX], *p=temp, *end=p+sizeof(temp);
120 
121         p = bufprint(temp, end, "%s/%s", rootPath, fileName);
122         if (p >= end) {
123             return NULL;
124         }
125         return ASTRDUP(temp);
126     }
127 }
128 
129 static uint64_t
_adjustPartitionSize(const char * description,uint64_t imageBytes,uint64_t defaultBytes,int inAndroidBuild)130 _adjustPartitionSize( const char*  description,
131                       uint64_t     imageBytes,
132                       uint64_t     defaultBytes,
133                       int          inAndroidBuild )
134 {
135     char      temp[64];
136     unsigned  imageMB;
137     unsigned  defaultMB;
138 
139     if (imageBytes <= defaultBytes)
140         return defaultBytes;
141 
142     imageMB   = convertBytesToMB(imageBytes);
143     defaultMB = convertBytesToMB(defaultBytes);
144 
145     if (imageMB > defaultMB) {
146         snprintf(temp, sizeof temp, "(%d MB > %d MB)", imageMB, defaultMB);
147     } else {
148         snprintf(temp, sizeof temp, "(%" PRIu64 "  bytes > %" PRIu64 " bytes)", imageBytes, defaultBytes);
149     }
150 
151     if (inAndroidBuild) {
152         dwarning("%s partition size adjusted to match image file %s\n", description, temp);
153     }
154 
155     return convertMBToBytes(imageMB);
156 }
157 
main(int argc,char ** argv)158 int main(int argc, char **argv)
159 {
160     char   tmp[MAX_PATH];
161     char*  tmpend = tmp + sizeof(tmp);
162     char*  args[128];
163     int    n;
164     char*  opt;
165     /* The emulator always uses the first serial port for kernel messages
166      * and the second one for qemud. So start at the third if we need one
167      * for logcat or 'shell'
168      */
169     int    serial = 2;
170     int    shell_serial = 0;
171 
172     int    forceArmv7 = 0;
173 
174     AndroidHwConfig*  hw;
175     AvdInfo*          avd;
176     AConfig*          skinConfig;
177     char*             skinPath;
178     int               inAndroidBuild;
179     uint64_t          defaultPartitionSize = convertMBToBytes(200);
180 
181     AndroidOptions  opts[1];
182     /* net.shared_net_ip boot property value. */
183     char boot_prop_ip[64];
184     boot_prop_ip[0] = '\0';
185 
186     args[0] = argv[0];
187 
188     if ( android_parse_options( &argc, &argv, opts ) < 0 ) {
189         exit(1);
190     }
191 
192 #ifdef _WIN32
193     socket_init();
194 #endif
195 
196     handle_ui_options(opts);
197 
198     while (argc-- > 1) {
199         opt = (++argv)[0];
200 
201         if(!strcmp(opt, "-qemu")) {
202             argc--;
203             argv++;
204             break;
205         }
206 
207         if (!strcmp(opt, "-help")) {
208             emulator_help();
209         }
210 
211         if (!strncmp(opt, "-help-",6)) {
212             STRALLOC_DEFINE(out);
213             opt += 6;
214 
215             if (!strcmp(opt, "all")) {
216                 android_help_all(out);
217             }
218             else if (android_help_for_option(opt, out) == 0) {
219                 /* ok */
220             }
221             else if (android_help_for_topic(opt, out) == 0) {
222                 /* ok */
223             }
224             if (out->n > 0) {
225                 printf("\n%.*s", out->n, out->s);
226                 exit(0);
227             }
228 
229             fprintf(stderr, "unknown option: -help-%s\n", opt);
230             fprintf(stderr, "please use -help for a list of valid topics\n");
231             exit(1);
232         }
233 
234         if (opt[0] == '-') {
235             fprintf(stderr, "unknown option: %s\n", opt);
236             fprintf(stderr, "please use -help for a list of valid options\n");
237             exit(1);
238         }
239 
240         fprintf(stderr, "invalid command-line parameter: %s.\n", opt);
241         fprintf(stderr, "Hint: use '@foo' to launch a virtual device named 'foo'.\n");
242         fprintf(stderr, "please use -help for more information\n");
243         exit(1);
244     }
245 
246     if (opts->version) {
247         printf("Android emulator version %s\n"
248                "Copyright (C) 2006-2011 The Android Open Source Project and many others.\n"
249                "This program is a derivative of the QEMU CPU emulator (www.qemu.org).\n\n",
250 #if defined ANDROID_BUILD_ID
251                VERSION_STRING " (build_id " STRINGIFY(ANDROID_BUILD_ID) ")" );
252 #else
253                VERSION_STRING);
254 #endif
255         printf("  This software is licensed under the terms of the GNU General Public\n"
256                "  License version 2, as published by the Free Software Foundation, and\n"
257                "  may be copied, distributed, and modified under those terms.\n\n"
258                "  This program is distributed in the hope that it will be useful,\n"
259                "  but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
260                "  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n"
261                "  GNU General Public License for more details.\n\n");
262 
263         exit(0);
264     }
265 
266     if (opts->snapshot_list) {
267         if (opts->snapstorage == NULL) {
268             /* Need to find the default snapstorage */
269             avd = createAVD(opts, &inAndroidBuild);
270             opts->snapstorage = avdInfo_getSnapStoragePath(avd);
271             if (opts->snapstorage != NULL) {
272                 D("autoconfig: -snapstorage %s", opts->snapstorage);
273             } else {
274                 if (inAndroidBuild) {
275                     derror("You must use the -snapstorage <file> option to specify a snapshot storage file!\n");
276                 } else {
277                     derror("This AVD doesn't have snapshotting enabled!\n");
278                 }
279                 exit(1);
280             }
281         }
282         snapshot_print_and_exit(opts->snapstorage);
283     }
284 
285     sanitizeOptions(opts);
286 
287     /* Initialization of UI started with -attach-core should work differently
288      * than initialization of UI that starts the core. In particular....
289      */
290 
291     /* -charmap is incompatible with -attach-core, because particular
292      * charmap gets set up in the running core. */
293     if (android_charmap_setup(opts->charmap)) {
294         exit(1);
295     }
296 
297     /* Parses options and builds an appropriate AVD. */
298     avd = android_avdInfo = createAVD(opts, &inAndroidBuild);
299 
300     /* get the skin from the virtual device configuration */
301     if (opts->skindir != NULL) {
302         if (opts->skin == NULL) {
303             /* NOTE: Normally handled by sanitizeOptions(), just be safe */
304             derror("The -skindir <path> option requires a -skin <name> option");
305             exit(2);
306         }
307     } else {
308         char* skinName;
309         char* skinDir;
310 
311         avdInfo_getSkinInfo(avd, &skinName, &skinDir);
312 
313         if (opts->skin == NULL) {
314             opts->skin = skinName;
315             D("autoconfig: -skin %s", opts->skin);
316         } else {
317             AFREE(skinName);
318         }
319 
320         opts->skindir = skinDir;
321         D("autoconfig: -skindir %s", opts->skindir);
322 
323         /* update the avd hw config from this new skin */
324         avdInfo_getSkinHardwareIni(avd, opts->skin, opts->skindir);
325     }
326 
327     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