17654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner// Copyright 2014 The Android Open Source Project
27654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner//
37654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner// This software is licensed under the terms of the GNU General Public
47654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner// License version 2, as published by the Free Software Foundation, and
57654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner// may be copied, distributed, and modified under those terms.
67654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner//
77654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner// This program is distributed in the hope that it will be useful,
87654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner// but WITHOUT ANY WARRANTY; without even the implied warranty of
97654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
107654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner// GNU General Public License for more details.
117654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
127654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner// This source file implements emulator-arm64 and emulator64-arm64
137654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner// which are used to launch QEMU binaries located under
147654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner// $PROGRAM_DIR/qemu/<host>/qemu-system-aarch64<exe>
157654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
167654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner#include "android/base/containers/StringVector.h"
177654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner#include "android/base/files/PathUtils.h"
187654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner#include "android/base/Limits.h"
197654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner#include "android/base/Log.h"
207654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner#include "android/base/String.h"
217654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner#include "android/base/StringFormat.h"
227654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
237654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner#include "android/cmdline-option.h"
247654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner#include "android/globals.h"
257654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner#include "android/help.h"
267654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner#include "android/kernel/kernel_utils.h"
277654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner#include "android/main-common.h"
287654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner#include "android/utils/bufprint.h"
297654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner#include "android/utils/debug.h"
307654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner#include "android/utils/path.h"
317654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner#include "android/utils/stralloc.h"
327654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner#include "android/utils/win32_cmdline_quote.h"
337654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
347654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner#include <limits.h>
357654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner#include <stdio.h>
367654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner#include <stdlib.h>
377654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner#include <unistd.h>
387654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
397654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner#define  STRINGIFY(x)   _STRINGIFY(x)
407654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner#define  _STRINGIFY(x)  #x
417654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
427654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner#ifdef ANDROID_SDK_TOOLS_REVISION
437654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner#  define  VERSION_STRING  STRINGIFY(ANDROID_SDK_TOOLS_REVISION)".0"
447654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner#else
457654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner#  define  VERSION_STRING  "standalone"
467654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner#endif
477654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
487654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner#define  D(...)  do {  if (VERBOSE_CHECK(init)) dprint(__VA_ARGS__); } while (0)
497654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
507654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner/* The execv() definition in older mingw is slightly bogus.
517654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner * It takes a second argument of type 'const char* const*'
527654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner * while POSIX mandates char** instead.
537654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner *
547654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner * To avoid compiler warnings, define the safe_execv macro
557654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner * to perform an explicit cast with mingw.
567654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner */
577654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner#if defined(_WIN32) && !ANDROID_GCC_PREREQ(4,4)
587654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner#  define safe_execv(_filepath,_argv)  execv((_filepath),(const char* const*)(_argv))
597654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner#else
607654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner#  define safe_execv(_filepath,_argv)  execv((_filepath),(_argv))
617654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner#endif
627654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
637654e7efee943bdbaf167170a087388c54681366David 'Digit' Turnerusing namespace android::base;
647654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
657654e7efee943bdbaf167170a087388c54681366David 'Digit' Turnernamespace {
667654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
677654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner// The host CPU architecture.
687654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner#ifdef __i386__
697654e7efee943bdbaf167170a087388c54681366David 'Digit' Turnerconst char kHostArch[] = "x86";
707654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner#elif defined(__x86_64__)
717654e7efee943bdbaf167170a087388c54681366David 'Digit' Turnerconst char kHostArch[] = "x86_64";
727654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner#else
737654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner#error "Your host CPU is not supported!"
747654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner#endif
757654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
767654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner// The host operating system name.
777654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner#ifdef __linux__
787654e7efee943bdbaf167170a087388c54681366David 'Digit' Turnerstatic const char kHostOs[] = "linux";
797654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner#elif defined(__APPLE__)
807654e7efee943bdbaf167170a087388c54681366David 'Digit' Turnerstatic const char kHostOs[] = "darwin";
817654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner#elif defined(_WIN32)
827654e7efee943bdbaf167170a087388c54681366David 'Digit' Turnerstatic const char kHostOs[] = "windows";
837654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner#endif
847654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
857654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner// The target CPU architecture.
867654e7efee943bdbaf167170a087388c54681366David 'Digit' Turnerconst char kTargetArch[] = "aarch64";
877654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
887654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner// Return the path of the QEMU executable
897654e7efee943bdbaf167170a087388c54681366David 'Digit' TurnerString getQemuExecutablePath(const char* programPath) {
907654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    StringVector path = PathUtils::decompose(programPath);
917654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    if (path.size() < 1) {
927654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        return String();
937654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    }
947654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    // Remove program from path.
957654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    path.resize(path.size() - 1U);
967654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
977654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    // Add sub-directories.
987654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    path.append(String("qemu"));
997654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
1007654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    String host = kHostOs;
1017654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    host += "-";
1027654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    host += kHostArch;
1037654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    path.append(host);
1047654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
1057654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    String qemuProgram = "qemu-system-";
1067654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    qemuProgram += kTargetArch;
1077654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner#ifdef _WIN32
1087654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    qemuProgram += ".exe";
1097654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner#endif
1107654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    path.append(qemuProgram);
1117654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
1127654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    return PathUtils::recompose(path);
1137654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner}
1147654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
1157654e7efee943bdbaf167170a087388c54681366David 'Digit' Turnervoid emulator_help( void ) {
1167654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    STRALLOC_DEFINE(out);
1177654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    android_help_main(out);
1187654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    printf("%.*s", out->n, out->s);
1197654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    stralloc_reset(out);
1207654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    exit(1);
1217654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner}
1227654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
1237654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner/* TODO: Put in shared source file */
1247654e7efee943bdbaf167170a087388c54681366David 'Digit' Turnerchar* _getFullFilePath(const char* rootPath, const char* fileName) {
1257654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    if (path_is_absolute(fileName)) {
1267654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        return ASTRDUP(fileName);
1277654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    } else {
1287654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        char temp[PATH_MAX], *p=temp, *end=p+sizeof(temp);
1297654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
1307654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        p = bufprint(temp, end, "%s/%s", rootPath, fileName);
1317654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        if (p >= end) {
1327654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            return NULL;
1337654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        }
1347654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        return ASTRDUP(temp);
1357654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    }
1367654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner}
1377654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
1387654e7efee943bdbaf167170a087388c54681366David 'Digit' Turneruint64_t _adjustPartitionSize(const char*  description,
1397654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner                              uint64_t     imageBytes,
1407654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner                              uint64_t     defaultBytes,
1417654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner                              int          inAndroidBuild ) {
1427654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    char      temp[64];
1437654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    unsigned  imageMB;
1447654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    unsigned  defaultMB;
1457654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
1467654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    if (imageBytes <= defaultBytes)
1477654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        return defaultBytes;
1487654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
1497654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    imageMB   = convertBytesToMB(imageBytes);
1507654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    defaultMB = convertBytesToMB(defaultBytes);
1517654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
1527654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    if (imageMB > defaultMB) {
1537654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        snprintf(temp, sizeof temp, "(%d MB > %d MB)", imageMB, defaultMB);
1547654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    } else {
1557654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        snprintf(temp, sizeof temp, "(%" PRIu64 "  bytes > %" PRIu64 " bytes)", imageBytes, defaultBytes);
1567654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    }
1577654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
1587654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    if (inAndroidBuild) {
1597654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        dwarning("%s partition size adjusted to match image file %s\n", description, temp);
1607654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    }
1617654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
1627654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    return convertMBToBytes(imageMB);
1637654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner}
1647654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
1657654e7efee943bdbaf167170a087388c54681366David 'Digit' Turnerbool android_op_wipe_data;
1667654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
1677654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner}  // namespace
1687654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
1697654e7efee943bdbaf167170a087388c54681366David 'Digit' Turnerextern "C" int main(int argc, char **argv, char **envp) {
1707654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    if (argc < 1) {
1717654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        fprintf(stderr, "Invalid invokation (no program path)\n");
1727654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        return 1;
1737654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    }
1747654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
1757654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    AndroidOptions opts[1];
1767654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
1777654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    if (android_parse_options(&argc, &argv, opts) < 0) {
1787654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        return 1;
1797654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    }
1807654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
1817654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    // TODO(digit): This code is very similar to the one in main.c,
1827654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    // refactor everything so that it fits into a single shared source
1837654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    // file, if possible, with the least amount of dependencies.
1847654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
1857654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    while (argc-- > 1) {
1867654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        const char* opt = (++argv)[0];
1877654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
1887654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        if(!strcmp(opt, "-qemu")) {
1897654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            argc--;
1907654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            argv++;
1917654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            break;
1927654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        }
1937654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
1947654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        if (!strcmp(opt, "-help")) {
1957654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            emulator_help();
1967654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        }
1977654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
1987654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        if (!strncmp(opt, "-help-",6)) {
1997654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            STRALLOC_DEFINE(out);
2007654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            opt += 6;
2017654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
2027654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            if (!strcmp(opt, "all")) {
2037654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner                android_help_all(out);
2047654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            }
2057654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            else if (android_help_for_option(opt, out) == 0) {
2067654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner                /* ok */
2077654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            }
2087654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            else if (android_help_for_topic(opt, out) == 0) {
2097654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner                /* ok */
2107654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            }
2117654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            if (out->n > 0) {
2127654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner                printf("\n%.*s", out->n, out->s);
2137654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner                exit(0);
2147654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            }
2157654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
2167654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            fprintf(stderr, "unknown option: -help-%s\n", opt);
2177654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            fprintf(stderr, "please use -help for a list of valid topics\n");
2187654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            exit(1);
2197654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        }
2207654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
2217654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        if (opt[0] == '-') {
2227654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            fprintf(stderr, "unknown option: %s\n", opt);
2237654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            fprintf(stderr, "please use -help for a list of valid options\n");
2247654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            exit(1);
2257654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        }
2267654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
2277654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        fprintf(stderr, "invalid command-line parameter: %s.\n", opt);
2287654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        fprintf(stderr, "Hint: use '@foo' to launch a virtual device named 'foo'.\n");
2297654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        fprintf(stderr, "please use -help for more information\n");
2307654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        exit(1);
2317654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    }
2327654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
2337654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    if (opts->version) {
2347654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        printf("Android emulator version %s\n"
2357654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner               "Copyright (C) 2006-2011 The Android Open Source Project and many others.\n"
2367654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner               "This program is a derivative of the QEMU CPU emulator (www.qemu.org).\n\n",
2377654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner#if defined ANDROID_BUILD_ID
2387654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner               VERSION_STRING " (build_id " STRINGIFY(ANDROID_BUILD_ID) ")" );
2397654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner#else
2407654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner               VERSION_STRING);
2417654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner#endif
2427654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        printf("  This software is licensed under the terms of the GNU General Public\n"
2437654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner               "  License version 2, as published by the Free Software Foundation, and\n"
2447654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner               "  may be copied, distributed, and modified under those terms.\n\n"
2457654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner               "  This program is distributed in the hope that it will be useful,\n"
2467654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner               "  but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
2477654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner               "  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n"
2487654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner               "  GNU General Public License for more details.\n\n");
2497654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
2507654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        exit(0);
2517654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    }
2527654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
2537654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    sanitizeOptions(opts);
2547654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
2557654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    // Ignore snapshot storage here.
2567654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
2577654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    int inAndroidBuild = 0;
2587654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    AvdInfo* avd = createAVD(opts, &inAndroidBuild);
2597654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
2607654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    // Ignore skin options here.
2617654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
2627654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    // Read hardware configuration, apply overrides from options.
2637654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    AndroidHwConfig* hw = android_hw;
2647654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    if (avdInfo_initHwConfig(avd, hw) < 0) {
2657654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        derror("could not read hardware configuration ?");
2667654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        exit(1);
2677654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    }
2687654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
2697654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    /* Update CPU architecture for HW configs created from build dir. */
2707654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    if (inAndroidBuild) {
2717654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner#if defined(TARGET_ARM)
2727654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        reassign_string(&android_hw->hw_cpu_arch, "arm");
2737654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner#elif defined(TARGET_I386)
2747654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        reassign_string(&android_hw->hw_cpu_arch, "x86");
2757654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner#elif defined(TARGET_MIPS)
2767654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        reassign_string(&android_hw->hw_cpu_arch, "mips");
2777654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner#elif defined(TARGET_ARM64)
2787654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        reassign_string(&android_hw->hw_cpu_arch, "arm64");
2797654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner#endif
2807654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    }
2817654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
2827654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    /* generate arguments for the underlying qemu main() */
2837654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    {
2847654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        char*  kernelFile    = opts->kernel;
2857654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
2867654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        if (kernelFile == NULL) {
2877654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            kernelFile = avdInfo_getKernelPath(avd);
2887654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            if (kernelFile == NULL) {
2897654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner                derror( "This AVD's configuration is missing a kernel file!!" );
2907654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner                exit(2);
2917654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            }
2927654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            D("autoconfig: -kernel %s", kernelFile);
2937654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        }
2947654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        if (!path_exists(kernelFile)) {
2957654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            derror( "Invalid or missing kernel image file: %s", kernelFile );
2967654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            exit(2);
2977654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        }
2987654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
2997654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        hw->kernel_path = kernelFile;
3007654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    }
3017654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
3027654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    KernelType kernelType = KERNEL_TYPE_LEGACY;
3037654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    if (!android_pathProbeKernelType(hw->kernel_path, &kernelType)) {
3047654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        D("WARNING: Could not determine kernel device naming scheme. Assuming legacy\n"
3057654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            "If this AVD doesn't boot, and uses a recent kernel (3.10 or above) try setting\n"
3067654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            "'kernel.newDeviceNaming' to 'yes' in its configuration.\n");
3077654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    }
3087654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
3097654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    // Auto-detect kernel device naming scheme if needed.
3107654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    if (androidHwConfig_getKernelDeviceNaming(hw) < 0) {
3117654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        const char* newDeviceNaming = "no";
3127654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        if (kernelType == KERNEL_TYPE_3_10_OR_ABOVE) {
3137654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            D("Auto-detect: Kernel image requires new device naming scheme.");
3147654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            newDeviceNaming = "yes";
3157654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        } else {
3167654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            D("Auto-detect: Kernel image requires legacy device naming scheme.");
3177654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        }
3187654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        AFREE(hw->kernel_newDeviceNaming);
3197654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        hw->kernel_newDeviceNaming = ASTRDUP(newDeviceNaming);
3207654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    }
3217654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
3227654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    // Auto-detect YAFFS2 partition support if needed.
3237654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    if (androidHwConfig_getKernelYaffs2Support(hw) < 0) {
3247654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        // Essentially, anything before API level 20 supports Yaffs2
3257654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        const char* newYaffs2Support = "no";
3267654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        if (avdInfo_getApiLevel(avd) < 20) {
3277654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            newYaffs2Support = "yes";
3287654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            D("Auto-detect: Kernel does support YAFFS2 partitions.");
3297654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        } else {
3307654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            D("Auto-detect: Kernel does not support YAFFS2 partitions.");
3317654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        }
3327654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        AFREE(hw->kernel_supportsYaffs2);
3337654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        hw->kernel_supportsYaffs2 = ASTRDUP(newYaffs2Support);
3347654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    }
3357654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
3367654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
3377654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    /* opts->ramdisk is never NULL (see createAVD) here */
3387654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    if (opts->ramdisk) {
3397654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        reassign_string(&hw->disk_ramdisk_path, opts->ramdisk);
3407654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    }
3417654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    else if (!hw->disk_ramdisk_path[0]) {
3427654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        hw->disk_ramdisk_path = avdInfo_getRamdiskPath(avd);
3437654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        D("autoconfig: -ramdisk %s", hw->disk_ramdisk_path);
3447654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    }
3457654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
3467654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    /* -partition-size is used to specify the max size of both the system
3477654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner     * and data partition sizes.
3487654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner     */
3497654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    uint64_t defaultPartitionSize = convertMBToBytes(200);
3507654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
3517654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    if (opts->partition_size) {
3527654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        char*  end;
3537654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        long   sizeMB = strtol(opts->partition_size, &end, 0);
3547654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        long   minSizeMB = 10;
3557654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        long   maxSizeMB = LONG_MAX / ONE_MB;
3567654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
3577654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        if (sizeMB < 0 || *end != 0) {
3587654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            derror( "-partition-size must be followed by a positive integer" );
3597654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            exit(1);
3607654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        }
3617654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        if (sizeMB < minSizeMB || sizeMB > maxSizeMB) {
3627654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            derror( "partition-size (%d) must be between %dMB and %dMB",
3637654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner                    sizeMB, minSizeMB, maxSizeMB );
3647654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            exit(1);
3657654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        }
3667654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        defaultPartitionSize = (uint64_t) sizeMB * ONE_MB;
3677654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    }
3687654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
3697654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    /** SYSTEM PARTITION **/
3707654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
3717654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    if (opts->sysdir == NULL) {
3727654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        if (avdInfo_inAndroidBuild(avd)) {
3737654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            opts->sysdir = ASTRDUP(avdInfo_getContentPath(avd));
3747654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            D("autoconfig: -sysdir %s", opts->sysdir);
3757654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        }
3767654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    }
3777654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
3787654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    if (opts->sysdir != NULL) {
3797654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        if (!path_exists(opts->sysdir)) {
3807654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            derror("Directory does not exist: %s", opts->sysdir);
3817654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            exit(1);
3827654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        }
3837654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    }
3847654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
3857654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    {
3867654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        char*  rwImage   = NULL;
3877654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        char*  initImage = NULL;
3887654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
3897654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        do {
3907654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            if (opts->system == NULL) {
3917654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner                /* If -system is not used, try to find a runtime system image
3927654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner                * (i.e. system-qemu.img) in the content directory.
3937654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner                */
3947654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner                rwImage = avdInfo_getSystemImagePath(avd);
3957654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner                if (rwImage != NULL) {
3967654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner                    break;
3977654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner                }
3987654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner                /* Otherwise, try to find the initial system image */
3997654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner                initImage = avdInfo_getSystemInitImagePath(avd);
4007654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner                if (initImage == NULL) {
4017654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner                    derror("No initial system image for this configuration!");
4027654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner                    exit(1);
4037654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner                }
4047654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner                break;
4057654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            }
4067654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
4077654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            /* If -system <name> is used, use it to find the initial image */
4087654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            if (opts->sysdir != NULL && !path_exists(opts->system)) {
4097654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner                initImage = _getFullFilePath(opts->sysdir, opts->system);
4107654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            } else {
4117654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner                initImage = ASTRDUP(opts->system);
4127654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            }
4137654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            if (!path_exists(initImage)) {
4147654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner                derror("System image file doesn't exist: %s", initImage);
4157654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner                exit(1);
4167654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            }
4177654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
4187654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        } while (0);
4197654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
4207654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        if (rwImage != NULL) {
4217654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            /* Use the read/write image file directly */
4227654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            hw->disk_systemPartition_path     = rwImage;
4237654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            hw->disk_systemPartition_initPath = NULL;
4247654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            D("Using direct system image: %s", rwImage);
4257654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        } else if (initImage != NULL) {
4267654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            hw->disk_systemPartition_path = NULL;
4277654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            hw->disk_systemPartition_initPath = initImage;
4287654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            D("Using initial system image: %s", initImage);
4297654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        }
4307654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
4317654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        /* Check the size of the system partition image.
4327654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        * If we have an AVD, it must be smaller than
4337654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        * the disk.systemPartition.size hardware property.
4347654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        *
4357654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        * Otherwise, we need to adjust the systemPartitionSize
4367654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        * automatically, and print a warning.
4377654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        *
4387654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        */
4397654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        const char* systemImage = hw->disk_systemPartition_path;
4407654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        uint64_t    systemBytes;
4417654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
4427654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        if (systemImage == NULL)
4437654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            systemImage = hw->disk_systemPartition_initPath;
4447654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
4457654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        if (path_get_size(systemImage, &systemBytes) < 0) {
4467654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            derror("Missing system image: %s", systemImage);
4477654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            exit(1);
4487654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        }
4497654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
4507654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        hw->disk_systemPartition_size =
4517654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            _adjustPartitionSize("system", systemBytes, defaultPartitionSize,
4527654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner                                 avdInfo_inAndroidBuild(avd));
4537654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    }
4547654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
4557654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    /** DATA PARTITION **/
4567654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
4577654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    if (opts->datadir) {
4587654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        if (!path_exists(opts->datadir)) {
4597654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            derror("Invalid -datadir directory: %s", opts->datadir);
4607654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        }
4617654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    }
4627654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
4637654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    {
4647654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        char*  dataImage = NULL;
4657654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        char*  initImage = NULL;
4667654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
4677654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        do {
4687654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            if (!opts->data) {
4697654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner                dataImage = avdInfo_getDataImagePath(avd);
4707654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner                if (dataImage != NULL) {
4717654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner                    D("autoconfig: -data %s", dataImage);
4727654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner                    break;
4737654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner                }
4747654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner                dataImage = avdInfo_getDefaultDataImagePath(avd);
4757654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner                if (dataImage == NULL) {
4767654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner                    derror("No data image path for this configuration!");
4777654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner                    exit (1);
4787654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner                }
4797654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner                opts->wipe_data = 1;
4807654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner                break;
4817654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            }
4827654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
4837654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            if (opts->datadir) {
4847654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner                dataImage = _getFullFilePath(opts->datadir, opts->data);
4857654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            } else {
4867654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner                dataImage = ASTRDUP(opts->data);
4877654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            }
4887654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        } while (0);
4897654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
4907654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        if (opts->initdata != NULL) {
4917654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            initImage = ASTRDUP(opts->initdata);
4927654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            if (!path_exists(initImage)) {
4937654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner                derror("Invalid initial data image path: %s", initImage);
4947654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner                exit(1);
4957654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            }
4967654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        } else {
4977654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            initImage = avdInfo_getDataInitImagePath(avd);
4987654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            D("autoconfig: -initdata %s", initImage);
4997654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        }
5007654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
5017654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        hw->disk_dataPartition_path = dataImage;
5027654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        if (opts->wipe_data) {
5037654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            hw->disk_dataPartition_initPath = initImage;
5047654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        } else {
5057654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            hw->disk_dataPartition_initPath = NULL;
5067654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        }
5077654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        android_op_wipe_data = opts->wipe_data;
5087654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
5097654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        uint64_t     defaultBytes =
5107654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner                hw->disk_dataPartition_size == 0 ?
5117654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner                defaultPartitionSize :
5127654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner                hw->disk_dataPartition_size;
5137654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        uint64_t     dataBytes;
5147654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        const char*  dataPath = hw->disk_dataPartition_initPath;
5157654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
5167654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        if (dataPath == NULL)
5177654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            dataPath = hw->disk_dataPartition_path;
5187654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
5197654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        path_get_size(dataPath, &dataBytes);
5207654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
5217654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        hw->disk_dataPartition_size =
5227654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            _adjustPartitionSize("data", dataBytes, defaultBytes,
5237654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner                                 avdInfo_inAndroidBuild(avd));
5247654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    }
5257654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
5267654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    /** CACHE PARTITION **/
5277654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
5287654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    if (opts->no_cache) {
5297654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        /* No cache partition at all */
5307654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        hw->disk_cachePartition = 0;
5317654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    }
5327654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    else if (!hw->disk_cachePartition) {
5337654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        if (opts->cache) {
5347654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            dwarning( "Emulated hardware doesn't support a cache partition. -cache option ignored!" );
5357654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            opts->cache = NULL;
5367654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        }
5377654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    }
5387654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    else
5397654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    {
5407654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        if (!opts->cache) {
5417654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            /* Find the current cache partition file */
5427654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            opts->cache = avdInfo_getCachePath(avd);
5437654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            if (opts->cache == NULL) {
5447654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner                /* The file does not exists, we will force its creation
5457654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner                 * if we are not in the Android build system. Otherwise,
5467654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner                 * a temporary file will be used.
5477654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner                 */
5487654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner                if (!avdInfo_inAndroidBuild(avd)) {
5497654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner                    opts->cache = avdInfo_getDefaultCachePath(avd);
5507654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner                }
5517654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            }
5527654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            if (opts->cache) {
5537654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner                D("autoconfig: -cache %s", opts->cache);
5547654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            }
5557654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        }
5567654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
5577654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        if (opts->cache) {
5587654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            hw->disk_cachePartition_path = ASTRDUP(opts->cache);
5597654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        }
5607654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    }
5617654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
5627654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    if (hw->disk_cachePartition_path && opts->cache_size) {
5637654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        /* Set cache partition size per user options. */
5647654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        char*  end;
5657654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        long   sizeMB = strtol(opts->cache_size, &end, 0);
5667654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
5677654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        if (sizeMB < 0 || *end != 0) {
5687654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            derror( "-cache-size must be followed by a positive integer" );
5697654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            exit(1);
5707654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        }
5717654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        hw->disk_cachePartition_size = (uint64_t) sizeMB * ONE_MB;
5727654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    }
5737654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
5747654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    /** SD CARD PARTITION */
5757654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
5767654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    if (!hw->hw_sdCard) {
5777654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        /* No SD Card emulation, so -sdcard will be ignored */
5787654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        if (opts->sdcard) {
5797654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            dwarning( "Emulated hardware doesn't support SD Cards. -sdcard option ignored." );
5807654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            opts->sdcard = NULL;
5817654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        }
5827654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    } else {
5837654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        /* Auto-configure -sdcard if it is not available */
5847654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        if (!opts->sdcard) {
5857654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            do {
5867654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner                /* If -datadir <path> is used, look for a sdcard.img file here */
5877654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner                if (opts->datadir) {
5887654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner                    char tmp[PATH_MAX], *tmpend = tmp + sizeof(tmp);
5897654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner                    bufprint(tmp, tmpend, "%s/%s", opts->datadir, "system.img");
5907654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner                    if (path_exists(tmp)) {
5917654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner                        opts->sdcard = strdup(tmp);
5927654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner                        break;
5937654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner                    }
5947654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner                }
5957654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
5967654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner                /* Otherwise, look at the AVD's content */
5977654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner                opts->sdcard = avdInfo_getSdCardPath(avd);
5987654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner                if (opts->sdcard != NULL) {
5997654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner                    break;
6007654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner                }
6017654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
6027654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner                /* Nothing */
6037654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            } while (0);
6047654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
6057654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            if (opts->sdcard) {
6067654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner                D("autoconfig: -sdcard %s", opts->sdcard);
6077654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            }
6087654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        }
6097654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    }
6107654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
6117654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    if(opts->sdcard) {
6127654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        uint64_t  size;
6137654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        if (path_get_size(opts->sdcard, &size) == 0) {
6147654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            /* see if we have an sdcard image.  get its size if it exists */
6157654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            /* due to what looks like limitations of the MMC protocol, one has
6167654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner             * to use an SD Card image that is equal or larger than 9 MB
6177654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner             */
6187654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            if (size < 9*1024*1024ULL) {
6197654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner                fprintf(stderr, "### WARNING: SD Card files must be at least 9MB, ignoring '%s'\n", opts->sdcard);
6207654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            } else {
6217654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner                hw->hw_sdCard_path = ASTRDUP(opts->sdcard);
6227654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            }
6237654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        } else {
6247654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            dwarning("no SD Card image at '%s'", opts->sdcard);
6257654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        }
6267654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    }
6277654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
6287654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    if (opts->memory) {
6297654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        char*  end;
6307654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        long   ramSize = strtol(opts->memory, &end, 0);
6317654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        if (ramSize < 0 || *end != 0) {
6327654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            derror( "-memory must be followed by a positive integer" );
6337654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            exit(1);
6347654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        }
6357654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        if (ramSize < 32 || ramSize > 4096) {
6367654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            derror( "physical memory size must be between 32 and 4096 MB" );
6377654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            exit(1);
6387654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        }
6397654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        hw->hw_ramSize = ramSize;
6407654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    } else {
6417654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        int ramSize = hw->hw_ramSize;
6427654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        if (ramSize <= 0) {
6437654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner#if 1
6447654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            // For ARM64, use 1GB by default.
6457654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            ramSize = 1024 * 1024ULL;
6467654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner#else
6477654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            /* Compute the default RAM size based on the size of screen.
6487654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner             * This is only used when the skin doesn't provide the ram
6497654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner             * size through its hardware.ini (i.e. legacy ones) or when
6507654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner             * in the full Android build system.
6517654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner             */
6527654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            int64_t pixels  = hw->hw_lcd_width * hw->hw_lcd_height;
6537654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            /* The following thresholds are a bit liberal, but we
6547654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner             * essentially want to ensure the following mappings:
6557654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner             *
6567654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner             *   320x480 -> 96
6577654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner             *   800x600 -> 128
6587654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner             *  1024x768 -> 256
6597654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner             *
6607654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner             * These are just simple heuristics, they could change in
6617654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner             * the future.
6627654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner             */
6637654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            if (pixels <= 250000)
6647654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner                ramSize = 96;
6657654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            else if (pixels <= 500000)
6667654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner                ramSize = 128;
6677654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            else
6687654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner                ramSize = 256;
6697654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        }
6707654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner#endif
6717654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        hw->hw_ramSize = ramSize;
6727654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    }
6737654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
6747654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    D("Physical RAM size: %dMB\n", hw->hw_ramSize);
6757654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
6767654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    if (opts->gpu) {
6777654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        const char* gpu = opts->gpu;
6787654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        if (!strcmp(gpu,"on") || !strcmp(gpu,"enable")) {
6797654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            hw->hw_gpu_enabled = 1;
6807654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        } else if (!strcmp(gpu,"off") || !strcmp(gpu,"disable")) {
6817654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            hw->hw_gpu_enabled = 0;
6827654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        } else if (!strcmp(gpu,"auto")) {
6837654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            /* Nothing to do */
6847654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        } else {
6857654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            derror("Invalid value for -gpu <mode> parameter: %s\n", gpu);
6867654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            derror("Valid values are: on, off or auto\n");
6877654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            exit(1);
6887654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        }
6897654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    }
6907654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
6917654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    hw->avd_name = ASTRDUP(avdInfo_getName(avd));
6927654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
6937654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    String qemuExecutable = getQemuExecutablePath(argv[0]);
6947654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    D("QEMU EXECUTABLE=%s\n", qemuExecutable.c_str());
6957654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
6967654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    // Now build the QEMU parameters.
6977654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    const char* args[128];
6987654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    int n = 0;
6997654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
7007654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    args[n++] = qemuExecutable.c_str();
7017654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
7027654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    args[n++] = "-cpu";
7037654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    args[n++] = "cortex-a57";
7047654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    args[n++] = "-machine";
7057654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    args[n++] = "type=ranchu";
7067654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
7077654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    // Memory size
7087654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    args[n++] = "-m";
7097654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    String memorySize = StringFormat("%ld", hw->hw_ramSize);
7107654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    args[n++] = memorySize.c_str();
7117654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
7127654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    // Command-line
7137654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    args[n++] = "-append";
7147654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    String kernelCommandLine =
7157654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            "console=ttyAMA0,38400 keep_bootcon earlyprintk=ttyAMA0";
7167654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    args[n++] = kernelCommandLine.c_str();
7177654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
7187654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    args[n++] = "-serial";
7197654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    args[n++] = "mon:stdio";
7207654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
7217654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    // Kernel image
7227654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    args[n++] = "-kernel";
7237654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    args[n++] = hw->kernel_path;
7247654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
7257654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    // Ramdisk
7267654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    args[n++] = "-initrd";
7277654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    args[n++] = hw->disk_ramdisk_path;
7287654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
7297654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    // Data partition.
7307654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    args[n++] = "-drive";
7317654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    String userDataParam =
7327654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            StringFormat("index=2,id=userdata,file=%s",
7337654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner                         hw->disk_dataPartition_path);
7347654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    args[n++] = userDataParam.c_str();
7357654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    args[n++] = "-device";
7367654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    args[n++] = "virtio-blk-device,drive=userdata";
7377654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
7387654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    // Cache partition.
7397654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    args[n++] = "-drive";
7407654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    String cacheParam =
7417654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            StringFormat("index=1,id=cache,file=%s",
7427654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner                         hw->disk_cachePartition_path);
7437654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    args[n++] = cacheParam.c_str();
7447654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    args[n++] = "-device";
7457654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    args[n++] = "virtio-blk-device,drive=cache";
7467654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
7477654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    // System partition.
7487654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    args[n++] = "-drive";
7497654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    String systemParam =
7507654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            StringFormat("index=0,id=system,file=%s",
7517654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner                         hw->disk_systemPartition_initPath);
7527654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    args[n++] = systemParam.c_str();
7537654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    args[n++] = "-device";
7547654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    args[n++] = "virtio-blk-device,drive=system";
7557654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
7567654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    // Network
7577654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    args[n++] = "-netdev";
7587654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    args[n++] = "user,id=mynet";
7597654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    args[n++] = "-device";
7607654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    args[n++] = "virtio-net-device,netdev=mynet";
7617654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    args[n++] = "-show-cursor";
7627654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
7637654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    if(VERBOSE_CHECK(init)) {
7647654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        int i;
7657654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        printf("QEMU options list:\n");
7667654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        for(i = 0; i < n; i++) {
7677654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            printf("emulator: argv[%02d] = \"%s\"\n", i, args[i]);
7687654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        }
7697654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        /* Dump final command-line option to make debugging the core easier */
7707654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        printf("Concatenated QEMU options:\n");
7717654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        for (i = 0; i < n; i++) {
7727654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            /* To make it easier to copy-paste the output to a command-line,
7737654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner             * quote anything that contains spaces.
7747654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner             */
7757654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            if (strchr(args[i], ' ') != NULL) {
7767654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner                printf(" '%s'", args[i]);
7777654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            } else {
7787654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner                printf(" %s", args[i]);
7797654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            }
7807654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        }
7817654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        printf("\n");
7827654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    }
7837654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
7847654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    if (!path_exists(qemuExecutable.c_str())) {
7857654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        fprintf(stderr, "Missing QEMU executable: %s\n",
7867654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner                qemuExecutable.c_str());
7877654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        return 1;
7887654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    }
7897654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
7907654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    // Now launch executable.
7917654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner#ifdef _WIN32
7927654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    // Take care of quoting all parameters before sending them to execv().
7937654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    // See the "Eveyone quotes command line arguments the wrong way" on
7947654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    // MSDN.
7957654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    int i;
7967654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    for (i = 0; i < n; ++i) {
7977654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        // Technically, this leaks the quoted strings, but we don't care
7987654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        // since this process will terminate after the execv() anyway.
7997654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        args[i] = win32_cmdline_quote(args[i]);
8007654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner        D("Quoted param: [%s]\n", args[i]);
8017654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    }
8027654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner#endif
8037654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
8047654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    safe_execv(qemuExecutable.c_str(), (char* const*)args);
8057654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
8067654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    fprintf(stderr,
8077654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            "Could not launch QEMU [%s]: %s\n",
8087654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            qemuExecutable.c_str(),
8097654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner            strerror(errno));
8107654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner
8117654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner    return errno;
8127654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner}
8137654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner}
8147654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner}
8157654e7efee943bdbaf167170a087388c54681366David 'Digit' Turner}
816