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