merge from tools_r10
Change-Id: I70d9ccafb5912c85baa0711f7e9010bec223efaa
diff --git a/Makefile b/Makefile
index 7b23968..053525c 100644
--- a/Makefile
+++ b/Makefile
@@ -13,17 +13,28 @@
# limitations under the License.
#
+# disable implicit rules
+.SUFFIXES:
+%:: %,v
+%:: RCS/%
+%:: RCS/%,v
+%:: s.%
+%:: SCCS/s.%
+%.c: %.w %.ch
+
+
# this is a set of definitions that allow the usage of Makefile.android
# even if we're not using the Android build system.
#
BUILD_SYSTEM := android/build
OBJS_DIR := objs
+LIBS_DIR := $(OBJS_DIR)/libs
CONFIG_MAKE := $(OBJS_DIR)/config.make
CONFIG_H := $(OBJS_DIR)/config-host.h
ifeq ($(wildcard $(CONFIG_MAKE)),)
- $(error "The configuration file '$(CONFIG_MAKE)' doesnt' exist, please run the "rebuilt.sh" script)
+ $(error "The configuration file '$(CONFIG_MAKE)' doesnt' exist, please run the "android-configure.sh" script)
endif
include $(CONFIG_MAKE)
diff --git a/Makefile.android b/Makefile.android
index 1b44140..4b6e211 100644
--- a/Makefile.android
+++ b/Makefile.android
@@ -17,7 +17,6 @@
# determine the location of platform-specific directories
#
CONFIG_DIRS := \
- $(LOCAL_PATH)/android/config \
$(LOCAL_PATH)/android/config/$(QEMU_HOST_TAG)
ifeq ($(BUILD_STANDALONE_EMULATOR),true)
@@ -26,7 +25,9 @@
CONFIG_INCLUDES := $(CONFIG_DIRS:%=-I%)
-MY_CC := $(HOST_CC)
+MY_CC := $(HOST_CC)
+MY_CXX := $(HOST_CXX)
+MY_AR := $(HOST_AR)
MY_OPTIM := -O2 -g -fno-PIC -falign-functions=0 -fomit-frame-pointer
ifeq ($(BUILD_DEBUG_EMULATOR),true)
@@ -42,13 +43,6 @@
-fno-PIC -falign-functions=0
endif
-MY_CFLAGS += -DCONFIG_MEMCHECK
-
-# prepare config.h for x86
-ifeq ($(TARGET_ARCH),x86)
-MY_CFLAGS += -DARCH_FLAGS_x86
-endif
-
MY_LDLIBS :=
# this is needed to build the emulator on 64-bit Linux systems
@@ -96,9 +90,22 @@
# adequate values for HOST_CC
#
ifneq ($(BUILD_STANDALONE_EMULATOR),true)
+ # On Linux, use our custom 32-bit host toolchain, which contains the
+ # relevant headers and 32-bit libraries for audio (The host 64-bit Lucid
+ # doesn't provide these anymore, only their 64-bit versions).
+ ifeq ($(HOST_OS),linux)
+ HOST_SDK_TOOLCHAIN_PREFIX := prebuilt/linux-x86/toolchain/i686-linux-glibc2.7-4.4.3/bin/i686-linux
+ # Don't do anything if the toolchain is not there
+ ifneq (,$(strip $(wildcard $(HOST_SDK_TOOLCHAIN_PREFIX)-gcc)))
+ MY_CC := $(HOST_SDK_TOOLCHAIN_PREFIX)-gcc
+ MY_CXX := $(HOST_SDK_TOOLCHAIN_PREFIX)-g++
+ MY_AR := $(HOST_SDK_TOOLCHAIN_PREFIX)-ar
+ endif # $(HOST_SDK_TOOLCHAIN_PREFIX)-gcc exists
+ endif # HOST_OS == linux
ifneq ($(USE_CCACHE),)
ccache := prebuilt/$(HOST_PREBUILT_TAG)/ccache/ccache
+ ccache := $(strip $(wildcard $(ccache)))
ifneq ($(ccache),$(firstword $(MY_CC)))
MY_CC := $(ccache) $(MY_CC)
endif
@@ -119,751 +126,43 @@
#
MY_CFLAGS += -Wall -Wno-missing-field-initializers
-include $(CLEAR_VARS)
+# Needed to build fpu/softfloat-native.h properly
+MY_CFLAGS += -D_GNU_SOURCE=1
-###########################################################
-# Zlib configuration
+# A useful function that can be used to start the declaration of a host
+# module. Avoids repeating the same stuff again and again.
+# Usage:
#
-ZLIB_DIR := distrib/zlib-1.2.3
-include $(LOCAL_PATH)/$(ZLIB_DIR)/sources.make
-
-###########################################################
-# Libpng configuration
+# $(call start-emulator-library, <module-name>)
#
-LIBPNG_DIR := distrib/libpng-1.2.19
-include $(LOCAL_PATH)/$(LIBPNG_DIR)/sources.make
-
-###############################################################################
-# build the TCG code generator
+# ... declarations
#
-include $(CLEAR_VARS)
-
-LOCAL_NO_DEFAULT_COMPILER_FLAGS := true
-LOCAL_CC := $(MY_CC)
-LOCAL_CFLAGS := $(MY_CFLAGS) $(LOCAL_CFLAGS)
-LOCAL_LDLIBS := $(MY_LDLIBS)
-LOCAL_MODULE := emulator-tcg
-
-TCG_TARGET := $(HOST_ARCH)
-ifeq ($(TCG_TARGET),x86)
- TCG_TARGET := i386
-endif
-
-TCG_CFLAGS := -I$(LOCAL_PATH)/tcg -I$(LOCAL_PATH)/tcg/$(TCG_TARGET)
-
-LOCAL_CFLAGS += $(TCG_CFLAGS) -DNEED_CPU_H \
- -I$(LOCAL_PATH)/$(EMULATOR_TARGET_CPU) \
- -I$(LOCAL_PATH)/fpu \
-
-LOCAL_SRC_FILES := \
- tcg/tcg.c \
-
-include $(BUILD_HOST_STATIC_LIBRARY)
-
-##############################################################################
-# build the HW emulation support
+# $(call end-emulator-library)
#
-include $(CLEAR_VARS)
+start-emulator-library = \
+ $(eval include $(CLEAR_VARS)) \
+ $(eval LOCAL_NO_DEFAULT_COMPILER_FLAGS := true) \
+ $(eval LOCAL_CC := $(MY_CC)) \
+ $(eval LOCAL_CXX := $(MY_CXX)) \
+ $(eval LOCAL_CFLAGS := $(MY_CFLAGS)) \
+ $(eval LOCAL_AR := $(MY_AR)) \
+ $(eval LOCAL_LDLIBS := $(MY_LDLIBS)) \
+ $(eval LOCAL_MODULE_TAGS := debug) \
+ $(eval LOCAL_MODULE := $1)
-LOCAL_NO_DEFAULT_COMPILER_FLAGS := true
-LOCAL_CC := $(MY_CC)
-LOCAL_LDLIBS := $(MY_LDLIBS)
-LOCAL_MODULE := emulator-hw
+# Used with start-emulator-library
+end-emulator-library = \
+ $(eval include $(BUILD_HOST_STATIC_LIBRARY))
-HW_CFLAGS := -I$(LOCAL_PATH)/hw
+# A variant of start-emulator-library to start the definition of a host
+# program instead. Use with end-emulator-program
+start-emulator-program = $(call start-emulator-library,$1)
-LOCAL_CFLAGS := $(MY_CFLAGS) $(LOCAL_CFLAGS) -DNEED_CPU_H
-LOCAL_CFLAGS += -I$(LOCAL_PATH)/$(EMULATOR_TARGET_CPU) -I$(LOCAL_PATH)/fpu $(HW_CFLAGS)
-LOCAL_CFLAGS += $(ZLIB_CFLAGS) -I$(LOCAL_PATH)/$(ZLIB_DIR)
-
-HW_SOURCES := \
- bt.c \
- bt-hci.c \
- bt-hid.c \
- bt-l2cap.c \
- bt-sdp.c \
- cdrom.c \
- dma.c \
- irq.c \
- goldfish_device.c \
- goldfish_events_device.c \
- goldfish_fb.c \
- goldfish_battery.c \
- goldfish_mmc.c \
- goldfish_memlog.c \
- goldfish_nand.c \
- goldfish_tty.c \
- msmouse.c \
- pci.c \
- qdev.c \
- scsi-disk.c \
- sysbus.c \
- usb-hid.c \
- usb-hub.c \
- usb-msd.c \
- usb-ohci.c \
- usb.c \
- watchdog.c \
-
-ifeq ($(TARGET_ARCH),arm)
-HW_SOURCES += android_arm.c \
- arm_pic.c \
- smc91c111.c \
- goldfish_audio.c \
- goldfish_interrupt.c \
- goldfish_switch.c \
- goldfish_timer.c \
- goldfish_trace.c \
-
-endif
-
-ifeq ($(TARGET_ARCH),x86)
-HW_SOURCES += pc.c \
- apic.c \
- i8259.c \
- mc146818rtc.c \
- piix_pci.c \
- i8254.c \
- ne2000.c \
- pckbd.c \
- ioapic.c \
- ps2.c \
- smbios.c \
- fw_cfg.c \
-
-endif
-
-LOCAL_SRC_FILES += $(HW_SOURCES:%=hw/%)
-
-include $(BUILD_HOST_STATIC_LIBRARY)
-
-##############################################################################
-# build the ELF/DWARF stuff
-# This library is used by emulator's memory checker to extract debug information
-# from the symbol files when reporting memory allocation violations. In
-# particular, this library is used to extract routine name and source file
-# location for the code address where violation has been detected.
-#
-include $(CLEAR_VARS)
-
-LOCAL_NO_DEFAULT_COMPILER_FLAGS := true
-LOCAL_CC := $(MY_CC)
-LOCAL_LDLIBS := $(MY_LDLIBS)
-LOCAL_MODULE := emulator-elff
-LOCAL_CPP_EXTENSION := .cc
-
-ELFF_CFLAGS := -I$(LOCAL_PATH)/elff
-
-LOCAL_CFLAGS := $(MY_CFLAGS) $(LOCAL_CFLAGS) -fno-exceptions
-LOCAL_CFLAGS += -I$(LOCAL_PATH)/$(EMULATOR_TARGET_CPU) -I$(LOCAL_PATH)/fpu $(ELFF_CFLAGS)
-LOCAL_CFLAGS += $(ZLIB_CFLAGS) -I$(LOCAL_PATH)/$(ZLIB_DIR)
-
-ELFF_SOURCES := \
- dwarf_cu.cc \
- dwarf_die.cc \
- dwarf_utils.cc \
- elf_alloc.cc \
- elf_file.cc \
- elf_mapped_section.cc \
- elff_api.cc \
-
-LOCAL_SRC_FILES += $(ELFF_SOURCES:%=elff/%)
-ELFF_LDLIBS := -lstdc++
-
-include $(BUILD_HOST_STATIC_LIBRARY)
-
-##############################################################################
-# build the memory access checking support
-# Memory access checker uses information collected by instrumented code in
-# libc.so in order to keep track of memory blocks allocated from heap. Memory
-# checker then uses this information to make sure that every access to allocated
-# memory is within allocated block. This information also allows detecting
-# memory leaks and attempts to free/realloc invalid pointers.
-#
-include $(CLEAR_VARS)
-
-LOCAL_NO_DEFAULT_COMPILER_FLAGS := true
-LOCAL_CC := $(MY_CC)
-LOCAL_LDLIBS := $(MY_LDLIBS)
-LOCAL_MODULE := emulator-memcheck
-
-MCHK_CFLAGS := -I$(LOCAL_PATH)/memcheck -I$(LOCAL_PATH)/elff
-
-LOCAL_CFLAGS := $(MY_CFLAGS) $(LOCAL_CFLAGS) -DNEED_CPU_H
-LOCAL_CFLAGS += -I$(LOCAL_PATH)/$(EMULATOR_TARGET_CPU) -I$(LOCAL_PATH)/fpu $(MCHK_CFLAGS)
-LOCAL_CFLAGS += $(ZLIB_CFLAGS) -I$(LOCAL_PATH)/$(ZLIB_DIR)
-
-MCHK_SOURCES := \
- memcheck.c \
- memcheck_proc_management.c \
- memcheck_malloc_map.c \
- memcheck_mmrange_map.c \
- memcheck_util.c \
-
-LOCAL_SRC_FILES += $(MCHK_SOURCES:%=memcheck/%)
-
-include $(BUILD_HOST_STATIC_LIBRARY)
-
-##############################################################################
-# build the CPU-specific emulation engine sources
-#
-include $(CLEAR_VARS)
-
-ifeq ($(TARGET_ARCH),arm)
-LOCAL_MODULE := emulator-arm
-endif
-ifeq ($(TARGET_ARCH),x86)
-LOCAL_MODULE := emulator-i386
-LOCAL_MODULE_TAGS := optional
-endif
-
-LOCAL_NO_DEFAULT_COMPILER_FLAGS := true
-LOCAL_CC := $(MY_CC)
-LOCAL_MODULE := $(LOCAL_MODULE)
-LOCAL_LDLIBS := $(MY_LDLIBS)
-LOCAL_CFLAGS := $(MY_CFLAGS) $(LOCAL_CFLAGS)
-LOCAL_STATIC_LIBRARIES := emulator-hw
-
-LOCAL_CFLAGS := -fno-PIC -fomit-frame-pointer -Wno-sign-compare
-LOCAL_CFLAGS := $(MY_CFLAGS) $(LOCAL_CFLAGS)
-
-LOCAL_CFLAGS += -I$(LOCAL_PATH) \
- -I$(LOCAL_PATH)/$(EMULATOR_TARGET_CPU) \
- -I$(LOCAL_PATH)/fpu \
- $(TCG_CFLAGS) \
- $(HW_CFLAGS) \
- -DNEED_CPU_H \
-
-ifeq ($(HOST_ARCH),ppc)
- LOCAL_CFLAGS += -D__powerpc__
-endif
-
-ifeq ($(TARGET_ARCH),arm)
-LOCAL_SRC_FILES += exec.c cpu-exec.c \
- $(EMULATOR_TARGET_CPU)/op_helper.c \
- $(EMULATOR_TARGET_CPU)/iwmmxt_helper.c \
- $(EMULATOR_TARGET_CPU)/neon_helper.c \
- $(EMULATOR_TARGET_CPU)/helper.c \
- $(EMULATOR_TARGET_CPU)/translate.c \
- $(EMULATOR_TARGET_CPU)/machine.c \
- translate-all.c \
- hw/armv7m.c \
- hw/armv7m_nvic.c \
- arm-semi.c \
- trace.c \
- varint.c \
- dcache.c \
- softmmu_outside_jit.c \
-
-LOCAL_SRC_FILES += fpu/softfloat.c
-endif
-
-ifeq ($(TARGET_ARCH), x86)
-LOCAL_SRC_FILES += exec.c cpu-exec.c \
- $(EMULATOR_TARGET_CPU)/op_helper.c \
- $(EMULATOR_TARGET_CPU)/helper.c \
- $(EMULATOR_TARGET_CPU)/translate.c \
- $(EMULATOR_TARGET_CPU)/machine.c \
- translate-all.c \
- trace.c \
- varint.c \
- dcache.c \
- softmmu_outside_jit.c \
-
-LOCAL_SRC_FILES += fpu/softfloat-native.c
-endif
-
-include $(BUILD_HOST_STATIC_LIBRARY)
-
-##############################################################################
-# SDL-related definitions
-#
-
-# Build SDL from sources except on linux-x86, to avoid installing all
-# the X11 development packages on our build servers.
-#
-BUILD_SDL_FROM_SOURCES := true
-ifeq ($(QEMU_HOST_TAG),linux-x86)
- BUILD_SDL_FROM_SOURCES := false
-endif
-ifeq ($(QEMU_HOST_TAG),darwin-x86)
- BUILD_SDL_FROM_SOURCES := false
-endif
-ifeq ($(BUILD_STANDALONE_EMULATOR),true)
- BUILD_SDL_FROM_SOURCES := true
-endif
-
-ifneq ($(SDL_CONFIG),)
- BUILD_SDL_FROM_SOURCES := false
-endif
-
-ifneq ($(BUILD_SDL_FROM_SOURCES),true)
-
-SDL_CONFIG ?= prebuilt/$(QEMU_HOST_TAG)/sdl/bin/sdl-config
-SDL_CFLAGS := $(shell $(SDL_CONFIG) --cflags)
-
-# We need to filter out the _GNU_SOURCE variable because it breaks recent
-# releases of Cygwin when using the -mno-cygwin option. Moreover, we don't
-# need this macro at all to build the Android emulator.
-SDL_CFLAGS := $(filter-out -D_GNU_SOURCE=1,$(SDL_CFLAGS))
-SDL_LDLIBS := $(filter-out %.a %.lib,$(shell $(SDL_CONFIG) --static-libs))
-
-# Circular dependencies between libSDL and libSDLmain;
-# We repeat the libraries in the final link to work around it.
-SDL_STATIC_LIBRARIES := libSDL libSDLmain libSDL libSDLmain
-
-else # !BUILD_STANDALONE_EMULATOR
-
-SDL_DIR := distrib/sdl-1.2.12
-include $(LOCAL_PATH)/$(SDL_DIR)/sources.make
-
-endif # !BUILD_STANDALONE_EMULATOR
-
-##############################################################################
-# determine audio sources, build the prebuilt audio-library if needed
-#
-
-# determine AUDIO sources based on current configuration
-#
-AUDIO_SOURCES := audio.c noaudio.c wavaudio.c wavcapture.c mixeng.c
-AUDIO_CFLAGS := -I$(LOCAL_PATH)/audio -DHAS_AUDIO
-AUDIO_LDLIBS :=
-
-ifeq ($(HOST_OS),darwin)
- CONFIG_COREAUDIO ?= yes
- AUDIO_CFLAGS += -DHOST_BSD=1
-endif
-
-ifeq ($(HOST_OS),windows)
- CONFIG_WINAUDIO ?= yes
-endif
-
-ifeq ($(HOST_OS),linux)
- CONFIG_OSS ?= yes
- CONFIG_ALSA ?= yes
- CONFIG_PULSEAUDIO ?= yes
- CONFIG_ESD ?= yes
-endif
-
-ifeq ($(HOST_OS),freebsd)
- CONFIG_OSS ?= yes
-endif
-
-ifeq ($(CONFIG_COREAUDIO),yes)
- AUDIO_SOURCES += coreaudio.c
- AUDIO_CFLAGS += -DCONFIG_COREAUDIO
- AUDIO_LDLIBS += -Wl,-framework,CoreAudio
-endif
-
-ifeq ($(CONFIG_WINAUDIO),yes)
- AUDIO_SOURCES += winaudio.c
- AUDIO_CFLAGS += -DCONFIG_WINAUDIO
-endif
-
-ifeq ($(CONFIG_PULSEAUDIO),yes)
- AUDIO_SOURCES += paaudio.c audio_pt_int.c
- AUDIO_CFLAGS += -DCONFIG_PULSEAUDIO
-endif
-
-ifeq ($(CONFIG_ALSA),yes)
- AUDIO_SOURCES += alsaaudio.c audio_pt_int.c
- AUDIO_CFLAGS += -DCONFIG_ALSA
-endif
-
-ifeq ($(CONFIG_ESD),yes)
- AUDIO_SOURCES += esdaudio.c
- AUDIO_CFLAGS += -DCONFIG_ESD
-endif
-
-ifeq ($(CONFIG_OSS),yes)
- AUDIO_SOURCES += ossaudio.c
- AUDIO_CFLAGS += -DCONFIG_OSS
-endif
-
-AUDIO_SOURCES := $(call sort,$(AUDIO_SOURCES:%=audio/%))
-
-# determine whether we're going to use the prebuilt
-# audio library (this is useful on Linux to avoid requiring
-# all sound-related development packages to be installed on
-# the build and developer machines).
-#
-# note that you can define BUILD_QEMU_AUDIO_LIB to true
-# in your environment to force recompilation.
-#
-QEMU_AUDIO_LIB :=
-
-ifneq ($(BUILD_STANDALONE_EMULATOR),true)
- QEMU_AUDIO_LIB := $(wildcard \
- prebuilt/$(QEMU_HOST_TAG)/emulator/libqemu-audio.a)
-endif
-
-ifeq ($(BUILD_QEMU_AUDIO_LIB),true)
- include $(CLEAR_VARS)
- LOCAL_NO_DEFAULT_COMPILER_FLAGS := true
- LOCAL_CC := $(MY_CC)
- LOCAL_MODULE := libqemu-audio
- LOCAL_LDLIBS := $(MY_LDLIBS)
-
- LOCAL_CFLAGS := -Wno-sign-compare \
- -fno-strict-aliasing -W -Wall -Wno-unused-parameter \
- -I$(LOCAL_PATH) \
- -I$(LOCAL_PATH)/$(EMULATOR_TARGET_CPU) \
- -I$(LOCAL_PATH)/fpu \
-
- # this is very important, otherwise the generated binaries may
- # not link properly on our build servers
- ifeq ($(HOST_OS),linux)
- LOCAL_CFLAGS += -fno-stack-protector
- endif
-
- LOCAL_CFLAGS := $(MY_CFLAGS) $(LOCAL_CFLAGS) $(AUDIO_CFLAGS)
-
- LOCAL_CFLAGS += $(SDL_CFLAGS)
-
- LOCAL_SRC_FILES += $(AUDIO_SOURCES)
-
- include $(BUILD_HOST_STATIC_LIBRARY)
- QEMU_AUDIO_LIB := $(LOCAL_BUILT_MODULE)
-
-endif # !QEMU_AUDIO_LIB
-
-##############################################################################
-# Common CFLAGS for UI and Core builds
-
-# add the build ID to the default macro definitions
-UI_AND_CORE_CFLAGS := -DANDROID_BUILD_ID="$(strip $(BUILD_ID))-$(strip $(BUILD_NUMBER))"
-
-# For non-standalone builds, extract the major version number from the Android SDK
-# tools revision number.
-ifneq ($(BUILD_STANDALONE_EMULATOR),true)
- ANDROID_SDK_TOOLS_REVISION := $(shell awk -F= '/Pkg.Revision/ { print $$2; }' sdk/files/tools_source.properties)
-endif
-
-ANDROID_SDK_TOOLS_REVISION := $(strip $(ANDROID_SDK_TOOLS_REVISION))
-ifdef ANDROID_SDK_TOOLS_REVISION
- UI_AND_CORE_CFLAGS += -DANDROID_SDK_TOOLS_REVISION=$(ANDROID_SDK_TOOLS_REVISION)
-endif
-
-UI_AND_CORE_CFLAGS += -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
-
-
-##############################################################################
-# Build emulator core library.
-# This library contains "pure" emulation code separated from the intricacies
-# of the UI.
-#
-include $(CLEAR_VARS)
-
-LOCAL_NO_DEFAULT_COMPILER_FLAGS := true
-LOCAL_CC := $(MY_CC)
-LOCAL_LDLIBS := $(MY_LDLIBS)
-LOCAL_MODULE := emulator-core
-
-# don't remove the -fno-strict-aliasing, or you'll break things
-# (e.g. slirp-android/network support)
-#
-EMULATOR_CORE_CFLAGS := -fno-PIC -Wno-sign-compare \
- -fno-strict-aliasing -g -W -Wall -Wno-unused-parameter
-
-# Needed by the upstream code
-EMULATOR_CORE_CFLAGS += -DNEED_CPU_H
-
-# Common includes for the emulator
-EMULATOR_CORE_CFLAGS += -I$(LOCAL_PATH)/ \
- -I$(LOCAL_PATH)/$(EMULATOR_TARGET_CPU) \
- -I$(LOCAL_PATH)/fpu \
- $(TCG_CFLAGS) \
- $(HW_CFLAGS) \
-
-# Required by block.c, default value is empty in upstream
-EMULATOR_CORE_CFLAGS += -DCONFIG_BDRV_WHITELIST=""
-
-# Required
-EMULATOR_CORE_CFLAGS += -D_XOPEN_SOURCE=600 -D_BSD_SOURCE=1
-# include slirp-android code, i.e. the user-level networking stuff
-#
-SLIRP_SOURCES := bootp.c cksum.c debug.c if.c ip_icmp.c ip_input.c ip_output.c \
- mbuf.c misc.c sbuf.c slirp.c socket.c tcp_input.c tcp_output.c \
- tcp_subr.c tcp_timer.c tftp.c udp.c
-
-LOCAL_SRC_FILES += $(SLIRP_SOURCES:%=slirp-android/%)
-EMULATOR_CORE_CFLAGS += -I$(LOCAL_PATH)/slirp-android
-
-# socket proxy support
-#
-PROXY_SOURCES := \
- proxy_common.c \
- proxy_http.c \
- proxy_http_connector.c \
- proxy_http_rewriter.c \
-
-LOCAL_SRC_FILES += $(PROXY_SOURCES:%=proxy/%)
-EMULATOR_CORE_CFLAGS += -I$(LOCAL_PATH)/proxy
-
-# include telephony stuff
-#
-TELEPHONY_SOURCES := android_modem.c modem_driver.c gsm.c sim_card.c sysdeps_qemu.c sms.c remote_call.c
-LOCAL_SRC_FILES += $(TELEPHONY_SOURCES:%=telephony/%)
-EMULATOR_CORE_CFLAGS += -I$(LOCAL_PATH)/telephony
-
-# include android related stuff
-#
-ANDROID_SOURCES := qemu-setup.c
-LOCAL_SRC_FILES += $(ANDROID_SOURCES:%=android/%)
-
-LOCAL_CFLAGS := $(MY_CFLAGS) $(LOCAL_CFLAGS) $(EMULATOR_CORE_CFLAGS)
-LOCAL_CFLAGS += $(UI_AND_CORE_CFLAGS)
-
-include $(BUILD_HOST_STATIC_LIBRARY)
-
-##############################################################################
-# Build emulator UI library.
-# This library contains some emulator related UI components.
-#
-include $(CLEAR_VARS)
-
-LOCAL_NO_DEFAULT_COMPILER_FLAGS := true
-LOCAL_CC := $(MY_CC)
-LOCAL_LDLIBS := $(MY_LDLIBS)
-LOCAL_MODULE := emulator-uilib
-
-EMULATOR_UI_CFLAGS :=
-
-# include the SDL sources
-#
-
-# IMPORTANT: Normally, we should add SDLMAIN_SOURCES here, however this breaks
-# the Linux mingw32 build. Apparently, the i586-mingw32-ld wants the
-# implementation of _WinMain@16 to be in an object file on the final
-# link command used to generate the executable, and will not search
-# in the static libraries that are used to build it.
-#
-LOCAL_SRC_FILES += $(SDL_SOURCES) #$(SDLMAIN_SOURCES)
-EMULATOR_UI_CFLAGS += $(SDL_CFLAGS) -I$(LOCAL_PATH)/$(SDL_DIR)/include
-
-# the skin support sources
-#
-SKIN_SOURCES := rect.c \
- region.c \
- image.c \
- trackball.c \
- keyboard.c \
- keyset.c \
- file.c \
- window.c \
- scaler.c \
- composer.c \
- surface.c \
-
-LOCAL_SRC_FILES += $(SKIN_SOURCES:%=android/skin/%)
-EMULATOR_UI_CFLAGS += -I$(LOCAL_PATH)/skin
-
-LOCAL_CFLAGS := $(MY_CFLAGS) $(LOCAL_CFLAGS) $(EMULATOR_CORE_CFLAGS) $(EMULATOR_UI_CFLAGS)
-
-LOCAL_MODULE_TAGS := debug
-
-include $(BUILD_HOST_STATIC_LIBRARY)
-
-##############################################################################
-# lists of source files used to build the emulator core
-#
-
-# block sources
-#
-CORE_BLOCK_SOURCES = block.c \
- blockdev.c \
- block/qcow.c \
- block/qcow2.c \
- block/qcow2-refcount.c \
- block/qcow2-snapshot.c \
- block/qcow2-cluster.c \
- block/cloop.c \
- block/dmg.c \
- block/vvfat.c \
- block/raw.c
-ifeq ($(HOST_OS),windows)
- CORE_BLOCK_SOURCES += block/raw-win32.c
-else
- CORE_BLOCK_SOURCES += block/raw-posix.c
-endif
-
-# hw sources
-#
-ifeq ($(TARGET_ARCH),arm)
-CORE_HW_SOURCES = hw/arm_boot.c \
- hw/android_arm.c
-endif
-
-ifeq ($(TARGET_ARCH),x86)
-CORE_HW_SOURCES = hw/pc.c
-endif
-
-# migration sources
-#
-CORE_MIGRATION_SOURCES = iolooper-select.c
-ifeq ($(HOST_OS),windows)
- CORE_MIGRATION_SOURCES += migration-dummy-android.c
-else
- CORE_MIGRATION_SOURCES += migration.c \
- migration-exec.c \
- migration-tcp-android.c
-endif
-
-# misc. sources
-#
-CORE_MISC_SOURCES = vl-android.c \
- async.c \
- console.c \
- qemu-malloc.c \
- cutils.c \
- osdep.c \
- loader.c \
- monitor.c \
- readline.c \
- qemu-char-android.c \
- outputchannel.c \
- qemu-error.c \
- qerror.c \
- disas.c \
- aes.c \
- d3des.c \
- vnc-android.c \
- acl.c \
- keymaps.c \
- buffered_file.c \
- cbuffer.c \
- gdbstub.c \
- input.c \
- ioport.c \
- notify.c \
- path.c \
- shaper.c \
- charpipe.c \
- tcpdump.c \
- qemu-option.c \
- savevm.c \
- net-android.c \
- aio-android.c \
- dma-helpers.c \
- qemu-config.c \
- qemu-sockets-android.c \
- bt-host.c \
- bt-vhci.c \
- module.c \
- qemu-timer.c \
- android/boot-properties.c \
- android/hw-kmsg.c \
- android/hw-lcd.c \
- android/gps.c \
- android/hw-events.c \
- android/hw-control.c \
- android/console.c \
- android/hw-sensors.c \
- android/hw-qemud.c \
- android/core-init-utils.c \
- android/config.c \
- android/snapshot.c \
- android/utils/timezone.c \
-
-ifeq ($(TARGET_ARCH),arm)
- CORE_MISC_SOURCES += arm-dis.c
-endif
-
-ifeq ($(HOST_ARCH),x86)
- CORE_MISC_SOURCES += i386-dis.c
-endif
-ifeq ($(HOST_ARCH),x86_64)
- CORE_MISC_SOURCES += i386-dis.c
-endif
-ifeq ($(HOST_ARCH),ppc)
- CORE_MISC_SOURCES += ppc-dis.c \
- cache-utils.c
-endif
-
-ifeq ($(HOST_OS),linux)
- CORE_MISC_SOURCES += usb-linux.c \
- qemu-thread.c
-else
- CORE_MISC_SOURCES += usb-dummy-android.c
-endif
-
-ifeq ($(HOST_OS),windows)
- CORE_MISC_SOURCES += tap-win32.c
-else
- CORE_MISC_SOURCES += posix-aio-compat.c
-endif
-
-# sources inherited from upstream, but not fully
-# integrated into android emulator
-#
-CORE_UPSTREAM_SOURCES = json-lexer.c \
- json-parser.c \
- json-streamer.c \
- qjson.c \
- qbool.c \
- qdict.c \
- qfloat.c \
- qint.c \
- qlist.c \
- qstring.c \
-
-
-CORE_SOURCES = $(CORE_BLOCK_SOURCES) $(CORE_HW_SOURCES)
-CORE_SOURCES += $(CORE_MIGRATION_SOURCES) $(CORE_MISC_SOURCES)
-CORE_SOURCES += $(CORE_UPSTREAM_SOURCES)
-
-CORE_SOURCES += android/audio-test.c
-
-##############################################################################
-# lists of source files used to build the emulator UI
-#
-
-UI_SOURCES = loadpng.c \
- android/user-config.c \
- android/resource.c \
- android/qemulator.c \
- android/keycode.c \
- android/help.c \
- android/avd/info.c \
-
-##############################################################################
-# lists of source files used by both, emulator UI and emulator core
-#
-
-UI_AND_CORE_SOURCES = \
- sockets.c \
- android/keycode-array.c \
- android/charmap.c \
- android/async-utils.c \
- android/sync-utils.c \
- android/async-console.c \
- android/utils/assert.c \
- android/utils/bufprint.c \
- android/utils/debug.c \
- android/utils/path.c \
- android/utils/dirscanner.c \
- android/utils/filelock.c \
- android/utils/mapfile.c \
- android/utils/misc.c \
- android/utils/panic.c \
- android/utils/reflist.c \
- android/utils/refset.c \
- android/utils/stralloc.c \
- android/utils/system.c \
- android/utils/tempfile.c \
- android/utils/vector.c \
- android/avd/hw-config.c \
- android/utils/ini.c \
-
-# include the Zlib sources
-#
-UI_AND_CORE_SOURCES += $(ZLIB_SOURCES)
-UI_AND_CORE_CFLAGS += $(ZLIB_CFLAGS) -I$(LOCAL_PATH)/$(ZLIB_DIR)
+# A varient of end-emulator-library for host programs instead
+end-emulator-program = \
+ $(eval LOCAL_LDLIBS += $(QEMU_SYSTEM_LDLIBS)) \
+ $(eval include $(BUILD_HOST_EXECUTABLE))
-# include the Libpng sources
-#
-UI_AND_CORE_SOURCES += $(LIBPNG_SOURCES)
-UI_AND_CORE_CFLAGS += $(LIBPNG_CFLAGS) -I$(LOCAL_PATH)/$(LIBPNG_DIR)
# The common libraries
#
@@ -890,471 +189,57 @@
QEMU_SYSTEM_LDLIBS += -Wl,-framework,Cocoa
endif
+include $(LOCAL_PATH)/Makefile.common
+
+# We want to build all variants of the emulator binaries. This makes
+# it easier to catch target-specific regressions during emulator development.
+EMULATOR_TARGET_ARCH := arm
+include $(LOCAL_PATH)/Makefile.target
+
+EMULATOR_TARGET_ARCH := x86
+include $(LOCAL_PATH)/Makefile.target
##############################################################################
-# now build the emulator itself
-#
-include $(CLEAR_VARS)
+##############################################################################
+###
+### emulator-ui: UI FRONT-END PROGRAM
+###
+###
+$(call start-emulator-program, emulator-ui)
-LOCAL_GENERATED_SOURCES :=
-LOCAL_NO_DEFAULT_COMPILER_FLAGS := true
-LOCAL_CC := $(MY_CC)
-LOCAL_MODULE := emulator
-ifeq ($(TARGET_ARCH),arm)
-LOCAL_STATIC_LIBRARIES := emulator-memcheck emulator-hw emulator-arm emulator-tcg
-endif
-ifeq ($(TARGET_ARCH),x86)
-LOCAL_STATIC_LIBRARIES := emulator-memcheck emulator-hw emulator-i386 emulator-tcg
-endif
-LOCAL_STATIC_LIBRARIES += emulator-elff
-LOCAL_STATIC_LIBRARIES += emulator-core emulator-uilib
-LOCAL_LDLIBS := $(MY_LDLIBS)
-
-LOCAL_CFLAGS := $(MY_CFLAGS) $(LOCAL_CFLAGS) $(EMULATOR_CORE_CFLAGS) $(EMULATOR_UI_CFLAGS)
-
-# add the build ID to the default macro definitions
-LOCAL_CFLAGS += $(UI_AND_CORE_CFLAGS)
-
-# include sound support source files. we first try to see if we have a prebuilt audio
-# library. if not, we build things the "hard" way.
-#
-# note that to generate the prebuilt audio library, you should do the following:
-#
-# cd tools/qemu
-# ./android-rebuild.sh
-# distrib/update-audio.sh
-#
-ifeq ($(QEMU_AUDIO_LIB),)
- LOCAL_SRC_FILES += $(AUDIO_SOURCES)
-endif # !QEMU_AUDIO_LIB
-
-LOCAL_CFLAGS += $(AUDIO_CFLAGS)
-LOCAL_LDLIBS += $(AUDIO_LDLIBS)
-
-# the linux-user sources, I doubt we really need these
-#
-#LINUX_SOURCES := main.c elfload.c mmap.c signal.c path.c syscall.c
-#LOCAL_SRC_FILES += $(LINUX_SOURCES:%=linux-user/%)
-
-ifeq ($(HOST_ARCH),x86)
-# enable MMX code for our skin scaler
-LOCAL_CFLAGS += -DUSE_MMX=1 -mmmx -DNEED_CPU_H
-endif
-
-# include other sources
-#
-VL_SOURCES := android/framebuffer.c \
- user-events-qemu.c \
- android/cmdline-option.c \
- android/display.c \
- android/looper-qemu.c \
- android/protocol/ui-commands-qemu.c \
- android/protocol/core-commands-qemu.c \
- android/main-common.c \
- android/main.c \
-
-# Add common system libraries
-#
-LOCAL_LDLIBS += $(QEMU_SYSTEM_LDLIBS)
-
-LOCAL_SRC_FILES += $(VL_SOURCES) $(CORE_SOURCES) $(UI_SOURCES) $(UI_AND_CORE_SOURCES)
-
-# add SDL-specific flags
-#
-LOCAL_CFLAGS += $(SDL_CFLAGS)
-LOCAL_LDLIBS += $(SDL_LDLIBS)
-LOCAL_STATIC_LIBRARIES += $(SDL_STATIC_LIBRARIES)
-
-# add ELFF-specific flags
-#
-LOCAL_LDLIBS += $(ELFF_LDLIBS)
-
-# on Windows, link the icon file as well into the executable
-# unfortunately, our build system doesn't help us much, so we need
-# to use some weird pathnames to make this work...
-#
-ifeq ($(HOST_OS),windows)
-
-# Locate windres executable
-WINDRES := windres
-ifneq ($(USE_MINGW),)
- # When building the Windows emulator under Linux, use the MinGW one
- WINDRES := i586-mingw32msvc-windres
-endif
-
-INTERMEDIATE := $(call intermediates-dir-for,EXECUTABLES,$(LOCAL_MODULE),true)
-ANDROID_ICON_OBJ := android_icon.o
-ANDROID_ICON_PATH := $(LOCAL_PATH)/images
-$(ANDROID_ICON_PATH)/$(ANDROID_ICON_OBJ): $(ANDROID_ICON_PATH)/android_icon.rc
- $(WINDRES) $< -I $(ANDROID_ICON_PATH) -o $@
-
-# seems to be the only way to add an object file that was not generated from
-# a C/C++/Java source file to our build system. and very unfortunately,
-# $(TOPDIR)/$(LOCALPATH) will always be prepended to this value, which forces
-# us to put the object file in the source directory...
-#
-LOCAL_PREBUILT_OBJ_FILES += images/$(ANDROID_ICON_OBJ)
-endif
-
-# qemu-options.h is generated from qemu-options.hx with the "hxtool" shell script
-#
-intermediates := $(call intermediates-dir-for,EXECUTABLES,$(LOCAL_MODULE),true)
-
-QEMU_OPTIONS_H := $(intermediates)/qemu-options.h
-$(QEMU_OPTIONS_H): PRIVATE_PATH := $(LOCAL_PATH)
-$(QEMU_OPTIONS_H): PRIVATE_CUSTOM_TOOL = $(PRIVATE_PATH)/hxtool -h < $< > $@
-$(QEMU_OPTIONS_H): $(LOCAL_PATH)/qemu-options.hx $(LOCAL_PATH)/hxtool
- $(transform-generated-source)
-
-$(intermediates)/vl-android.o: $(QEMU_OPTIONS_H)
-
-LOCAL_GENERATED_SOURCES += $(QEMU_OPTIONS_H)
-
-# qemu-monitor.h is generated from qemu-monitor.hx with the "hxtool" shell script
-#
-intermediates := $(call intermediates-dir-for,EXECUTABLES,$(LOCAL_MODULE),true)
-
-QEMU_MONITOR_H := $(intermediates)/qemu-monitor.h
-$(QEMU_MONITOR_H): PRIVATE_PATH := $(LOCAL_PATH)
-$(QEMU_MONITOR_H): PRIVATE_CUSTOM_TOOL = $(PRIVATE_PATH)/hxtool -h < $< > $@
-$(QEMU_MONITOR_H): $(LOCAL_PATH)/qemu-monitor.hx $(LOCAL_PATH)/hxtool
- $(transform-generated-source)
-
-$(intermediates)/vl-android.o: $(QEMU_MONITOR_H)
-
-LOCAL_GENERATED_SOURCES += $(QEMU_MONITOR_H)
+LOCAL_STATIC_LIBRARIES := \
+ emulator-common \
+ emulator-libui \
+ emulator-common \
-# gdbstub-xml.c contains C-compilable arrays corresponding to the content
-# of $(LOCAL_PATH)/gdb-xml/, and is generated with the 'feature_to_c.sh' script.
-#
-ifeq ($(QEMU_TARGET_XML_SOURCES),)
- QEMU_TARGET_XML_SOURCES := arm-core arm-neon arm-vfp arm-vfp3
- QEMU_TARGET_XML_SOURCES := $(QEMU_TARGET_XML_SOURCES:%=$(LOCAL_PATH)/gdb-xml/%.xml)
-endif
+LOCAL_CFLAGS += -DCONFIG_STANDALONE_UI=1
-QEMU_GDBSTUB_XML_C := $(intermediates)/gdbstub-xml.c
-$(QEMU_GDBSTUB_XML_C): PRIVATE_PATH := $(LOCAL_PATH)
-$(QEMU_GDBSTUB_XML_C): PRIVATE_SOURCES := $(TARGET_XML_SOURCES)
-$(QEMU_GDBSTUB_XML_C): PRIVATE_CUSTOM_TOOL = $(PRIVATE_PATH)/feature_to_c.sh $@ $(QEMU_TARGET_XML_SOURCES)
-$(QEMU_GDBSTUB_XML_C): $(QEMU_TARGET_XML_SOURCES) $(LOCAL_PATH)/feature_to_c.sh
- $(hide) rm -f $@
- $(transform-generated-source)
+LOCAL_CFLAGS += $(EMULATOR_COMMON_CFLAGS) $(EMULATOR_LIBUI_CFLAGS)
+LOCAL_LDLIBS += $(EMULATOR_COMMON_LDLIBS) $(EMULATOR_LIBUI_LDLIBS)
-$(intermediates)/vl-android.o: $(QEMU_GDBSTUB_XML_C)
+LOCAL_SRC_FILES := \
+ android/cmdline-option.c \
+ android/config.c \
+ android/help.c \
+ android/looper-generic.c \
+ android/snapshot.c \
+ android/main-common.c \
+ android/main.c \
+ vl-android-ui.c \
+ android/protocol/core-connection.c \
+ android/protocol/attach-ui-impl.c \
+ android/protocol/fb-updates-impl.c \
+ android/protocol/ui-commands-impl.c \
+ android/protocol/core-commands-proxy.c \
+ android/protocol/user-events-proxy.c \
-LOCAL_GENERATED_SOURCES += $(QEMU_GDBSTUB_XML_C)
-
-# hw-config-defs.h is generated from android/avd/hardware-properties.ini
-#
-QEMU_HARDWARE_PROPERTIES_INI := $(LOCAL_PATH)/android/avd/hardware-properties.ini
-QEMU_HW_CONFIG_DEFS_H := $(LOCAL_PATH)/android/avd/hw-config-defs.h
-$(QEMU_HW_CONFIG_DEFS_H): PRIVATE_PATH := $(LOCAL_PATH)
-$(QEMU_HW_CONFIG_DEFS_H): PRIVATE_SOURCES := $(QEMU_HARDWARE_PROPERTIES_INI)
-$(QEMU_HW_CONFIG_DEFS_H): PRIVATE_CUSTOM_TOOL = $(PRIVATE_PATH)/android/tools/gen-hw-config.py $(QEMU_HARDWARE_PROPERTIES_INI) $@
-$(QEMU_HW_CONFIG_DEFS_H): $(QEMU_HARDWARE_PROPERTIES_INI) $(LOCAL_PATH)/android/tools/gen-hw-config.py
- $(hide) rm -f $@
- $(transform-generated-source)
-
-$(LOCAL_PATH)/android/avd/hw-config.h: $(QEMU_HW_CONFIG_DEFS_H)
-
-LOCAL_GENERATED_SOURCES += $(QEMU_HW_CONFIG_DEFS_H)
-
-# this is already done by the Android build system, but is done for the
-# benefit of the stand-alone one.
-#
-ifeq ($(BUILD_STANDALONE_EMULATOR),true)
- LOCAL_CFLAGS += -I$(intermediates)
-endif
-
-LOCAL_LDLIBS += $(QEMU_AUDIO_LIB)
-
-# Generate a completely static executable if needed.
-# Note that this means no sound and graphics on Linux.
-#
-ifeq ($(CONFIG_STATIC_EXECUTABLE),true)
- LOCAL_SRC_FILES += dynlink-static.c
- LOCAL_LDLIBS += -static
-endif
-
-LOCAL_MODULE := emulator
-
-# See comment about SDLMAIN_SOURCES in the 'emulator-uilib' module declarations.
LOCAL_SRC_FILES += $(SDLMAIN_SOURCES)
-include $(BUILD_HOST_EXECUTABLE)
-
-##############################################################################
-# Build standalone emulator core.
-#
-include $(CLEAR_VARS)
-
-LOCAL_GENERATED_SOURCES :=
-LOCAL_NO_DEFAULT_COMPILER_FLAGS := true
-LOCAL_CC := $(MY_CC)
-LOCAL_MODULE := qemu-android-$(TARGET_ARCH)
-ifeq ($(TARGET_ARCH),arm)
-LOCAL_STATIC_LIBRARIES := emulator-memcheck emulator-hw emulator-arm emulator-tcg
-endif
-ifeq ($(TARGET_ARCH),x86)
-LOCAL_STATIC_LIBRARIES := emulator-memcheck emulator-hw emulator-i386 emulator-tcg
-endif
-
-LOCAL_STATIC_LIBRARIES += emulator-elff
-LOCAL_STATIC_LIBRARIES += emulator-core
-LOCAL_LDLIBS := $(MY_LDLIBS)
-
-LOCAL_CFLAGS := $(MY_CFLAGS) $(LOCAL_CFLAGS) $(EMULATOR_CORE_CFLAGS)
-LOCAL_CFLAGS += $(UI_AND_CORE_CFLAGS) -DCONFIG_STANDALONE_CORE
-
-# include sound support source files. we first try to see if we have a prebuilt audio
-# library. if not, we build things the "hard" way.
-#
-# note that to generate the prebuilt audio library, you should do the following:
-#
-# cd tools/qemu
-# ./android-rebuild.sh
-# distrib/update-audio.sh
-#
-ifeq ($(QEMU_AUDIO_LIB),)
- LOCAL_SRC_FILES += $(AUDIO_SOURCES)
-endif # !QEMU_AUDIO_LIB
-
-LOCAL_CFLAGS += $(AUDIO_CFLAGS)
-LOCAL_LDLIBS += $(AUDIO_LDLIBS)
-
-# the linux-user sources, I doubt we really need these
-#
-#LINUX_SOURCES := main.c elfload.c mmap.c signal.c path.c syscall.c
-#LOCAL_SRC_FILES += $(LINUX_SOURCES:%=linux-user/%)
-
-# include other sources
-#
-VL_SOURCES := android/framebuffer.c \
- user-events-qemu.c \
- android/looper-qemu.c \
- android/looper-generic.c \
- android/display-core.c \
- android/protocol/attach-ui-proxy.c \
- android/protocol/fb-updates-proxy.c \
- android/protocol/user-events-impl.c \
- android/protocol/ui-commands-proxy.c \
- android/protocol/core-commands-impl.c \
-
-# Add common system libraries
-#
-LOCAL_LDLIBS += $(QEMU_SYSTEM_LDLIBS)
-
-LOCAL_SRC_FILES += $(VL_SOURCES) $(CORE_SOURCES) $(UI_AND_CORE_SOURCES)
-
-# add ELFF-specific flags
-#
-LOCAL_LDLIBS += $(ELFF_LDLIBS)
-
-# on Windows, link the icon file as well into the executable
-# unfortunately, our build system doesn't help us much, so we need
-# to use some weird pathnames to make this work...
-#
-ifeq ($(HOST_OS),windows)
-
-# Locate windres executable
-WINDRES := windres
-ifneq ($(USE_MINGW),)
- # When building the Windows emulator under Linux, use the MinGW one
- WINDRES := i586-mingw32msvc-windres
-endif
-
-INTERMEDIATE := $(call intermediates-dir-for,EXECUTABLES,$(LOCAL_MODULE),true)
-ANDROID_ICON_OBJ := android_icon.o
-ANDROID_ICON_PATH := $(LOCAL_PATH)/images
-$(ANDROID_ICON_PATH)/$(ANDROID_ICON_OBJ): $(ANDROID_ICON_PATH)/android_icon.rc
- $(WINDRES) $< -I $(ANDROID_ICON_PATH) -o $@
-
-# seems to be the only way to add an object file that was not generated from
-# a C/C++/Java source file to our build system. and very unfortunately,
-# $(TOPDIR)/$(LOCALPATH) will always be prepended to this value, which forces
-# us to put the object file in the source directory...
-#
-LOCAL_PREBUILT_OBJ_FILES += images/$(ANDROID_ICON_OBJ)
-endif
-
-# qemu-options.h is generated from qemu-options.hx with the "hxtool" shell script
-#
-intermediates := $(call intermediates-dir-for,EXECUTABLES,$(LOCAL_MODULE),true)
-
-QEMU_OPTIONS_H := $(intermediates)/qemu-options.h
-$(QEMU_OPTIONS_H): PRIVATE_PATH := $(LOCAL_PATH)
-$(QEMU_OPTIONS_H): PRIVATE_CUSTOM_TOOL = $(PRIVATE_PATH)/hxtool -h < $< > $@
-$(QEMU_OPTIONS_H): $(LOCAL_PATH)/qemu-options.hx $(LOCAL_PATH)/hxtool
- $(transform-generated-source)
-
-$(intermediates)/vl-android.o: $(QEMU_OPTIONS_H)
-
-LOCAL_GENERATED_SOURCES += $(QEMU_OPTIONS_H)
-
-# qemu-monitor.h is generated from qemu-monitor.hx with the "hxtool" shell script
-#
-intermediates := $(call intermediates-dir-for,EXECUTABLES,$(LOCAL_MODULE),true)
-
-QEMU_MONITOR_H := $(intermediates)/qemu-monitor.h
-$(QEMU_MONITOR_H): PRIVATE_PATH := $(LOCAL_PATH)
-$(QEMU_MONITOR_H): PRIVATE_CUSTOM_TOOL = $(PRIVATE_PATH)/hxtool -h < $< > $@
-$(QEMU_MONITOR_H): $(LOCAL_PATH)/qemu-monitor.hx $(LOCAL_PATH)/hxtool
- $(transform-generated-source)
-
-$(intermediates)/vl-android.o: $(QEMU_MONITOR_H)
-
-LOCAL_GENERATED_SOURCES += $(QEMU_MONITOR_H)
-
-
-# gdbstub-xml.c contains C-compilable arrays corresponding to the content
-# of $(LOCAL_PATH)/gdb-xml/, and is generated with the 'feature_to_c.sh' script.
-#
-ifeq ($(QEMU_TARGET_XML_SOURCES),)
- QEMU_TARGET_XML_SOURCES := arm-core arm-neon arm-vfp arm-vfp3
- QEMU_TARGET_XML_SOURCES := $(QEMU_TARGET_XML_SOURCES:%=$(LOCAL_PATH)/gdb-xml/%.xml)
-endif
-
-QEMU_GDBSTUB_XML_C := $(intermediates)/gdbstub-xml.c
-$(QEMU_GDBSTUB_XML_C): PRIVATE_PATH := $(LOCAL_PATH)
-$(QEMU_GDBSTUB_XML_C): PRIVATE_SOURCES := $(TARGET_XML_SOURCES)
-$(QEMU_GDBSTUB_XML_C): PRIVATE_CUSTOM_TOOL = $(PRIVATE_PATH)/feature_to_c.sh $@ $(QEMU_TARGET_XML_SOURCES)
-$(QEMU_GDBSTUB_XML_C): $(QEMU_TARGET_XML_SOURCES) $(LOCAL_PATH)/feature_to_c.sh
- $(hide) rm -f $@
- $(transform-generated-source)
-
-$(intermediates)/vl-android.o: $(QEMU_GDBSTUB_XML_C)
-
-LOCAL_GENERATED_SOURCES += $(QEMU_GDBSTUB_XML_C)
-
-# this is already done by the Android build system, but is done for the
-# benefit of the stand-alone one.
-#
-ifeq ($(BUILD_STANDALONE_EMULATOR),true)
- LOCAL_CFLAGS += -I$(intermediates)
-endif
-
-# other flags
-ifneq ($(HOST_OS),windows)
- LOCAL_LDLIBS += -ldl
-endif
-
-LOCAL_LDLIBS += $(QEMU_AUDIO_LIB)
-
-ifeq ($(HOST_OS),darwin)
- FRAMEWORKS := OpenGL Cocoa QuickTime ApplicationServices Carbon IOKit
- LOCAL_LDLIBS += $(FRAMEWORKS:%=-Wl,-framework,%)
-endif
-
-# Generate a completely static executable if needed.
-# Note that this means no sound and graphics on Linux.
-#
-ifeq ($(CONFIG_STATIC_EXECUTABLE),true)
- LOCAL_SRC_FILES += dynlink-static.c
- LOCAL_LDLIBS += -static
-endif
-
-LOCAL_MODULE_TAGS := debug
-
-include $(BUILD_HOST_EXECUTABLE)
-
-##############################################################################
-# now build the emulator UI
-#
-include $(CLEAR_VARS)
-
-LOCAL_GENERATED_SOURCES :=
-LOCAL_NO_DEFAULT_COMPILER_FLAGS := true
-LOCAL_CC := $(MY_CC)
-LOCAL_MODULE := emulator-ui
-LOCAL_STATIC_LIBRARIES := emulator-uilib
-LOCAL_LDLIBS := $(MY_LDLIBS)
-
-LOCAL_CFLAGS := $(MY_CFLAGS) $(LOCAL_CFLAGS) $(EMULATOR_UI_CFLAGS) $(EMULATOR_CORE_CFLAGS)
-
-# add the build ID to the default macro definitions
-LOCAL_CFLAGS += $(UI_AND_CORE_CFLAGS) -DCONFIG_STANDALONE_UI
-
-ifeq ($(HOST_ARCH),x86)
-# enable MMX code for our skin scaler
-LOCAL_CFLAGS += -DUSE_MMX=1 -mmmx
-endif
-
-# include other sources
-#
-VL_SOURCES := android/framebuffer.c \
- android/cmdline-option.c \
- android/config.c \
- android/looper-generic.c \
- android/snapshot.c \
- android/main-common.c \
- android/main-ui.c \
- vl-android-ui.c \
- iolooper-select.c \
- android/protocol/core-connection.c \
- android/protocol/attach-ui-impl.c \
- android/protocol/fb-updates-impl.c \
- android/protocol/ui-commands-impl.c \
- android/protocol/core-commands-proxy.c \
- android/protocol/user-events-proxy.c \
-
-# Add common system libraries
-#
-LOCAL_LDLIBS += $(QEMU_SYSTEM_LDLIBS)
-
-LOCAL_SRC_FILES += $(VL_SOURCES) $(UI_SOURCES) $(UI_AND_CORE_SOURCES)
-
-# add SDL-specific flags
-#
-LOCAL_CFLAGS += $(SDL_CFLAGS)
-LOCAL_LDLIBS += $(SDL_LDLIBS)
LOCAL_STATIC_LIBRARIES += $(SDL_STATIC_LIBRARIES)
-# on Windows, link the icon file as well into the executable
-# unfortunately, our build system doesn't help us much, so we need
-# to use some weird pathnames to make this work...
-#
-ifeq ($(HOST_OS),windows)
+$(call end-emulator-program)
-# Locate windres executable
-WINDRES := windres
-ifneq ($(USE_MINGW),)
- # When building the Windows emulator under Linux, use the MinGW one
- WINDRES := i586-mingw32msvc-windres
-endif
-
-INTERMEDIATE := $(call intermediates-dir-for,EXECUTABLES,$(LOCAL_MODULE),true)
-ANDROID_ICON_OBJ := android_icon.o
-ANDROID_ICON_PATH := $(LOCAL_PATH)/images
-$(ANDROID_ICON_PATH)/$(ANDROID_ICON_OBJ): $(ANDROID_ICON_PATH)/android_icon.rc
- $(WINDRES) $< -I $(ANDROID_ICON_PATH) -o $@
-
-# seems to be the only way to add an object file that was not generated from
-# a C/C++/Java source file to our build system. and very unfortunately,
-# $(TOPDIR)/$(LOCALPATH) will always be prepended to this value, which forces
-# us to put the object file in the source directory...
-#
-LOCAL_PREBUILT_OBJ_FILES += images/$(ANDROID_ICON_OBJ)
-endif
-
-# this is already done by the Android build system, but is done for the
-# benefit of the stand-alone one.
-#
-ifeq ($(BUILD_STANDALONE_EMULATOR),true)
- LOCAL_CFLAGS += -I$(intermediates)
-endif
-
-# Generate a completely static executable if needed.
-# Note that this means no sound and graphics on Linux.
-#
-ifeq ($(CONFIG_STATIC_EXECUTABLE),true)
- LOCAL_SRC_FILES += dynlink-static.c
- LOCAL_LDLIBS += -static
-endif
-
-# See comment about SDLMAIN_SOURCES in the 'emulator-uilib' module declarations.
-LOCAL_SRC_FILES += $(SDLMAIN_SOURCES)
-
-include $(BUILD_HOST_EXECUTABLE)
+## VOILA!!
endif # TARGET_ARCH == arm || TARGET_ARCH == x86
diff --git a/Makefile.common b/Makefile.common
new file mode 100644
index 0000000..e872734
--- /dev/null
+++ b/Makefile.common
@@ -0,0 +1,613 @@
+# When building this project, we actually generate several components which
+# are the following:
+#
+# - the emulator-ui program (which is target-agnostic)
+# - the target-specific qemu-android-$ARCH programs (headless emulation engines)
+# - the "standalone" emulator programs (embed both UI and engine in a single
+# binary and process), i.e. "emulator" for ARM and "emulator-x86" for x86.
+#
+# This file defines static host libraries that will be used by at least two
+# of these components.
+#
+
+##############################################################################
+##############################################################################
+###
+### emulator-common: LIBRARY OF COMMON FUNCTIONS
+###
+### THESE ARE POTENTIALLY USED BY ALL COMPONENTS
+###
+
+$(call start-emulator-library, emulator-common)
+
+EMULATOR_COMMON_CFLAGS :=
+
+# Needed by everything about the host
+EMULATOR_COMMON_CFLAGS += \
+ -I$(LOCAL_PATH)/android/config/$(QEMU_HOST_TAG)
+
+# add the build ID to the default macro definitions
+ifeq ($(BUILD_STANDALONE_EMULATOR),)
+EMULATOR_COMMON_CFLAGS += -DANDROID_BUILD_ID="$(strip $(BUILD_ID))-$(strip $(BUILD_NUMBER))"
+endif
+
+# For non-standalone builds, extract the major version number from the Android SDK
+# tools revision number.
+ifneq ($(BUILD_STANDALONE_EMULATOR),true)
+ ANDROID_SDK_TOOLS_REVISION := $(shell awk -F= '/Pkg.Revision/ { print $$2; }' sdk/files/tools_source.properties)
+endif
+
+ANDROID_SDK_TOOLS_REVISION := $(strip $(ANDROID_SDK_TOOLS_REVISION))
+ifdef ANDROID_SDK_TOOLS_REVISION
+ EMULATOR_COMMON_CFLAGS += -DANDROID_SDK_TOOLS_REVISION=$(ANDROID_SDK_TOOLS_REVISION)
+endif
+
+# Enable large-file support (i.e. make off_t a 64-bit value)
+ifeq ($(HOST_OS),linux)
+EMULATOR_COMMON_CFLAGS += -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
+endif
+
+###########################################################
+# Zlib sources
+#
+ZLIB_DIR := distrib/zlib-1.2.3
+include $(LOCAL_PATH)/$(ZLIB_DIR)/sources.make
+EMULATOR_COMMON_CFLAGS += -I$(LOCAL_PATH)/$(ZLIB_DIR)
+
+LOCAL_SRC_FILES += $(ZLIB_SOURCES)
+
+###########################################################
+# Android utility functions
+#
+LOCAL_SRC_FILES += \
+ sockets.c \
+ iolooper-select.c \
+ android/async-console.c \
+ android/async-utils.c \
+ android/charmap.c \
+ android/framebuffer.c \
+ android/keycode-array.c \
+ android/avd/hw-config.c \
+ android/avd/info.c \
+ android/sync-utils.c \
+ android/utils/assert.c \
+ android/utils/bufprint.c \
+ android/utils/debug.c \
+ android/utils/dirscanner.c \
+ android/utils/filelock.c \
+ android/utils/ini.c \
+ android/utils/mapfile.c \
+ android/utils/misc.c \
+ android/utils/panic.c \
+ android/utils/path.c \
+ android/utils/reflist.c \
+ android/utils/refset.c \
+ android/utils/stralloc.c \
+ android/utils/system.c \
+ android/utils/tempfile.c \
+ android/utils/vector.c \
+
+LOCAL_CFLAGS += $(EMULATOR_COMMON_CFLAGS)
+
+$(call end-emulator-library)
+
+##############################################################################
+##############################################################################
+###
+### emulator-libui: LIBRARY OF UI-RELATED FUNCTIONS
+###
+### THESE ARE USED BY 'emulator-ui' AND THE STANDALONE PROGRAMS
+###
+
+$(call start-emulator-library, emulator-libui)
+
+EMULATOR_LIBUI_CFLAGS :=
+
+LOCAL_CFLAGS += $(EMULATOR_COMMON_CFLAGS)
+
+###########################################################
+# Libpng configuration
+#
+LIBPNG_DIR := distrib/libpng-1.2.19
+include $(LOCAL_PATH)/$(LIBPNG_DIR)/sources.make
+
+EMULATOR_LIBUI_CFLAGS += \
+ $(LIBPNG_CFLAGS) \
+ -I$(LOCAL_PATH)/$(LIBPNG_DIR)
+
+LOCAL_SRC_FILES += $(LIBPNG_SOURCES) loadpng.c
+
+##############################################################################
+# SDL-related definitions
+#
+
+# Build SDL from sources except in certain cases where we use
+# prebuilt libraries instead.
+#
+BUILD_SDL_FROM_SOURCES := true
+
+# On linux-x86, using the prebuilts avoid installing all the X11
+# development packages on our build servers.
+#
+ifeq ($(QEMU_HOST_TAG),linux-x86)
+ BUILD_SDL_FROM_SOURCES := false
+endif
+
+# On darwin-x86, a bug in the Android build system prevents the compilation
+# of Objective-C sources. Fixed recently in AOSP, but we still use the
+# prebuilts for the benefit of older platform branches.
+#
+ifeq ($(QEMU_HOST_TAG),darwin-x86)
+ BUILD_SDL_FROM_SOURCES := false
+endif
+
+# If we're building with android-configure.sh && make, always build from
+# sources to catch regressions as soon as they happen.
+#
+ifeq ($(BUILD_STANDALONE_EMULATOR),true)
+ BUILD_SDL_FROM_SOURCES := true
+endif
+
+# Except if we used android-configure.sh --sdl-config=<script>
+#
+ifneq ($(SDL_CONFIG),)
+ BUILD_SDL_FROM_SOURCES := false
+endif
+
+ifneq ($(BUILD_SDL_FROM_SOURCES),true)
+
+ SDL_CONFIG ?= prebuilt/$(QEMU_HOST_TAG)/sdl/bin/sdl-config
+ SDL_CFLAGS := $(shell $(SDL_CONFIG) --cflags)
+
+ # We need to filter out the _GNU_SOURCE variable because it breaks recent
+ # releases of Cygwin when using the -mno-cygwin option. Moreover, we don't
+ # need this macro at all to build the Android emulator.
+ SDL_CFLAGS := $(filter-out -D_GNU_SOURCE=1,$(SDL_CFLAGS))
+ SDL_LDLIBS := $(filter-out %.a %.lib,$(shell $(SDL_CONFIG) --static-libs))
+
+ # Circular dependencies between libSDL and libSDLmain
+ # We repeat the libraries in the final link to work around it
+ SDL_STATIC_LIBRARIES := libSDL libSDLmain libSDL libSDLmain
+
+else # BUILD_SDL_FROM_SOURCES
+
+ SDL_DIR := distrib/sdl-1.2.12
+ include $(LOCAL_PATH)/$(SDL_DIR)/sources.make
+ LOCAL_SRC_FILES += $(SDL_SOURCES)
+
+ EMULATOR_LIBUI_CFLAGS += \
+ -I$(LOCAL_PATH)/$(SDL_DIR)/include
+
+ SDL_STATIC_LIBRARIES :=
+
+endif # BUILD_SDL_FROM_SOURCES
+
+EMULATOR_LIBUI_CFLAGS += $(SDL_CFLAGS)
+EMULATOR_LIBUI_LDLIBS += $(SDL_LDLIBS)
+
+# The following is needed by SDL_LoadObject
+ifneq ($(HOST_OS),windows)
+ EMULATOR_LIBUI_LDLIBS += -ldl
+endif
+
+# the skin support sources
+#
+SKIN_SOURCES := rect.c \
+ region.c \
+ image.c \
+ trackball.c \
+ keyboard.c \
+ keyset.c \
+ file.c \
+ window.c \
+ scaler.c \
+ composer.c \
+ surface.c \
+
+LOCAL_SRC_FILES += $(SKIN_SOURCES:%=android/skin/%)
+
+LOCAL_SRC_FILES += \
+ android/user-config.c \
+ android/resource.c \
+ android/qemulator.c \
+ android/keycode.c \
+
+# enable MMX code for our skin scaler
+ifeq ($(HOST_ARCH),x86)
+LOCAL_CFLAGS += -DUSE_MMX=1 -mmmx
+endif
+
+LOCAL_CFLAGS += $(EMULATOR_LIBUI_CFLAGS)
+
+$(call end-emulator-library)
+
+##############################################################################
+##############################################################################
+###
+### emulator-libqemu: TARGET-INDEPENDENT QEMU FUNCTIONS
+###
+### THESE ARE USED BY EVERYTHING EXCEPT 'emulator-ui'
+###
+
+$(call start-emulator-library, emulator-libqemu)
+
+EMULATOR_LIBQEMU_CFLAGS :=
+
+LOCAL_CFLAGS += $(EMULATOR_COMMON_CFLAGS)
+
+AUDIO_SOURCES := noaudio.c wavaudio.c wavcapture.c mixeng.c
+AUDIO_CFLAGS := -I$(LOCAL_PATH)/audio -DHAS_AUDIO
+AUDIO_LDLIBS :=
+
+LOCAL_CFLAGS += -Wall -Wno-missing-field-initializers
+
+ifeq ($(HOST_OS),darwin)
+ CONFIG_COREAUDIO ?= yes
+ AUDIO_CFLAGS += -DHOST_BSD=1
+endif
+
+ifeq ($(HOST_OS),windows)
+ CONFIG_WINAUDIO ?= yes
+endif
+
+ifeq ($(HOST_OS),linux)
+ CONFIG_OSS ?= yes
+ CONFIG_ALSA ?= yes
+ CONFIG_PULSEAUDIO ?= yes
+ CONFIG_ESD ?= yes
+endif
+
+ifeq ($(HOST_OS),freebsd)
+ CONFIG_OSS ?= yes
+endif
+
+ifeq ($(CONFIG_COREAUDIO),yes)
+ AUDIO_SOURCES += coreaudio.c
+ AUDIO_CFLAGS += -DCONFIG_COREAUDIO
+ AUDIO_LDLIBS += -Wl,-framework,CoreAudio
+endif
+
+ifeq ($(CONFIG_WINAUDIO),yes)
+ AUDIO_SOURCES += winaudio.c
+ AUDIO_CFLAGS += -DCONFIG_WINAUDIO
+endif
+
+ifeq ($(CONFIG_PULSEAUDIO),yes)
+ AUDIO_SOURCES += paaudio.c audio_pt_int.c
+ AUDIO_CFLAGS += -DCONFIG_PULSEAUDIO
+endif
+
+ifeq ($(CONFIG_ALSA),yes)
+ AUDIO_SOURCES += alsaaudio.c audio_pt_int.c
+ AUDIO_CFLAGS += -DCONFIG_ALSA
+endif
+
+ifeq ($(CONFIG_ESD),yes)
+ AUDIO_SOURCES += esdaudio.c
+ AUDIO_CFLAGS += -DCONFIG_ESD
+endif
+
+ifeq ($(CONFIG_OSS),yes)
+ AUDIO_SOURCES += ossaudio.c
+ AUDIO_CFLAGS += -DCONFIG_OSS
+endif
+
+AUDIO_SOURCES := $(call sort,$(AUDIO_SOURCES:%=audio/%))
+
+LOCAL_CFLAGS += -Wno-sign-compare \
+ -fno-strict-aliasing -W -Wall -Wno-unused-parameter \
+
+# this is very important, otherwise the generated binaries may
+# not link properly on our build servers
+ifeq ($(HOST_OS),linux)
+LOCAL_CFLAGS += -fno-stack-protector
+endif
+
+LOCAL_SRC_FILES += $(AUDIO_SOURCES)
+LOCAL_SRC_FILES += \
+ android/audio-test.c
+
+# other flags
+ifneq ($(HOST_OS),windows)
+ AUDIO_LDLIBS += -ldl
+else
+endif
+
+
+EMULATOR_LIBQEMU_CFLAGS += $(AUDIO_CFLAGS)
+EMULATOR_LIBQEMU_LDLIBS += $(AUDIO_LDLIBS)
+
+LOCAL_CFLAGS += -Wno-missing-field-initializers
+
+# migration sources
+#
+ifeq ($(HOST_OS),windows)
+ LOCAL_SRC_FILES += migration-dummy-android.c
+else
+ LOCAL_SRC_FILES += migration.c \
+ migration-exec.c \
+ migration-tcp-android.c
+endif
+
+# misc. sources
+#
+CORE_MISC_SOURCES = \
+ acl.c \
+ aes.c \
+ aio-android.c \
+ async.c \
+ bt-host.c \
+ bt-vhci.c \
+ buffered_file.c \
+ cbuffer.c \
+ charpipe.c \
+ console.c \
+ cutils.c \
+ d3des.c \
+ input.c \
+ ioport.c \
+ module.c \
+ net-android.c \
+ notify.c \
+ osdep.c \
+ outputchannel.c \
+ path.c \
+ qemu-char-android.c \
+ qemu-config.c \
+ qemu-error.c \
+ qemu-malloc.c \
+ qemu-option.c \
+ qemu-sockets-android.c \
+ qerror.c \
+ readline.c \
+ savevm.c \
+ shaper.c \
+ tcpdump.c \
+ vnc-android.c \
+ android/boot-properties.c \
+ android/config.c \
+ android/core-init-utils.c \
+ android/gps.c \
+ android/hw-kmsg.c \
+ android/hw-lcd.c \
+ android/hw-events.c \
+ android/hw-control.c \
+ android/hw-sensors.c \
+ android/hw-qemud.c \
+ android/looper-qemu.c \
+ android/qemu-setup.c \
+ android/snapshot.c \
+ android/utils/timezone.c \
+
+ifeq ($(HOST_ARCH),x86)
+ CORE_MISC_SOURCES += i386-dis.c
+endif
+ifeq ($(HOST_ARCH),x86_64)
+ CORE_MISC_SOURCES += i386-dis.c
+endif
+ifeq ($(HOST_ARCH),ppc)
+ CORE_MISC_SOURCES += ppc-dis.c \
+ cache-utils.c
+endif
+
+ifeq ($(HOST_OS),linux)
+ CORE_MISC_SOURCES += usb-linux.c \
+ qemu-thread.c
+else
+ CORE_MISC_SOURCES += usb-dummy-android.c
+endif
+
+ifeq ($(HOST_OS),windows)
+ CORE_MISC_SOURCES += tap-win32.c
+else
+ CORE_MISC_SOURCES += posix-aio-compat.c
+endif
+
+LOCAL_SRC_FILES += $(CORE_MISC_SOURCES)
+
+# Required
+LOCAL_CFLAGS += -D_XOPEN_SOURCE=600 -D_BSD_SOURCE=1
+
+SLIRP_SOURCES := \
+ bootp.c \
+ cksum.c \
+ debug.c \
+ if.c \
+ ip_icmp.c \
+ ip_input.c \
+ ip_output.c \
+ mbuf.c \
+ misc.c \
+ sbuf.c \
+ slirp.c \
+ socket.c \
+ tcp_input.c \
+ tcp_output.c \
+ tcp_subr.c \
+ tcp_timer.c \
+ tftp.c \
+ udp.c
+
+LOCAL_SRC_FILES += $(SLIRP_SOURCES:%=slirp-android/%)
+EMULATOR_LIBQEMU_CFLAGS += -I$(LOCAL_PATH)/slirp-android
+
+# socket proxy support
+#
+PROXY_SOURCES := \
+ proxy_common.c \
+ proxy_http.c \
+ proxy_http_connector.c \
+ proxy_http_rewriter.c \
+
+LOCAL_SRC_FILES += $(PROXY_SOURCES:%=proxy/%)
+EMULATOR_LIBQEMU_CFLAGS += -I$(LOCAL_PATH)/proxy
+
+# include telephony stuff
+#
+TELEPHONY_SOURCES := \
+ android_modem.c \
+ modem_driver.c \
+ gsm.c \
+ sim_card.c \
+ sysdeps_qemu.c \
+ sms.c \
+ remote_call.c
+
+LOCAL_SRC_FILES += $(TELEPHONY_SOURCES:%=telephony/%)
+EMULATOR_LIBQEMU_CFLAGS += -I$(LOCAL_PATH)/telephony
+
+# sources inherited from upstream, but not fully
+# integrated into android emulator
+#
+LOCAL_SRC_FILES += \
+ json-lexer.c \
+ json-parser.c \
+ json-streamer.c \
+ qjson.c \
+ qbool.c \
+ qdict.c \
+ qfloat.c \
+ qint.c \
+ qlist.c \
+ qstring.c \
+
+# hw-config-defs.h is generated from android/avd/hardware-properties.ini
+#
+QEMU_HARDWARE_PROPERTIES_INI := $(LOCAL_PATH)/android/avd/hardware-properties.ini
+QEMU_HW_CONFIG_DEFS_H := $(LOCAL_PATH)/android/avd/hw-config-defs.h
+$(QEMU_HW_CONFIG_DEFS_H): PRIVATE_PATH := $(LOCAL_PATH)
+$(QEMU_HW_CONFIG_DEFS_H): PRIVATE_SOURCES := $(QEMU_HARDWARE_PROPERTIES_INI)
+$(QEMU_HW_CONFIG_DEFS_H): PRIVATE_CUSTOM_TOOL = $(PRIVATE_PATH)/android/tools/gen-hw-config.py $(QEMU_HARDWARE_PROPERTIES_INI) $@
+$(QEMU_HW_CONFIG_DEFS_H): $(QEMU_HARDWARE_PROPERTIES_INI) $(LOCAL_PATH)/android/tools/gen-hw-config.py
+ $(hide) rm -f $@
+ $(transform-generated-source)
+
+$(LOCAL_PATH)/android/avd/hw-config.h: $(QEMU_HW_CONFIG_DEFS_H)
+
+# gdbstub-xml.c contains C-compilable arrays corresponding to the content
+# of $(LOCAL_PATH)/gdb-xml/, and is generated with the 'feature_to_c.sh' script.
+#
+intermediates := $(call intermediates-dir-for,STATIC_LIBRARIES,$(LOCAL_MODULE),true)
+
+ifeq ($(QEMU_TARGET_XML_SOURCES),)
+ QEMU_TARGET_XML_SOURCES := arm-core arm-neon arm-vfp arm-vfp3
+ QEMU_TARGET_XML_SOURCES := $(QEMU_TARGET_XML_SOURCES:%=$(LOCAL_PATH)/gdb-xml/%.xml)
+endif
+
+QEMU_GDBSTUB_XML_C := $(intermediates)/gdbstub-xml.c
+$(QEMU_GDBSTUB_XML_C): PRIVATE_PATH := $(LOCAL_PATH)
+$(QEMU_GDBSTUB_XML_C): PRIVATE_SOURCES := $(TARGET_XML_SOURCES)
+$(QEMU_GDBSTUB_XML_C): PRIVATE_CUSTOM_TOOL = $(PRIVATE_PATH)/feature_to_c.sh $@ $(QEMU_TARGET_XML_SOURCES)
+$(QEMU_GDBSTUB_XML_C): $(QEMU_TARGET_XML_SOURCES) $(LOCAL_PATH)/feature_to_c.sh
+ $(hide) rm -f $@
+ $(transform-generated-source)
+
+LOCAL_GENERATED_SOURCES += $(QEMU_GDBSTUB_XML_C)
+
+EMULATOR_LIBQEMU_CFLAGS += -I$(intermediates)
+
+LOCAL_CFLAGS += $(EMULATOR_LIBQEMU_CFLAGS)
+
+$(call end-emulator-library)
+
+# Block sources, we must compile them with each executable because they
+# are only referenced by the rest of the code using constructor functions.
+# If their object files are put in a static library, these are never compiled
+# into the final linked executable that uses them.
+#
+# Normally, one would solve thus using LOCAL_WHOLE_STATIC_LIBRARIES, but
+# the Darwin linker doesn't support -Wl,--whole-archive or equivalent :-(
+#
+BLOCK_SOURCES += \
+ block.c \
+ blockdev.c \
+ block/qcow.c \
+ block/qcow2.c \
+ block/qcow2-refcount.c \
+ block/qcow2-snapshot.c \
+ block/qcow2-cluster.c \
+ block/cloop.c \
+ block/dmg.c \
+ block/vvfat.c \
+ block/raw.c
+
+ifeq ($(HOST_OS),windows)
+ BLOCK_SOURCES += block/raw-win32.c
+else
+ BLOCK_SOURCES += block/raw-posix.c
+endif
+
+BLOCK_CFLAGS += $(EMULATOR_COMMON_CFLAGS)
+BLOCK_CFLAGS += -DCONFIG_BDRV_WHITELIST=""
+
+
+##############################################################################
+##############################################################################
+###
+### emulator-libelff: TARGET-INDEPENDENT ELF/DWARD PARSER
+###
+### THESE ARE USED BY EVERYTHING EXCEPT 'emulator-ui', BUT WE CANNOT PUT
+### THEM IN emulator-libqemu SINCE THE SOURCES ARE C++
+###
+
+$(call start-emulator-library, emulator-libelff)
+
+LOCAL_CPP_EXTENSION := .cc
+
+ELFF_CFLAGS := -I$(LOCAL_PATH)/elff
+ELFF_LDLIBS := -lstdc++
+
+ELFF_SOURCES := \
+ dwarf_cu.cc \
+ dwarf_die.cc \
+ dwarf_utils.cc \
+ elf_alloc.cc \
+ elf_file.cc \
+ elf_mapped_section.cc \
+ elff_api.cc \
+
+LOCAL_SRC_FILES += $(ELFF_SOURCES:%=elff/%)
+
+LOCAL_CFLAGS += \
+ -fno-exceptions \
+ $(ELFF_CFLAGS) \
+
+$(call end-emulator-library)
+
+
+##############################################################################
+##############################################################################
+###
+### gen-hx-header: Generate headers from .hx file with "hxtool" script.
+###
+### The 'hxtool' script is used to generate header files from an input
+### file with the .hx suffix. I.e. foo.hx --> foo.h
+###
+### Due to the way the Android build system works, we need to regenerate
+### it for each module (the output will go into a module-specific directory).
+###
+### This defines a function that can be used inside a module definition
+###
+### $(call gen-hx-header,<input>,<source-files>)
+###
+### Where: <input> is the input file, with a .hx suffix (e.g. foo.hx)
+### <source-files> is a list of source files that include the header
+###
+
+
+gen-hx-header = $(eval $(call gen-hx-header-ev,$1,$2,$3))
+
+define gen-hx-header-ev
+intermediates := $$(call intermediates-dir-for,EXECUTABLES,$$(LOCAL_MODULE),true)
+
+QEMU_HEADER_H := $$(intermediates)/$$(1:%.hx=%.h)
+$$(QEMU_HEADER_H): PRIVATE_PATH := $$(LOCAL_PATH)
+$$(QEMU_HEADER_H): PRIVATE_CUSTOM_TOOL = $$(PRIVATE_PATH)/hxtool -h < $$< > $$@
+$$(QEMU_HEADER_H): $$(LOCAL_PATH)/$$1 $$(LOCAL_PATH)/hxtool
+ $$(transform-generated-source)
+
+LOCAL_GENERATED_SOURCES += $$(QEMU_HEADER_H)
+_objects := $$(patsubst %,$$(intermediates)/%,$$(2:.c=.o))
+$$(_objects): $$(QEMU_HEADER_H)
+endef
+
diff --git a/Makefile.target b/Makefile.target
new file mode 100644
index 0000000..fa76ed7
--- /dev/null
+++ b/Makefile.target
@@ -0,0 +1,362 @@
+# This file is included several times to build target-specific
+# modules for the Android emulator. It will be called several times
+# (e.g. once for the arm target, and once for the x86 target).
+#
+
+ifndef EMULATOR_TARGET_ARCH
+$(error EMULATOR_TARGET_ARCH is not defined!)
+endif
+
+EMULATOR_TARGET_CPU := $(EMULATOR_TARGET_ARCH)
+ifeq ($(EMULATOR_TARGET_CPU),x86)
+ EMULATOR_TARGET_CPU := i386
+endif
+
+##############################################################################
+##############################################################################
+###
+### emulator-target-$CPU: target-specific emulation code.
+###
+### Used by both the core and standalone programs.
+###
+
+# Common compiler flags for all target-dependent libraries
+EMULATOR_TARGET_CFLAGS := \
+ -I$(LOCAL_PATH)/android/config/$(HOST_PREBUILT_TAG) \
+ -I$(LOCAL_PATH)/android/config/target-$(EMULATOR_TARGET_ARCH) \
+ -I$(LOCAL_PATH)/target-$(EMULATOR_TARGET_CPU) \
+ -I$(LOCAL_PATH)/fpu \
+ -DNEED_CPU_H \
+
+TCG_TARGET := $(HOST_ARCH)
+ifeq ($(TCG_TARGET),x86)
+ TCG_TARGET := i386
+endif
+
+EMULATOR_TARGET_CFLAGS += \
+ -I$(LOCAL_PATH)/tcg \
+ -I$(LOCAL_PATH)/tcg/$(TCG_TARGET) \
+ -DTARGET_ARCH=\"$(EMULATOR_TARGET_ARCH)\"
+
+
+$(call start-emulator-library, emulator-target-$(EMULATOR_TARGET_CPU))
+
+# The following is to ensure that "config.h" will map to a target-specific
+# configuration file header.
+LOCAL_CFLAGS += $(EMULATOR_TARGET_CFLAGS)
+
+LOCAL_SRC_FILES += \
+ tcg/tcg.c \
+
+##############################################################################
+# Emulated hardware devices.
+#
+
+HW_SOURCES := \
+ bt.c \
+ bt-hci.c \
+ bt-hid.c \
+ bt-l2cap.c \
+ bt-sdp.c \
+ cdrom.c \
+ dma.c \
+ irq.c \
+ goldfish_audio.c \
+ goldfish_device.c \
+ goldfish_events_device.c \
+ goldfish_fb.c \
+ goldfish_battery.c \
+ goldfish_mmc.c \
+ goldfish_memlog.c \
+ goldfish_nand.c \
+ goldfish_tty.c \
+ msmouse.c \
+ pci.c \
+ qdev.c \
+ scsi-disk.c \
+ sysbus.c \
+ usb-hid.c \
+ usb-hub.c \
+ usb-msd.c \
+ usb-ohci.c \
+ usb.c \
+ watchdog.c
+
+ifeq ($(EMULATOR_TARGET_ARCH),arm)
+HW_SOURCES += android_arm.c \
+ arm_pic.c \
+ goldfish_interrupt.c \
+ goldfish_switch.c \
+ goldfish_timer.c \
+ goldfish_trace.c \
+ arm_boot.c \
+
+# The following sources must be compiled with the final executables
+# because they contain device_init() or machine_init() statements.
+HW_OBJ_SOURCES := hw/smc91c111.c
+HW_OBJ_CFLAGS := $(EMULATOR_TARGET_CFLAGS)
+
+LOCAL_SRC_FILES += arm-dis.c
+
+# smc91c111.c requires <zlib.h>
+LOCAL_CFLAGS += $(ZLIB_CFLAGS)
+endif
+
+ifeq ($(EMULATOR_TARGET_ARCH),x86)
+HW_SOURCES += \
+ apic.c \
+ i8259.c \
+ mc146818rtc.c \
+ piix_pci.c \
+ i8254.c \
+ pckbd.c \
+ ioapic.c \
+ ps2.c \
+ smbios.c \
+ fw_cfg.c
+
+# The following sources must be compiled with the final executables
+# because they contain device_init() or machine_init() statements.
+HW_OBJ_SOURCES := \
+ hw/ne2000.c \
+ hw/pc.c
+
+HW_OBJ_CFLAGS := $(EMULATOR_TARGET_CFLAGS)
+
+endif
+
+LOCAL_SRC_FILES += $(HW_SOURCES:%=hw/%)
+
+LOCAL_SRC_FILES += \
+ exec.c \
+ cpu-exec.c \
+ translate-all.c \
+ trace.c \
+ varint.c \
+ dcache.c \
+ softmmu_outside_jit.c \
+
+##############################################################################
+# CPU-specific emulation.
+#
+LOCAL_CFLAGS += -fno-PIC -fomit-frame-pointer -Wno-sign-compare
+
+ifeq ($(HOST_ARCH),ppc)
+ LOCAL_CFLAGS += -D__powerpc__
+endif
+
+ifeq ($(EMULATOR_TARGET_ARCH),arm)
+LOCAL_SRC_FILES += \
+ target-arm/op_helper.c \
+ target-arm/iwmmxt_helper.c \
+ target-arm/neon_helper.c \
+ target-arm/helper.c \
+ target-arm/translate.c \
+ target-arm/machine.c \
+ hw/armv7m.c \
+ hw/armv7m_nvic.c \
+ arm-semi.c \
+
+LOCAL_SRC_FILES += fpu/softfloat.c
+endif
+
+ifeq ($(EMULATOR_TARGET_ARCH), x86)
+LOCAL_SRC_FILES += \
+ target-i386/op_helper.c \
+ target-i386/helper.c \
+ target-i386/translate.c \
+ target-i386/machine.c \
+
+LOCAL_SRC_FILES += fpu/softfloat-native.c
+endif
+
+# compile KVM only if target is x86 on x86 Linux
+ifeq ($(QEMU_HOST_TAG)-$(EMULATOR_TARGET_ARCH),linux-x86-x86)
+# the following is to include linux/kvm.h
+LOCAL_CFLAGS += -I /usr/include
+LOCAL_SRC_FILES += \
+ target-i386/kvm.c \
+ kvm-all.c
+endif
+
+##############################################################################
+# Memory-access checking support.
+# Memory access checker uses information collected by instrumented code in
+# libc.so in order to keep track of memory blocks allocated from heap. Memory
+# checker then uses this information to make sure that every access to allocated
+# memory is within allocated block. This information also allows detecting
+# memory leaks and attempts to free/realloc invalid pointers.
+#
+LOCAL_CFLAGS += \
+ -I$(LOCAL_PATH)/memcheck \
+ -I$(LOCAL_PATH)/elff
+
+MCHK_SOURCES := \
+ memcheck.c \
+ memcheck_proc_management.c \
+ memcheck_malloc_map.c \
+ memcheck_mmrange_map.c \
+ memcheck_util.c \
+
+LOCAL_SRC_FILES += $(MCHK_SOURCES:%=memcheck/%)
+
+
+$(call end-emulator-library)
+
+##############################################################################
+##############################################################################
+###
+### qemu-android-$CPU: headless emulator core program
+###
+###
+$(call start-emulator-program, qemu-android-$(EMULATOR_TARGET_ARCH))
+
+LOCAL_CFLAGS += \
+ $(EMULATOR_COMMON_CFLAGS) \
+ $(ELFF_CFLAGS) \
+ $(EMULATOR_LIBQEMU_CFLAGS) \
+ $(EMULATOR_TARGET_CFLAGS) \
+ -DCONFIG_STANDALONE_CORE \
+
+LOCAL_CFLAGS += -Wno-missing-field-initializers
+
+
+LOCAL_STATIC_LIBRARIES := \
+ emulator-libqemu \
+ emulator-target-$(EMULATOR_TARGET_CPU) \
+ emulator-libelff \
+ emulator-common \
+
+
+LOCAL_LDLIBS += \
+ $(EMULATOR_COMMON_LDLIBS) \
+ $(EMULATOR_LIBQEMU_LDLIBS) \
+ $(ELFF_LDLIBS) \
+
+LOCAL_SRC_FILES := \
+ audio/audio.c \
+ disas.c \
+ dma-helpers.c \
+ gdbstub.c \
+ keymaps.c \
+ loader.c \
+ monitor.c \
+ qemu-timer.c \
+ user-events-qemu.c \
+ vl-android.c \
+ android/console.c \
+ android/display-core.c \
+ android/protocol/attach-ui-proxy.c \
+ android/protocol/fb-updates-proxy.c \
+ android/protocol/user-events-impl.c \
+ android/protocol/ui-commands-proxy.c \
+ android/protocol/core-commands-impl.c \
+ android/protocol/core-commands-qemu.c \
+
+$(call gen-hx-header,qemu-monitor.hx,monitor.c)
+$(call gen-hx-header,qemu-options.hx,vl-android.c)
+
+ifeq ($(HOST_OS),darwin)
+ FRAMEWORKS := OpenGL Cocoa QuickTime ApplicationServices Carbon IOKit
+ LOCAL_LDLIBS += $(FRAMEWORKS:%=-Wl,-framework,%)
+endif
+
+# Generate a completely static executable if needed.
+# Note that this means no sound and graphics on Linux.
+#
+ifeq ($(CONFIG_STATIC_EXECUTABLE),true)
+ LOCAL_SRC_FILES += dynlink-static.c
+ LOCAL_LDLIBS += -static
+endif
+
+# The following files cannot be in static libraries because they contain
+# constructor functions that are otherwise stripped by the final linker
+LOCAL_SRC_FILES += $(HW_OBJ_SOURCES)
+LOCAL_CFLAGS += $(HW_OBJ_CFLAGS)
+
+LOCAL_SRC_FILES += $(BLOCK_SOURCES)
+LOCAL_CFLAGS += $(BLOCK_CFLAGS)
+
+LOCAL_MODULE_TAGS := debug
+
+$(call end-emulator-program)
+
+##############################################################################
+##############################################################################
+###
+### emulator-$ARCH: Standalone emulator program
+###
+###
+
+# Special case, "emulator-arm" is named "emulator" for now.
+ifeq ($(EMULATOR_TARGET_ARCH),arm)
+$(call start-emulator-program, emulator)
+else
+$(call start-emulator-program, emulator-$(EMULATOR_TARGET_ARCH))
+endif
+
+LOCAL_STATIC_LIBRARIES := \
+ emulator-libui \
+ emulator-libqemu \
+ emulator-target-$(EMULATOR_TARGET_CPU) \
+ emulator-libelff \
+ emulator-common \
+
+LOCAL_LDLIBS += \
+ $(EMULATOR_COMMON_LDLIBS) \
+ $(EMULATOR_LIBQEMU_LDLIBS) \
+ $(EMULATOR_LIBUI_LDLIBS) \
+ $(ELFF_LDLIBS) \
+
+LOCAL_CFLAGS += \
+ $(EMULATOR_TARGET_CFLAGS) \
+ $(EMULATOR_COMMON_CFLAGS) \
+ $(EMULATOR_LIBQEMU_CFLAGS) \
+ $(EMULATOR_LIBUI_CFLAGS)
+
+LOCAL_SRC_FILES := \
+ audio/audio.c \
+ disas.c \
+ dma-helpers.c \
+ gdbstub.c \
+ keymaps.c \
+ loader.c \
+ monitor.c \
+ qemu-timer.c \
+ user-events-qemu.c \
+ vl-android.c \
+ android/cmdline-option.c \
+ android/console.c \
+ android/display.c \
+ android/display-core.c \
+ android/help.c \
+ android/main-common.c \
+ android/main.c \
+ android/protocol/core-commands-qemu.c \
+ android/protocol/ui-commands-qemu.c \
+ android/
+
+$(call gen-hx-header,qemu-monitor.hx,monitor.c)
+$(call gen-hx-header,qemu-options.hx,vl-android.c)
+
+# The following files cannot be in static libraries because they contain
+# constructor functions that are otherwise stripped by the final linker
+LOCAL_SRC_FILES += $(HW_OBJ_SOURCES)
+LOCAL_CFLAGS += $(HW_OBJ_CFLAGS)
+
+LOCAL_SRC_FILES += $(BLOCK_SOURCES)
+LOCAL_CFLAGS += $(BLOCK_CFLAGS)
+
+LOCAL_SRC_FILES += $(SDLMAIN_SOURCES)
+
+# Generate a completely static executable if needed.
+# Note that this means no sound and graphics on Linux.
+#
+ifeq ($(CONFIG_STATIC_EXECUTABLE),true)
+ LOCAL_SRC_FILES += dynlink-static.c
+ LOCAL_LDLIBS += -static
+endif
+
+LOCAL_STATIC_LIBRARIES += $(SDL_STATIC_LIBRARIES)
+
+$(call end-emulator-program)
diff --git a/android/avd/hardware-properties.ini b/android/avd/hardware-properties.ini
index 6b106f4..6b5caae 100644
--- a/android/avd/hardware-properties.ini
+++ b/android/avd/hardware-properties.ini
@@ -24,6 +24,8 @@
#
# Ram size
+# Default value will be computed based on screen pixels
+# or skin version
name = hw.ramSize
type = integer
default = 0
@@ -134,6 +136,11 @@
abstract = SD Card support
description = Whether the device supports insertion/removal of virtual SD Cards.
+name = hw.sdCard.path
+type = string
+default =
+abstract = SD Card image path
+
# Cache partition
name = disk.cachePartition
type = boolean
@@ -141,11 +148,34 @@
abstract = Cache partition support
description = Whether we use a /cache partition on the device.
+name = disk.cachePartition.path
+type = string
+default =
+abstract = Cache partition
+description = Cache partition to use on the device. Ignored if disk.cachePartition is not 'yes'.
+
name = disk.cachePartition.size
type = diskSize
abstract = Cache partition size
default = 66MB
+# LCD width
+name = hw.lcd.width
+type = integer
+default = 320
+abstract = LCD pixel width
+
+name = hw.lcd.height
+type = integer
+default = 640
+abstract = LCD pixel height
+
+name = hw.lcd.depth
+type = integer
+default = 16
+abstract = LCD color depth
+description = Must be 16 or 32. Color bit depth of emulated framebuffer.
+
# LCD density
name = hw.lcd.density
type = integer
@@ -155,9 +185,10 @@
# Maximum VM heap size
# Higher values are required for high-dpi devices
+# Default will depend on RAM size.
name = vm.heapSize
type = integer
-default = 16
+default = 0
abstract = Max VM application heap size
description = The maximum heap size a Dalvik application might allocate before being killed by the system. Value is in megabytes.
@@ -167,3 +198,89 @@
default = yes
abstract = Proximity support
description = Whether there is an proximity in the device.
+
+# Kernel image.
+#
+# kernel.path specified the path to the kernel image
+# kernel.parameters specifies the string of kernel boot parameters.
+#
+name = kernel.path
+type = string
+default =
+abstract = Path to the kernel image
+description = Path to the kernel image.
+
+name = kernel.parameters
+type = string
+default =
+abstract = kernel boot parameters string.
+
+# Path to the ramdisk image.
+name = disk.ramdisk.path
+type = string
+default =
+abstract = Path to the ramdisk image
+description = Path to the ramdisk image.
+
+# System partition image(s).
+#
+# disk.systemPartition.path points to the read/write system partition image.
+# if empty, a temporary file will be created, initialized with the content
+# of .initPath
+#
+# disk.systemPartition.initPath is only used when .path is empty. It must
+# then point to a read-only initialization system image file.
+#
+# disk.systemPartition.size is the ideal size of the system partition. The
+# size is ignored if the actual system partition image is larger. Otherwise,
+# it indicates the maximum size the disk image file can grow to.
+#
+name = disk.systemPartition.path
+type = string
+default =
+abstract = Path to runtime system partition image
+
+name = disk.systemPartition.initPath
+type = string
+default =
+abstract = Initial system partition image
+
+name = disk.systemPartition.size
+type = diskSize
+default = 0
+abstract = Ideal size of system partition
+
+# Path to the data partition.
+name = disk.dataPartition.path
+type = string
+default = <temp>
+abstract = Path to data partition file
+description = Path to data partition file. Cannot be empty. Special value <temp> means using a temporary file. If disk.dataPartition.initPath is not empty, its content will be copied to the disk.dataPartition.path file at boot-time.
+
+# Initial path to the data partition.
+name = disk.dataPartition.initPath
+type = string
+default =
+abstract = Initial data partition
+description = If not empty, its content will be copied to the disk.dataPartition.path file at boot-time.
+
+# Data partition size.
+name = disk.dataPartition.size
+type = diskSize
+default = 0
+abstract = Ideal size of data partition
+
+# Path to the snapshots storage file.
+name = disk.snapStorage.path
+type = string
+default =
+abstract = Path to snapshot storage
+description = Path to a 'snapshot storage' file, where all snapshots are stored.
+
+# Android AVD name
+# This is set automatically before launching a core.
+#
+name = avd.name
+type = string
+default = <build>
+abstract = Name of the AVD being run
diff --git a/android/avd/hw-config-defs.h b/android/avd/hw-config-defs.h
index 0c87bdb..0ab1f0f 100644
--- a/android/avd/hw-config-defs.h
+++ b/android/avd/hw-config-defs.h
@@ -129,6 +129,13 @@
"SD Card support",
"Whether the device supports insertion/removal of virtual SD Cards.")
+HWCFG_STRING(
+ hw_sdCard_path,
+ "hw.sdCard.path",
+ "",
+ "SD Card image path",
+ "")
+
HWCFG_BOOL(
disk_cachePartition,
"disk.cachePartition",
@@ -136,6 +143,13 @@
"Cache partition support",
"Whether we use a /cache partition on the device.")
+HWCFG_STRING(
+ disk_cachePartition_path,
+ "disk.cachePartition.path",
+ "",
+ "Cache partition",
+ "Cache partition to use on the device. Ignored if disk.cachePartition is not 'yes'.")
+
HWCFG_DISKSIZE(
disk_cachePartition_size,
"disk.cachePartition.size",
@@ -144,6 +158,27 @@
"")
HWCFG_INT(
+ hw_lcd_width,
+ "hw.lcd.width",
+ 320,
+ "LCD pixel width",
+ "")
+
+HWCFG_INT(
+ hw_lcd_height,
+ "hw.lcd.height",
+ 640,
+ "LCD pixel height",
+ "")
+
+HWCFG_INT(
+ hw_lcd_depth,
+ "hw.lcd.depth",
+ 16,
+ "LCD color depth",
+ "Must be 16 or 32. Color bit depth of emulated framebuffer.")
+
+HWCFG_INT(
hw_lcd_density,
"hw.lcd.density",
160,
@@ -153,7 +188,7 @@
HWCFG_INT(
vm_heapSize,
"vm.heapSize",
- 16,
+ 0,
"Max VM application heap size",
"The maximum heap size a Dalvik application might allocate before being killed by the system. Value is in megabytes.")
@@ -164,6 +199,83 @@
"Proximity support",
"Whether there is an proximity in the device.")
+HWCFG_STRING(
+ kernel_path,
+ "kernel.path",
+ "",
+ "Path to the kernel image",
+ "Path to the kernel image.")
+
+HWCFG_STRING(
+ kernel_parameters,
+ "kernel.parameters",
+ "",
+ "kernel boot parameters string.",
+ "")
+
+HWCFG_STRING(
+ disk_ramdisk_path,
+ "disk.ramdisk.path",
+ "",
+ "Path to the ramdisk image",
+ "Path to the ramdisk image.")
+
+HWCFG_STRING(
+ disk_systemPartition_path,
+ "disk.systemPartition.path",
+ "",
+ "Path to runtime system partition image",
+ "")
+
+HWCFG_STRING(
+ disk_systemPartition_initPath,
+ "disk.systemPartition.initPath",
+ "",
+ "Initial system partition image",
+ "")
+
+HWCFG_DISKSIZE(
+ disk_systemPartition_size,
+ "disk.systemPartition.size",
+ "0",
+ "Ideal size of system partition",
+ "")
+
+HWCFG_STRING(
+ disk_dataPartition_path,
+ "disk.dataPartition.path",
+ "<temp>",
+ "Path to data partition file",
+ "Path to data partition file. Cannot be empty. Special value <temp> means using a temporary file. If disk.dataPartition.initPath is not empty, its content will be copied to the disk.dataPartition.path file at boot-time.")
+
+HWCFG_STRING(
+ disk_dataPartition_initPath,
+ "disk.dataPartition.initPath",
+ "",
+ "Initial data partition",
+ "If not empty, its content will be copied to the disk.dataPartition.path file at boot-time.")
+
+HWCFG_DISKSIZE(
+ disk_dataPartition_size,
+ "disk.dataPartition.size",
+ "0",
+ "Ideal size of data partition",
+ "")
+
+HWCFG_STRING(
+ disk_snapStorage_path,
+ "disk.snapStorage.path",
+ "",
+ "Path to snapshot storage",
+ "Path to a 'snapshot storage' file, where all snapshots are stored.")
+
+HWCFG_STRING(
+ avd_name,
+ "avd.name",
+ "<build>",
+ "Name of the AVD being run",
+ "")
+
#undef HWCFG_INT
#undef HWCFG_BOOL
#undef HWCFG_DISKSIZE
diff --git a/android/avd/info.c b/android/avd/info.c
index 058226c..aaf1111 100644
--- a/android/avd/info.c
+++ b/android/avd/info.c
@@ -84,6 +84,11 @@
*/
#define SKIN_PATH "skin.path"
+/* the config.ini key that will be used to indicate the default skin's name.
+ * this is ignored if there is a valid SKIN_PATH entry in the file.
+ */
+#define SKIN_NAME "skin.name"
+
/* default skin name */
#define SKIN_DEFAULT "HVGA"
@@ -93,6 +98,12 @@
*/
#define SDCARD_PATH "sdcard.path"
+/* the name of the .ini file that will contain the complete hardware
+ * properties for the AVD. This will be used to launch the corresponding
+ * core from the UI.
+ */
+#define CORE_HARDWARE_INI "hardware-qemu.ini"
+
/* certain disk image files are mounted read/write by the emulator
* to ensure that several emulators referencing the same files
* do not corrupt these files, we need to lock them and respond
@@ -124,6 +135,7 @@
char inAndroidBuild;
char* androidOut;
char* androidBuildRoot;
+ char* targetArch;
/* for the normal virtual device case */
char* deviceName;
@@ -132,13 +144,14 @@
char* searchPaths[ MAX_SEARCH_PATHS ];
int numSearchPaths;
char* contentPath;
- IniFile* rootIni; /* root <foo>.ini file */
- IniFile* configIni; /* virtual device's config.ini */
- IniFile* hardwareIni; /* skin-specific hardware.ini */
+ IniFile* rootIni; /* root <foo>.ini file, empty if missing */
+ IniFile* configIni; /* virtual device's config.ini, NULL if missing */
+ IniFile* skinHardwareIni; /* skin-specific hardware.ini */
/* for both */
char* skinName; /* skin name */
char* skinDirPath; /* skin directory */
+ char* coreHardwareIniPath; /* core hardware.ini path */
/* image files */
char* imagePath [ AVD_IMAGE_MAX ];
@@ -157,6 +170,7 @@
AFREE(i->skinName);
AFREE(i->skinDirPath);
+ AFREE(i->coreHardwareIniPath);
for (nn = 0; nn < i->numSearchPaths; nn++)
AFREE(i->searchPaths[nn]);
@@ -168,9 +182,9 @@
i->configIni = NULL;
}
- if (i->hardwareIni) {
- iniFile_free(i->hardwareIni);
- i->hardwareIni = NULL;
+ if (i->skinHardwareIni) {
+ iniFile_free(i->skinHardwareIni);
+ i->skinHardwareIni = NULL;
}
if (i->rootIni) {
@@ -208,80 +222,99 @@
/***************************************************************
***************************************************************
*****
- ***** NORMAL VIRTUAL DEVICE SUPPORT
+ ***** UTILITY FUNCTIONS
+ *****
+ ***** The following functions do not depend on the AvdInfo
+ ***** structure and could easily be moved elsewhere.
*****
*****/
-/* compute path to the root SDK directory
- * assume we are in $SDKROOT/tools/emulator[.exe]
+/* Return the path to the Android SDK root installation.
+ *
+ * (*pFromEnv) will be set to 1 if it comes from the $ANDROID_SDK_ROOT
+ * environment variable, or 0 otherwise.
+ *
+ * Caller must free() returned string.
*/
-static int
-_getSdkRoot( AvdInfo* i )
+static char*
+_getSdkRoot( char *pFromEnv )
{
const char* env;
+ char* sdkPath;
char temp[PATH_MAX], *p=temp, *end=p+sizeof(temp);
+ /* If ANDROID_SDK_ROOT is defined is must point to a directory
+ * containing a valid SDK installation.
+ */
#define SDK_ROOT_ENV "ANDROID_SDK_ROOT"
env = getenv(SDK_ROOT_ENV);
if (env != NULL && env[0] != 0) {
if (path_exists(env)) {
D("found " SDK_ROOT_ENV ": %s", env);
- i->sdkRootPath = ASTRDUP(env);
- i->sdkRootPathFromEnv = 1;
- return 0;
+ *pFromEnv = 1;
+ return ASTRDUP(env);
}
D(SDK_ROOT_ENV " points to unknown directory: %s", env);
}
- (void) bufprint_app_dir(temp, end);
+ *pFromEnv = 0;
- i->sdkRootPath = path_parent(temp, 1);
- if (i->sdkRootPath == NULL) {
+ /* We assume the emulator binary is under tools/ so use its
+ * parent as the Android SDK root.
+ */
+ (void) bufprint_app_dir(temp, end);
+ sdkPath = path_parent(temp, 1);
+ if (sdkPath == NULL) {
derror("can't find root of SDK directory");
- return -1;
+ return NULL;
}
- D("found SDK root at %s", i->sdkRootPath);
- return 0;
+ D("found SDK root at %s", sdkPath);
+ return sdkPath;
}
-static void
-_getSearchPaths( AvdInfo* i )
+/* Parse a given config.ini file and extract the list of SDK search paths
+ * from it. Returns the number of valid paths stored in 'searchPaths', or -1
+ * in case of problem.
+ *
+ * Relative search paths in the config.ini will be stored as full pathnames
+ * relative to 'sdkRootPath'.
+ *
+ * 'searchPaths' must be an array of char* pointers of at most 'maxSearchPaths'
+ * entries.
+ */
+static int
+_getSearchPaths( IniFile* configIni,
+ const char* sdkRootPath,
+ int maxSearchPaths,
+ char** searchPaths )
{
char temp[PATH_MAX], *p = temp, *end= p+sizeof temp;
int nn, count = 0;
-
-
- for (nn = 0; nn < MAX_SEARCH_PATHS; nn++) {
+ for (nn = 0; nn < maxSearchPaths; nn++) {
char* path;
p = bufprint(temp, end, "%s%d", SEARCH_PREFIX, nn+1 );
if (p >= end)
continue;
- path = iniFile_getString( i->configIni, temp, NULL );
+ path = iniFile_getString(configIni, temp, NULL);
if (path != NULL) {
DD(" found image search path: %s", path);
if (!path_is_absolute(path)) {
- p = bufprint(temp, end, "%s/%s", i->sdkRootPath, path);
+ p = bufprint(temp, end, "%s/%s", sdkRootPath, path);
AFREE(path);
path = ASTRDUP(temp);
}
- i->searchPaths[count++] = path;
+ searchPaths[count++] = path;
}
}
-
- i->numSearchPaths = count;
- if (count == 0) {
- derror("no search paths found in this AVD's configuration.\n"
- "Weird, the AVD's config.ini file is malformed. Try re-creating it.\n");
- exit(2);
- }
- else
- DD("found a total of %d search paths for this AVD", count);
+ return count;
}
+/* Check that an AVD name is valid. Returns 1 on success, 0 otherwise.
+ */
static int
_checkAvdName( const char* name )
{
@@ -292,533 +325,120 @@
return (len == len2);
}
-/* parse the root config .ini file. it is located in
+/* Return the path to the AVD's root configuration .ini file. it is located in
* ~/.android/avd/<name>.ini or Windows equivalent
+ *
+ * This file contains the path to the AVD's content directory, which
+ * includes its own config.ini.
*/
-static int
-_getRootIni( AvdInfo* i )
+static char*
+_getRootIniPath( const char* avdName )
{
- char temp[PATH_MAX], *p=temp, *end=p+sizeof(temp);
+ char temp[PATH_MAX], *p=temp, *end=p+sizeof(temp);
p = bufprint_config_path(temp, end);
- p = bufprint(p, end, "/" ANDROID_AVD_DIR "/%s.ini", i->deviceName);
+ p = bufprint(p, end, "/" ANDROID_AVD_DIR "/%s.ini", avdName);
if (p >= end) {
- derror("device name too long");
- return -1;
- }
-
- i->rootIni = iniFile_newFromFile(temp);
- if (i->rootIni == NULL) {
- derror("unknown virtual device name: '%s'", i->deviceName);
- return -1;
- }
- D("root virtual device file at %s", temp);
- return 0;
-}
-
-/* the .ini variable name that points to the content directory
- * in a root AVD ini file. This is required */
-# define ROOT_PATH_KEY "path"
-
-static int
-_getContentPath( AvdInfo* i )
-{
- i->contentPath = iniFile_getString(i->rootIni, ROOT_PATH_KEY, NULL);
-
- if (i->contentPath == NULL) {
- derror("bad config: %s",
- "virtual device file lacks a "ROOT_PATH_KEY" entry");
- return -1;
- }
- D("virtual device content at %s", i->contentPath);
- return 0;
-}
-
-/* find and parse the config.ini file from the content directory */
-static int
-_getConfigIni(AvdInfo* i)
-{
- char temp[PATH_MAX], *p=temp, *end=p+sizeof(temp);
-
- p = bufprint(p, end, "%s/config.ini", i->contentPath);
- if (p >= end) {
- derror("can't access virtual device content directory");
- return -1;
- }
-
-#if 1 /* XXX: TODO: remove this in the future */
- /* for now, allow a non-existing config.ini */
- if (!path_exists(temp)) {
- D("virtual device has no config file - no problem");
- return 0;
- }
-#endif
-
- i->configIni = iniFile_newFromFile(temp);
- if (i->configIni == NULL) {
- derror("bad config: %s",
- "virtual device directory lacks config.ini");
- return -1;
- }
- D("virtual device config file: %s", temp);
- return 0;
-}
-
-/***************************************************************
- ***************************************************************
- *****
- ***** KERNEL/DISK IMAGE LOADER
- *****
- *****/
-
-/* a structure used to handle the loading of
- * kernel/disk images.
- */
-typedef struct {
- AvdInfo* info;
- AvdInfoParams* params;
- AvdImageType id;
- const char* imageFile;
- const char* imageText;
- char** pPath;
- char* pState;
- char temp[PATH_MAX];
-} ImageLoader;
-
-static void
-imageLoader_init( ImageLoader* l, AvdInfo* info, AvdInfoParams* params )
-{
- memset(l, 0, sizeof(*l));
- l->info = info;
- l->params = params;
-}
-
-/* set the type of the image to load */
-static void
-imageLoader_set( ImageLoader* l, AvdImageType id )
-{
- l->id = id;
- l->imageFile = _imageFileNames[id];
- l->imageText = _imageFileText[id];
- l->pPath = &l->info->imagePath[id];
- l->pState = &l->info->imageState[id];
-
- l->pState[0] = IMAGE_STATE_READONLY;
-}
-
-/* change the image path */
-static char*
-imageLoader_setPath( ImageLoader* l, const char* path )
-{
- path = path ? ASTRDUP(path) : NULL;
-
- AFREE(l->pPath[0]);
- l->pPath[0] = (char*) path;
-
- return (char*) path;
-}
-
-static char*
-imageLoader_extractPath( ImageLoader* l )
-{
- char* result = l->pPath[0];
- l->pPath[0] = NULL;
- return result;
-}
-
-/* flags used when loading images */
-enum {
- IMAGE_REQUIRED = (1<<0), /* image is required */
- IMAGE_SEARCH_SDK = (1<<1), /* search image in SDK */
- IMAGE_EMPTY_IF_MISSING = (1<<2), /* create empty file if missing */
- IMAGE_DONT_LOCK = (1<<4), /* don't try to lock image */
- IMAGE_IGNORE_IF_LOCKED = (1<<5), /* ignore file if it's locked */
-};
-
-#define IMAGE_OPTIONAL 0
-
-/* find an image from the SDK search directories.
- * returns the full path or NULL if the file could not be found.
- *
- * note: this stores the result in the image's path as well
- */
-static char*
-imageLoader_lookupSdk( ImageLoader* l )
-{
- AvdInfo* i = l->info;
- const char* image = l->imageFile;
- char* temp = l->temp, *p = temp, *end = p + sizeof(l->temp);
-
- do {
- /* try the search paths */
- int nn;
-
- for (nn = 0; nn < i->numSearchPaths; nn++) {
- const char* searchDir = i->searchPaths[nn];
-
- p = bufprint(temp, end, "%s/%s", searchDir, image);
- if (p < end && path_exists(temp)) {
- DD("found %s in search dir: %s", image, searchDir);
- goto FOUND;
- }
- DD(" no %s in search dir: %s", image, searchDir);
- }
-
- return NULL;
-
- } while (0);
-
-FOUND:
- l->pState[0] = IMAGE_STATE_READONLY;
-
- return imageLoader_setPath(l, temp);
-}
-
-/* search for a file in the content directory.
- * returns NULL if the file cannot be found.
- *
- * note that this formats l->temp with the file's path
- * allowing you to retrieve it if the function returns NULL
- */
-static char*
-imageLoader_lookupContent( ImageLoader* l )
-{
- AvdInfo* i = l->info;
- char* temp = l->temp, *p = temp, *end = p + sizeof(l->temp);
-
- p = bufprint(temp, end, "%s/%s", i->contentPath, l->imageFile);
- if (p >= end) {
- derror("content directory path too long");
- exit(2);
- }
- if (!path_exists(temp)) {
- DD(" no %s in content directory", l->imageFile);
return NULL;
}
- DD("found %s in content directory", l->imageFile);
-
- /* assume content image files must be locked */
- l->pState[0] = IMAGE_STATE_MUSTLOCK;
-
- return imageLoader_setPath(l, temp);
-}
-
-/* lock a file image depending on its state and user flags
- * note that this clears l->pPath[0] if the lock could not
- * be acquired and that IMAGE_IGNORE_IF_LOCKED is used.
- */
-static void
-imageLoader_lock( ImageLoader* l, unsigned flags )
-{
- const char* path = l->pPath[0];
-
- if (flags & IMAGE_DONT_LOCK)
- return;
-
- if (l->pState[0] != IMAGE_STATE_MUSTLOCK)
- return;
-
- D(" locking %s image at %s", l->imageText, path);
-
- if (filelock_create(path) != NULL) {
- /* succesful lock */
- l->pState[0] = IMAGE_STATE_LOCKED;
- return;
+ if (!path_exists(temp)) {
+ return NULL;
}
-
- if (flags & IMAGE_IGNORE_IF_LOCKED) {
- dwarning("ignoring locked %s image at %s", l->imageText, path);
- imageLoader_setPath(l, NULL);
- return;
- }
-
- derror("the %s image is used by another emulator. aborting",
- l->imageText);
- exit(2);
-}
-
-/* make a file image empty, this may require locking */
-static void
-imageLoader_empty( ImageLoader* l, unsigned flags )
-{
- const char* path;
-
- imageLoader_lock(l, flags);
-
- path = l->pPath[0];
- if (path == NULL) /* failed to lock, caller will handle it */
- return;
-
- if (path_empty_file(path) < 0) {
- derror("could not create %s image at %s: %s",
- l->imageText, path, strerror(errno));
- exit(2);
- }
- l->pState[0] = IMAGE_STATE_LOCKED_EMPTY;
+ return ASTRDUP(temp);
}
-/* copy image file from a given source
- * assumes locking is needed.
- */
-static void
-imageLoader_copyFrom( ImageLoader* l, const char* srcPath )
-{
- const char* dstPath = NULL;
-
- /* find destination file */
- if (l->params) {
- dstPath = l->params->forcePaths[l->id];
- }
- if (!dstPath) {
- imageLoader_lookupContent(l);
- dstPath = l->temp;
- }
-
- /* lock destination */
- imageLoader_setPath(l, dstPath);
- l->pState[0] = IMAGE_STATE_MUSTLOCK;
- imageLoader_lock(l, 0);
-
- /* make the copy */
- if (path_copy_file(dstPath, srcPath) < 0) {
- derror("can't initialize %s image from SDK: %s: %s",
- l->imageText, dstPath, strerror(errno));
- exit(2);
- }
-}
-
-/* this will load and eventually lock and image file, depending
- * on the flags being used. on exit, this function udpates
- * l->pState[0] and l->pPath[0]
+/* Retrieves a string corresponding to the target architecture
+ * when in the Android platform tree. The only way to do that
+ * properly for now is to look at $OUT/system/build.prop:
*
- * returns the path to the file. Note that it returns NULL
- * only if the file was optional and could not be found.
+ * ro.product.cpu-abi=<abi>
*
- * if the file is required and missing, the function aborts
- * the program.
+ * Where <abi> can be 'armeabi', 'armeabi-v7a' or 'x86'.
*/
-static char*
-imageLoader_load( ImageLoader* l,
- unsigned flags )
+static const char*
+_getBuildTargetArch( const char* androidOut )
{
- const char* path = NULL;
+ const char* arch = "arm";
+ char temp[PATH_MAX], *p=temp, *end=p+sizeof(temp);
+ FILE* file;
- /* set image state */
- l->pState[0] = (flags & IMAGE_DONT_LOCK) == 0
- ? IMAGE_STATE_MUSTLOCK
- : IMAGE_STATE_READONLY;
+#define ABI_PREFIX "ro.product.cpu.abi="
+#define ABI_PREFIX_LEN (sizeof(ABI_PREFIX)-1)
- /* check user-provided path */
- path = l->params->forcePaths[l->id];
- if (path != NULL) {
- imageLoader_setPath(l, path);
- if (path_exists(path)) {
- DD("found user-provided %s image: %s", l->imageText, l->imageFile);
- goto EXIT;
- }
- D("user-provided %s image does not exist: %s",
- l->imageText, path);
-
- /* if the file is required, abort */
- if (flags & IMAGE_REQUIRED) {
- derror("user-provided %s image at %s doesn't exist",
- l->imageText, path);
- exit(2);
- }
+ p = bufprint(temp, end, "%s/system/build.prop", androidOut);
+ if (p >= end) {
+ D("%s: ANDROID_PRODUCT_OUT too long: %s", __FUNCTION__, androidOut);
+ goto EXIT;
}
- else {
- const char* contentFile;
-
- /* second, look in the content directory */
- path = imageLoader_lookupContent(l);
- if (path) goto EXIT;
-
- contentFile = ASTRDUP(l->temp);
-
- /* it's not there */
- if (flags & IMAGE_SEARCH_SDK) {
- /* third, look in the SDK directory */
- path = imageLoader_lookupSdk(l);
- if (path) {
- AFREE((char*)contentFile);
- goto EXIT;
- }
- }
- DD("found no %s image (%s)", l->imageText, l->imageFile);
-
- /* if the file is required, abort */
- if (flags & IMAGE_REQUIRED) {
- AvdInfo* i = l->info;
-
- derror("could not find required %s image (%s).",
- l->imageText, l->imageFile);
-
- if (i->inAndroidBuild) {
- dprint( "Did you build everything ?" );
- } else if (!i->sdkRootPathFromEnv) {
- dprint( "Maybe defining %s to point to a valid SDK "
- "installation path might help ?", SDK_ROOT_ENV );
- } else {
- dprint( "Your %s is probably wrong: %s", SDK_ROOT_ENV,
- i->sdkRootPath );
- }
- exit(2);
- }
-
- path = imageLoader_setPath(l, contentFile);
- AFREE((char*)contentFile);
+ file = fopen(temp, "rb");
+ if (file == NULL) {
+ D("Could not open file: %s: %s", temp, strerror(errno));
+ D("Default target architecture=%s", arch);
+ goto EXIT;
}
- /* otherwise, do we need to create it ? */
- if (flags & IMAGE_EMPTY_IF_MISSING) {
- imageLoader_empty(l, flags);
- return l->pPath[0];
- }
- return NULL;
+ while (fgets(temp, sizeof temp, file) != NULL) {
+ /* Trim trailing newlines, if any */
+ p = memchr(temp, '\0', sizeof temp);
+ if (p == NULL)
+ p = end;
+ if (p > temp && p[-1] == '\n') {
+ *--p = '\0';
+ }
+ if (p > temp && p[-1] == '\r') {
+ *--p = '\0';
+ }
+ /* force zero-termination in case of full-buffer */
+ if (p == end)
+ *--p = '\0';
+ if (memcmp(temp, ABI_PREFIX, ABI_PREFIX_LEN) != 0) {
+ continue;
+ }
+ p = temp + ABI_PREFIX_LEN;
+ if (p >= end || !*p)
+ goto EXIT2;
+
+ if (!strcmp("armeabi",p))
+ arch = "arm";
+ else if (!strcmp("armeabi-v7a",p))
+ arch = "arm";
+ else
+ arch = p;
+
+ D("Found target ABI=%s, architecture=%s", p, arch);
+ goto EXIT2;
+ }
+
+ D("Could not find target architecture, defaulting to %s", arch);
+EXIT2:
+ fclose(file);
EXIT:
- imageLoader_lock(l, flags);
- return l->pPath[0];
+ return arch;
}
-/* Attempts to load an AVD image, but does not kill the process if loading
- * fails.
+/* Returns the full path of a given file.
+ *
+ * If 'fileName' is an absolute path, this returns a simple copy.
+ * Otherwise, this returns a new string corresponding to <rootPath>/<fileName>
+ *
+ * This returns NULL if the paths are too long.
*/
-static void
-imageLoader_loadOptional( ImageLoader *l, AvdImageType img_type,
- const char *forcedPath )
+static char*
+_getFullFilePath( const char* rootPath, const char* fileName )
{
- imageLoader_set (l, img_type);
- imageLoader_load(l, IMAGE_OPTIONAL |
- IMAGE_IGNORE_IF_LOCKED);
+ if (path_is_absolute(fileName)) {
+ return ASTRDUP(fileName);
+ } else {
+ char temp[PATH_MAX], *p=temp, *end=p+sizeof(temp);
- /* if the file was not found, ignore it */
- if (l->pPath[0] && !path_exists(l->pPath[0]))
- {
- D("ignoring non-existing %s at %s: %s",
- l->imageText, l->pPath[0], strerror(errno));
-
- /* if the user provided the path by hand, warn him. */
- if (forcedPath != NULL)
- dwarning("ignoring non-existing %s image", l->imageText);
-
- imageLoader_setPath(l, NULL);
- }
-}
-
-/* find the correct path of all image files we're going to need
- * and lock the files that need it.
- */
-static int
-_getImagePaths(AvdInfo* i, AvdInfoParams* params )
-{
- int wipeData = (params->flags & AVDINFO_WIPE_DATA) != 0;
- int wipeCache = (params->flags & AVDINFO_WIPE_CACHE) != 0;
- int noCache = (params->flags & AVDINFO_NO_CACHE) != 0;
- int noSdCard = (params->flags & AVDINFO_NO_SDCARD) != 0;
-#if CONFIG_ANDROID_SNAPSHOTS
- int noSnapshots = (params->flags & AVDINFO_NO_SNAPSHOTS) != 0;
-#endif
-
- ImageLoader l[1];
-
- imageLoader_init(l, i, params);
-
- /* pick up the kernel and ramdisk image files - these don't
- * need a specific handling.
- */
- imageLoader_set ( l, AVD_IMAGE_KERNEL );
- imageLoader_load( l, IMAGE_REQUIRED | IMAGE_SEARCH_SDK | IMAGE_DONT_LOCK );
-
- imageLoader_set ( l, AVD_IMAGE_RAMDISK );
- imageLoader_load( l, IMAGE_REQUIRED | IMAGE_SEARCH_SDK | IMAGE_DONT_LOCK );
-
- /* the system image
- *
- * if there is one in the content directory just lock
- * and use it.
- */
- imageLoader_set ( l, AVD_IMAGE_INITSYSTEM );
- imageLoader_load( l, IMAGE_REQUIRED | IMAGE_SEARCH_SDK | IMAGE_DONT_LOCK );
-
- /* the data partition - this one is special because if it
- * is missing, we need to copy the initial image file into it.
- *
- * first, try to see if it is in the content directory
- * (or the user-provided path)
- */
- imageLoader_set( l, AVD_IMAGE_USERDATA );
- if ( !imageLoader_load( l, IMAGE_OPTIONAL |
- IMAGE_DONT_LOCK ) )
- {
- /* it's not, we're going to initialize it. simply
- * forcing a data wipe should be enough */
- D("initializing new data partition image: %s", l->pPath[0]);
- wipeData = 1;
- }
-
- if (wipeData) {
- /* find SDK source file */
- const char* srcPath;
-
- imageLoader_set( l, AVD_IMAGE_INITDATA );
- if (imageLoader_lookupSdk(l) == NULL) {
- derror("can't locate initial %s image in SDK",
- l->imageText);
- exit(2);
+ p = bufprint(temp, end, "%s/%s", rootPath, fileName);
+ if (p >= end) {
+ return NULL;
}
- srcPath = imageLoader_extractPath(l);
-
- imageLoader_set( l, AVD_IMAGE_USERDATA );
- imageLoader_copyFrom( l, srcPath );
- AFREE((char*) srcPath);
+ return ASTRDUP(temp);
}
- else
- {
- /* lock the data partition image */
- l->pState[0] = IMAGE_STATE_MUSTLOCK;
- imageLoader_lock( l, 0 );
- }
-
- /* the cache partition: unless the user doesn't want one,
- * we're going to create it in the content directory
- */
- if (!noCache) {
- imageLoader_set (l, AVD_IMAGE_CACHE);
- imageLoader_load(l, IMAGE_OPTIONAL |
- IMAGE_EMPTY_IF_MISSING );
-
- if (wipeCache) {
- if (path_empty_file(l->pPath[0]) < 0) {
- derror("cannot wipe %s image at %s: %s",
- l->imageText, l->pPath[0],
- strerror(errno));
- exit(2);
- }
- }
- }
-
- /* the SD Card image. unless the user doesn't want to, we're
- * going to mount it if available. Note that if the image is
- * already used, we must ignore it.
- */
- if (!noSdCard) {
- imageLoader_loadOptional(l, AVD_IMAGE_SDCARD,
- params->forcePaths[AVD_IMAGE_SDCARD]);
- }
-
-#if CONFIG_ANDROID_SNAPSHOTS
- /* the state snapshot image. Mounting behaviour identical to
- * SD card.
- */
- if (!noSnapshots) {
- imageLoader_loadOptional(l, AVD_IMAGE_SNAPSHOTS,
- params->forcePaths[AVD_IMAGE_SNAPSHOTS]);
- }
-#endif
-
- return 0;
}
/* check that a given directory contains a valid skin.
@@ -837,39 +457,35 @@
return 1;
}
-/* check that there is a skin named 'skinName' listed from 'skinDirRoot'
- * this returns 1 on success, 0 on failure
- * on success, the 'temp' buffer will get the path containing the real
- * skin directory (after alias expansion), including the skin name.
+/* Check that there is a skin named 'skinName' listed from 'skinDirRoot'
+ * this returns the full path of the skin directory (after alias expansions),
+ * including the skin name, or NULL on failure.
*/
-static int
-_checkSkinDir( char* temp,
- char* end,
- const char* skinDirRoot,
+static char*
+_checkSkinSkinsDir( const char* skinDirRoot,
const char* skinName )
{
DirScanner* scanner;
- char *p;
- int result;
+ char* result;
+ char temp[MAX_PATH], *p = temp, *end = p + sizeof(temp);
- p = bufprint(temp, end, "%s/skins/%s",
- skinDirRoot, skinName);
-
+ p = bufprint(temp, end, "%s/skins/%s", skinDirRoot, skinName);
+ DD("Probing skin directory: %s", temp);
if (p >= end || !path_exists(temp)) {
DD(" ignore bad skin directory %s", temp);
- return 0;
+ return NULL;
}
/* first, is this a normal skin directory ? */
if (_checkSkinPath(temp)) {
/* yes */
DD(" found skin directory: %s", temp);
- return 1;
+ return ASTRDUP(temp);
}
/* second, is it an alias to another skin ? */
*p = 0;
- result = 0;
+ result = NULL;
scanner = dirScanner_new(temp);
if (scanner != NULL) {
for (;;) {
@@ -881,14 +497,12 @@
if (strncmp(file, "alias-", 6) || file[6] == 0)
continue;
- p = bufprint(temp, end, "%s/skins/%s",
- skinDirRoot, file+6);
-
+ p = bufprint(temp, end, "%s/skins/%s", skinDirRoot, file+6);
if (p < end && _checkSkinPath(temp)) {
/* yes, it's an alias */
DD(" skin alias '%s' points to skin directory: %s",
file+6, temp);
- result = 1;
+ result = ASTRDUP(temp);
break;
}
}
@@ -899,10 +513,14 @@
/* try to see if the skin name leads to a magic skin or skin path directly
* returns 1 on success, 0 on error.
- * on success, this sets up 'skinDirPath' and 'skinName' in the AvdInfo.
+ *
+ * on success, this sets up '*pSkinName' and '*pSkinDir'
*/
static int
-_getSkinPathFromName( AvdInfo* i, const char* skinName )
+_getSkinPathFromName( const char* skinName,
+ const char* sdkRootPath,
+ char** pSkinName,
+ char** pSkinDir )
{
char temp[PATH_MAX], *p=temp, *end=p+sizeof(temp);
@@ -914,19 +532,19 @@
int width, height;
if (sscanf(skinName, "%dx%d", &width, &height) == 2) {
D("'magic' skin format detected: %s", skinName);
- i->skinName = ASTRDUP(skinName);
- i->skinDirPath = NULL;
+ *pSkinName = ASTRDUP(skinName);
+ *pSkinDir = NULL;
return 1;
}
}
/* is the skin name a direct path to the skin directory ? */
- if (_checkSkinPath(skinName)) {
+ if (path_is_absolute(skinName) && _checkSkinPath(skinName)) {
goto FOUND_IT;
}
/* is the skin name a relative path from the SDK root ? */
- p = bufprint(temp, end, "%s/%s", i->sdkRootPath, skinName);
+ p = bufprint(temp, end, "%s/%s", sdkRootPath, skinName);
if (p < end && _checkSkinPath(temp)) {
skinName = temp;
goto FOUND_IT;
@@ -936,156 +554,230 @@
return 0;
FOUND_IT:
- if (path_split(skinName, &i->skinDirPath, &i->skinName) < 0) {
+ if (path_split(skinName, pSkinDir, pSkinName) < 0) {
derror("malformed skin name: %s", skinName);
exit(2);
}
- D("found skin '%s' in directory: %s", i->skinName, i->skinDirPath);
+ D("found skin '%s' in directory: %s", *pSkinName, *pSkinDir);
return 1;
}
-/* return 0 on success, -1 on error */
+/***************************************************************
+ ***************************************************************
+ *****
+ ***** NORMAL VIRTUAL DEVICE SUPPORT
+ *****
+ *****/
+
+/* compute path to the root SDK directory
+ * assume we are in $SDKROOT/tools/emulator[.exe]
+ */
static int
-_getSkin( AvdInfo* i, AvdInfoParams* params )
+_avdInfo_getSdkRoot( AvdInfo* i )
{
- char* skinName;
- char temp[PATH_MAX], *p=temp, *end=p+sizeof(temp);
- char explicitSkin = 1;
- /* this function is used to compute the 'skinName' and 'skinDirPath'
- * fields of the AvdInfo.
- */
-
- /* processing here is a bit tricky, so here's how it happens
- *
- * - command-line option '-skin <name>' can be used to specify the
- * name of a skin, to override the AVD settings.
- *
- * - skins are searched from <dir>/../skins for each <dir> in the
- * images search list, unless a '-skindir <path>' option has been
- * provided on the command-line
- *
- * - otherwise, the config.ini can also contain a SKIN_PATH key that
- * shall give the full path to the skin directory, either relative
- * to the SDK root, or an absolute path.
- *
- * - skin names like '320x480' corresponds to "magic skins" that
- * simply display a framebuffer, without any ornaments of the
- * corresponding size. They do not correspond to any real skin
- * directory / files and are handled later. But they must be
- * recognized here and report a NULL skindir.
- */
- if (params->skinName) {
- skinName = ASTRDUP(params->skinName);
- } else {
- skinName = iniFile_getString( i->configIni, SKIN_PATH, NULL );
- explicitSkin = 0;
- }
-
- /* first, check that the skin name is not magic or a direct
- * directory path
- */
- if (skinName != NULL && _getSkinPathFromName(i, skinName)) {
- AFREE(skinName);
- return 0;
- }
-
- /* if not, the default skinName is "HVGA" */
- if (skinName == NULL) {
- skinName = ASTRDUP(SKIN_DEFAULT);
- explicitSkin = 0;
- }
-
- i->skinName = skinName;
-
- /* now try to find the skin directory for that name -
- * first try the content directory */
- do {
- /* if there is a single 'skin' directory in
- * the content directory, assume that's what the
- * user wants, unless an explicit name was given
- */
- if (!explicitSkin) {
- p = bufprint(temp, end, "%s/skin", i->contentPath);
- if (p < end && _checkSkinPath(temp)) {
- D("using skin content from %s", temp);
- AFREE(i->skinName);
- i->skinName = ASTRDUP("skin");
- i->skinDirPath = ASTRDUP(i->contentPath);
- return 0;
- }
- }
-
- /* look in content directory */
- if (_checkSkinDir(temp, end, i->contentPath, skinName))
- break;
-
- /* look in the search paths. For each <dir> in the list,
- * look the skins in <dir>/.. */
- {
- int nn;
- for (nn = 0; nn < i->numSearchPaths; nn++) {
- char* parentDir = path_parent(i->searchPaths[nn], 1);
- int ret;
- if (parentDir == NULL)
- continue;
- ret=_checkSkinDir(temp, end, parentDir, skinName);
- AFREE(parentDir);
- if (ret)
- break;
- }
- if (nn < i->numSearchPaths)
- break;
- }
-
- /* didn't find it */
- if (explicitSkin) {
- derror("could not find directory for skin '%s',"
- " please use a different name", skinName);
- exit(2);
- } else {
- dwarning("no skin directory matched '%s', so reverted to default",
- skinName);
- AFREE(i->skinName);
- params->skinName = SKIN_DEFAULT;
- return _getSkin(i, params);
- }
-
+ i->sdkRootPath = _getSdkRoot(&i->sdkRootPathFromEnv);
+ if (i->sdkRootPath == NULL)
return -1;
- } while (0);
-
- /* separate skin name from parent directory. the skin name
- * returned in 'temp' might be different from the original
- * one due to alias expansion so strip it.
- */
- AFREE(i->skinName);
-
- if (path_split(temp, &i->skinDirPath, &i->skinName) < 0) {
- derror("weird skin path: %s", temp);
- return -1;
- }
- DD("found skin '%s' in directory: %s", i->skinName, i->skinDirPath);
return 0;
}
-/* If the user didn't explicitely provide an SD Card path,
- * check the SDCARD_PATH key in config.ini and use that if
- * available.
+/* parse the root config .ini file. it is located in
+ * ~/.android/avd/<name>.ini or Windows equivalent
+ */
+static int
+_avdInfo_getRootIni( AvdInfo* i )
+{
+ char* iniPath = _getRootIniPath( i->deviceName );
+
+ if (iniPath == NULL) {
+ derror("unknown virtual device name: '%s'", i->deviceName);
+ return -1;
+ }
+
+ D("Android virtual device file at: %s", iniPath);
+
+ i->rootIni = iniFile_newFromFile(iniPath);
+ AFREE(iniPath);
+
+ if (i->rootIni == NULL) {
+ derror("Corrupt virtual device config file!");
+ return -1;
+ }
+ return 0;
+}
+
+/* Returns the AVD's content path, i.e. the directory that contains
+ * the AVD's content files (e.g. data partition, cache, sd card, etc...).
+ *
+ * We extract this by parsing the root config .ini file, looking for
+ * a "path" elements.
+ */
+static int
+_avdInfo_getContentPath( AvdInfo* i )
+{
+# define ROOT_PATH_KEY "path"
+
+ i->contentPath = iniFile_getString(i->rootIni, ROOT_PATH_KEY, NULL);
+
+ if (i->contentPath == NULL) {
+ derror("bad config: %s",
+ "virtual device file lacks a "ROOT_PATH_KEY" entry");
+ return -1;
+ }
+ D("virtual device content at %s", i->contentPath);
+ return 0;
+}
+
+/* Look for a named file inside the AVD's content directory.
+ * Returns NULL if it doesn't exist, or a strdup() copy otherwise.
+ */
+static char*
+_avdInfo_getContentFilePath(AvdInfo* i, const char* fileName)
+{
+ char temp[MAX_PATH], *p = temp, *end = p + sizeof(temp);
+
+ p = bufprint(p, end, "%s/%s", i->contentPath, fileName);
+ if (p >= end) {
+ derror("can't access virtual device content directory");
+ return NULL;
+ }
+ if (!path_exists(temp)) {
+ return NULL;
+ }
+ return ASTRDUP(temp);
+}
+
+/* find and parse the config.ini file from the content directory */
+static int
+_avdInfo_getConfigIni(AvdInfo* i)
+{
+ char* iniPath = _avdInfo_getContentFilePath(i, "config.ini");
+
+ /* Allow non-existing config.ini */
+ if (iniPath == NULL) {
+ D("virtual device has no config file - no problem");
+ return 0;
+ }
+
+ D("virtual device config file: %s", iniPath);
+ i->configIni = iniFile_newFromFile(iniPath);
+ AFREE(iniPath);
+
+ if (i->configIni == NULL) {
+ derror("bad config: %s",
+ "virtual device has corrupted config.ini");
+ return -1;
+ }
+ return 0;
+}
+
+/* The AVD's config.ini contains a list of search paths (all beginning
+ * with SEARCH_PREFIX) which are directory locations searched for
+ * AVD platform files.
*/
static void
-_getSDCardPath( AvdInfo* i, AvdInfoParams* params )
+_avdInfo_getSearchPaths( AvdInfo* i )
{
- const char* path;
-
- if (params->forcePaths[AVD_IMAGE_SDCARD] != NULL)
+ if (i->configIni == NULL)
return;
- path = iniFile_getString(i->configIni, SDCARD_PATH, NULL);
+ i->numSearchPaths = _getSearchPaths( i->configIni,
+ i->sdkRootPath,
+ MAX_SEARCH_PATHS,
+ i->searchPaths );
+ if (i->numSearchPaths == 0) {
+ derror("no search paths found in this AVD's configuration.\n"
+ "Weird, the AVD's config.ini file is malformed. Try re-creating it.\n");
+ exit(2);
+ }
+ else
+ DD("found a total of %d search paths for this AVD", i->numSearchPaths);
+}
+
+/* Search a file in the SDK search directories. Return NULL if not found,
+ * or a strdup() otherwise.
+ */
+static char*
+_avdInfo_getSdkFilePath(AvdInfo* i, const char* fileName)
+{
+ char temp[MAX_PATH], *p = temp, *end = p + sizeof(temp);
+
+ do {
+ /* try the search paths */
+ int nn;
+
+ for (nn = 0; nn < i->numSearchPaths; nn++) {
+ const char* searchDir = i->searchPaths[nn];
+
+ p = bufprint(temp, end, "%s/%s", searchDir, fileName);
+ if (p < end && path_exists(temp)) {
+ DD("found %s in search dir: %s", fileName, searchDir);
+ goto FOUND;
+ }
+ DD(" no %s in search dir: %s", fileName, searchDir);
+ }
+
+ return NULL;
+
+ } while (0);
+
+FOUND:
+ return ASTRDUP(temp);
+}
+
+/* Search for a file in the content directory, and if not found, in the
+ * SDK search directory. Returns NULL if not found.
+ */
+static char*
+_avdInfo_getContentOrSdkFilePath(AvdInfo* i, const char* fileName)
+{
+ char* path;
+
+ path = _avdInfo_getContentFilePath(i, fileName);
+ if (path)
+ return path;
+
+ path = _avdInfo_getSdkFilePath(i, fileName);
+ if (path)
+ return path;
+
+ return NULL;
+}
+
+#if 0
+static int
+_avdInfo_findContentOrSdkImage(AvdInfo* i, AvdImageType id)
+{
+ const char* fileName = _imageFileNames[id];
+ char* path = _avdInfo_getContentOrSdkFilePath(i, fileName);
+
+ i->imagePath[id] = path;
+ i->imageState[id] = IMAGE_STATE_READONLY;
+
if (path == NULL)
- return;
+ return -1;
+ else
+ return 0;
+}
+#endif
- params->forcePaths[AVD_IMAGE_SDCARD] = path;
+/* Returns path to the core hardware .ini file. This contains the
+ * hardware configuration that is read by the core. The content of this
+ * file is auto-generated before launching a core, but we need to know
+ * its path before that.
+ */
+static int
+_avdInfo_getCoreHwIniPath( AvdInfo* i, const char* basePath )
+{
+ i->coreHardwareIniPath = _getFullFilePath(basePath, CORE_HARDWARE_INI);
+ if (i->coreHardwareIniPath == NULL) {
+ DD("Path too long for %s: %s", CORE_HARDWARE_INI, basePath);
+ return -1;
+ }
+ D("using core hw config path: %s", i->coreHardwareIniPath);
+ return 0;
}
AvdInfo*
@@ -1104,26 +796,22 @@
ANEW0(i);
i->deviceName = ASTRDUP(name);
- if ( _getSdkRoot(i) < 0 ||
- _getRootIni(i) < 0 ||
- _getContentPath(i) < 0 ||
- _getConfigIni(i) < 0 )
+ if ( _avdInfo_getSdkRoot(i) < 0 ||
+ _avdInfo_getRootIni(i) < 0 ||
+ _avdInfo_getContentPath(i) < 0 ||
+ _avdInfo_getConfigIni(i) < 0 ||
+ _avdInfo_getCoreHwIniPath(i, i->contentPath) < 0 )
goto FAIL;
/* look for image search paths. handle post 1.1/pre cupcake
* obsolete SDKs.
*/
- _getSearchPaths(i);
- _getSDCardPath(i, params);
+ _avdInfo_getSearchPaths(i);
/* don't need this anymore */
iniFile_free(i->rootIni);
i->rootIni = NULL;
- if ( _getImagePaths(i, params) < 0 ||
- _getSkin (i, params) < 0 )
- goto FAIL;
-
return i;
FAIL:
@@ -1155,246 +843,32 @@
***** the content directory, no SDK images search path.
*****/
-/* used to fake a config.ini located in the content directory */
-static int
-_getBuildConfigIni( AvdInfo* i )
-{
- /* a blank file is ok at the moment */
- i->configIni = iniFile_newFromMemory( "", 0 );
- return 0;
-}
-
-static int
-_getBuildImagePaths( AvdInfo* i, AvdInfoParams* params )
-{
- int wipeData = (params->flags & AVDINFO_WIPE_DATA) != 0;
- int noCache = (params->flags & AVDINFO_NO_CACHE) != 0;
- int noSdCard = (params->flags & AVDINFO_NO_SDCARD) != 0;
-#if CONFIG_ANDROID_SNAPSHOTS
- int noSnapshots = (params->flags & AVDINFO_NO_SNAPSHOTS) != 0;
-#endif
-
- char temp[PATH_MAX], *p=temp, *end=p+sizeof temp;
- char* srcData;
- ImageLoader l[1];
-
- imageLoader_init(l, i, params);
-
- /** load the kernel image
- **/
-
- /* if it is not in the out directory, get it from prebuilt
- */
- imageLoader_set ( l, AVD_IMAGE_KERNEL );
-
- if ( !imageLoader_load( l, IMAGE_OPTIONAL |
- IMAGE_DONT_LOCK ) )
- {
-#ifdef TARGET_ARM
-#define PREBUILT_KERNEL_PATH "prebuilt/android-arm/kernel/kernel-qemu"
-#endif
-#ifdef TARGET_I386
-#define PREBUILT_KERNEL_PATH "prebuilt/android-x86/kernel/kernel-qemu"
-#endif
- p = bufprint(temp, end, "%s/%s", i->androidBuildRoot,
- PREBUILT_KERNEL_PATH);
- if (p >= end || !path_exists(temp)) {
- derror("bad workspace: cannot find prebuilt kernel in: %s", temp);
- exit(1);
- }
- imageLoader_setPath(l, temp);
- }
-
- /** load the data partition. note that we use userdata-qemu.img
- ** since we don't want to modify userdata.img at all
- **/
- imageLoader_set ( l, AVD_IMAGE_USERDATA );
- imageLoader_load( l, IMAGE_OPTIONAL | IMAGE_DONT_LOCK );
-
- /* get the path of the source file, and check that it actually exists
- * if the user didn't provide an explicit data file
- */
- srcData = imageLoader_extractPath(l);
- if (srcData == NULL && params->forcePaths[AVD_IMAGE_USERDATA] == NULL) {
- derror("There is no %s image in your build directory. Please make a full build",
- l->imageText, l->imageFile);
- exit(2);
- }
-
- /* get the path of the target file */
- l->imageFile = "userdata-qemu.img";
- imageLoader_load( l, IMAGE_OPTIONAL |
- IMAGE_EMPTY_IF_MISSING |
- IMAGE_IGNORE_IF_LOCKED );
-
- /* force a data wipe if we just created the image */
- if (l->pState[0] == IMAGE_STATE_LOCKED_EMPTY)
- wipeData = 1;
-
- /* if the image was already locked, create a temp file
- * then force a data wipe.
- */
- if (l->pPath[0] == NULL) {
- TempFile* temp = tempfile_create();
- imageLoader_setPath(l, tempfile_path(temp));
- dwarning( "Another emulator is running. user data changes will *NOT* be saved");
- wipeData = 1;
- }
-
- /* in the case of a data wipe, copy userdata.img into
- * the destination */
- if (wipeData) {
- if (srcData == NULL || !path_exists(srcData)) {
- derror("There is no %s image in your build directory. Please make a full build",
- l->imageText, _imageFileNames[l->id]);
- exit(2);
- }
- if (path_copy_file( l->pPath[0], srcData ) < 0) {
- derror("could not initialize %s image from %s: %s",
- l->imageText, temp, strerror(errno));
- exit(2);
- }
- }
-
- AFREE(srcData);
-
- /** load the ramdisk image
- **/
- imageLoader_set ( l, AVD_IMAGE_RAMDISK );
- imageLoader_load( l, IMAGE_REQUIRED |
- IMAGE_DONT_LOCK );
-
- /** load the system image. read-only. the caller must
- ** take care of checking the state
- **/
- imageLoader_set ( l, AVD_IMAGE_INITSYSTEM );
- imageLoader_load( l, IMAGE_REQUIRED | IMAGE_DONT_LOCK );
-
- /* force the system image to read-only status */
- l->pState[0] = IMAGE_STATE_READONLY;
-
- /** cache partition handling
- **/
- if (!noCache) {
- imageLoader_set (l, AVD_IMAGE_CACHE);
-
- /* if the user provided one cache image, lock & use it */
- if ( params->forcePaths[l->id] != NULL ) {
- imageLoader_load(l, IMAGE_REQUIRED |
- IMAGE_IGNORE_IF_LOCKED);
- }
- }
-
- /** SD Card image
- **/
- if (!noSdCard) {
- imageLoader_set (l, AVD_IMAGE_SDCARD);
- imageLoader_load(l, IMAGE_OPTIONAL | IMAGE_IGNORE_IF_LOCKED);
- }
-
-#if CONFIG_ANDROID_SNAPSHOTS
- /** State snapshots image
- **/
- if (!noSnapshots) {
- imageLoader_set (l, AVD_IMAGE_SNAPSHOTS);
- imageLoader_load(l, IMAGE_OPTIONAL | IMAGE_IGNORE_IF_LOCKED);
- }
-#endif
-
- return 0;
-}
-
-static int
-_getBuildSkin( AvdInfo* i, AvdInfoParams* params )
-{
- /* the (current) default skin name for our build system */
- const char* skinName = params->skinName;
- const char* skinDir = params->skinRootPath;
- char temp[PATH_MAX], *p=temp, *end=p+sizeof(temp);
- char* q;
-
- if (!skinName) {
- /* the (current) default skin name for the build system */
- skinName = SKIN_DEFAULT;
- D("selecting default skin name '%s'", skinName);
- }
-
- if (!skinDir) {
-
-#define PREBUILT_SKINS_DIR "development/tools/emulator/skins"
-#define PRODUCT_SKIN_DIR "skin"
-
- do {
- /* look for the product skin in $ANDROID_PRODUCT_OUT/skin if no skin name is defined */
- if (!params->skinName) {
- /* look for <product_out>/skin first */
- p = bufprint( temp, end, "%s/skin",
- i->androidOut );
- if (path_exists(temp)) {
- p = bufprint( temp, end, "%s",
- i->androidOut );
- skinName = PRODUCT_SKIN_DIR;
- D("selecting default product skin at '%s/%s'", temp, skinName);
- break;
- }
- }
-
- /* next try in <sysdir>/../skins */
- p = bufprint( temp, end, "%s/../skins",
- i->androidBuildRoot );
- if (path_exists(temp))
- break;
-
- /* the (current) default skin directory */
- p = bufprint( temp, end, "%s/%s",
- i->androidBuildRoot, PREBUILT_SKINS_DIR );
- } while (0);
-
- } else {
- p = bufprint( temp, end, "%s", skinDir );
- }
-
- i->skinName = ASTRDUP(skinName);
-
- q = bufprint(p, end, "/%s/layout", skinName);
- if (q >= end || !path_exists(temp)) {
- DD("skin content directory does not exist: %s", temp);
- if (skinDir)
- dwarning("could not find valid skin '%s' in %s:\n",
- skinName, temp);
- return -1;
- }
- *p = 0;
- DD("found skin path: %s", temp);
- i->skinDirPath = ASTRDUP(temp);
-
- return 0;
-}
-
/* Read a hardware.ini if it is located in the skin directory */
static int
-_getBuildHardwareIni( AvdInfo* i )
+_avdInfo_getBuildSkinHardwareIni( AvdInfo* i )
{
+ char* skinName;
+ char* skinDirPath;
char temp[PATH_MAX], *p=temp, *end=p+sizeof(temp);
- if (i->skinDirPath == NULL || i->skinName == NULL)
+ avdInfo_getSkinInfo(i, &skinName, &skinDirPath);
+ if (skinDirPath == NULL)
return 0;
- p = bufprint(temp, end, "%s/%s/hardware.ini", i->skinDirPath, i->skinName);
+ p = bufprint(temp, end, "%s/%s/hardware.ini", skinDirPath, skinName);
if (p >= end || !path_exists(temp)) {
- DD("no skin-specific hardware.ini in %s", i->skinDirPath);
+ DD("no skin-specific hardware.ini in %s", skinDirPath);
return 0;
}
D("found skin-specific hardware.ini: %s", temp);
- i->hardwareIni = iniFile_newFromFile(temp);
- if (i->hardwareIni == NULL)
+ i->skinHardwareIni = iniFile_newFromFile(temp);
+ if (i->skinHardwareIni == NULL)
return -1;
return 0;
}
-
AvdInfo*
avdInfo_newForAndroidBuild( const char* androidBuildRoot,
const char* androidOut,
@@ -1408,17 +882,19 @@
i->androidBuildRoot = ASTRDUP(androidBuildRoot);
i->androidOut = ASTRDUP(androidOut);
i->contentPath = ASTRDUP(androidOut);
+ i->targetArch = ASTRDUP(_getBuildTargetArch(i->androidOut));
/* TODO: find a way to provide better information from the build files */
i->deviceName = ASTRDUP("<build>");
- if (_getBuildConfigIni(i) < 0 ||
- _getBuildImagePaths(i, params) < 0 )
+ /* There is no config.ini in the build */
+ i->configIni = NULL;
+
+ if (_avdInfo_getCoreHwIniPath(i, i->androidOut) < 0 )
goto FAIL;
- /* we don't need to fail if there is no valid skin */
- _getBuildSkin(i, params);
- _getBuildHardwareIni(i);
+ /* Read the build skin's hardware.ini, if any */
+ _avdInfo_getBuildSkinHardwareIni(i);
return i;
@@ -1466,16 +942,113 @@
return (i->imageState[imageType] == IMAGE_STATE_READONLY);
}
-const char*
-avdInfo_getSkinName( AvdInfo* i )
+char*
+avdInfo_getKernelPath( AvdInfo* i )
{
- return i->skinName;
+ const char* imageName = _imageFileNames[ AVD_IMAGE_KERNEL ];
+
+ char* kernelPath = _avdInfo_getContentOrSdkFilePath(i, imageName);
+
+ if (kernelPath == NULL && i->inAndroidBuild) {
+ /* When in the Android build, look into the prebuilt directory
+ * for our target architecture.
+ */
+ char temp[PATH_MAX], *p = temp, *end = p + sizeof(temp);
+
+ p = bufprint(temp, end, "%s/prebuilt/android-%s/kernel/kernel-qemu",
+ i->androidBuildRoot, i->targetArch);
+ if (p >= end || !path_exists(temp)) {
+ derror("bad workspace: cannot find prebuilt kernel in: %s", temp);
+ exit(1);
+ }
+ kernelPath = ASTRDUP(temp);
+ }
+ return kernelPath;
}
-const char*
-avdInfo_getSkinDir ( AvdInfo* i )
+
+char*
+avdInfo_getRamdiskPath( AvdInfo* i )
{
- return i->skinDirPath;
+ const char* imageName = _imageFileNames[ AVD_IMAGE_RAMDISK ];
+ return _avdInfo_getContentOrSdkFilePath(i, imageName);
+}
+
+char* avdInfo_getCachePath( AvdInfo* i )
+{
+ const char* imageName = _imageFileNames[ AVD_IMAGE_CACHE ];
+ return _avdInfo_getContentFilePath(i, imageName);
+}
+
+char* avdInfo_getDefaultCachePath( AvdInfo* i )
+{
+ const char* imageName = _imageFileNames[ AVD_IMAGE_CACHE ];
+ return _getFullFilePath(i->contentPath, imageName);
+}
+
+char* avdInfo_getSdCardPath( AvdInfo* i )
+{
+ const char* imageName = _imageFileNames[ AVD_IMAGE_SDCARD ];
+ char* path;
+
+ /* Special case, the config.ini can have a SDCARD_PATH entry
+ * that gives the full path to the SD Card.
+ */
+ if (i->configIni != NULL) {
+ path = iniFile_getString(i->configIni, SDCARD_PATH, NULL);
+ if (path != NULL) {
+ if (path_exists(path))
+ return path;
+
+ dwarning("Ignoring invalid SDCard path: %s", path);
+ AFREE(path);
+ }
+ }
+
+ /* Otherwise, simply look into the content directory */
+ return _avdInfo_getContentFilePath(i, imageName);
+}
+
+char*
+avdInfo_getSnapStoragePath( AvdInfo* i )
+{
+ const char* imageName = _imageFileNames[ AVD_IMAGE_SNAPSHOTS ];
+ return _avdInfo_getContentFilePath(i, imageName);
+}
+
+char*
+avdInfo_getSystemImagePath( AvdInfo* i )
+{
+ const char* imageName = _imageFileNames[ AVD_IMAGE_USERSYSTEM ];
+ return _avdInfo_getContentFilePath(i, imageName);
+}
+
+char*
+avdInfo_getSystemInitImagePath( AvdInfo* i )
+{
+ const char* imageName = _imageFileNames[ AVD_IMAGE_INITSYSTEM ];
+ return _avdInfo_getContentOrSdkFilePath(i, imageName);
+}
+
+char*
+avdInfo_getDataImagePath( AvdInfo* i )
+{
+ const char* imageName = _imageFileNames[ AVD_IMAGE_USERDATA ];
+ return _avdInfo_getContentFilePath(i, imageName);
+}
+
+char*
+avdInfo_getDefaultDataImagePath( AvdInfo* i )
+{
+ const char* imageName = _imageFileNames[ AVD_IMAGE_USERDATA ];
+ return _getFullFilePath(i->contentPath, imageName);
+}
+
+char*
+avdInfo_getDataInitImagePath( AvdInfo* i )
+{
+ const char* imageName = _imageFileNames[ AVD_IMAGE_INITDATA ];
+ return _avdInfo_getContentOrSdkFilePath(i, imageName);
}
int
@@ -1492,8 +1065,8 @@
if (ini != i->configIni)
iniFile_free(ini);
- if (ret == 0 && i->hardwareIni != NULL) {
- ret = androidHwConfig_read(hw, i->hardwareIni);
+ if (ret == 0 && i->skinHardwareIni != NULL) {
+ ret = androidHwConfig_read(hw, i->skinHardwareIni);
}
/* special product-specific hardware configuration */
@@ -1539,3 +1112,113 @@
}
return ASTRDUP(tmp);
}
+
+const char*
+avdInfo_getCoreHwIniPath( AvdInfo* i )
+{
+ return i->coreHardwareIniPath;
+}
+
+
+void
+avdInfo_getSkinInfo( AvdInfo* i, char** pSkinName, char** pSkinDir )
+{
+ char* skinName = NULL;
+ char* skinPath;
+ char temp[PATH_MAX], *p=temp, *end=p+sizeof(temp);
+
+ *pSkinName = NULL;
+ *pSkinDir = NULL;
+
+ /* First, see if the config.ini contains a SKIN_PATH entry that
+ * names the full directory path for the skin.
+ */
+ if ( i->configIni != NULL ) {
+ skinPath = iniFile_getString( i->configIni, SKIN_PATH, NULL );
+ if (skinPath != NULL) {
+ /* If this skin name is magic or a direct directory path
+ * we have our result right here.
+ */
+ if (_getSkinPathFromName(skinPath, i->sdkRootPath,
+ pSkinName, pSkinDir )) {
+ AFREE(skinPath);
+ return;
+ }
+ }
+
+ /* The SKIN_PATH entry was not valid, so look at SKIN_NAME */
+ D("Warning: config.ini contains invalid %s entry: %s", SKIN_PATH, skinPath);
+ AFREE(skinPath);
+
+ skinName = iniFile_getString( i->configIni, SKIN_NAME, NULL );
+ }
+
+ if (skinName == NULL) {
+ /* If there is no skin listed in the config.ini, try to see if
+ * there is one single 'skin' directory in the content directory.
+ */
+ p = bufprint(temp, end, "%s/skin", i->contentPath);
+ if (p < end && _checkSkinPath(temp)) {
+ D("using skin content from %s", temp);
+ AFREE(i->skinName);
+ *pSkinName = ASTRDUP("skin");
+ *pSkinDir = ASTRDUP(i->contentPath);
+ return;
+ }
+
+ /* otherwise, use the default name */
+ skinName = ASTRDUP(SKIN_DEFAULT);
+ }
+
+ /* now try to find the skin directory for that name -
+ */
+ do {
+ /* first try the content directory, i.e. $CONTENT/skins/<name> */
+ skinPath = _checkSkinSkinsDir(i->contentPath, skinName);
+ if (skinPath != NULL)
+ break;
+
+#define PREBUILT_SKINS_ROOT "development/tools/emulator"
+
+ /* if we are in the Android build, try the prebuilt directory */
+ if (i->inAndroidBuild) {
+ p = bufprint( temp, end, "%s/%s",
+ i->androidBuildRoot, PREBUILT_SKINS_ROOT );
+ if (p < end) {
+ skinPath = _checkSkinSkinsDir(temp, skinName);
+ if (skinPath != NULL)
+ break;
+ }
+ }
+
+ /* look in the search paths. For each <dir> in the list,
+ * look into <dir>/../skins/<name>/ */
+ {
+ int nn;
+ for (nn = 0; nn < i->numSearchPaths; nn++) {
+ char* parentDir = path_parent(i->searchPaths[nn], 1);
+ if (parentDir == NULL)
+ continue;
+ skinPath = _checkSkinSkinsDir(parentDir, skinName);
+ AFREE(parentDir);
+ if (skinPath != NULL)
+ break;
+ }
+ if (nn < i->numSearchPaths)
+ break;
+ }
+
+ /* We didn't find anything ! */
+ return;
+
+ } while (0);
+
+ if (path_split(skinPath, pSkinDir, pSkinName) < 0) {
+ derror("weird skin path: %s", skinPath);
+ AFREE(skinPath);
+ return;
+ }
+ DD("found skin '%s' in directory: %s", *pSkinName, *pSkinDir);
+ AFREE(skinPath);
+ return;
+}
diff --git a/android/avd/info.h b/android/avd/info.h
index 2b2899f..aa3ddcd 100644
--- a/android/avd/info.h
+++ b/android/avd/info.h
@@ -47,11 +47,6 @@
*/
-#if CONFIG_ANDROID_SNAPSHOTS
-#define _AVD_IMG_SNAPSHOT _AVD_IMG(SNAPSHOTS,"snapshots.img","snapshots")
-#else
-#define _AVD_IMG_SNAPSHOT
-#endif
/* a macro used to define the list of disk images managed by the
* implementation. This macro will be expanded several times with
* varying definitions of _AVD_IMG
@@ -65,7 +60,7 @@
_AVD_IMG(USERDATA,"userdata-qemu.img", "user data") \
_AVD_IMG(CACHE,"cache.img","cache") \
_AVD_IMG(SDCARD,"sdcard.img","SD Card") \
- _AVD_IMG_SNAPSHOT \
+ _AVD_IMG(SNAPSHOTS,"snapshots.img","snapshots") \
/* define the enumared values corresponding to each AVD image type
* examples are: AVD_IMAGE_KERNEL, AVD_IMAGE_SYSTEM, etc..
@@ -94,10 +89,8 @@
AVDINFO_NO_SDCARD = (1 << 3),
/* use to wipe the system image with new initial values */
AVDINFO_WIPE_SYSTEM = (1 << 4),
-#if CONFIG_ANDROID_SNAPSHOTS
/* use to ignore ignore state snapshot image (default or provided) */
AVDINFO_NO_SNAPSHOTS = (1 << 5),
-#endif
} AvdFlags;
typedef struct {
@@ -137,6 +130,48 @@
*/
const char* avdInfo_getName( AvdInfo* i );
+/* Returns the path to various images corresponding to a given AVD.
+ * NULL if the image cannot be found. Returned strings must be freed
+ * by the caller.
+ */
+char* avdInfo_getKernelPath( AvdInfo* i );
+char* avdInfo_getRamdiskPath( AvdInfo* i );
+char* avdInfo_getSdCardPath( AvdInfo* i );
+char* avdInfo_getSnapStoragePath( AvdInfo* i );
+
+/* This function returns NULL if the cache image file cannot be found.
+ * Use avdInfo_getDefaultCachePath() to retrieve the default path
+ * if you intend to create the partition file there.
+ */
+char* avdInfo_getCachePath( AvdInfo* i );
+char* avdInfo_getDefaultCachePath( AvdInfo* i );
+
+
+/* avdInfo_getSystemImagePath() will return NULL, except if the AVD content
+ * directory contains a file named "system-qemu.img".
+ */
+char* avdInfo_getSystemImagePath( AvdInfo* i );
+
+/* avdInfo_getSystemInitImagePath() retrieves the path to the read-only
+ * initialization image for this disk image.
+ */
+char* avdInfo_getSystemInitImagePath( AvdInfo* i );
+
+char* avdInfo_getDataImagePath( AvdInfo* i );
+char* avdInfo_getDefaultDataImagePath( AvdInfo* i );
+char* avdInfo_getDataInitImagePath( AvdInfo* i );
+
+/* Returns the path to a given AVD image file. This will return NULL if
+ * the file cannot be found / does not exist.
+ */
+const char* avdInfo_getImagePath( AvdInfo* i, AvdImageType imageType );
+
+/* Returns the default path of a given AVD image file. This only makes sense
+ * if avdInfo_getImagePath() returned NULL.
+ */
+const char* avdInfo_getImageDefaultPath( AvdInfo* i, AvdImageType imageType );
+
+
/* Try to find the path of a given image file, returns NULL
* if the corresponding file could not be found. the string
* belongs to the AvdInfo object.
@@ -161,19 +196,18 @@
/* Manually set the path of a given image file. */
void avdInfo_setImageFile( AvdInfo* i, AvdImageType imageType, const char* imagePath );
-/* Returns the path of the skin directory */
-/* the string belongs to the AvdInfo object */
-const char* avdInfo_getSkinPath( AvdInfo* i );
-
-/* Returns the name of the virtual device's skin */
-const char* avdInfo_getSkinName( AvdInfo* i );
-
-/* Returns the root skin directory for this device */
-const char* avdInfo_getSkinDir ( AvdInfo* i );
-
/* Returns the content path of the virtual device */
const char* avdInfo_getContentPath( AvdInfo* i );
+/* Retrieve the AVD's specific skin information.
+ * On exit:
+ * '*pSkinName' points to the skin's name.
+ * '*pSkinDir' points to the skin's directory.
+ *
+ * Note that the skin's content will be under <skinDir>/<skinName>.
+ */
+void avdInfo_getSkinInfo( AvdInfo* i, char** pSkinName, char** pSkinDir );
+
/* Returns TRUE iff in the Android build system */
int avdInfo_inAndroidBuild( AvdInfo* i );
@@ -183,6 +217,12 @@
/* Returns a *copy* of the path used to store trace 'foo'. result must be freed by caller */
char* avdInfo_getTracePath( AvdInfo* i, const char* traceName );
+/* Returns the path of the hardware.ini where we will write the AVD's
+ * complete hardware configuration before launching the corresponding
+ * core.
+ */
+const char* avdInfo_getCoreHwIniPath( AvdInfo* i );
+
/* */
#endif /* ANDROID_AVD_INFO_H */
diff --git a/android/build/clear_vars.make b/android/build/clear_vars.make
index f4ca9b7..5cdce07 100644
--- a/android/build/clear_vars.make
+++ b/android/build/clear_vars.make
@@ -18,6 +18,7 @@
LOCAL_NO_DEFAULT_COMPILER_FLAGS:=
LOCAL_CC :=
LOCAL_CXX :=
+LOCAL_AR :=
LOCAL_CFLAGS :=
LOCAL_LDFLAGS :=
LOCAL_LDLIBS :=
diff --git a/android/build/definitions.make b/android/build/definitions.make
index ab9a34d..e31131b 100644
--- a/android/build/definitions.make
+++ b/android/build/definitions.make
@@ -55,7 +55,7 @@
OBJ:=$$(LOCAL_OBJS_DIR)/$$(SRC:%.c=%.o)
LOCAL_OBJECTS += $$(OBJ)
DEPENDENCY_DIRS += $$(dir $$(OBJ))
-$$(OBJ): PRIVATE_CFLAGS := $$(CFLAGS) $$(LOCAL_CFLAGS) -I$$(LOCAL_PATH) -I$$(OBJS_DIR)
+$$(OBJ): PRIVATE_CFLAGS := $$(CFLAGS) $$(LOCAL_CFLAGS) -I$$(LOCAL_PATH) -I$$(LOCAL_OBJS_DIR)
$$(OBJ): PRIVATE_CC := $$(LOCAL_CC)
$$(OBJ): PRIVATE_OBJ := $$(OBJ)
$$(OBJ): PRIVATE_MODULE := $$(LOCAL_MODULE)
@@ -75,7 +75,7 @@
OBJ:=$$(LOCAL_OBJS_DIR)/$$(SRC:%$(LOCAL_CPP_EXTENSION)=%.o)
LOCAL_OBJECTS += $$(OBJ)
DEPENDENCY_DIRS += $$(dir $$(OBJ))
-$$(OBJ): PRIVATE_CFLAGS := $$(CFLAGS) $$(LOCAL_CFLAGS) -I$$(LOCAL_PATH) -I$$(OBJS_DIR)
+$$(OBJ): PRIVATE_CFLAGS := $$(CFLAGS) $$(LOCAL_CFLAGS) -I$$(LOCAL_PATH) -I$$(LOCAL_OBJS_DIR)
$$(OBJ): PRIVATE_CXX := $$(LOCAL_CC)
$$(OBJ): PRIVATE_OBJ := $$(OBJ)
$$(OBJ): PRIVATE_MODULE := $$(LOCAL_MODULE)
@@ -95,7 +95,7 @@
OBJ:=$$(LOCAL_OBJS_DIR)/$$(notdir $$(SRC:%.m=%.o))
LOCAL_OBJECTS += $$(OBJ)
DEPENDENCY_DIRS += $$(dir $$(OBJ))
-$$(OBJ): PRIVATE_CFLAGS := $$(CFLAGS) $$(LOCAL_CFLAGS) -I$$(LOCAL_PATH) -I$$(OBJS_DIR)
+$$(OBJ): PRIVATE_CFLAGS := $$(CFLAGS) $$(LOCAL_CFLAGS) -I$$(LOCAL_PATH) -I$$(LOCAL_OBJS_DIR)
$$(OBJ): PRIVATE_CC := $$(LOCAL_CC)
$$(OBJ): PRIVATE_OBJ := $$(OBJ)
$$(OBJ): PRIVATE_MODULE := $$(LOCAL_MODULE)
@@ -115,7 +115,7 @@
OBJ:=$$(LOCAL_OBJS_DIR)/$$(notdir $$(SRC:%.c=%.o))
LOCAL_OBJECTS += $$(OBJ)
DEPENDENCY_DIRS += $$(dir $$(OBJ))
-$$(OBJ): PRIVATE_CFLAGS := $$(CFLAGS) $$(LOCAL_CFLAGS) -I$$(LOCAL_PATH) -I$$(OBJS_DIR)
+$$(OBJ): PRIVATE_CFLAGS := $$(CFLAGS) $$(LOCAL_CFLAGS) -I$$(LOCAL_PATH) -I$$(LOCAL_OBJS_DIR)
$$(OBJ): PRIVATE_CC := $$(LOCAL_CC)
$$(OBJ): PRIVATE_OBJ := $$(OBJ)
$$(OBJ): PRIVATE_MODULE := $$(LOCAL_MODULE)
@@ -148,7 +148,7 @@
define copy-prebuilt-lib
_SRC := $(1)
_SRC1 := $$(notdir $$(_SRC))
-_DST := $$(OBJS_DIR)/$$(_SRC1)
+_DST := $$(LIBS_DIR)/$$(_SRC1)
LIBRARIES += $$(_DST)
$$(_DST): PRIVATE_DST := $$(_DST)
$$(_DST): PRIVATE_SRC := $$(_SRC)
diff --git a/android/build/host_static_library.make b/android/build/host_static_library.make
index 3de5a99..38ff625 100644
--- a/android/build/host_static_library.make
+++ b/android/build/host_static_library.make
@@ -22,7 +22,10 @@
LOCAL_CC ?= $(CC)
include $(BUILD_SYSTEM)/binary.make
-LOCAL_AR ?= $(AR)
+LOCAL_AR := $(strip $(LOCAL_AR))
+ifndef LOCAL_AR
+ LOCAL_AR := $(AR)
+endif
ARFLAGS := crs
$(LOCAL_BUILT_MODULE): PRIVATE_AR := $(LOCAL_AR)
diff --git a/android/cmdline-options.h b/android/cmdline-options.h
index 273d151..b7d7bfa 100644
--- a/android/cmdline-options.h
+++ b/android/cmdline-options.h
@@ -75,7 +75,6 @@
CFG_FLAG ( no_cache, "disable the cache partition" )
CFG_FLAG ( nocache, "same as -no-cache" )
OPT_PARAM( sdcard, "<file>", "SD card image (default <system>/sdcard.img")
-#if CONFIG_ANDROID_SNAPSHOTS
OPT_PARAM( snapstorage, "<file>", "file that contains all state snapshots (default <datadir>/snapshots.img)")
OPT_FLAG ( no_snapstorage, "do not mount a snapshot storage file (this disables all snapshot functionality)" )
OPT_PARAM( snapshot, "<name>", "name of snapshot within storage file for auto-start and auto-save (default 'default-boot')" )
@@ -84,8 +83,7 @@
OPT_FLAG ( no_snapshot_load, "do not auto-start from snapshot: perform a full boot" )
OPT_FLAG ( snapshot_list, "show a list of available snapshots" )
OPT_FLAG ( no_snapshot_update_time, "do not do try to correct snapshot time on restore" )
-#endif
-OPT_FLAG ( wipe_data, "reset the use data image (copy it from initdata)" )
+OPT_FLAG ( wipe_data, "reset the user data image (copy it from initdata)" )
CFG_PARAM( avd, "<name>", "use a specific android virtual device" )
CFG_PARAM( skindir, "<dir>", "search skins in <dir> (default <system>/skins)" )
CFG_PARAM( skin, "<name>", "select a given skin" )
@@ -133,7 +131,6 @@
OPT_PARAM( gps, "<device>", "redirect NMEA GPS to character device" )
OPT_PARAM( keyset, "<name>", "specify keyset file name" )
OPT_PARAM( shell_serial, "<device>", "specific character device for root shell" )
-OPT_FLAG ( old_system, "support old (pre 1.4) system images" )
OPT_PARAM( tcpdump, "<file>", "capture network packets to file" )
OPT_PARAM( bootchart, "<timeout>", "enable bootcharting")
diff --git a/android/config/config.h b/android/config/config.h
index fdfbe31..35cc9da 100644
--- a/android/config/config.h
+++ b/android/config/config.h
@@ -1,4 +1,9 @@
-/* Automatically generated by configure - do not modify */
+/* This file is included by target-specific files under
+ * android/config/target-$ARCH/config.h, but contains all config
+ * definitions that are independent of the target CPU.
+ *
+ * Do not include directly.
+ */
#include "config-host.h"
#define TARGET_PHYS_ADDR_BITS 32
@@ -10,14 +15,4 @@
#ifndef _WIN32
#define CONFIG_NAND_LIMITS 1
#endif
-#define CONFIG_ANDROID_SNAPSHOTS 1
-
-#ifdef ARCH_FLAGS_x86
-#define TARGET_ARCH "x86"
-#define TARGET_I386 1
-#else
-#define TARGET_ARCH "arm"
-#define TARGET_ARM 1
-#define CONFIG_SOFTFLOAT 1
-#endif
-
+#define CONFIG_MEMCHECK 1
diff --git a/android/config/linux-x86/config-host.h b/android/config/linux-x86/config-host.h
index 2dba514..903e98b 100644
--- a/android/config/linux-x86/config-host.h
+++ b/android/config/linux-x86/config-host.h
@@ -12,6 +12,7 @@
#define QEMU_VERSION "0.10.50"
#define QEMU_PKGVERSION "Android"
#define HOST_I386 1
+#define CONFIG_KVM 1
#define CONFIG_IOVEC 1
#define CONFIG_LINUX 1
#define CONFIG_ANDROID 1
diff --git a/android/config/target-arm/config.h b/android/config/target-arm/config.h
new file mode 100644
index 0000000..d6da04f
--- /dev/null
+++ b/android/config/target-arm/config.h
@@ -0,0 +1,5 @@
+/* ARM-specific configuration */
+#include "android/config/config.h"
+
+#define TARGET_ARM 1
+#define CONFIG_SOFTFLOAT 1
diff --git a/android/config/target-x86/config.h b/android/config/target-x86/config.h
new file mode 100644
index 0000000..ea31c39
--- /dev/null
+++ b/android/config/target-x86/config.h
@@ -0,0 +1,3 @@
+/* x86-specific configuration */
+#include "android/config/config.h"
+#define TARGET_I386 1
diff --git a/android/console.c b/android/console.c
index d883002..de32ddb 100644
--- a/android/console.c
+++ b/android/console.c
@@ -2049,8 +2049,6 @@
{ NULL, NULL, NULL, NULL, NULL, NULL }
};
-#if CONFIG_ANDROID_SNAPSHOTS
-
/********************************************************************************************/
/********************************************************************************************/
@@ -2150,8 +2148,6 @@
};
-#endif
-
/********************************************************************************************/
/********************************************************************************************/
@@ -2215,11 +2211,9 @@
"'avd name' will return the name of this virtual device\r\n",
NULL, do_avd_name, NULL },
-#if CONFIG_ANDROID_SNAPSHOTS
{ "snapshot", "state snapshot commands",
"allows you to save and restore the virtual device state in snapshots\r\n",
NULL, NULL, snapshot_commands },
-#endif
{ NULL, NULL, NULL, NULL, NULL, NULL }
};
diff --git a/android/help.c b/android/help.c
index 7df6704..cd5a3a6 100644
--- a/android/help.c
+++ b/android/help.c
@@ -166,9 +166,7 @@
" system-qemu.img an *optional* persistent system image\n"
" cache.img an *optional* cache partition image\n"
" sdcard.img an *optional* SD Card partition image\n\n"
-#if CONFIG_ANDROID_SNAPSHOTS
" snapshots.img an *optional* state snapshots image\n\n"
-#endif
" If you use a virtual device, its content directory should store\n"
" all writable images, and read-only ones will be found from the\n"
@@ -184,11 +182,7 @@
" can still run the emulator by explicitely providing the paths to\n"
" *all* required disk images through a combination of the following\n"
" options: -sysdir, -datadir, -kernel, -ramdisk, -system, -data, -cache\n"
-#if CONFIG_ANDROID_SNAPSHOTS
" -sdcard and -snapstorage.\n\n"
-#else
- " and -sdcard.\n\n"
-#endif
" The actual logic being that the emulator should be able to find all\n"
" images from the options you give it.\n\n"
@@ -205,10 +199,8 @@
" -no-cache do not use a cache partition, even if one is\n"
" available.\n\n"
-#if CONFIG_ANDROID_SNAPSHOTS
" -no-snapstorage do not use a state snapshot image, even if one is\n"
" available.\n\n"
-#endif
,
datadir );
}
@@ -619,7 +611,6 @@
);
}
-#if CONFIG_ANDROID_SNAPSHOTS
static void
help_snapstorage(stralloc_t* out)
{
@@ -733,8 +724,6 @@
);
}
-#endif
-
static void
help_skindir(stralloc_t* out)
{
@@ -1344,20 +1333,6 @@
);
}
-static void
-help_old_system(stralloc_t* out)
-{
- PRINTF(
- " use '-old-system' if you want to use a recent emulator binary to run\n"
- " an old version of the Android SDK system images. Here, 'old' means anything\n"
- " older than version 1.4 of the emulator.\n\n"
-
- " NOTE: using '-old-system' with recent system images is likely to not work\n"
- " properly, though you may not notice it immediately (e.g. failure to\n"
- " start the emulated GPS hardware)\n\n"
- );
-}
-
#ifdef CONFIG_NAND_LIMITS
static void
help_nand_limits(stralloc_t* out)
diff --git a/android/hw-sensors.c b/android/hw-sensors.c
index e191f68..c3ab12f 100644
--- a/android/hw-sensors.c
+++ b/android/hw-sensors.c
@@ -525,7 +525,7 @@
/* check number of sensors */
int32_t num_sensors = qemu_get_be32(f);
- if (num_sensors != MAX_SENSORS) {
+ if (num_sensors > MAX_SENSORS) {
D("%s: cannot load: snapshot requires %d sensors, %d available\n",
__FUNCTION__, num_sensors, MAX_SENSORS);
return -EIO;
@@ -533,7 +533,7 @@
/* load sensor state */
AndroidSensor i;
- for (i = 0 ; i < MAX_SENSORS; i++) {
+ for (i = 0 ; i < num_sensors; i++) {
Sensor* s = &h->sensors[i];
s->enabled = qemu_get_be32(f);
@@ -567,6 +567,14 @@
}
}
+ /* The following is necessary when we resume a snaphost
+ * created by an older version of the emulator that provided
+ * less hardware sensors.
+ */
+ for ( ; i < MAX_SENSORS; i++ ) {
+ h->sensors[i].enabled = 0;
+ }
+
return 0;
}
diff --git a/android/hw-sensors.h b/android/hw-sensors.h
index 5cfc748..665cc6d 100644
--- a/android/hw-sensors.h
+++ b/android/hw-sensors.h
@@ -20,6 +20,9 @@
/* NOTE: this list must be the same that the one defined in
* the sensors_qemu.c source of the libsensors.goldfish.so
* library.
+ *
+ * DO NOT CHANGE THE ORDER IN THIS LIST, UNLESS YOU INTEND
+ * TO BREAK SNAPSHOTS!
*/
#define SENSORS_LIST \
SENSOR_(ACCELERATION,"acceleration") \
diff --git a/android/main-common.c b/android/main-common.c
index bb07943..9cb97f8 100644
--- a/android/main-common.c
+++ b/android/main-common.c
@@ -27,6 +27,7 @@
#include "android/utils/debug.h"
#include "android/utils/path.h"
#include "android/utils/bufprint.h"
+#include "android/utils/dirscanner.h"
#include "android/main-common.h"
#include "android/globals.h"
#include "android/resource.h"
@@ -341,6 +342,7 @@
parse_skin_files(const char* skinDirPath,
const char* skinName,
AndroidOptions* opts,
+ AndroidHwConfig* hwConfig,
AConfig* *skinConfig,
char* *skinPath)
{
@@ -433,6 +435,53 @@
skin_network_delay = aconfig_str(n, "delay", 0);
}
+ /* extract framebuffer information from the skin.
+ *
+ * for version 1 of the skin format, they are in the top-level
+ * 'display' element.
+ *
+ * for version 2 of the skin format, they are under parts.device.display
+ */
+ n = aconfig_find(root, "display");
+ if (n == NULL) {
+ n = aconfig_find(root, "parts");
+ if (n != NULL) {
+ n = aconfig_find(root, "device");
+ if (n != NULL) {
+ n = aconfig_find(root, "display");
+ }
+ }
+ }
+
+ if (n != NULL) {
+ int width = aconfig_int(n, "width", hwConfig->hw_lcd_width);
+ int height = aconfig_int(n, "height", hwConfig->hw_lcd_height);
+ int depth = aconfig_int(n, "bpp", hwConfig->hw_lcd_depth);
+
+ if (width > 0 && height > 0) {
+ /* The emulated framebuffer wants sizes that are multiples of 4 */
+ if (((width|height) & 3) != 0) {
+ width = (width+3) & ~3;
+ height = (height+3) & ~3;
+ D("adjusting LCD dimensions to (%dx%dx)", width, height);
+ }
+
+ /* only depth values of 16 and 32 are correct. 16 is the default. */
+ if (depth != 32 && depth != 16) {
+ depth = 16;
+ D("adjusting LCD bit depth to %d", depth);
+ }
+
+ hwConfig->hw_lcd_width = width;
+ hwConfig->hw_lcd_height = height;
+ hwConfig->hw_lcd_depth = depth;
+ }
+ else {
+ D("ignoring invalid skin LCD dimensions (%dx%dx%d)",
+ width, height, depth);
+ }
+ }
+
*skinConfig = root;
*skinPath = strdup(path);
return;
@@ -537,21 +586,590 @@
}
}
-int64_t get_screen_pixels(AConfig* skinConfig)
+/* this function is used to perform auto-detection of the
+ * system directory in the case of a SDK installation.
+ *
+ * we want to deal with several historical usages, hence
+ * the slightly complicated logic.
+ *
+ * NOTE: the function returns the path to the directory
+ * containing 'fileName'. this is *not* the full
+ * path to 'fileName'.
+ */
+static char*
+_getSdkImagePath( const char* fileName )
{
- int64_t pixels = 0;
- AConfig* disp;
+ char temp[MAX_PATH];
+ char* p = temp;
+ char* end = p + sizeof(temp);
+ char* q;
+ char* app;
- if (skinConfig != NULL) {
- disp = aconfig_find(skinConfig, "display");
- if (disp != NULL) {
- int width = aconfig_int(disp, "width", 0);
- int height = aconfig_int(disp, "height", 0);
- pixels = (int64_t)width*height;
+ static const char* const searchPaths[] = {
+ "", /* program's directory */
+ "/lib/images", /* this is for SDK 1.0 */
+ "/../platforms/android-1.1/images", /* this is for SDK 1.1 */
+ NULL
+ };
+
+ app = bufprint_app_dir(temp, end);
+ if (app >= end)
+ return NULL;
+
+ do {
+ int nn;
+
+ /* first search a few well-known paths */
+ for (nn = 0; searchPaths[nn] != NULL; nn++) {
+ p = bufprint(app, end, "%s", searchPaths[nn]);
+ q = bufprint(p, end, "/%s", fileName);
+ if (q < end && path_exists(temp)) {
+ *p = 0;
+ goto FOUND_IT;
+ }
+ }
+
+ /* hmmm. let's assume that we are in a post-1.1 SDK
+ * scan ../platforms if it exists
+ */
+ p = bufprint(app, end, "/../platforms");
+ if (p < end) {
+ DirScanner* scanner = dirScanner_new(temp);
+ if (scanner != NULL) {
+ int found = 0;
+ const char* subdir;
+
+ for (;;) {
+ subdir = dirScanner_next(scanner);
+ if (!subdir) break;
+
+ q = bufprint(p, end, "/%s/images/%s", subdir, fileName);
+ if (q >= end || !path_exists(temp))
+ continue;
+
+ found = 1;
+ p = bufprint(p, end, "/%s/images", subdir);
+ break;
+ }
+ dirScanner_free(scanner);
+ if (found)
+ break;
+ }
+ }
+
+ /* I'm out of ideas */
+ return NULL;
+
+ } while (0);
+
+FOUND_IT:
+ //D("image auto-detection: %s/%s", temp, fileName);
+ return android_strdup(temp);
+}
+
+static char*
+_getSdkImage( const char* path, const char* file )
+{
+ char temp[MAX_PATH];
+ char *p = temp, *end = p + sizeof(temp);
+
+ p = bufprint(temp, end, "%s/%s", path, file);
+ if (p >= end || !path_exists(temp))
+ return NULL;
+
+ return android_strdup(temp);
+}
+
+static char*
+_getSdkSystemImage( const char* path, const char* optionName, const char* file )
+{
+ char* image = _getSdkImage(path, file);
+
+ if (image == NULL) {
+ derror("Your system directory is missing the '%s' image file.\n"
+ "Please specify one with the '%s <filepath>' option",
+ file, optionName);
+ exit(2);
+ }
+ return image;
+}
+
+void sanitizeOptions( AndroidOptions* opts )
+{
+ /* legacy support: we used to use -system <dir> and -image <file>
+ * instead of -sysdir <dir> and -system <file>, so handle this by checking
+ * whether the options point to directories or files.
+ */
+ if (opts->image != NULL) {
+ if (opts->system != NULL) {
+ if (opts->sysdir != NULL) {
+ derror( "You can't use -sysdir, -system and -image at the same time.\n"
+ "You should probably use '-sysdir <path> -system <file>'.\n" );
+ exit(2);
+ }
+ }
+ dwarning( "Please note that -image is obsolete and that -system is now used to point\n"
+ "to the system image. Next time, try using '-sysdir <path> -system <file>' instead.\n" );
+ opts->sysdir = opts->system;
+ opts->system = opts->image;
+ opts->image = NULL;
+ }
+ else if (opts->system != NULL && path_is_dir(opts->system)) {
+ if (opts->sysdir != NULL) {
+ derror( "Option -system should now be followed by a file path, not a directory one.\n"
+ "Please use '-sysdir <path>' to point to the system directory.\n" );
+ exit(1);
+ }
+ dwarning( "Please note that the -system option should now be used to point to the initial\n"
+ "system image (like the obsolete -image option). To point to the system directory\n"
+ "please now use '-sysdir <path>' instead.\n" );
+
+ opts->sysdir = opts->system;
+ opts->system = NULL;
+ }
+
+ if (opts->nojni) {
+ opts->no_jni = opts->nojni;
+ opts->nojni = 0;
+ }
+
+ if (opts->nocache) {
+ opts->no_cache = opts->nocache;
+ opts->nocache = 0;
+ }
+
+ if (opts->noaudio) {
+ opts->no_audio = opts->noaudio;
+ opts->noaudio = 0;
+ }
+
+ if (opts->noskin) {
+ opts->no_skin = opts->noskin;
+ opts->noskin = 0;
+ }
+
+ /* If -no-cache is used, ignore any -cache argument */
+ if (opts->no_cache) {
+ opts->cache = 0;
+ }
+
+ /* the purpose of -no-audio is to disable sound output from the emulator,
+ * not to disable Audio emulation. So simply force the 'none' backends */
+ if (opts->no_audio)
+ opts->audio = "none";
+
+ /* we don't accept -skindir without -skin now
+ * to simplify the autoconfig stuff with virtual devices
+ */
+ if (opts->no_skin) {
+ opts->skin = "320x480";
+ opts->skindir = NULL;
+ }
+
+ if (opts->skindir) {
+ if (!opts->skin) {
+ derror( "the -skindir <path> option requires a -skin <name> option");
+ exit(1);
}
}
- if (pixels == 0)
- pixels = 320*240;
- return pixels;
+ if (opts->bootchart) {
+ char* end;
+ int timeout = strtol(opts->bootchart, &end, 10);
+ if (timeout == 0)
+ opts->bootchart = NULL;
+ else if (timeout < 0 || timeout > 15*60) {
+ derror( "timeout specified for -bootchart option is invalid.\n"
+ "please use integers between 1 and 900\n");
+ exit(1);
+ }
+ }
}
+
+AvdInfo* createAVD(AndroidOptions* opts, int* inAndroidBuild)
+{
+ AvdInfo* ret = NULL;
+ char tmp[MAX_PATH];
+ char* tmpend = tmp + sizeof(tmp);
+ char* android_build_root = NULL;
+ char* android_build_out = NULL;
+
+ /* If no AVD name was given, try to find the top of the
+ * Android build tree
+ */
+ if (opts->avd == NULL) {
+ do {
+ char* out = getenv("ANDROID_PRODUCT_OUT");
+
+ if (out == NULL || out[0] == 0)
+ break;
+
+ if (!path_exists(out)) {
+ derror("Can't access ANDROID_PRODUCT_OUT as '%s'\n"
+ "You need to build the Android system before launching the emulator",
+ out);
+ exit(2);
+ }
+
+ android_build_root = path_parent( out, 4 );
+ if (android_build_root == NULL || !path_exists(android_build_root)) {
+ derror("Can't find the Android build root from '%s'\n"
+ "Please check the definition of the ANDROID_PRODUCT_OUT variable.\n"
+ "It should point to your product-specific build output directory.\n",
+ out );
+ exit(2);
+ }
+ android_build_out = out;
+ D( "found Android build root: %s", android_build_root );
+ D( "found Android build out: %s", android_build_out );
+ } while (0);
+ }
+ /* if no virtual device name is given, and we're not in the
+ * Android build system, we'll need to perform some auto-detection
+ * magic :-)
+ */
+ if (opts->avd == NULL && !android_build_out)
+ {
+ char dataDirIsSystem = 0;
+
+ if (!opts->sysdir) {
+ opts->sysdir = _getSdkImagePath("system.img");
+ if (!opts->sysdir) {
+ derror(
+ "You did not specify a virtual device name, and the system\n"
+ "directory could not be found.\n\n"
+ "If you are an Android SDK user, please use '@<name>' or '-avd <name>'\n"
+ "to start a given virtual device (see -help-avd for details).\n\n"
+
+ "Otherwise, follow the instructions in -help-disk-images to start the emulator\n"
+ );
+ exit(2);
+ }
+ D("autoconfig: -sysdir %s", opts->sysdir);
+ }
+
+ if (!opts->system) {
+ opts->system = _getSdkSystemImage(opts->sysdir, "-image", "system.img");
+ D("autoconfig: -image %s", opts->image);
+ }
+
+ if (!opts->kernel) {
+ opts->kernel = _getSdkSystemImage(opts->sysdir, "-kernel", "kernel-qemu");
+ D("autoconfig: -kernel %s", opts->kernel);
+ }
+
+ if (!opts->ramdisk) {
+ opts->ramdisk = _getSdkSystemImage(opts->sysdir, "-ramdisk", "ramdisk.img");
+ D("autoconfig: -ramdisk %s", opts->ramdisk);
+ }
+
+ /* if no data directory is specified, use the system directory */
+ if (!opts->datadir) {
+ opts->datadir = android_strdup(opts->sysdir);
+ dataDirIsSystem = 1;
+ D("autoconfig: -datadir %s", opts->sysdir);
+ }
+
+ if (!opts->data) {
+ /* check for userdata-qemu.img in the data directory */
+ bufprint(tmp, tmpend, "%s/userdata-qemu.img", opts->datadir);
+ if (!path_exists(tmp)) {
+ derror(
+ "You did not provide the name of an Android Virtual Device\n"
+ "with the '-avd <name>' option. Read -help-avd for more information.\n\n"
+
+ "If you *really* want to *NOT* run an AVD, consider using '-data <file>'\n"
+ "to specify a data partition image file (I hope you know what you're doing).\n"
+ );
+ exit(2);
+ }
+
+ opts->data = android_strdup(tmp);
+ D("autoconfig: -data %s", opts->data);
+ }
+
+ if (!opts->snapstorage && opts->datadir) {
+ bufprint(tmp, tmpend, "%s/snapshots.img", opts->datadir);
+ if (path_exists(tmp)) {
+ opts->snapstorage = android_strdup(tmp);
+ D("autoconfig: -snapstorage %s", opts->snapstorage);
+ }
+ }
+ }
+
+ /* setup the virtual device differently depending on whether
+ * we are in the Android build system or not
+ */
+ if (opts->avd != NULL)
+ {
+ ret = avdInfo_new( opts->avd, android_avdParams );
+ if (ret == NULL) {
+ /* an error message has already been printed */
+ dprint("could not find virtual device named '%s'", opts->avd);
+ exit(1);
+ }
+ }
+ else
+ {
+ if (!android_build_out) {
+ android_build_out = android_build_root = opts->sysdir;
+ }
+ ret = avdInfo_newForAndroidBuild(
+ android_build_root,
+ android_build_out,
+ android_avdParams );
+
+ if(ret == NULL) {
+ D("could not start virtual device\n");
+ exit(1);
+ }
+ }
+
+ if (android_build_out) {
+ *inAndroidBuild = 1;
+ } else {
+ *inAndroidBuild = 0;
+ }
+
+ return ret;
+}
+
+
+
+
+#ifdef CONFIG_STANDALONE_UI
+
+#include "android/protocol/core-connection.h"
+#include "android/protocol/fb-updates-impl.h"
+#include "android/protocol/user-events-proxy.h"
+#include "android/protocol/core-commands-proxy.h"
+#include "android/protocol/ui-commands-impl.h"
+#include "android/protocol/attach-ui-impl.h"
+
+/* Emulator's core port. */
+int android_base_port = 0;
+
+// Base console port
+#define CORE_BASE_PORT 5554
+
+// Maximum number of core porocesses running simultaneously on a machine.
+#define MAX_CORE_PROCS 16
+
+// Socket timeout in millisec (set to 5 seconds)
+#define CORE_PORT_TIMEOUT_MS 5000
+
+#include "android/async-console.h"
+
+typedef struct {
+ LoopIo io[1];
+ int port;
+ int ok;
+ AsyncConsoleConnector connector[1];
+} CoreConsole;
+
+static void
+coreconsole_io_func(void* opaque, int fd, unsigned events)
+{
+ CoreConsole* cc = opaque;
+ AsyncStatus status;
+ status = asyncConsoleConnector_run(cc->connector, cc->io);
+ if (status == ASYNC_COMPLETE) {
+ cc->ok = 1;
+ }
+}
+
+static void
+coreconsole_init(CoreConsole* cc, const SockAddress* address, Looper* looper)
+{
+ int fd = socket_create_inet(SOCKET_STREAM);
+ AsyncStatus status;
+ cc->port = sock_address_get_port(address);
+ cc->ok = 0;
+ loopIo_init(cc->io, looper, fd, coreconsole_io_func, cc);
+ if (fd >= 0) {
+ status = asyncConsoleConnector_connect(cc->connector, address, cc->io);
+ if (status == ASYNC_ERROR) {
+ cc->ok = 0;
+ }
+ }
+}
+
+static void
+coreconsole_done(CoreConsole* cc)
+{
+ socket_close(cc->io->fd);
+ loopIo_done(cc->io);
+}
+
+/* List emulator core processes running on the given machine.
+ * This routine is called from main() if -list-cores parameter is set in the
+ * command line.
+ * Param:
+ * host Value passed with -list-core parameter. Must be either "localhost", or
+ * an IP address of a machine where core processes must be enumerated.
+ */
+static void
+list_running_cores(const char* host)
+{
+ Looper* looper;
+ CoreConsole cores[MAX_CORE_PROCS];
+ SockAddress address;
+ int nn, found;
+
+ if (sock_address_init_resolve(&address, host, CORE_BASE_PORT, 0) < 0) {
+ derror("Unable to resolve hostname %s: %s", host, errno_str);
+ return;
+ }
+
+ looper = looper_newGeneric();
+
+ for (nn = 0; nn < MAX_CORE_PROCS; nn++) {
+ int port = CORE_BASE_PORT + nn*2;
+ sock_address_set_port(&address, port);
+ coreconsole_init(&cores[nn], &address, looper);
+ }
+
+ looper_runWithTimeout(looper, CORE_PORT_TIMEOUT_MS*2);
+
+ found = 0;
+ for (nn = 0; nn < MAX_CORE_PROCS; nn++) {
+ int port = CORE_BASE_PORT + nn*2;
+ if (cores[nn].ok) {
+ if (found == 0) {
+ fprintf(stdout, "Running emulator core processes:\n");
+ }
+ fprintf(stdout, "Emulator console port %d\n", port);
+ found++;
+ }
+ coreconsole_done(&cores[nn]);
+ }
+ looper_free(looper);
+
+ if (found == 0) {
+ fprintf(stdout, "There were no running emulator core processes found on %s.\n",
+ host);
+ }
+}
+
+/* Attaches starting UI to a running core process.
+ * This routine is called from main() when -attach-core parameter is set,
+ * indicating that this UI instance should attach to a running core, rather than
+ * start a new core process.
+ * Param:
+ * opts Android options containing non-NULL attach_core.
+ * Return:
+ * 0 on success, or -1 on failure.
+ */
+static int
+attach_to_core(AndroidOptions* opts) {
+ int iter;
+ SockAddress console_socket;
+ SockAddress** sockaddr_list;
+ QEmulator* emulator;
+
+ // Parse attach_core param extracting the host name, and the port name.
+ char* console_address = strdup(opts->attach_core);
+ char* host_name = console_address;
+ char* port_num = strchr(console_address, ':');
+ if (port_num == NULL) {
+ // The host name is ommited, indicating the localhost
+ host_name = "localhost";
+ port_num = console_address;
+ } else if (port_num == console_address) {
+ // Invalid.
+ derror("Invalid value %s for -attach-core parameter\n",
+ opts->attach_core);
+ return -1;
+ } else {
+ *port_num = '\0';
+ port_num++;
+ if (*port_num == '\0') {
+ // Invalid.
+ derror("Invalid value %s for -attach-core parameter\n",
+ opts->attach_core);
+ return -1;
+ }
+ }
+
+ /* Create socket address list for the given address, and pull appropriate
+ * address to use for connection. Note that we're fine copying that address
+ * out of the list, since INET and IN6 will entirely fit into SockAddress
+ * structure. */
+ sockaddr_list =
+ sock_address_list_create(host_name, port_num, SOCKET_LIST_FORCE_INET);
+ free(console_address);
+ if (sockaddr_list == NULL) {
+ derror("Unable to resolve address %s: %s\n",
+ opts->attach_core, errno_str);
+ return -1;
+ }
+ for (iter = 0; sockaddr_list[iter] != NULL; iter++) {
+ if (sock_address_get_family(sockaddr_list[iter]) == SOCKET_INET ||
+ sock_address_get_family(sockaddr_list[iter]) == SOCKET_IN6) {
+ memcpy(&console_socket, sockaddr_list[iter], sizeof(SockAddress));
+ break;
+ }
+ }
+ if (sockaddr_list[iter] == NULL) {
+ derror("Unable to resolve address %s. Note that 'port' parameter passed to -attach-core\n"
+ "must be resolvable into an IP address.\n", opts->attach_core);
+ sock_address_list_free(sockaddr_list);
+ return -1;
+ }
+ sock_address_list_free(sockaddr_list);
+
+ if (attachUiImpl_create(&console_socket)) {
+ return -1;
+ }
+
+ // Save core's port, and set the title.
+ android_base_port = sock_address_get_port(&console_socket);
+ emulator = qemulator_get();
+ qemulator_set_title(emulator);
+
+ return 0;
+}
+
+
+void handle_ui_options( AndroidOptions* opts )
+{
+ // Lets see if user just wants to list core process.
+ if (opts->list_cores) {
+ fprintf(stdout, "Enumerating running core processes.\n");
+ list_running_cores(opts->list_cores);
+ exit(0);
+ }
+}
+
+int attach_ui_to_core( AndroidOptions* opts )
+{
+ // Lets see if we're attaching to a running core process here.
+ if (opts->attach_core) {
+ if (attach_to_core(opts)) {
+ return -1;
+ }
+ // Connect to the core's UI control services.
+ if (coreCmdProxy_create(attachUiImpl_get_console_socket())) {
+ return -1;
+ }
+ // Connect to the core's user events service.
+ if (userEventsProxy_create(attachUiImpl_get_console_socket())) {
+ return -1;
+ }
+ }
+ return 0;
+}
+
+#else /* !CONFIG_STANDALONE_UI */
+
+void handle_ui_options( AndroidOptions* opts )
+{
+ return;
+}
+
+int attach_ui_to_core( AndroidOptions* opts )
+{
+ return 0;
+}
+
+#endif /* CONFIG_STANDALONE_UI */
diff --git a/android/main-common.h b/android/main-common.h
index c5131df..0d184d5 100644
--- a/android/main-common.h
+++ b/android/main-common.h
@@ -16,6 +16,7 @@
#include "android/cmdline-option.h"
#include "android/skin/keyset.h"
#include "android/config.h"
+#include "android/avd/hw-config.h"
/* Common routines used by both android/main.c and android/main-ui.c */
@@ -36,6 +37,9 @@
void parse_keyset(const char* keyset, AndroidOptions* opts);
void write_default_keyset( void );
+#define NETWORK_SPEED_DEFAULT "full"
+#define NETWORK_DELAY_DEFAULT "none"
+
extern const char* skin_network_speed;
extern const char* skin_network_delay;
@@ -45,6 +49,7 @@
void parse_skin_files(const char* skinDirPath,
const char* skinName,
AndroidOptions* opts,
+ AndroidHwConfig* hwConfig,
AConfig* *skinConfig,
char* *skinPath);
@@ -55,4 +60,47 @@
const char* skinPath,
AndroidOptions* opts);
+/* Sanitize options. This deals with a few legacy options that are now
+ * handled differently. Call before anything else that needs to read
+ * the options list.
+ */
+void sanitizeOptions( AndroidOptions* opts );
+
+/* Creates and initializes AvdInfo instance for the given options.
+ * Param:
+ * opts - Options passed to the main()
+ * inAndroidBuild - Upon exit contains 0 if AvdInfo has been initialized from
+ * AVD file, or 1 if AvdInfo has been initialized from the build directory.
+ * Return:
+ * AvdInfo instance initialized for the given options.
+ */
+struct AvdInfo* createAVD(AndroidOptions* opts, int* inAndroidBuild);
+
+/* Populate the hwConfig fields corresponding to the kernel/disk images
+ * used by the emulator. This will zero *hwConfig first.
+ */
+void findImagePaths( AndroidHwConfig* hwConfig,
+ AndroidOptions* opts );
+
+/* Updates hardware configuration for the given AVD and options.
+ * Param:
+ * hwConfig - Hardware configuration to update.
+ * avd - AVD info containig paths for the hardware configuration.
+ * opts - Options passed to the main()
+ * inAndroidBuild - 0 if AVD has been initialized from AVD file, or 1 if AVD
+ * has been initialized from the build directory.
+ */
+void updateHwConfigFromAVD(AndroidHwConfig* hwConfig, struct AvdInfo* avd,
+ AndroidOptions* opts, int inAndroidBuild);
+
+/* Called from android/main.c to handle options specific to the standalone
+ * UI program. This is a no-op otherwise.
+ */
+void handle_ui_options( AndroidOptions* opts );
+
+/* Called from android/main.c to potentially attach to a core from the
+ * standalone UI program. This is a no-op otherwise.
+ */
+int attach_ui_to_core( AndroidOptions* opts );
+
#endif /* ANDROID_MAIN_COMMON_H */
diff --git a/android/main-ui.c b/android/main-ui.c
deleted file mode 100644
index 273f402..0000000
--- a/android/main-ui.c
+++ /dev/null
@@ -1,1518 +0,0 @@
-/* Copyright (C) 2006-2008 The Android Open Source Project
-**
-** This software is licensed under the terms of the GNU General Public
-** License version 2, as published by the Free Software Foundation, and
-** may be copied, distributed, and modified under those terms.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-*/
-
-#include <signal.h>
-#include <unistd.h>
-#include <string.h>
-#include <sys/time.h>
-#ifdef _WIN32
-#include <process.h>
-#endif
-
-#include "sockets.h"
-
-#include "android/android.h"
-#include "qemu-common.h"
-#include "sysemu.h"
-#include "console.h"
-#include "user-events.h"
-
-#include <SDL.h>
-#include <SDL_syswm.h>
-
-#include "math.h"
-
-#include "android/charmap.h"
-#include "android/utils/debug.h"
-#include "android/config.h"
-#include "android/config/config.h"
-
-#include "android/user-config.h"
-#include "android/utils/bufprint.h"
-#include "android/utils/dirscanner.h"
-#include "android/utils/path.h"
-#include "android/utils/tempfile.h"
-
-#include "android/main-common.h"
-#include "android/help.h"
-#include "hw/goldfish_nand.h"
-
-#include "android/globals.h"
-
-#include "android/qemulator.h"
-#include "android/display.h"
-
-#include "android/snapshot.h"
-#include "android/protocol/core-connection.h"
-#include "android/protocol/fb-updates-impl.h"
-#include "android/protocol/user-events-proxy.h"
-#include "android/protocol/core-commands-proxy.h"
-#include "android/protocol/ui-commands-impl.h"
-#include "android/protocol/attach-ui-impl.h"
-
-#include "android/framebuffer.h"
-#include "iolooper.h"
-
-AndroidRotation android_framebuffer_rotation;
-
-#define STRINGIFY(x) _STRINGIFY(x)
-#define _STRINGIFY(x) #x
-
-#ifdef ANDROID_SDK_TOOLS_REVISION
-# define VERSION_STRING STRINGIFY(ANDROID_SDK_TOOLS_REVISION)".0"
-#else
-# define VERSION_STRING "standalone"
-#endif
-
-#define D(...) do { if (VERBOSE_CHECK(init)) dprint(__VA_ARGS__); } while (0)
-
-extern int control_console_start( int port ); /* in control.c */
-
-extern int qemu_milli_needed;
-
-/* the default device DPI if none is specified by the skin
- */
-#define DEFAULT_DEVICE_DPI 165
-
-#if 0
-static int opts->flashkeys; /* forward */
-#endif
-
-#ifdef CONFIG_TRACE
-extern void start_tracing(void);
-extern void stop_tracing(void);
-#endif
-
-unsigned long android_verbose;
-
-/* -ui-settings parameters received from the core on UI attachment. */
-char* core_ui_settings = "";
-
-/* Emulator's core port. */
-int android_base_port = 0;
-
-/* this is used by hw/events_device.c to send the charmap name to the system */
-extern const char* android_skin_keycharmap;
-
-
-int qemu_main(int argc, char **argv);
-
-/* this function dumps the QEMU help */
-extern void help( void );
-extern void emulator_help( void );
-
-#define VERBOSE_OPT(str,var) { str, &var }
-
-#define _VERBOSE_TAG(x,y) { #x, VERBOSE_##x, y },
-static const struct { const char* name; int flag; const char* text; }
-verbose_options[] = {
- VERBOSE_TAG_LIST
- { 0, 0, 0 }
-};
-
-void emulator_help( void )
-{
- STRALLOC_DEFINE(out);
- android_help_main(out);
- printf( "%.*s", out->n, out->s );
- stralloc_reset(out);
- exit(1);
-}
-
-/* this function is used to perform auto-detection of the
- * system directory in the case of a SDK installation.
- *
- * we want to deal with several historical usages, hence
- * the slightly complicated logic.
- *
- * NOTE: the function returns the path to the directory
- * containing 'fileName'. this is *not* the full
- * path to 'fileName'.
- */
-static char*
-_getSdkImagePath( const char* fileName )
-{
- char temp[MAX_PATH];
- char* p = temp;
- char* end = p + sizeof(temp);
- char* q;
- char* app;
-
- static const char* const searchPaths[] = {
- "", /* program's directory */
- "/lib/images", /* this is for SDK 1.0 */
- "/../platforms/android-1.1/images", /* this is for SDK 1.1 */
- NULL
- };
-
- app = bufprint_app_dir(temp, end);
- if (app >= end)
- return NULL;
-
- do {
- int nn;
-
- /* first search a few well-known paths */
- for (nn = 0; searchPaths[nn] != NULL; nn++) {
- p = bufprint(app, end, "%s", searchPaths[nn]);
- q = bufprint(p, end, "/%s", fileName);
- if (q < end && path_exists(temp)) {
- *p = 0;
- goto FOUND_IT;
- }
- }
-
- /* hmmm. let's assume that we are in a post-1.1 SDK
- * scan ../platforms if it exists
- */
- p = bufprint(app, end, "/../platforms");
- if (p < end) {
- DirScanner* scanner = dirScanner_new(temp);
- if (scanner != NULL) {
- int found = 0;
- const char* subdir;
-
- for (;;) {
- subdir = dirScanner_next(scanner);
- if (!subdir) break;
-
- q = bufprint(p, end, "/%s/images/%s", subdir, fileName);
- if (q >= end || !path_exists(temp))
- continue;
-
- found = 1;
- p = bufprint(p, end, "/%s/images", subdir);
- break;
- }
- dirScanner_free(scanner);
- if (found)
- break;
- }
- }
-
- /* I'm out of ideas */
- return NULL;
-
- } while (0);
-
-FOUND_IT:
- //D("image auto-detection: %s/%s", temp, fileName);
- return android_strdup(temp);
-}
-
-static char*
-_getSdkImage( const char* path, const char* file )
-{
- char temp[MAX_PATH];
- char *p = temp, *end = p + sizeof(temp);
-
- p = bufprint(temp, end, "%s/%s", path, file);
- if (p >= end || !path_exists(temp))
- return NULL;
-
- return android_strdup(temp);
-}
-
-static char*
-_getSdkSystemImage( const char* path, const char* optionName, const char* file )
-{
- char* image = _getSdkImage(path, file);
-
- if (image == NULL) {
- derror("Your system directory is missing the '%s' image file.\n"
- "Please specify one with the '%s <filepath>' option",
- file, optionName);
- exit(2);
- }
- return image;
-}
-
-static void
-_forceAvdImagePath( AvdImageType imageType,
- const char* path,
- const char* description,
- int required )
-{
- if (path == NULL)
- return;
-
- if (required && !path_exists(path)) {
- derror("Cannot find %s image file: %s", description, path);
- exit(1);
- }
- android_avdParams->forcePaths[imageType] = path;
-}
-
-static uint64_t
-_adjustPartitionSize( const char* description,
- uint64_t imageBytes,
- uint64_t defaultBytes,
- int inAndroidBuild )
-{
- char temp[64];
- unsigned imageMB;
- unsigned defaultMB;
-
- if (imageBytes <= defaultBytes)
- return defaultBytes;
-
- imageMB = convertBytesToMB(imageBytes);
- defaultMB = convertBytesToMB(defaultBytes);
-
- if (imageMB > defaultMB) {
- snprintf(temp, sizeof temp, "(%d MB > %d MB)", imageMB, defaultMB);
- } else {
- snprintf(temp, sizeof temp, "(%lld bytes > %lld bytes)", imageBytes, defaultBytes);
- }
-
- if (inAndroidBuild) {
- dwarning("%s partition size adjusted to match image file %s\n", description, temp);
- }
-
- return convertMBToBytes(imageMB);
-}
-
-// Base console port
-#define CORE_BASE_PORT 5554
-
-// Maximum number of core porocesses running simultaneously on a machine.
-#define MAX_CORE_PROCS 16
-
-// Socket timeout in millisec (set to 5 seconds)
-#define CORE_PORT_TIMEOUT_MS 5000
-
-#include "android/async-console.h"
-
-typedef struct {
- LoopIo io[1];
- int port;
- int ok;
- AsyncConsoleConnector connector[1];
-} CoreConsole;
-
-static void
-coreconsole_io_func(void* opaque, int fd, unsigned events)
-{
- CoreConsole* cc = opaque;
- AsyncStatus status;
- status = asyncConsoleConnector_run(cc->connector, cc->io);
- if (status == ASYNC_COMPLETE) {
- cc->ok = 1;
- }
-}
-
-static void
-coreconsole_init(CoreConsole* cc, const SockAddress* address, Looper* looper)
-{
- int fd = socket_create_inet(SOCKET_STREAM);
- AsyncStatus status;
- cc->port = sock_address_get_port(address);
- cc->ok = 0;
- loopIo_init(cc->io, looper, fd, coreconsole_io_func, cc);
- if (fd >= 0) {
- status = asyncConsoleConnector_connect(cc->connector, address, cc->io);
- if (status == ASYNC_ERROR) {
- cc->ok = 0;
- }
- }
-}
-
-static void
-coreconsole_done(CoreConsole* cc)
-{
- socket_close(cc->io->fd);
- loopIo_done(cc->io);
-}
-
-/* List emulator core processes running on the given machine.
- * This routine is called from main() if -list-cores parameter is set in the
- * command line.
- * Param:
- * host Value passed with -list-core parameter. Must be either "localhost", or
- * an IP address of a machine where core processes must be enumerated.
- */
-static void
-list_running_cores(const char* host)
-{
- Looper* looper;
- CoreConsole cores[MAX_CORE_PROCS];
- SockAddress address;
- int nn, found;
-
- if (sock_address_init_resolve(&address, host, CORE_BASE_PORT, 0) < 0) {
- derror("Unable to resolve hostname %s: %s", host, errno_str);
- return;
- }
-
- looper = looper_newGeneric();
-
- for (nn = 0; nn < MAX_CORE_PROCS; nn++) {
- int port = CORE_BASE_PORT + nn*2;
- sock_address_set_port(&address, port);
- coreconsole_init(&cores[nn], &address, looper);
- }
-
- looper_runWithTimeout(looper, CORE_PORT_TIMEOUT_MS*2);
-
- found = 0;
- for (nn = 0; nn < MAX_CORE_PROCS; nn++) {
- int port = CORE_BASE_PORT + nn*2;
- if (cores[nn].ok) {
- if (found == 0) {
- fprintf(stdout, "Running emulator core processes:\n");
- }
- fprintf(stdout, "Emulator console port %d\n", port);
- found++;
- }
- coreconsole_done(&cores[nn]);
- }
- looper_free(looper);
-
- if (found == 0) {
- fprintf(stdout, "There were no running emulator core processes found on %s.\n",
- host);
- }
-}
-
-/* Attaches starting UI to a running core process.
- * This routine is called from main() when -attach-core parameter is set,
- * indicating that this UI instance should attach to a running core, rather than
- * start a new core process.
- * Param:
- * opts Android options containing non-NULL attach_core.
- * Return:
- * 0 on success, or -1 on failure.
- */
-static int
-attach_to_core(AndroidOptions* opts) {
- int iter;
- SockAddress console_socket;
- SockAddress** sockaddr_list;
- QEmulator* emulator;
-
- // Parse attach_core param extracting the host name, and the port name.
- char* console_address = strdup(opts->attach_core);
- char* host_name = console_address;
- char* port_num = strchr(console_address, ':');
- if (port_num == NULL) {
- // The host name is ommited, indicating the localhost
- host_name = "localhost";
- port_num = console_address;
- } else if (port_num == console_address) {
- // Invalid.
- derror("Invalid value %s for -attach-core parameter\n",
- opts->attach_core);
- return -1;
- } else {
- *port_num = '\0';
- port_num++;
- if (*port_num == '\0') {
- // Invalid.
- derror("Invalid value %s for -attach-core parameter\n",
- opts->attach_core);
- return -1;
- }
- }
-
- /* Create socket address list for the given address, and pull appropriate
- * address to use for connection. Note that we're fine copying that address
- * out of the list, since INET and IN6 will entirely fit into SockAddress
- * structure. */
- sockaddr_list =
- sock_address_list_create(host_name, port_num, SOCKET_LIST_FORCE_INET);
- free(console_address);
- if (sockaddr_list == NULL) {
- derror("Unable to resolve address %s: %s\n",
- opts->attach_core, errno_str);
- return -1;
- }
- for (iter = 0; sockaddr_list[iter] != NULL; iter++) {
- if (sock_address_get_family(sockaddr_list[iter]) == SOCKET_INET ||
- sock_address_get_family(sockaddr_list[iter]) == SOCKET_IN6) {
- memcpy(&console_socket, sockaddr_list[iter], sizeof(SockAddress));
- break;
- }
- }
- if (sockaddr_list[iter] == NULL) {
- derror("Unable to resolve address %s. Note that 'port' parameter passed to -attach-core\n"
- "must be resolvable into an IP address.\n", opts->attach_core);
- sock_address_list_free(sockaddr_list);
- return -1;
- }
- sock_address_list_free(sockaddr_list);
-
- if (attachUiImpl_create(&console_socket)) {
- return -1;
- }
-
- // Save core's port, and set the title.
- android_base_port = sock_address_get_port(&console_socket);
- emulator = qemulator_get();
- qemulator_set_title(emulator);
-
- return 0;
-}
-
-int main(int argc, char **argv)
-{
- char tmp[MAX_PATH];
- char* tmpend = tmp + sizeof(tmp);
- char* args[128];
- int n;
- char* opt;
- int use_sdcard_img = 0;
- int serial = 0;
- int gps_serial = 0;
- int radio_serial = 0;
- int qemud_serial = 0;
- int shell_serial = 0;
- unsigned cachePartitionSize = 0;
- unsigned systemPartitionSize = 0;
- unsigned dataPartitionSize = 0;
- unsigned defaultPartitionSize = convertMBToBytes(66);
-
- AndroidHwConfig* hw;
- AvdInfo* avd;
- AConfig* skinConfig;
- char* skinPath;
-
- //const char *appdir = get_app_dir();
- char* android_build_root = NULL;
- char* android_build_out = NULL;
-
- AndroidOptions opts[1];
- /* LCD density value to pass to the core. */
- char lcd_density[16];
- /* net.shared_net_ip boot property value. */
- char boot_prop_ip[64];
- boot_prop_ip[0] = '\0';
-
- args[0] = argv[0];
-
- if ( android_parse_options( &argc, &argv, opts ) < 0 ) {
- exit(1);
- }
-
-#ifdef _WIN32
- socket_init();
-#endif
-
- // Lets see if user just wants to list core process.
- if (opts->list_cores) {
- fprintf(stdout, "Enumerating running core processes.\n");
- list_running_cores(opts->list_cores);
- exit(0);
- }
-
- while (argc-- > 1) {
- opt = (++argv)[0];
-
- if(!strcmp(opt, "-qemu")) {
- argc--;
- argv++;
- break;
- }
-
- if (!strcmp(opt, "-help")) {
- emulator_help();
- }
-
- if (!strncmp(opt, "-help-",6)) {
- STRALLOC_DEFINE(out);
- opt += 6;
-
- if (!strcmp(opt, "all")) {
- android_help_all(out);
- }
- else if (android_help_for_option(opt, out) == 0) {
- /* ok */
- }
- else if (android_help_for_topic(opt, out) == 0) {
- /* ok */
- }
- if (out->n > 0) {
- printf("\n%.*s", out->n, out->s);
- exit(0);
- }
-
- fprintf(stderr, "unknown option: -help-%s\n", opt);
- fprintf(stderr, "please use -help for a list of valid topics\n");
- exit(1);
- }
-
- if (opt[0] == '-') {
- fprintf(stderr, "unknown option: %s\n", opt);
- fprintf(stderr, "please use -help for a list of valid options\n");
- exit(1);
- }
-
- fprintf(stderr, "invalid command-line parameter: %s.\n", opt);
- fprintf(stderr, "Hint: use '@foo' to launch a virtual device named 'foo'.\n");
- fprintf(stderr, "please use -help for more information\n");
- exit(1);
- }
-
- if (opts->version) {
- printf("Android emulator version %s\n"
- "Copyright (C) 2006-2008 The Android Open Source Project and many others.\n"
- "This program is a derivative of the QEMU CPU emulator (www.qemu.org).\n\n",
-#if defined ANDROID_BUILD_ID
- VERSION_STRING " (build_id " STRINGIFY(ANDROID_BUILD_ID) ")" );
-#else
- VERSION_STRING);
-#endif
- printf(" This software is licensed under the terms of the GNU General Public\n"
- " License version 2, as published by the Free Software Foundation, and\n"
- " may be copied, distributed, and modified under those terms.\n\n"
- " This program is distributed in the hope that it will be useful,\n"
- " but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
- " MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
- " GNU General Public License for more details.\n\n");
-
- exit(0);
- }
-
- /* Initialization of UI started with -attach-core should work differently
- * than initialization of UI that starts the core. In particular....
- */
-
- /* -charmap is incompatible with -attach-core, because particular
- * charmap gets set up in the running core. */
- if (android_charmap_setup(opts->charmap)) {
- exit(1);
- }
-
- /* legacy support: we used to use -system <dir> and -image <file>
- * instead of -sysdir <dir> and -system <file>, so handle this by checking
- * whether the options point to directories or files.
- */
- if (opts->image != NULL) {
- if (opts->system != NULL) {
- if (opts->sysdir != NULL) {
- derror( "You can't use -sysdir, -system and -image at the same time.\n"
- "You should probably use '-sysdir <path> -system <file>'.\n" );
- exit(2);
- }
- }
- dwarning( "Please note that -image is obsolete and that -system is now used to point\n"
- "to the system image. Next time, try using '-sysdir <path> -system <file>' instead.\n" );
- opts->sysdir = opts->system;
- opts->system = opts->image;
- opts->image = NULL;
- }
- else if (opts->system != NULL && path_is_dir(opts->system)) {
- if (opts->sysdir != NULL) {
- derror( "Option -system should now be followed by a file path, not a directory one.\n"
- "Please use '-sysdir <path>' to point to the system directory.\n" );
- exit(1);
- }
- dwarning( "Please note that the -system option should now be used to point to the initial\n"
- "system image (like the obsolete -image option). To point to the system directory\n"
- "please now use '-sysdir <path>' instead.\n" );
-
- opts->sysdir = opts->system;
- opts->system = NULL;
- }
-
- if (opts->nojni)
- opts->no_jni = opts->nojni;
-
- if (opts->nocache)
- opts->no_cache = opts->nocache;
-
- if (opts->noaudio)
- opts->no_audio = opts->noaudio;
-
- if (opts->noskin)
- opts->no_skin = opts->noskin;
-
- /* If no AVD name was given, try to find the top of the
- * Android build tree
- */
- if (opts->avd == NULL) {
- do {
- char* out = getenv("ANDROID_PRODUCT_OUT");
-
- if (out == NULL || out[0] == 0)
- break;
-
- if (!path_exists(out)) {
- derror("Can't access ANDROID_PRODUCT_OUT as '%s'\n"
- "You need to build the Android system before launching the emulator",
- out);
- exit(2);
- }
-
- android_build_root = path_parent( out, 4 );
- if (android_build_root == NULL || !path_exists(android_build_root)) {
- derror("Can't find the Android build root from '%s'\n"
- "Please check the definition of the ANDROID_PRODUCT_OUT variable.\n"
- "It should point to your product-specific build output directory.\n",
- out );
- exit(2);
- }
- android_build_out = out;
- D( "found Android build root: %s", android_build_root );
- D( "found Android build out: %s", android_build_out );
- } while (0);
- }
- /* if no virtual device name is given, and we're not in the
- * Android build system, we'll need to perform some auto-detection
- * magic :-)
- */
- if (opts->avd == NULL && !android_build_out)
- {
- char dataDirIsSystem = 0;
-
- if (!opts->sysdir) {
- opts->sysdir = _getSdkImagePath("system.img");
- if (!opts->sysdir) {
- derror(
- "You did not specify a virtual device name, and the system\n"
- "directory could not be found.\n\n"
- "If you are an Android SDK user, please use '@<name>' or '-avd <name>'\n"
- "to start a given virtual device (see -help-avd for details).\n\n"
-
- "Otherwise, follow the instructions in -help-disk-images to start the emulator\n"
- );
- exit(2);
- }
- D("autoconfig: -sysdir %s", opts->sysdir);
- }
-
- if (!opts->system) {
- opts->system = _getSdkSystemImage(opts->sysdir, "-image", "system.img");
- D("autoconfig: -image %s", opts->image);
- }
-
- if (!opts->kernel) {
- opts->kernel = _getSdkSystemImage(opts->sysdir, "-kernel", "kernel-qemu");
- D("autoconfig: -kernel %s", opts->kernel);
- }
-
- if (!opts->ramdisk) {
- opts->ramdisk = _getSdkSystemImage(opts->sysdir, "-ramdisk", "ramdisk.img");
- D("autoconfig: -ramdisk %s", opts->ramdisk);
- }
-
- /* if no data directory is specified, use the system directory */
- if (!opts->datadir) {
- opts->datadir = android_strdup(opts->sysdir);
- dataDirIsSystem = 1;
- D("autoconfig: -datadir %s", opts->sysdir);
- }
-
- if (!opts->data) {
- /* check for userdata-qemu.img in the data directory */
- bufprint(tmp, tmpend, "%s/userdata-qemu.img", opts->datadir);
- if (!path_exists(tmp)) {
- derror(
- "You did not provide the name of an Android Virtual Device\n"
- "with the '-avd <name>' option. Read -help-avd for more information.\n\n"
-
- "If you *really* want to *NOT* run an AVD, consider using '-data <file>'\n"
- "to specify a data partition image file (I hope you know what you're doing).\n"
- );
- exit(2);
- }
-
- opts->data = android_strdup(tmp);
- D("autoconfig: -data %s", opts->data);
- }
-
- if (!opts->sdcard && opts->datadir) {
- bufprint(tmp, tmpend, "%s/sdcard.img", opts->datadir);
- if (path_exists(tmp)) {
- opts->sdcard = android_strdup(tmp);
- D("autoconfig: -sdcard %s", opts->sdcard);
- }
- }
-
-#if CONFIG_ANDROID_SNAPSHOTS
- if (!opts->snapstorage && opts->datadir) {
- bufprint(tmp, tmpend, "%s/snapshots.img", opts->datadir);
- if (path_exists(tmp)) {
- opts->snapstorage = android_strdup(tmp);
- D("autoconfig: -snapstorage %s", opts->snapstorage);
- }
- }
-#endif // CONFIG_ANDROID_SNAPSHOTS
- }
-
- /* setup the virtual device parameters from our options
- */
- if (opts->no_cache) {
- android_avdParams->flags |= AVDINFO_NO_CACHE;
- }
- if (opts->wipe_data) {
- android_avdParams->flags |= AVDINFO_WIPE_DATA | AVDINFO_WIPE_CACHE;
- }
-#if CONFIG_ANDROID_SNAPSHOTS
- if (opts->no_snapstorage) {
- android_avdParams->flags |= AVDINFO_NO_SNAPSHOTS;
- }
-#endif
-
- /* if certain options are set, we can force the path of
- * certain kernel/disk image files
- */
- _forceAvdImagePath(AVD_IMAGE_KERNEL, opts->kernel, "kernel", 1);
- _forceAvdImagePath(AVD_IMAGE_INITSYSTEM, opts->system, "system", 1);
- _forceAvdImagePath(AVD_IMAGE_RAMDISK, opts->ramdisk, "ramdisk", 1);
- _forceAvdImagePath(AVD_IMAGE_USERDATA, opts->data, "user data", 0);
- _forceAvdImagePath(AVD_IMAGE_CACHE, opts->cache, "cache", 0);
- _forceAvdImagePath(AVD_IMAGE_SDCARD, opts->sdcard, "SD Card", 0);
-#if CONFIG_ANDROID_SNAPSHOTS
- _forceAvdImagePath(AVD_IMAGE_SNAPSHOTS, opts->snapstorage, "snapshots", 0);
-#endif
-
- /* we don't accept -skindir without -skin now
- * to simplify the autoconfig stuff with virtual devices
- */
- if (opts->no_skin) {
- opts->skin = "320x480";
- opts->skindir = NULL;
- }
-
- if (opts->skindir) {
- if (!opts->skin) {
- derror( "the -skindir <path> option requires a -skin <name> option");
- exit(1);
- }
- }
- android_avdParams->skinName = opts->skin;
- android_avdParams->skinRootPath = opts->skindir;
-
- /* setup the virtual device differently depending on whether
- * we are in the Android build system or not
- */
- if (opts->avd != NULL)
- {
- android_avdInfo = avdInfo_new( opts->avd, android_avdParams );
- if (android_avdInfo == NULL) {
- /* an error message has already been printed */
- dprint("could not find virtual device named '%s'", opts->avd);
- exit(1);
- }
- }
- else
- {
- if (!android_build_out) {
- android_build_out = android_build_root = opts->sysdir;
- }
- android_avdInfo = avdInfo_newForAndroidBuild(
- android_build_root,
- android_build_out,
- android_avdParams );
-
- if(android_avdInfo == NULL) {
- D("could not start virtual device\n");
- exit(1);
- }
- }
-
- avd = android_avdInfo;
-
- /* get the skin from the virtual device configuration */
- opts->skin = (char*) avdInfo_getSkinName( avd );
- opts->skindir = (char*) avdInfo_getSkinDir( avd );
-
- if (opts->skin) {
- D("autoconfig: -skin %s", opts->skin);
- }
- if (opts->skindir) {
- D("autoconfig: -skindir %s", opts->skindir);
- }
-
- /* Read hardware configuration */
- hw = android_hw;
- if (avdInfo_getHwConfig(avd, hw) < 0) {
- derror("could not read hardware configuration ?");
- exit(1);
- }
-
- if (opts->keyset) {
- parse_keyset(opts->keyset, opts);
- if (!android_keyset) {
- fprintf(stderr,
- "emulator: WARNING: could not find keyset file named '%s',"
- " using defaults instead\n",
- opts->keyset);
- }
- }
- if (!android_keyset) {
- parse_keyset("default", opts);
- if (!android_keyset) {
- android_keyset = skin_keyset_new_from_text( skin_keyset_get_default() );
- if (!android_keyset) {
- fprintf(stderr, "PANIC: default keyset file is corrupted !!\n" );
- fprintf(stderr, "PANIC: please update the code in android/skin/keyset.c\n" );
- exit(1);
- }
- if (!opts->keyset)
- write_default_keyset();
- }
- }
-
- if (opts->shared_net_id) {
- char* end;
- long shared_net_id = strtol(opts->shared_net_id, &end, 0);
- if (end == NULL || *end || shared_net_id < 1 || shared_net_id > 255) {
- fprintf(stderr, "option -shared-net-id must be an integer between 1 and 255\n");
- exit(1);
- }
- snprintf(boot_prop_ip, sizeof(boot_prop_ip),
- "net.shared_net_ip=10.1.2.%ld", shared_net_id);
- }
-
-
- user_config_init();
- parse_skin_files(opts->skindir, opts->skin, opts,
- &skinConfig, &skinPath);
-
- if (!opts->netspeed) {
- if (skin_network_speed)
- D("skin network speed: '%s'", skin_network_speed);
- opts->netspeed = (char*)skin_network_speed;
- }
- if (!opts->netdelay) {
- if (skin_network_delay)
- D("skin network delay: '%s'", skin_network_delay);
- opts->netdelay = (char*)skin_network_delay;
- }
-
- if (opts->trace) {
- char* tracePath = avdInfo_getTracePath(avd, opts->trace);
- int ret;
-
- if (tracePath == NULL) {
- derror( "bad -trace parameter" );
- exit(1);
- }
- ret = path_mkdir_if_needed( tracePath, 0755 );
- if (ret < 0) {
- fprintf(stderr, "could not create directory '%s'\n", tmp);
- exit(2);
- }
- opts->trace = tracePath;
- }
-
- if (opts->no_cache)
- opts->cache = 0;
-
- n = 1;
- /* generate arguments for the underlying qemu main() */
- {
- const char* kernelFile = avdInfo_getImageFile(avd, AVD_IMAGE_KERNEL);
- int kernelFileLen = strlen(kernelFile);
-
- args[n++] = "-kernel";
- args[n++] = (char*)kernelFile;
-
- /* If the kernel image name ends in "-armv7", then change the cpu
- * type automatically. This is a poor man's approach to configuration
- * management, but should allow us to get past building ARMv7
- * system images with dex preopt pass without introducing too many
- * changes to the emulator sources.
- *
- * XXX:
- * A 'proper' change would require adding some sort of hardware-property
- * to each AVD config file, then automatically determine its value for
- * full Android builds (depending on some environment variable), plus
- * some build system changes. I prefer not to do that for now for reasons
- * of simplicity.
- */
- if (kernelFileLen > 6 && !memcmp(kernelFile + kernelFileLen - 6, "-armv7", 6)) {
- args[n++] = "-cpu";
- args[n++] = "cortex-a8";
- }
- }
-
- if (boot_prop_ip[0]) {
- args[n++] = "-boot-property";
- args[n++] = boot_prop_ip;
- }
-
- if (opts->tcpdump) {
- args[n++] = "-tcpdump";
- args[n++] = opts->tcpdump;
- }
-
-#ifdef CONFIG_NAND_LIMITS
- if (opts->nand_limits) {
- args[n++] = "-nand-limits";
- args[n++] = opts->nand_limits;
- }
-#endif
-
- if (opts->timezone) {
- args[n++] = "-timezone";
- args[n++] = opts->timezone;
- }
-
- if (opts->netspeed) {
- args[n++] = "-netspeed";
- args[n++] = opts->netspeed;
- }
- if (opts->netdelay) {
- args[n++] = "-netdelay";
- args[n++] = opts->netdelay;
- }
- if (opts->netfast) {
- args[n++] = "-netfast";
- }
-
- /* the purpose of -no-audio is to disable sound output from the emulator,
- * not to disable Audio emulation. So simply force the 'none' backends */
- if (opts->no_audio)
- opts->audio = "none";
-
- if (opts->audio) {
- args[n++] = "-audio";
- args[n++] = opts->audio;
- }
-
- if (opts->cpu_delay) {
- args[n++] = "-cpu-delay";
- args[n++] = opts->cpu_delay;
- }
-
- if (opts->dns_server) {
- args[n++] = "-dns-server";
- args[n++] = opts->dns_server;
- }
-
- args[n++] = "-initrd";
- args[n++] = (char*) avdInfo_getImageFile(avd, AVD_IMAGE_RAMDISK);
-
- if (opts->partition_size) {
- char* end;
- long sizeMB = strtol(opts->partition_size, &end, 0);
- long minSizeMB = 10;
- long maxSizeMB = LONG_MAX / ONE_MB;
-
- if (sizeMB < 0 || *end != 0) {
- derror( "-partition-size must be followed by a positive integer" );
- exit(1);
- }
- if (sizeMB < minSizeMB || sizeMB > maxSizeMB) {
- derror( "partition-size (%d) must be between %dMB and %dMB",
- sizeMB, minSizeMB, maxSizeMB );
- exit(1);
- }
- defaultPartitionSize = sizeMB * ONE_MB;
- }
-
- /* Check the size of the system partition image.
- * If we have an AVD, it must be smaller than
- * the disk.systemPartition.size hardware property.
- *
- * Otherwise, we need to adjust the systemPartitionSize
- * automatically, and print a warning.
- *
- */
- {
- uint64_t systemBytes = avdInfo_getImageFileSize(avd, AVD_IMAGE_INITSYSTEM);
- uint64_t defaultBytes = defaultPartitionSize;
-
- if (defaultBytes == 0 || opts->partition_size)
- defaultBytes = defaultPartitionSize;
-
- systemPartitionSize = _adjustPartitionSize("system", systemBytes, defaultBytes,
- android_build_out != NULL);
- }
-
- /* Check the size of the /data partition. The only interesting cases here are:
- * - when the USERDATA image already exists and is larger than the default
- * - when we're wiping data and the INITDATA is larger than the default.
- */
-
- {
- const char* dataPath = avdInfo_getImageFile(avd, AVD_IMAGE_USERDATA);
- uint64_t defaultBytes = defaultPartitionSize;
-
- if (defaultBytes == 0 || opts->partition_size)
- defaultBytes = defaultPartitionSize;
-
- if (dataPath == NULL || !path_exists(dataPath) || opts->wipe_data) {
- dataPath = avdInfo_getImageFile(avd, AVD_IMAGE_INITDATA);
- }
- if (dataPath == NULL || !path_exists(dataPath)) {
- dataPartitionSize = defaultBytes;
- }
- else {
- uint64_t dataBytes;
- path_get_size(dataPath, &dataBytes);
-
- dataPartitionSize = _adjustPartitionSize("data", dataBytes, defaultBytes,
- android_build_out != NULL);
- }
- }
-
- {
- const char* filetype = "file";
-
- if (avdInfo_isImageReadOnly(avd, AVD_IMAGE_INITSYSTEM))
- filetype = "initfile";
-
- bufprint(tmp, tmpend,
- "system,size=0x%x,%s=%s", systemPartitionSize, filetype,
- avdInfo_getImageFile(avd, AVD_IMAGE_INITSYSTEM));
-
- args[n++] = "-nand";
- args[n++] = strdup(tmp);
- }
-
- bufprint(tmp, tmpend,
- "userdata,size=0x%x,file=%s",
- dataPartitionSize,
- avdInfo_getImageFile(avd, AVD_IMAGE_USERDATA));
-
- args[n++] = "-nand";
- args[n++] = strdup(tmp);
-
- if (hw->disk_cachePartition) {
- opts->cache = (char*) avdInfo_getImageFile(avd, AVD_IMAGE_CACHE);
- cachePartitionSize = hw->disk_cachePartition_size;
- }
- else if (opts->cache) {
- dwarning( "Emulated hardware doesn't support a cache partition" );
- opts->cache = NULL;
- opts->no_cache = 1;
- }
-
- if (opts->cache) {
- /* use a specific cache file */
- sprintf(tmp, "cache,size=0x%0x,file=%s", cachePartitionSize, opts->cache);
- args[n++] = "-nand";
- args[n++] = strdup(tmp);
- }
- else if (!opts->no_cache) {
- /* create a temporary cache partition file */
- sprintf(tmp, "cache,size=0x%0x", cachePartitionSize);
- args[n++] = "-nand";
- args[n++] = strdup(tmp);
- }
-
- if (hw->hw_sdCard != 0)
- opts->sdcard = (char*) avdInfo_getImageFile(avd, AVD_IMAGE_SDCARD);
- else if (opts->sdcard) {
- dwarning( "Emulated hardware doesn't support SD Cards" );
- opts->sdcard = NULL;
- }
-
- if(opts->sdcard) {
- uint64_t size;
- if (path_get_size(opts->sdcard, &size) == 0) {
- /* see if we have an sdcard image. get its size if it exists */
- /* due to what looks like limitations of the MMC protocol, one has
- * to use an SD Card image that is equal or larger than 9 MB
- */
- if (size < 9*1024*1024ULL) {
- fprintf(stderr, "### WARNING: SD Card files must be at least 9MB, ignoring '%s'\n", opts->sdcard);
- } else {
- args[n++] = "-hda";
- args[n++] = opts->sdcard;
- use_sdcard_img = 1;
- }
- } else {
- D("no SD Card image at '%s'", opts->sdcard);
- }
- }
-
-#if CONFIG_ANDROID_SNAPSHOTS
- if (!opts->no_snapstorage) {
- opts->snapstorage = (char*) avdInfo_getImageFile(avd, AVD_IMAGE_SNAPSHOTS);
- if(opts->snapstorage) {
- if (path_exists(opts->snapstorage)) {
- args[n++] = "-hdb";
- args[n++] = opts->snapstorage;
- } else {
- D("no image at '%s', state snapshots disabled", opts->snapstorage);
- }
- }
-
- if (!opts->no_snapshot) {
- char* snapshot_name =
- opts->snapshot ? opts->snapshot : "default-boot";
- if (!opts->no_snapshot_load) {
- args[n++] = "-loadvm";
- args[n++] = snapshot_name;
- }
- if (!opts->no_snapshot_save) {
- args[n++] = "-savevm-on-exit";
- args[n++] = snapshot_name;
- }
- } else if (opts->snapshot) {
- dwarning("option '-no-snapshot' overrides '-snapshot', continuing with boot sequence");
- } else if (opts->no_snapshot_load || opts->no_snapshot_save) {
- D("ignoring redundant option(s) '-no-snapshot-load' and/or '-no-snapshot-save' implied by '-no-snapshot'");
- }
- // TODO: Convey -no-snapshot-time-update to core subprocess (?)
- } else if (opts->snapshot || opts->snapstorage) {
- dwarning("option '-no-snapstorage' overrides '-snapshot' and '-snapstorage', "
- "continuing with full boot, state snapshots are disabled");
- } else if (opts->no_snapshot) {
- D("ignoring redundant option '-no-snapshot' implied by '-no-snapstorage'");
- }
-
- if (opts->snapshot_list) {
- snapshot_print_and_exit(opts->snapstorage);
- }
-#endif // CONFIG_ANDROID_SNAPSHOTS
-
- if (!opts->logcat || opts->logcat[0] == 0) {
- opts->logcat = getenv("ANDROID_LOG_TAGS");
- if (opts->logcat && opts->logcat[0] == 0)
- opts->logcat = NULL;
- }
-
-#if 0
- if (opts->console) {
- derror( "option -console is obsolete. please use -shell instead" );
- exit(1);
- }
-#endif
-
- /* we always send the kernel messages from ttyS0 to android_kmsg */
- {
- if (opts->show_kernel) {
- args[n++] = "-show-kernel";
- }
-
- args[n++] = "-serial";
- args[n++] = "android-kmsg";
- serial++;
- }
-
- /* XXXX: TODO: implement -shell and -logcat through qemud instead */
- if (!opts->shell_serial) {
-#ifdef _WIN32
- opts->shell_serial = "con:";
-#else
- opts->shell_serial = "stdio";
-#endif
- }
- else
- opts->shell = 1;
-
- if (opts->shell || opts->logcat) {
- args[n++] = "-serial";
- args[n++] = opts->shell_serial;
- shell_serial = serial++;
- }
-
- if (opts->old_system)
- {
- if (opts->radio) {
- args[n++] = "-serial";
- args[n++] = opts->radio;
- radio_serial = serial++;
- }
- else {
- args[n++] = "-serial";
- args[n++] = "android-modem";
- radio_serial = serial++;
- }
- if (opts->gps) {
- args[n++] = "-serial";
- args[n++] = opts->gps;
- gps_serial = serial++;
- }
- }
- else /* !opts->old_system */
- {
- args[n++] = "-serial";
- args[n++] = "android-qemud";
- qemud_serial = serial++;
-
- if (opts->radio) {
- args[n++] = "-radio";
- args[n++] = opts->radio;
- }
-
- if (opts->gps) {
- args[n++] = "-gps";
- args[n++] = opts->gps;
- }
- }
-
- if (opts->memory) {
- char* end;
- long ramSize = strtol(opts->memory, &end, 0);
- if (ramSize < 0 || *end != 0) {
- derror( "-memory must be followed by a positive integer" );
- exit(1);
- }
- if (ramSize < 32 || ramSize > 4096) {
- derror( "physical memory size must be between 32 and 4096 MB" );
- exit(1);
- }
- }
- if (!opts->memory) {
- int ramSize = hw->hw_ramSize;
- if (ramSize <= 0) {
- /* Compute the default RAM size based on the size of screen.
- * This is only used when the skin doesn't provide the ram
- * size through its hardware.ini (i.e. legacy ones) or when
- * in the full Android build system.
- */
- int64_t pixels = get_screen_pixels(skinConfig);
-
- /* The following thresholds are a bit liberal, but we
- * essentially want to ensure the following mappings:
- *
- * 320x480 -> 96
- * 800x600 -> 128
- * 1024x768 -> 256
- *
- * These are just simple heuristics, they could change in
- * the future.
- */
- if (pixels <= 250000)
- ramSize = 96;
- else if (pixels <= 500000)
- ramSize = 128;
- else
- ramSize = 256;
- }
- bufprint(tmp, tmpend, "%d", ramSize);
- opts->memory = android_strdup(tmp);
- }
-
- if (opts->trace) {
- args[n++] = "-trace";
- args[n++] = opts->trace;
- args[n++] = "-tracing";
- args[n++] = "off";
- }
-
- /* Pass LCD density value to the core. */
- snprintf(lcd_density, sizeof(lcd_density), "%d", hw->hw_lcd_density);
- args[n++] = "-lcd-density";
- args[n++] = lcd_density;
-
- /* Pass boot properties to the core. */
- if (opts->prop != NULL) {
- ParamList* pl = opts->prop;
- for ( ; pl != NULL; pl = pl->next ) {
- args[n++] = "-boot-property";
- args[n++] = pl->param;
- }
- }
-
- args[n++] = "-append";
-
- if (opts->bootchart) {
- char* end;
- int timeout = strtol(opts->bootchart, &end, 10);
- if (timeout == 0)
- opts->bootchart = NULL;
- else if (timeout < 0 || timeout > 15*60) {
- derror( "timeout specified for -bootchart option is invalid.\n"
- "please use integers between 1 and 900\n");
- exit(1);
- }
- }
-
- /* Setup the kernel init options
- */
- {
- static char params[1024];
- char *p = params, *end = p + sizeof(params);
-
- p = bufprint(p, end, "qemu=1 console=ttyS0" );
-
- if (opts->shell || opts->logcat) {
- p = bufprint(p, end, " androidboot.console=ttyS%d", shell_serial );
- }
-
- if (opts->trace) {
- p = bufprint(p, end, " android.tracing=1");
- }
-
- if (!opts->no_jni) {
- p = bufprint(p, end, " android.checkjni=1");
- }
-
- if (opts->no_boot_anim) {
- p = bufprint( p, end, " android.bootanim=0" );
- }
-
- if (opts->logcat) {
- char* q = bufprint(p, end, " androidboot.logcat=%s", opts->logcat);
-
- if (q < end) {
- /* replace any space by a comma ! */
- {
- int nn;
- for (nn = 1; p[nn] != 0; nn++)
- if (p[nn] == ' ' || p[nn] == '\t')
- p[nn] = ',';
- p += nn;
- }
- }
- p = q;
- }
-
- if (opts->old_system)
- {
- p = bufprint(p, end, " android.ril=ttyS%d", radio_serial);
-
- if (opts->gps) {
- p = bufprint(p, end, " android.gps=ttyS%d", gps_serial);
- }
- }
- else
- {
- p = bufprint(p, end, " android.qemud=ttyS%d", qemud_serial);
- }
-
- if (opts->bootchart) {
- p = bufprint(p, end, " androidboot.bootchart=%s", opts->bootchart);
- }
-
- if (p >= end) {
- fprintf(stderr, "### ERROR: kernel parameters too long\n");
- exit(1);
- }
-
- args[n++] = strdup(params);
- }
-
- if (opts->ports) {
- args[n++] = "-android-ports";
- args[n++] = opts->ports;
- }
-
- if (opts->port) {
- args[n++] = "-android-port";
- args[n++] = opts->port;
- }
-
- if (opts->report_console) {
- args[n++] = "-android-report-console";
- args[n++] = opts->report_console;
- }
-
- if (opts->http_proxy) {
- args[n++] = "-http-proxy";
- args[n++] = opts->http_proxy;
- }
-
- if (opts->charmap) {
- args[n++] = "-charmap";
- args[n++] = opts->charmap;
- }
-
- if (opts->memcheck) {
- args[n++] = "-android-memcheck";
- args[n++] = opts->memcheck;
- }
-
- /* physical memory */
- args[n++] = "-m";
- args[n++] = opts->memory;
-
- /* on Linux, the 'dynticks' clock sometimes doesn't work
- * properly. this results in the UI freezing while emulation
- * continues, for several seconds...
- */
-#ifdef __linux__
- args[n++] = "-clock";
- args[n++] = "unix";
-#endif
-
- args[n++] = "-android-avdname";
- args[n++] = avdInfo_getName(avd);
-
- /* Set up the interfaces for inter-emulator networking */
- if (opts->shared_net_id) {
- unsigned int shared_net_id = atoi(opts->shared_net_id);
- char nic[37];
-
- args[n++] = "-net";
- args[n++] = "nic,vlan=0";
- args[n++] = "-net";
- args[n++] = "user,vlan=0";
-
- args[n++] = "-net";
- snprintf(nic, sizeof nic, "nic,vlan=1,macaddr=52:54:00:12:34:%02x", shared_net_id);
- args[n++] = strdup(nic);
- args[n++] = "-net";
- args[n++] = "socket,vlan=1,mcast=230.0.0.10:1234";
- }
-
- while(argc-- > 0) {
- args[n++] = *argv++;
- }
- args[n] = 0;
-
- /* Generate a temporary hardware.ini for this AVD. The real hardware
- * configuration is ususally stored in several files, e.g. the AVD's
- * config.ini plus the skin-specific hardware.ini.
- *
- * The new temp file will group all definitions and will be used to
- * launch the core with the -android-hw <file> option.
- */
- {
- TempFile* tempHw = tempfile_create();
- if (tempHw == NULL) {
- derror("Could not create temporary hardware.ini: %s", strerror(errno));
- exit(2);
- }
-
- const char* tempHwPath = tempfile_path(tempHw);
- IniFile* hwIni = iniFile_newFromMemory("", NULL);
- androidHwConfig_write(hw, hwIni);
- if (iniFile_saveToFile(hwIni, tempHwPath) < 0) {
- derror("Could not write temporary hardware.ini: %s", tempHwPath);
- exit(2);
- }
- args[n++] = "-android-hw";
- args[n++] = strdup(tempHwPath);
- }
-
- if(VERBOSE_CHECK(init)) {
- int i;
- printf("QEMU options list:\n");
- for(i = 0; i < n; i++) {
- printf("emulator: argv[%02d] = \"%s\"\n", i, args[i]);
- }
- /* Dump final command-line option to make debugging the core easier */
- printf("Concatenated QEMU options:\n");
- for (i = 0; i < n; i++) {
- printf(" %s", args[i]);
- }
- printf("\n");
- }
-
- /* Setup SDL UI just before calling the code */
- init_sdl_ui(skinConfig, skinPath, opts);
-
- // Lets see if we're attaching to a running core process here.
- if (opts->attach_core) {
- if (attach_to_core(opts)) {
- return -1;
- }
- // Connect to the core's UI control services.
- if (coreCmdProxy_create(attachUiImpl_get_console_socket())) {
- return -1;
- }
- // Connect to the core's user events service.
- if (userEventsProxy_create(attachUiImpl_get_console_socket())) {
- return -1;
- }
- }
-
- return qemu_main(n, args);
-}
diff --git a/android/main.c b/android/main.c
index 51ef6d7..7b6ea03 100644
--- a/android/main.c
+++ b/android/main.c
@@ -38,7 +38,7 @@
#include "android/user-config.h"
#include "android/utils/bufprint.h"
-#include "android/utils/dirscanner.h"
+#include "android/utils/filelock.h"
#include "android/utils/path.h"
#include "android/utils/tempfile.h"
@@ -56,11 +56,6 @@
#include "android/framebuffer.h"
#include "iolooper.h"
-#ifdef TARGET_I386
-nand_threshold android_nand_read_threshold;
-nand_threshold android_nand_write_threshold;
-#endif
-
AndroidRotation android_framebuffer_rotation;
#define STRINGIFY(x) _STRINGIFY(x)
@@ -82,10 +77,6 @@
*/
#define DEFAULT_DEVICE_DPI 165
-#if 0
-static int opts->flashkeys; /* forward */
-#endif
-
#ifdef CONFIG_TRACE
extern void start_tracing(void);
extern void stop_tracing(void);
@@ -117,128 +108,21 @@
exit(1);
}
-/* this function is used to perform auto-detection of the
- * system directory in the case of a SDK installation.
- *
- * we want to deal with several historical usages, hence
- * the slightly complicated logic.
- *
- * NOTE: the function returns the path to the directory
- * containing 'fileName'. this is *not* the full
- * path to 'fileName'.
- */
+/* TODO: Put in shared source file */
static char*
-_getSdkImagePath( const char* fileName )
+_getFullFilePath( const char* rootPath, const char* fileName )
{
- char temp[MAX_PATH];
- char* p = temp;
- char* end = p + sizeof(temp);
- char* q;
- char* app;
+ if (path_is_absolute(fileName)) {
+ return ASTRDUP(fileName);
+ } else {
+ char temp[PATH_MAX], *p=temp, *end=p+sizeof(temp);
- static const char* const searchPaths[] = {
- "", /* program's directory */
- "/lib/images", /* this is for SDK 1.0 */
- "/../platforms/android-1.1/images", /* this is for SDK 1.1 */
- NULL
- };
-
- app = bufprint_app_dir(temp, end);
- if (app >= end)
- return NULL;
-
- do {
- int nn;
-
- /* first search a few well-known paths */
- for (nn = 0; searchPaths[nn] != NULL; nn++) {
- p = bufprint(app, end, "%s", searchPaths[nn]);
- q = bufprint(p, end, "/%s", fileName);
- if (q < end && path_exists(temp)) {
- *p = 0;
- goto FOUND_IT;
- }
+ p = bufprint(temp, end, "%s/%s", rootPath, fileName);
+ if (p >= end) {
+ return NULL;
}
-
- /* hmmm. let's assume that we are in a post-1.1 SDK
- * scan ../platforms if it exists
- */
- p = bufprint(app, end, "/../platforms");
- if (p < end) {
- DirScanner* scanner = dirScanner_new(temp);
- if (scanner != NULL) {
- int found = 0;
- const char* subdir;
-
- for (;;) {
- subdir = dirScanner_next(scanner);
- if (!subdir) break;
-
- q = bufprint(p, end, "/%s/images/%s", subdir, fileName);
- if (q >= end || !path_exists(temp))
- continue;
-
- found = 1;
- p = bufprint(p, end, "/%s/images", subdir);
- break;
- }
- dirScanner_free(scanner);
- if (found)
- break;
- }
- }
-
- /* I'm out of ideas */
- return NULL;
-
- } while (0);
-
-FOUND_IT:
- //D("image auto-detection: %s/%s", temp, fileName);
- return android_strdup(temp);
-}
-
-static char*
-_getSdkImage( const char* path, const char* file )
-{
- char temp[MAX_PATH];
- char *p = temp, *end = p + sizeof(temp);
-
- p = bufprint(temp, end, "%s/%s", path, file);
- if (p >= end || !path_exists(temp))
- return NULL;
-
- return android_strdup(temp);
-}
-
-static char*
-_getSdkSystemImage( const char* path, const char* optionName, const char* file )
-{
- char* image = _getSdkImage(path, file);
-
- if (image == NULL) {
- derror("Your system directory is missing the '%s' image file.\n"
- "Please specify one with the '%s <filepath>' option",
- file, optionName);
- exit(2);
+ return ASTRDUP(temp);
}
- return image;
-}
-
-static void
-_forceAvdImagePath( AvdImageType imageType,
- const char* path,
- const char* description,
- int required )
-{
- if (path == NULL)
- return;
-
- if (required && !path_exists(path)) {
- derror("Cannot find %s image file: %s", description, path);
- exit(1);
- }
- android_avdParams->forcePaths[imageType] = path;
}
static uint64_t
@@ -277,29 +161,21 @@
char* args[128];
int n;
char* opt;
- int use_sdcard_img = 0;
- int serial = 0;
- int gps_serial = 0;
- int radio_serial = 0;
- int qemud_serial = 0;
+ /* The emulator always uses the first serial port for kernel messages
+ * and the second one for qemud. So start at the third if we need one
+ * for logcat or 'shell'
+ */
+ int serial = 2;
int shell_serial = 0;
- unsigned cachePartitionSize = 0;
- unsigned systemPartitionSize = 0;
- unsigned dataPartitionSize = 0;
- unsigned defaultPartitionSize = convertMBToBytes(66);
AndroidHwConfig* hw;
AvdInfo* avd;
AConfig* skinConfig;
char* skinPath;
-
- //const char *appdir = get_app_dir();
- char* android_build_root = NULL;
- char* android_build_out = NULL;
+ int inAndroidBuild;
+ uint64_t defaultPartitionSize = convertMBToBytes(66);
AndroidOptions opts[1];
- /* LCD density value to pass to the core. */
- char lcd_density[16];
/* net.shared_net_ip boot property value. */
char boot_prop_ip[64];
boot_prop_ip[0] = '\0';
@@ -310,6 +186,12 @@
exit(1);
}
+#ifdef _WIN32
+ socket_init();
+#endif
+
+ handle_ui_options(opts);
+
while (argc-- > 1) {
opt = (++argv)[0];
@@ -360,7 +242,7 @@
if (opts->version) {
printf("Android emulator version %s\n"
- "Copyright (C) 2006-2008 The Android Open Source Project and many others.\n"
+ "Copyright (C) 2006-2011 The Android Open Source Project and many others.\n"
"This program is a derivative of the QEMU CPU emulator (www.qemu.org).\n\n",
#if defined ANDROID_BUILD_ID
VERSION_STRING " (build_id " STRINGIFY(ANDROID_BUILD_ID) ")" );
@@ -378,249 +260,46 @@
exit(0);
}
+ if (opts->snapshot_list) {
+ snapshot_print_and_exit(opts->snapstorage);
+ }
+
+ sanitizeOptions(opts);
+
+ /* Initialization of UI started with -attach-core should work differently
+ * than initialization of UI that starts the core. In particular....
+ */
+
+ /* -charmap is incompatible with -attach-core, because particular
+ * charmap gets set up in the running core. */
if (android_charmap_setup(opts->charmap)) {
exit(1);
}
- /* legacy support: we used to use -system <dir> and -image <file>
- * instead of -sysdir <dir> and -system <file>, so handle this by checking
- * whether the options point to directories or files.
- */
- if (opts->image != NULL) {
- if (opts->system != NULL) {
- if (opts->sysdir != NULL) {
- derror( "You can't use -sysdir, -system and -image at the same time.\n"
- "You should probably use '-sysdir <path> -system <file>'.\n" );
- exit(2);
- }
- }
- dwarning( "Please note that -image is obsolete and that -system is now used to point\n"
- "to the system image. Next time, try using '-sysdir <path> -system <file>' instead.\n" );
- opts->sysdir = opts->system;
- opts->system = opts->image;
- opts->image = NULL;
- }
- else if (opts->system != NULL && path_is_dir(opts->system)) {
- if (opts->sysdir != NULL) {
- derror( "Option -system should now be followed by a file path, not a directory one.\n"
- "Please use '-sysdir <path>' to point to the system directory.\n" );
- exit(1);
- }
- dwarning( "Please note that the -system option should now be used to point to the initial\n"
- "system image (like the obsolete -image option). To point to the system directory\n"
- "please now use '-sysdir <path>' instead.\n" );
-
- opts->sysdir = opts->system;
- opts->system = NULL;
- }
-
- if (opts->nojni)
- opts->no_jni = opts->nojni;
-
- if (opts->nocache)
- opts->no_cache = opts->nocache;
-
- if (opts->noaudio)
- opts->no_audio = opts->noaudio;
-
- if (opts->noskin)
- opts->no_skin = opts->noskin;
-
- /* If no AVD name was given, try to find the top of the
- * Android build tree
- */
- if (opts->avd == NULL) {
- do {
- char* out = getenv("ANDROID_PRODUCT_OUT");
-
- if (out == NULL || out[0] == 0)
- break;
-
- if (!path_exists(out)) {
- derror("Can't access ANDROID_PRODUCT_OUT as '%s'\n"
- "You need to build the Android system before launching the emulator",
- out);
- exit(2);
- }
-
- android_build_root = path_parent( out, 4 );
- if (android_build_root == NULL || !path_exists(android_build_root)) {
- derror("Can't find the Android build root from '%s'\n"
- "Please check the definition of the ANDROID_PRODUCT_OUT variable.\n"
- "It should point to your product-specific build output directory.\n",
- out );
- exit(2);
- }
- android_build_out = out;
- D( "found Android build root: %s", android_build_root );
- D( "found Android build out: %s", android_build_out );
- } while (0);
- }
- /* if no virtual device name is given, and we're not in the
- * Android build system, we'll need to perform some auto-detection
- * magic :-)
- */
- if (opts->avd == NULL && !android_build_out)
- {
- char dataDirIsSystem = 0;
-
- if (!opts->sysdir) {
- opts->sysdir = _getSdkImagePath("system.img");
- if (!opts->sysdir) {
- derror(
- "You did not specify a virtual device name, and the system\n"
- "directory could not be found.\n\n"
- "If you are an Android SDK user, please use '@<name>' or '-avd <name>'\n"
- "to start a given virtual device (see -help-avd for details).\n\n"
-
- "Otherwise, follow the instructions in -help-disk-images to start the emulator\n"
- );
- exit(2);
- }
- D("autoconfig: -sysdir %s", opts->sysdir);
- }
-
- if (!opts->system) {
- opts->system = _getSdkSystemImage(opts->sysdir, "-image", "system.img");
- D("autoconfig: -image %s", opts->image);
- }
-
- if (!opts->kernel) {
- opts->kernel = _getSdkSystemImage(opts->sysdir, "-kernel", "kernel-qemu");
- D("autoconfig: -kernel %s", opts->kernel);
- }
-
- if (!opts->ramdisk) {
- opts->ramdisk = _getSdkSystemImage(opts->sysdir, "-ramdisk", "ramdisk.img");
- D("autoconfig: -ramdisk %s", opts->ramdisk);
- }
-
- /* if no data directory is specified, use the system directory */
- if (!opts->datadir) {
- opts->datadir = android_strdup(opts->sysdir);
- dataDirIsSystem = 1;
- D("autoconfig: -datadir %s", opts->sysdir);
- }
-
- if (!opts->data) {
- /* check for userdata-qemu.img in the data directory */
- bufprint(tmp, tmpend, "%s/userdata-qemu.img", opts->datadir);
- if (!path_exists(tmp)) {
- derror(
- "You did not provide the name of an Android Virtual Device\n"
- "with the '-avd <name>' option. Read -help-avd for more information.\n\n"
-
- "If you *really* want to *NOT* run an AVD, consider using '-data <file>'\n"
- "to specify a data partition image file (I hope you know what you're doing).\n"
- );
- exit(2);
- }
-
- opts->data = android_strdup(tmp);
- D("autoconfig: -data %s", opts->data);
- }
-
- if (!opts->sdcard && opts->datadir) {
- bufprint(tmp, tmpend, "%s/sdcard.img", opts->datadir);
- if (path_exists(tmp)) {
- opts->sdcard = android_strdup(tmp);
- D("autoconfig: -sdcard %s", opts->sdcard);
- }
- }
-
-#if CONFIG_ANDROID_SNAPSHOTS
- if (!opts->snapstorage && opts->datadir) {
- bufprint(tmp, tmpend, "%s/snapshots.img", opts->datadir);
- if (path_exists(tmp)) {
- opts->snapstorage = android_strdup(tmp);
- D("autoconfig: -snapstorage %s", opts->snapstorage);
- }
- }
-#endif // CONFIG_ANDROID_SNAPSHOTS
- }
-
- /* setup the virtual device parameters from our options
- */
- if (opts->no_cache) {
- android_avdParams->flags |= AVDINFO_NO_CACHE;
- }
- if (opts->wipe_data) {
- android_avdParams->flags |= AVDINFO_WIPE_DATA | AVDINFO_WIPE_CACHE;
- }
-#if CONFIG_ANDROID_SNAPSHOTS
- if (opts->no_snapstorage) {
- android_avdParams->flags |= AVDINFO_NO_SNAPSHOTS;
- }
-#endif
-
- /* if certain options are set, we can force the path of
- * certain kernel/disk image files
- */
- _forceAvdImagePath(AVD_IMAGE_KERNEL, opts->kernel, "kernel", 1);
- _forceAvdImagePath(AVD_IMAGE_INITSYSTEM, opts->system, "system", 1);
- _forceAvdImagePath(AVD_IMAGE_RAMDISK, opts->ramdisk, "ramdisk", 1);
- _forceAvdImagePath(AVD_IMAGE_USERDATA, opts->data, "user data", 0);
- _forceAvdImagePath(AVD_IMAGE_CACHE, opts->cache, "cache", 0);
- _forceAvdImagePath(AVD_IMAGE_SDCARD, opts->sdcard, "SD Card", 0);
-#if CONFIG_ANDROID_SNAPSHOTS
- _forceAvdImagePath(AVD_IMAGE_SNAPSHOTS, opts->snapstorage, "snapshots", 0);
-#endif
-
- /* we don't accept -skindir without -skin now
- * to simplify the autoconfig stuff with virtual devices
- */
- if (opts->no_skin) {
- opts->skin = "320x480";
- opts->skindir = NULL;
- }
-
- if (opts->skindir) {
- if (!opts->skin) {
- derror( "the -skindir <path> option requires a -skin <name> option");
- exit(1);
- }
- }
- android_avdParams->skinName = opts->skin;
- android_avdParams->skinRootPath = opts->skindir;
-
- /* setup the virtual device differently depending on whether
- * we are in the Android build system or not
- */
- if (opts->avd != NULL)
- {
- android_avdInfo = avdInfo_new( opts->avd, android_avdParams );
- if (android_avdInfo == NULL) {
- /* an error message has already been printed */
- dprint("could not find virtual device named '%s'", opts->avd);
- exit(1);
- }
- }
- else
- {
- if (!android_build_out) {
- android_build_out = android_build_root = opts->sysdir;
- }
- android_avdInfo = avdInfo_newForAndroidBuild(
- android_build_root,
- android_build_out,
- android_avdParams );
-
- if(android_avdInfo == NULL) {
- D("could not start virtual device\n");
- exit(1);
- }
- }
-
- avd = android_avdInfo;
+ /* Parses options and builds an appropriate AVD. */
+ avd = android_avdInfo = createAVD(opts, &inAndroidBuild);
/* get the skin from the virtual device configuration */
- opts->skin = (char*) avdInfo_getSkinName( avd );
- opts->skindir = (char*) avdInfo_getSkinDir( avd );
+ if (opts->skindir != NULL) {
+ if (opts->skin == NULL) {
+ /* NOTE: Normally handled by sanitizeOptions(), just be safe */
+ derror("The -skindir <path> option requires a -skin <name> option");
+ exit(2);
+ }
+ } else {
+ char* skinName;
+ char* skinDir;
- if (opts->skin) {
- D("autoconfig: -skin %s", opts->skin);
- }
- if (opts->skindir) {
+ avdInfo_getSkinInfo(avd, &skinName, &skinDir);
+
+ if (opts->skin == NULL) {
+ opts->skin = skinName;
+ D("autoconfig: -skin %s", opts->skin);
+ } else {
+ AFREE(skinName);
+ }
+
+ opts->skindir = skinDir;
D("autoconfig: -skindir %s", opts->skindir);
}
@@ -667,18 +346,20 @@
user_config_init();
- parse_skin_files(opts->skindir, opts->skin, opts,
+ parse_skin_files(opts->skindir, opts->skin, opts, hw,
&skinConfig, &skinPath);
- if (!opts->netspeed) {
- if (skin_network_speed)
- D("skin network speed: '%s'", skin_network_speed);
- opts->netspeed = (char*)skin_network_speed;
+ if (!opts->netspeed && skin_network_speed) {
+ D("skin network speed: '%s'", skin_network_speed);
+ if (strcmp(skin_network_speed, NETWORK_SPEED_DEFAULT) != 0) {
+ opts->netspeed = (char*)skin_network_speed;
+ }
}
- if (!opts->netdelay) {
- if (skin_network_delay)
- D("skin network delay: '%s'", skin_network_delay);
- opts->netdelay = (char*)skin_network_delay;
+ if (!opts->netdelay && skin_network_delay) {
+ D("skin network delay: '%s'", skin_network_delay);
+ if (strcmp(skin_network_delay, NETWORK_DELAY_DEFAULT) != 0) {
+ opts->netdelay = (char*)skin_network_delay;
+ }
}
if (opts->trace) {
@@ -697,17 +378,26 @@
opts->trace = tracePath;
}
- if (opts->no_cache)
- opts->cache = 0;
-
n = 1;
/* generate arguments for the underlying qemu main() */
{
- const char* kernelFile = avdInfo_getImageFile(avd, AVD_IMAGE_KERNEL);
- int kernelFileLen = strlen(kernelFile);
+ char* kernelFile = opts->kernel;
+ int kernelFileLen;
- args[n++] = "-kernel";
- args[n++] = (char*)kernelFile;
+ if (kernelFile == NULL) {
+ kernelFile = avdInfo_getKernelPath(avd);
+ if (kernelFile == NULL) {
+ derror( "This AVD's configuration is missing a kernel file!!" );
+ exit(2);
+ }
+ D("autoconfig: -kernel %s", kernelFile);
+ }
+ if (!path_exists(kernelFile)) {
+ derror( "Invalid or missing kernel image file: %s", kernelFile );
+ exit(2);
+ }
+
+ hw->kernel_path = kernelFile;
/* If the kernel image name ends in "-armv7", then change the cpu
* type automatically. This is a poor man's approach to configuration
@@ -722,6 +412,7 @@
* some build system changes. I prefer not to do that for now for reasons
* of simplicity.
*/
+ kernelFileLen = strlen(kernelFile);
if (kernelFileLen > 6 && !memcmp(kernelFile + kernelFileLen - 6, "-armv7", 6)) {
args[n++] = "-cpu";
args[n++] = "cortex-a8";
@@ -762,11 +453,6 @@
args[n++] = "-netfast";
}
- /* the purpose of -no-audio is to disable sound output from the emulator,
- * not to disable Audio emulation. So simply force the 'none' backends */
- if (opts->no_audio)
- opts->audio = "none";
-
if (opts->audio) {
args[n++] = "-audio";
args[n++] = opts->audio;
@@ -782,9 +468,12 @@
args[n++] = opts->dns_server;
}
- args[n++] = "-initrd";
- args[n++] = (char*) avdInfo_getImageFile(avd, AVD_IMAGE_RAMDISK);
+ hw->disk_ramdisk_path = avdInfo_getRamdiskPath(avd);
+ D("autoconfig: -ramdisk %s", hw->disk_ramdisk_path);
+ /* -partition-size is used to specify the max size of both the system
+ * and data partition sizes.
+ */
if (opts->partition_size) {
char* end;
long sizeMB = strtol(opts->partition_size, &end, 0);
@@ -800,105 +489,233 @@
sizeMB, minSizeMB, maxSizeMB );
exit(1);
}
- defaultPartitionSize = sizeMB * ONE_MB;
+ defaultPartitionSize = (uint64_t) sizeMB * ONE_MB;
}
- /* Check the size of the system partition image.
- * If we have an AVD, it must be smaller than
- * the disk.systemPartition.size hardware property.
- *
- * Otherwise, we need to adjust the systemPartitionSize
- * automatically, and print a warning.
- *
- */
- {
- uint64_t systemBytes = avdInfo_getImageFileSize(avd, AVD_IMAGE_INITSYSTEM);
- uint64_t defaultBytes = defaultPartitionSize;
- if (defaultBytes == 0 || opts->partition_size)
- defaultBytes = defaultPartitionSize;
+ /** SYSTEM PARTITION **/
- systemPartitionSize = _adjustPartitionSize("system", systemBytes, defaultBytes,
- android_build_out != NULL);
+ if (opts->sysdir == NULL) {
+ if (avdInfo_inAndroidBuild(avd)) {
+ opts->sysdir = ASTRDUP(avdInfo_getContentPath(avd));
+ D("autoconfig: -sysdir %s", opts->sysdir);
+ }
}
- /* Check the size of the /data partition. The only interesting cases here are:
- * - when the USERDATA image already exists and is larger than the default
- * - when we're wiping data and the INITDATA is larger than the default.
- */
+ if (opts->sysdir != NULL) {
+ if (!path_exists(opts->sysdir)) {
+ derror("Directory does not exist: %s", opts->sysdir);
+ exit(1);
+ }
+ }
{
- const char* dataPath = avdInfo_getImageFile(avd, AVD_IMAGE_USERDATA);
+ char* rwImage = NULL;
+ char* initImage = NULL;
+
+ do {
+ if (opts->system == NULL) {
+ /* If -system is not used, try to find a runtime system image
+ * (i.e. system-qemu.img) in the content directory.
+ */
+ rwImage = avdInfo_getSystemImagePath(avd);
+ if (rwImage != NULL) {
+ break;
+ }
+ /* Otherwise, try to find the initial system image */
+ initImage = avdInfo_getSystemInitImagePath(avd);
+ if (initImage == NULL) {
+ derror("No initial system image for this configuration!");
+ exit(1);
+ }
+ break;
+ }
+
+ /* If -system <name> is used, use it to find the initial image */
+ if (opts->sysdir != NULL) {
+ initImage = _getFullFilePath(opts->sysdir, opts->system);
+ } else {
+ initImage = ASTRDUP(opts->system);
+ }
+ if (!path_exists(initImage)) {
+ derror("System image file doesn't exist: %s", initImage);
+ exit(1);
+ }
+
+ } while (0);
+
+ if (rwImage != NULL) {
+ /* Use the read/write image file directly */
+ hw->disk_systemPartition_path = rwImage;
+ hw->disk_systemPartition_initPath = NULL;
+ D("Using direct system image: %s", rwImage);
+ } else if (initImage != NULL) {
+ hw->disk_systemPartition_path = NULL;
+ hw->disk_systemPartition_initPath = initImage;
+ D("Using initial system image: %s", initImage);
+ }
+
+ /* Check the size of the system partition image.
+ * If we have an AVD, it must be smaller than
+ * the disk.systemPartition.size hardware property.
+ *
+ * Otherwise, we need to adjust the systemPartitionSize
+ * automatically, and print a warning.
+ *
+ */
+ const char* systemImage = hw->disk_systemPartition_path;
+ uint64_t systemBytes;
+
+ if (systemImage == NULL)
+ systemImage = hw->disk_systemPartition_initPath;
+
+ if (path_get_size(systemImage, &systemBytes) < 0) {
+ derror("Missing system image: %s", systemImage);
+ exit(1);
+ }
+
+ hw->disk_systemPartition_size =
+ _adjustPartitionSize("system", systemBytes, defaultPartitionSize,
+ avdInfo_inAndroidBuild(avd));
+ }
+
+ /** DATA PARTITION **/
+
+ if (opts->datadir) {
+ if (!path_exists(opts->datadir)) {
+ derror("Invalid -datadir directory: %s", opts->datadir);
+ }
+ }
+
+ {
+ char* dataImage = NULL;
+ char* initImage = NULL;
+
+ do {
+ if (!opts->data) {
+ dataImage = avdInfo_getDataImagePath(avd);
+ if (dataImage != NULL) {
+ D("autoconfig: -data %s", dataImage);
+ break;
+ }
+ dataImage = avdInfo_getDefaultDataImagePath(avd);
+ if (dataImage == NULL) {
+ derror("No data image path for this configuration!");
+ exit (1);
+ }
+ opts->wipe_data = 1;
+ break;
+ }
+
+ if (opts->datadir) {
+ dataImage = _getFullFilePath(opts->datadir, opts->data);
+ } else {
+ dataImage = ASTRDUP(opts->data);
+ }
+ } while (0);
+
+ if (opts->initdata != NULL) {
+ initImage = ASTRDUP(opts->initdata);
+ if (!path_exists(initImage)) {
+ derror("Invalid initial data image path: %s", initImage);
+ exit(1);
+ }
+ } else {
+ initImage = avdInfo_getDataInitImagePath(avd);
+ D("autoconfig: -initdata %s", initImage);
+ }
+
+ hw->disk_dataPartition_path = dataImage;
+ if (opts->wipe_data) {
+ hw->disk_dataPartition_initPath = initImage;
+ } else {
+ hw->disk_dataPartition_initPath = NULL;
+ }
+
uint64_t defaultBytes = defaultPartitionSize;
+ uint64_t dataBytes;
+ const char* dataPath = hw->disk_dataPartition_initPath;
- if (defaultBytes == 0 || opts->partition_size)
- defaultBytes = defaultPartitionSize;
+ if (dataPath == NULL)
+ dataPath = hw->disk_dataPartition_path;
- if (dataPath == NULL || !path_exists(dataPath) || opts->wipe_data) {
- dataPath = avdInfo_getImageFile(avd, AVD_IMAGE_INITDATA);
- }
- if (dataPath == NULL || !path_exists(dataPath)) {
- dataPartitionSize = defaultBytes;
- }
- else {
- uint64_t dataBytes;
- path_get_size(dataPath, &dataBytes);
+ path_get_size(dataPath, &dataBytes);
- dataPartitionSize = _adjustPartitionSize("data", dataBytes, defaultBytes,
- android_build_out != NULL);
- }
+ hw->disk_dataPartition_size =
+ _adjustPartitionSize("data", dataBytes, defaultBytes,
+ avdInfo_inAndroidBuild(avd));
}
+ /** CACHE PARTITION **/
+
+ if (opts->no_cache) {
+ /* No cache partition at all */
+ hw->disk_cachePartition = 0;
+ }
+ else if (!hw->disk_cachePartition) {
+ if (opts->cache) {
+ dwarning( "Emulated hardware doesn't support a cache partition. -cache option ignored!" );
+ opts->cache = NULL;
+ }
+ }
+ else
{
- const char* filetype = "file";
+ if (!opts->cache) {
+ /* Find the current cache partition file */
+ opts->cache = avdInfo_getCachePath(avd);
+ if (opts->cache == NULL) {
+ /* The file does not exists, we will force its creation
+ * if we are not in the Android build system. Otherwise,
+ * a temporary file will be used.
+ */
+ if (!avdInfo_inAndroidBuild(avd)) {
+ opts->cache = avdInfo_getDefaultCachePath(avd);
+ }
+ }
+ if (opts->cache) {
+ D("autoconfig: -cache %s", opts->cache);
+ }
+ }
- if (avdInfo_isImageReadOnly(avd, AVD_IMAGE_INITSYSTEM))
- filetype = "initfile";
-
- bufprint(tmp, tmpend,
- "system,size=0x%x,%s=%s", systemPartitionSize, filetype,
- avdInfo_getImageFile(avd, AVD_IMAGE_INITSYSTEM));
-
- args[n++] = "-nand";
- args[n++] = strdup(tmp);
+ if (opts->cache) {
+ hw->disk_cachePartition_path = ASTRDUP(opts->cache);
+ }
}
- bufprint(tmp, tmpend,
- "userdata,size=0x%x,file=%s",
- dataPartitionSize,
- avdInfo_getImageFile(avd, AVD_IMAGE_USERDATA));
+ /** SD CARD PARTITION */
- args[n++] = "-nand";
- args[n++] = strdup(tmp);
+ if (!hw->hw_sdCard) {
+ /* No SD Card emulation, so -sdcard will be ignored */
+ if (opts->sdcard) {
+ dwarning( "Emulated hardware doesn't support SD Cards. -sdcard option ignored." );
+ opts->sdcard = NULL;
+ }
+ } else {
+ /* Auto-configure -sdcard if it is not available */
+ if (!opts->sdcard) {
+ do {
+ /* If -datadir <path> is used, look for a sdcard.img file here */
+ if (opts->datadir) {
+ bufprint(tmp, tmpend, "%s/%s", opts->datadir, "system.img");
+ if (path_exists(tmp)) {
+ opts->sdcard = strdup(tmp);
+ break;
+ }
+ }
- if (hw->disk_cachePartition) {
- opts->cache = (char*) avdInfo_getImageFile(avd, AVD_IMAGE_CACHE);
- cachePartitionSize = hw->disk_cachePartition_size;
- }
- else if (opts->cache) {
- dwarning( "Emulated hardware doesn't support a cache partition" );
- opts->cache = NULL;
- opts->no_cache = 1;
- }
+ /* Otherwise, look at the AVD's content */
+ opts->sdcard = avdInfo_getSdCardPath(avd);
+ if (opts->sdcard != NULL) {
+ break;
+ }
- if (opts->cache) {
- /* use a specific cache file */
- sprintf(tmp, "cache,size=0x%0x,file=%s", cachePartitionSize, opts->cache);
- args[n++] = "-nand";
- args[n++] = strdup(tmp);
- }
- else if (!opts->no_cache) {
- /* create a temporary cache partition file */
- sprintf(tmp, "cache,size=0x%0x", cachePartitionSize);
- args[n++] = "-nand";
- args[n++] = strdup(tmp);
- }
+ /* Nothing */
+ } while (0);
- if (hw->hw_sdCard != 0)
- opts->sdcard = (char*) avdInfo_getImageFile(avd, AVD_IMAGE_SDCARD);
- else if (opts->sdcard) {
- dwarning( "Emulated hardware doesn't support SD Cards" );
- opts->sdcard = NULL;
+ if (opts->sdcard) {
+ D("autoconfig: -sdcard %s", opts->sdcard);
+ }
+ }
}
if(opts->sdcard) {
@@ -911,80 +728,102 @@
if (size < 9*1024*1024ULL) {
fprintf(stderr, "### WARNING: SD Card files must be at least 9MB, ignoring '%s'\n", opts->sdcard);
} else {
- args[n++] = "-hda";
- args[n++] = opts->sdcard;
- use_sdcard_img = 1;
+ hw->hw_sdCard_path = ASTRDUP(opts->sdcard);
}
} else {
- D("no SD Card image at '%s'", opts->sdcard);
+ dwarning("no SD Card image at '%s'", opts->sdcard);
}
}
-#if CONFIG_ANDROID_SNAPSHOTS
- if (!opts->no_snapstorage) {
- opts->snapstorage = (char*) avdInfo_getImageFile(avd, AVD_IMAGE_SNAPSHOTS);
- if(opts->snapstorage) {
- if (path_exists(opts->snapstorage)) {
- args[n++] = "-hdb";
- args[n++] = opts->snapstorage;
- } else {
- D("no image at '%s', state snapshots disabled", opts->snapstorage);
+
+ /** SNAPSHOT STORAGE HANDLING */
+
+ /* Determine snapstorage path. -no-snapstorage disables all snapshotting
+ * support. This means you can't resume a snapshot at load, save it at
+ * exit, or even load/save them dynamically at runtime with the console.
+ */
+ if (opts->no_snapstorage) {
+
+ if (opts->snapshot) {
+ dwarning("ignoring -snapshot option due to the use of -no-snapstorage");
+ opts->snapshot = NULL;
+ }
+
+ if (opts->snapstorage) {
+ dwarning("ignoring -snapstorage option due to the use of -no-snapstorage");
+ opts->snapstorage = NULL;
+ }
+ }
+ else
+ {
+ if (!opts->snapstorage) {
+ opts->snapstorage = avdInfo_getSnapStoragePath(avd);
+ if (opts->snapstorage != NULL) {
+ D("autoconfig: -snapstorage %s", opts->snapstorage);
}
}
- if (!opts->no_snapshot) {
- char* snapshot_name =
- opts->snapshot ? opts->snapshot : "default-boot";
- if (!opts->no_snapshot_load) {
- args[n++] = "-loadvm";
- args[n++] = snapshot_name;
- }
- if (!opts->no_snapshot_save) {
- args[n++] = "-savevm-on-exit";
- args[n++] = snapshot_name;
- }
- } else if (opts->snapshot) {
- dwarning("option '-no-snapshot' overrides '-snapshot', continuing with boot sequence");
- } else if (opts->no_snapshot_load || opts->no_snapshot_save) {
- D("ignoring redundant option(s) '-no-snapshot-load' and/or '-no-snapshot-save' implied by '-no-snapshot'");
+ if (opts->snapstorage && !path_exists(opts->snapstorage)) {
+ D("no image at '%s', state snapshots disabled", opts->snapstorage);
+ opts->snapstorage = NULL;
}
+ }
+
+ /* If we have a valid snapshot storage path */
+
+ if (opts->snapstorage) {
+
+ hw->disk_snapStorage_path = ASTRDUP(opts->snapstorage);
+
+ /* -no-snapshot is equivalent to using both -no-snapshot-load
+ * and -no-snapshot-save. You can still load/save snapshots dynamically
+ * from the console though.
+ */
+ if (opts->no_snapshot) {
+
+ opts->no_snapshot_load = 1;
+ opts->no_snapshot_save = 1;
+
+ if (opts->snapshot) {
+ dwarning("ignoring -snapshot option due to the use of -no-snapshot.");
+ }
+ }
+
+ if (!opts->no_snapshot_load || !opts->no_snapshot_save) {
+ if (opts->snapshot == NULL) {
+ opts->snapshot = "default-boot";
+ D("autoconfig: -snapshot %s", opts->snapshot);
+ }
+ }
+
+ /* We still use QEMU command-line options for the following since
+ * they can change from one invokation to the next and don't really
+ * correspond to the hardware configuration itself.
+ */
+ if (!opts->no_snapshot_load) {
+ args[n++] = "-loadvm";
+ args[n++] = ASTRDUP(opts->snapshot);
+ }
+
+ if (!opts->no_snapshot_save) {
+ args[n++] = "-savevm-on-exit";
+ args[n++] = ASTRDUP(opts->snapshot);
+ }
+
if (opts->no_snapshot_update_time) {
- android_snapshot_update_time = 0;
+ args[n++] = "-snapshot-no-time-update";
}
- } else if (opts->snapshot || opts->snapstorage) {
- dwarning("option '-no-snapstorage' overrides '-snapshot' and '-snapstorage', "
- "continuing with full boot, state snapshots are disabled");
- } else if (opts->no_snapshot) {
- D("ignoring redundant option '-no-snapshot' implied by '-no-snapstorage'");
}
- if (opts->snapshot_list) {
- snapshot_print_and_exit(opts->snapstorage);
- }
-#endif // CONFIG_ANDROID_SNAPSHOTS
-
if (!opts->logcat || opts->logcat[0] == 0) {
opts->logcat = getenv("ANDROID_LOG_TAGS");
if (opts->logcat && opts->logcat[0] == 0)
opts->logcat = NULL;
}
-#if 0
- if (opts->console) {
- derror( "option -console is obsolete. please use -shell instead" );
- exit(1);
- }
-#endif
-
/* we always send the kernel messages from ttyS0 to android_kmsg */
- {
- if (opts->show_kernel) {
- args[n++] = "-show-kernel";
- }
-
- args[n++] = "-serial";
- args[n++] = "android-kmsg";
- serial++;
+ if (opts->show_kernel) {
+ args[n++] = "-show-kernel";
}
/* XXXX: TODO: implement -shell and -logcat through qemud instead */
@@ -1004,39 +843,14 @@
shell_serial = serial++;
}
- if (opts->old_system)
- {
- if (opts->radio) {
- args[n++] = "-serial";
- args[n++] = opts->radio;
- radio_serial = serial++;
- }
- else {
- args[n++] = "-serial";
- args[n++] = "android-modem";
- radio_serial = serial++;
- }
- if (opts->gps) {
- args[n++] = "-serial";
- args[n++] = opts->gps;
- gps_serial = serial++;
- }
+ if (opts->radio) {
+ args[n++] = "-radio";
+ args[n++] = opts->radio;
}
- else /* !opts->old_system */
- {
- args[n++] = "-serial";
- args[n++] = "android-qemud";
- qemud_serial = serial++;
- if (opts->radio) {
- args[n++] = "-radio";
- args[n++] = opts->radio;
- }
-
- if (opts->gps) {
- args[n++] = "-gps";
- args[n++] = opts->gps;
- }
+ if (opts->gps) {
+ args[n++] = "-gps";
+ args[n++] = opts->gps;
}
if (opts->memory) {
@@ -1050,6 +864,7 @@
derror( "physical memory size must be between 32 and 4096 MB" );
exit(1);
}
+ hw->hw_ramSize = ramSize;
}
if (!opts->memory) {
int ramSize = hw->hw_ramSize;
@@ -1059,8 +874,7 @@
* size through its hardware.ini (i.e. legacy ones) or when
* in the full Android build system.
*/
- int64_t pixels = get_screen_pixels(skinConfig);
-
+ int64_t pixels = hw->hw_lcd_width * hw->hw_lcd_height;
/* The following thresholds are a bit liberal, but we
* essentially want to ensure the following mappings:
*
@@ -1078,8 +892,30 @@
else
ramSize = 256;
}
- bufprint(tmp, tmpend, "%d", ramSize);
- opts->memory = android_strdup(tmp);
+ hw->hw_ramSize = ramSize;
+ }
+
+ D("Physical RAM size: %dMB\n", hw->hw_ramSize);
+
+ if (hw->vm_heapSize == 0) {
+ /* Compute the default heap size based on the RAM size.
+ * Essentially, we want to ensure the following liberal mappings:
+ *
+ * 96MB RAM -> 16MB heap
+ * 128MB RAM -> 24MB heap
+ * 256MB RAM -> 48MB heap
+ */
+ int ramSize = hw->hw_ramSize;
+ int heapSize;
+
+ if (ramSize < 100)
+ heapSize = 16;
+ else if (ramSize < 192)
+ heapSize = 24;
+ else
+ heapSize = 48;
+
+ hw->vm_heapSize = heapSize;
}
if (opts->trace) {
@@ -1089,11 +925,6 @@
args[n++] = "off";
}
- /* Pass LCD density value to the core. */
- snprintf(lcd_density, sizeof(lcd_density), "%d", get_device_dpi(opts));
- args[n++] = "-lcd-density";
- args[n++] = lcd_density;
-
/* Pass boot properties to the core. */
if (opts->prop != NULL) {
ParamList* pl = opts->prop;
@@ -1103,27 +934,15 @@
}
}
- args[n++] = "-append";
-
- if (opts->bootchart) {
- char* end;
- int timeout = strtol(opts->bootchart, &end, 10);
- if (timeout == 0)
- opts->bootchart = NULL;
- else if (timeout < 0 || timeout > 15*60) {
- derror( "timeout specified for -bootchart option is invalid.\n"
- "please use integers between 1 and 900\n");
- exit(1);
- }
- }
-
/* Setup the kernel init options
*/
{
static char params[1024];
char *p = params, *end = p + sizeof(params);
- p = bufprint(p, end, "qemu=1 console=ttyS0" );
+ /* Don't worry about having a leading space here, this is handled
+ * by the core later. */
+
#ifdef TARGET_I386
p = bufprint(p, end, " androidboot.hardware=goldfish");
p = bufprint(p, end, " clocksource=pit");
@@ -1161,19 +980,6 @@
p = q;
}
- if (opts->old_system)
- {
- p = bufprint(p, end, " android.ril=ttyS%d", radio_serial);
-
- if (opts->gps) {
- p = bufprint(p, end, " android.gps=ttyS%d", gps_serial);
- }
- }
- else
- {
- p = bufprint(p, end, " android.qemud=ttyS%d", qemud_serial);
- }
-
if (opts->bootchart) {
p = bufprint(p, end, " androidboot.bootchart=%s", opts->bootchart);
}
@@ -1183,7 +989,7 @@
exit(1);
}
- args[n++] = strdup(params);
+ hw->kernel_parameters = strdup(params);
}
if (opts->ports) {
@@ -1216,21 +1022,9 @@
args[n++] = opts->memcheck;
}
- /* physical memory */
- args[n++] = "-m";
- args[n++] = opts->memory;
+ /* physical memory is now in hw->hw_ramSize */
- /* on Linux, the 'dynticks' clock sometimes doesn't work
- * properly. this results in the UI freezing while emulation
- * continues, for several seconds...
- */
-#ifdef __linux__
- args[n++] = "-clock";
- args[n++] = "unix";
-#endif
-
- args[n++] = "-android-avdname";
- args[n++] = avdInfo_getName(avd);
+ hw->avd_name = ASTRDUP(avdInfo_getName(avd));
/* Set up the interfaces for inter-emulator networking */
if (opts->shared_net_id) {
@@ -1254,29 +1048,32 @@
}
args[n] = 0;
- /* Generate a temporary hardware.ini for this AVD. The real hardware
+ /* Generate a hardware-qemu.ini for this AVD. The real hardware
* configuration is ususally stored in several files, e.g. the AVD's
* config.ini plus the skin-specific hardware.ini.
*
- * The new temp file will group all definitions and will be used to
+ * The new file will group all definitions and will be used to
* launch the core with the -android-hw <file> option.
*/
{
- TempFile* tempHw = tempfile_create();
- if (tempHw == NULL) {
- derror("Could not create temporary hardware.ini: %s", strerror(errno));
- exit(2);
+ const char* coreHwIniPath = avdInfo_getCoreHwIniPath(avd);
+ IniFile* hwIni = iniFile_newFromMemory("", NULL);
+ androidHwConfig_write(hw, hwIni);
+
+ if (filelock_create(coreHwIniPath) == NULL) {
+ /* The AVD is already in use, we still support this as an
+ * experimental feature. Use a temporary hardware-qemu.ini
+ * file though to avoid overwriting the existing one. */
+ TempFile* tempIni = tempfile_create();
+ coreHwIniPath = tempfile_path(tempIni);
}
- const char* tempHwPath = tempfile_path(tempHw);
- IniFile* hwIni = iniFile_newFromMemory("", NULL);
- androidHwConfig_write(hw, hwIni);
- if (iniFile_saveToFile(hwIni, tempHwPath) < 0) {
- derror("Could not write temporary hardware.ini: %s", tempHwPath);
+ if (iniFile_saveToFile(hwIni, coreHwIniPath) < 0) {
+ derror("Could not write hardware.ini to %s: %s", coreHwIniPath, strerror(errno));
exit(2);
}
args[n++] = "-android-hw";
- args[n++] = strdup(tempHwPath);
+ args[n++] = strdup(coreHwIniPath);
}
if(VERBOSE_CHECK(init)) {
@@ -1288,7 +1085,14 @@
/* Dump final command-line option to make debugging the core easier */
printf("Concatenated QEMU options:\n");
for (i = 0; i < n; i++) {
- printf(" %s", args[i]);
+ /* To make it easier to copy-paste the output to a command-line,
+ * quote anything that contains spaces.
+ */
+ if (strchr(args[i], ' ') != NULL) {
+ printf(" '%s'", args[i]);
+ } else {
+ printf(" %s", args[i]);
+ }
}
printf("\n");
}
@@ -1296,5 +1100,10 @@
/* Setup SDL UI just before calling the code */
init_sdl_ui(skinConfig, skinPath, opts);
+ if (attach_ui_to_core(opts) < 0) {
+ derror("Can't attach to core!");
+ exit(1);
+ }
+
return qemu_main(n, args);
}
diff --git a/android/qemulator.c b/android/qemulator.c
index ee9ccbb..b15d751 100644
--- a/android/qemulator.c
+++ b/android/qemulator.c
@@ -258,7 +258,7 @@
* Helper routines
*/
-int
+static int
get_device_dpi( AndroidOptions* opts )
{
int dpi_device = corecmd_get_hw_lcd_density();
diff --git a/android/qemulator.h b/android/qemulator.h
index 189cc53..bd77ae1 100644
--- a/android/qemulator.h
+++ b/android/qemulator.h
@@ -66,8 +66,4 @@
QFrameBuffer*
qemulator_get_first_framebuffer(QEmulator* emulator);
-/* A helper routine for getting device DPI. */
-int
-get_device_dpi( AndroidOptions* opts );
-
#endif // QEMU_ANDROID_QEMULATOR_H
diff --git a/android/skin/file.c b/android/skin/file.c
index dddc279..252a7c4 100644
--- a/android/skin/file.c
+++ b/android/skin/file.c
@@ -128,6 +128,7 @@
{ "soft-left", kKeyCodeSoftLeft },
{ "soft-right", kKeyCodeSoftRight },
{ "search", kKeyCodeSearch },
+ { "camera", kKeyCodeCamera },
{ "volume-up", kKeyCodeVolumeUp },
{ "volume-down", kKeyCodeVolumeDown },
{ "power", kKeyCodePower },
diff --git a/android/snapshot.c b/android/snapshot.c
index ca86700..047465f 100644
--- a/android/snapshot.c
+++ b/android/snapshot.c
@@ -33,12 +33,10 @@
#include <time.h>
#include <unistd.h>
+#include "bswap.h"
#include "android/utils/debug.h"
#include "android/utils/system.h"
-#include "bswap.h"
-#include "snapshot.h"
-
-#if CONFIG_ANDROID_SNAPSHOTS
+#include "android/snapshot.h"
/* "Magic" sequence of four bytes required by spec to be the first four bytes
* of any Qcow file.
@@ -333,4 +331,3 @@
close(fd);
exit(0);
}
-#endif // CONFIG_ANDROID_SNAPSHOTS
diff --git a/android/snapshot.h b/android/snapshot.h
index c0d5965..b3d954f 100644
--- a/android/snapshot.h
+++ b/android/snapshot.h
@@ -14,13 +14,11 @@
* limitations under the License.
*/
-#ifndef SNAPSHOTS_H_
-#define SNAPSHOTS_H_
+#ifndef ANDROID_SNAPSHOT_H
+#define ANDROID_SNAPSHOT_H
#include "config/config.h"
-#if CONFIG_ANDROID_SNAPSHOTS
-
/* Prints a table with information on the snapshot stored in the file
* 'snapstorage', then exit()s.
*/
@@ -30,6 +28,4 @@
extern int android_snapshot_update_time;
extern int android_snapshot_update_time_request;
-#endif
-
-#endif /* SNAPSHOTS_H_ */
+#endif /* ANDROID_SNAPSHOT_H */
diff --git a/android/utils/ini.c b/android/utils/ini.c
index a5914dd..ff4a8af 100644
--- a/android/utils/ini.c
+++ b/android/utils/ini.c
@@ -480,19 +480,22 @@
{
char temp[32];
int64_t divisor = 0;
+ const int64_t kilo = 1024;
+ const int64_t mega = 1024*kilo;
+ const int64_t giga = 1024*mega;
char suffix = '\0';
- if (size >= 0) {
- if (!(size % 1024)) {
- suffix = 'k';
- divisor = 1024;
- } else if (!(size % 1024*1024)) {
- divisor = 1024*1024;
- suffix = 'm';
- } else if (!(size % 1024*1024*1024LL)) {
- divisor = 1024*1024*1024;
- suffix = 'g';
- }
+ if (size >= giga && !(size % giga)) {
+ divisor = giga;
+ suffix = 'g';
+ }
+ else if (size >= mega && !(size % mega)) {
+ divisor = mega;
+ suffix = 'm';
+ }
+ else if (size >= kilo && !(size % kilo)) {
+ divisor = kilo;
+ suffix = 'k';
}
if (divisor) {
snprintf(temp, sizeof temp, "%" PRId64 "%c", size/divisor, suffix);
diff --git a/android/utils/stralloc.c b/android/utils/stralloc.c
index 2a924e4..ce5d800 100644
--- a/android/utils/stralloc.c
+++ b/android/utils/stralloc.c
@@ -19,7 +19,7 @@
#include <limits.h>
extern void
-stralloc_tabular( stralloc_t* out,
+stralloc_tabular( stralloc_t* out,
const char** strings, int count,
const char* prefix, int width )
{
@@ -138,6 +138,40 @@
return s->s;
}
+void
+stralloc_lstrip( stralloc_t* s )
+{
+ int count;
+
+ for (count = 0; count < s->n; count++) {
+ if (s->s[count] != ' ' && s->s[count] != '\t')
+ break;
+ }
+
+ if (count > 0) {
+ memmove(s->s, s->s + count, s->n - count);
+ s->n -= count;
+ }
+}
+
+void
+stralloc_rstrip( stralloc_t* s )
+{
+ int count = s->n;
+
+ while (count > 0 && (s->s[count-1] == ' ' || s->s[count-1] == '\t'))
+ count--;
+
+ s->n = count;
+}
+
+void
+stralloc_strip( stralloc_t* s )
+{
+ stralloc_rstrip(s);
+ stralloc_lstrip(s);
+}
+
extern char*
stralloc_to_tempstr( stralloc_t* s )
{
diff --git a/android/utils/stralloc.h b/android/utils/stralloc.h
index 4d17060..626a638 100644
--- a/android/utils/stralloc.h
+++ b/android/utils/stralloc.h
@@ -52,6 +52,11 @@
extern void stralloc_add_hex( stralloc_t* s, unsigned value, int num_digits );
extern void stralloc_add_hexdump( stralloc_t* s, void* base, int size, const char* prefix );
+/* Remove leading, trailing or leading+trailing whitespace */
+extern void stralloc_lstrip( stralloc_t* s );
+extern void stralloc_rstrip( stralloc_t* s );
+extern void stralloc_strip( stralloc_t* s );
+
extern void stralloc_tabular( stralloc_t* s, const char** strings, int count,
const char* prefix, int width );
diff --git a/android/utils/system.h b/android/utils/system.h
index c8163c6..464957d 100644
--- a/android/utils/system.h
+++ b/android/utils/system.h
@@ -173,6 +173,12 @@
#ifndef PRIx64
# define PRIx64 "llx"
#endif
+#ifndef PRUd64
+# define PRUd64 "llu"
+#endif
+#ifndef PRUx64
+# define PRUx64 "llx"
+#endif
/* */
diff --git a/disas.c b/disas.c
index 79a98de..475aa86 100644
--- a/disas.c
+++ b/disas.c
@@ -8,6 +8,10 @@
#include "exec-all.h"
#include "disas.h"
+#ifdef TARGET_I386
+#include "kvm.h"
+#endif
+
/* Filled in by elfload.c. Simplistic, but will do for now. */
struct syminfo *syminfos = NULL;
@@ -33,6 +37,10 @@
int length,
struct disassemble_info *info)
{
+#ifdef TARGET_I386
+ if (kvm_enabled())
+ cpu_synchronize_state(cpu_single_env, 0);
+#endif
cpu_memory_rw_debug(cpu_single_env, memaddr, myaddr, length, 0);
return 0;
}
diff --git a/distrib/build-kernel.sh b/distrib/build-kernel.sh
new file mode 100755
index 0000000..c7e9a8f
--- /dev/null
+++ b/distrib/build-kernel.sh
@@ -0,0 +1,214 @@
+#!/bin/sh
+#
+# A small script used to rebuild the Android goldfish kernel image
+# See docs/KERNEL.TXT for usage instructions.
+#
+MACHINE=goldfish
+VARIANT=goldfish
+OUTPUT=/tmp/kernel-qemu
+CROSSPREFIX=arm-eabi-
+CONFIG=goldfish
+
+# Determine the host architecture, and which default prebuilt tag we need.
+# For the toolchain auto-detection.
+#
+HOST_OS=`uname -s`
+case "$HOST_OS" in
+ Darwin)
+ HOST_OS=darwin
+ HOST_TAG=darwin-x86
+ BUILD_NUM_CPUS=$(sysctl -n hw.ncpu)
+ ;;
+ Linux)
+ # note that building 32-bit binaries on x86_64 is handled later
+ HOST_OS=linux
+ HOST_TAG=linux-x86
+ BUILD_NUM_CPUS=$(grep -c processor /proc/cpuinfo)
+ ;;
+ *)
+ echo "ERROR: Unsupported OS: $HOST_OS"
+ exit 1
+esac
+
+# Default number of parallel jobs during the build: cores * 2
+JOBS=$(( $BUILD_NUM_CPUS * 2 ))
+
+ARCH=arm
+
+OPTION_HELP=no
+OPTION_ARMV7=no
+OPTION_OUT=
+OPTION_CROSS=
+OPTION_ARCH=
+OPTION_CONFIG=
+OPTION_JOBS=
+
+for opt do
+ optarg=$(expr "x$opt" : 'x[^=]*=\(.*\)')
+ case $opt in
+ --help|-h|-\?) OPTION_HELP=yes
+ ;;
+ --armv7)
+ OPTION_ARMV7=yes
+ ;;
+ --out=*)
+ OPTION_OUT=$optarg
+ ;;
+ --cross=*)
+ OPTION_CROSS=$optarg
+ ;;
+ --arch=*)
+ OPTION_ARCH=$optarg
+ ;;
+ --config=*)
+ OPTION_CONFIG=$optarg
+ ;;
+ -j*)
+ OPTION_JOBS=$optarg
+ ;;
+ *)
+ echo "unknown option '$opt', use --help"
+ exit 1
+ esac
+done
+
+if [ $OPTION_HELP = "yes" ] ; then
+ echo "Rebuild the prebuilt kernel binary for Android's emulator."
+ echo ""
+ echo "options (defaults are within brackets):"
+ echo ""
+ echo " --help print this message"
+ echo " --arch=<arch> change target architecture [$ARCH]"
+ echo " --armv7 build ARMv7 binaries (see note below)"
+ echo " --out=<directory> output directory [$OUTPUT]"
+ echo " --cross=<prefix> cross-toolchain prefix [$CROSSPREFIX]"
+ echo " --config=<name> kernel config name [$CONFIG]"
+ echo " -j<number> launch <number> parallel build jobs [$JOBS]"
+ echo ""
+ echo "NOTE: --armv7 is equivalent to --config=goldfish_armv7. It is"
+ echo " ignored if --config=<name> is used."
+ echo ""
+ exit 0
+fi
+
+if [ -n "$OPTION_ARCH" ]; then
+ ARCH=$OPTION_ARCH
+fi
+
+if [ -n "$OPTION_CONFIG" ]; then
+ CONFIG=$OPTION_CONFIG
+else
+ if [ "$OPTION_ARMV7" = "yes" ]; then
+ CONFIG=goldfish_armv7
+ fi
+ echo "Auto-config: --config=$CONFIG"
+fi
+
+# Check that we are in the kernel directory
+if [ ! -d arch/$ARCH/mach-$MACHINE ] ; then
+ echo "Cannot find arch/$ARCH/mach-$MACHINE. Please cd to the kernel source directory."
+ echo "Aborting."
+ #exit 1
+fi
+
+# Check output directory.
+if [ -n "$OPTION_OUT" ] ; then
+ if [ ! -d "$OPTION_OUT" ] ; then
+ echo "Output directory '$OPTION_OUT' does not exist ! Aborting."
+ exit 1
+ fi
+ OUTPUT=$OPTION_OUT
+else
+ mkdir -p $OUTPUT
+fi
+
+if [ -n "$OPTION_CROSS" ] ; then
+ CROSSPREFIX="$OPTION_CROSS"
+else
+ case $ARCH in
+ arm)
+ CROSSTOOLCHAIN=arm-eabi-4.4.3
+ CROSSPREFIX=arm-eabi-
+ ZIMAGE=zImage
+ ;;
+ x86)
+ CROSSTOOLCHAIN=i686-android-linux-4.4.3
+ CROSSPREFIX=i686-android-linux-
+ ZIMAGE=bzImage
+ ;;
+ *)
+ echo "ERROR: Unsupported architecture!"
+ exit 1
+ ;;
+ esac
+ echo "Auto-config: --cross=$CROSSPREFIX"
+fi
+
+# If the cross-compiler is not in the path, try to find it automatically
+CROSS_COMPILER="${CROSSPREFIX}gcc"
+CROSS_COMPILER_VERSION=$($CROSS_COMPILER --version 2>/dev/null)
+if [ $? != 0 ] ; then
+ BUILD_TOP=$ANDROID_BUILD_TOP
+ if [ -z "$BUILD_TOP" ]; then
+ # Assume this script is under external/qemu/distrib/ in the
+ # Android source tree.
+ BUILD_TOP=$(dirname $0)/../../..
+ if [ ! -d "$BUILD_TOP/prebuilt" ]; then
+ BUILD_TOP=
+ else
+ BUILD_TOP=$(cd $BUILD_TOP && pwd)
+ fi
+ fi
+ CROSSPREFIX=$BUILD_TOP/prebuilt/$HOST_TAG/toolchain/$CROSSTOOLCHAIN/bin/$CROSSPREFIX
+ if [ "$BUILD_TOP" -a -f ${CROSSPREFIX}gcc ]; then
+ echo "Auto-config: --cross=$CROSSPREFIX"
+ else
+ echo "It looks like $CROSS_COMPILER is not in your path ! Aborting."
+ exit 1
+ fi
+fi
+
+export CROSS_COMPILE="$CROSSPREFIX" ARCH SUBARCH=$ARCH
+
+if [ "$OPTION_JOBS" ]; then
+ JOBS=$OPTION_JOBS
+else
+ echo "Auto-config: -j$JOBS"
+fi
+
+# Do the build
+#
+rm -f include/asm &&
+make ${CONFIG}_defconfig && # configure the kernel
+make -j$JOBS # build it
+
+if [ $? != 0 ] ; then
+ echo "Could not build the kernel. Aborting !"
+ exit 1
+fi
+
+# Note: The exact names of the output files are important for the Android build,
+# do not change the definitions lightly.
+case $CONFIG in
+ vbox*)
+ OUTPUT_KERNEL=kernel-vbox
+ OUTPUT_VMLINUX=vmlinux-vbox
+ ;;
+ goldfish)
+ OUTPUT_KERNEL=kernel-qemu
+ OUTPUT_VMLINUX=vmlinux-qemu
+ ;;
+ goldfish_armv7)
+ OUTPUT_KERNEL=kernel-qemu-armv7
+ OUTPUT_VMLINUX=vmlinux-qemu-armv7
+ ;;
+ *)
+ OUTPUT_KERNEL=kernel-$CONFIG
+ OUTPUT_VMLINUX=vmlinux-$CONFIG
+esac
+
+cp -f arch/$ARCH/boot/$ZIMAGE $OUTPUT/$OUTPUT_KERNEL
+cp -f vmlinux $OUTPUT/$OUTPUT_VMLINUX
+
+echo "Kernel $CONFIG prebuilt images ($OUTPUT_KERNEL and $OUTPUT_VMLINUX) copied to $OUTPUT successfully !"
+exit 0
diff --git a/distrib/sdl-1.2.12/Makefile.android b/distrib/sdl-1.2.12/Makefile.android
index 4e89fc7..2dfa7dd 100644
--- a/distrib/sdl-1.2.12/Makefile.android
+++ b/distrib/sdl-1.2.12/Makefile.android
@@ -85,8 +85,8 @@
$(foreach target,$(INSTALL_TARGETS),\
$(eval $(call install-target,objs/sdl-config,$(target)/bin/sdl-config)) \
$(eval $(call install-target,objs/SDL_config.h,$(target)/include/SDL/SDL_config.h)) \
- $(eval $(call install-target,objs/libSDL.a,$(target)/lib/libSDL.a)) \
- $(eval $(call install-target,objs/libSDLmain.a,$(target)/lib/libSDLmain.a)) \
+ $(eval $(call install-target,objs/libs/libSDL.a,$(target)/libs/libSDL.a)) \
+ $(eval $(call install-target,objs/libs/libSDLmain.a,$(target)/libs/libSDLmain.a)) \
$(foreach header,$(SDL_HEADERS), \
$(eval $(call install-target,include/$(header),$(target)/include/SDL/$(header))) \
) \
diff --git a/distrib/sdl-1.2.12/android-configure.sh b/distrib/sdl-1.2.12/android-configure.sh
index 133daf4..95bb91f 100755
--- a/distrib/sdl-1.2.12/android-configure.sh
+++ b/distrib/sdl-1.2.12/android-configure.sh
@@ -479,7 +479,7 @@
# replace @exec_prefix@ with "{prefix}", and @libdir@ with "{libdir}"
cat > $TMPC <<EOF
s!@exec_prefix@!\$\{prefix\}!g
-s!@libdir@!\$\{exec_prefix\}/lib!g
+s!@libdir@!\$\{exec_prefix\}/libs!g
s!@includedir@!\$\{prefix\}/include!g
EOF
diff --git a/docs/KERNEL.TXT b/docs/KERNEL.TXT
index e174fe5..35d1f1f 100644
--- a/docs/KERNEL.TXT
+++ b/docs/KERNEL.TXT
@@ -1,6 +1,37 @@
HOW TO REBUILT THE ANDROID EMULATOR-SPECIFIC KERNEL:
====================================================
+I. Helper script:
+-----------------
+
+We now provide a helper script to rebuild the kernel,
+it is under distrib/rebuild-kernel.sh.
+
+You need the sources in android.git.kernel.org/kernel/common.git,
+in branch origin/archive/android-gldfish-2.6.29 (note the typo!)
+
+To rebuild the ARM kernel:
+
+ cd $KERNEL_SOURCES
+ /path/to/rebuild-kernel.sh --out=$ANDROID/prebuilt/android-arm/kernel
+
+To rebuild the x86 kernel:
+
+ cd $KERNEL_SOURCES
+ /path/to/rebuild-kernel.sh --arch=x86 --out=$ANDROID/prebuilt/android-x86/kernel
+
+Note that you will need to have your cross-toolchain in your path.
+If this is not the case, the script will complain and give you the
+expected name. Use --cross=<prefix> to specify a different toolchain.
+
+See rebuild-kernel.sh --help for more options and details.
+
+
+II. Rebuilding from scratch:
+----------------------------
+
+If you don't or can't use the script, here are manual instructions:
+
You need to have the Android toolchain in your path
(i.e. 'arm-eabi-gcc --version' must work)
@@ -8,7 +39,7 @@
git clone git://android.git.kernel.org/kernel/common.git kernel-common
cd kernel-common
-git checkout origin/android-goldfish-2.6.29
+git checkout origin/archive/android-gldfish-2.6.29
export CROSS_COMPILE=arm-eabi-
export ARCH=arm
diff --git a/hw/goldfish_device.c b/hw/goldfish_device.c
index 3ced4ce..e98161a 100644
--- a/hw/goldfish_device.c
+++ b/hw/goldfish_device.c
@@ -12,6 +12,9 @@
#include "qemu_file.h"
#include "arm_pic.h"
#include "goldfish_device.h"
+#ifdef TARGET_I386
+#include "kvm.h"
+#endif
#define PDEV_BUS_OP_DONE (0x00)
#define PDEV_BUS_OP_REMOVE_DEV (0x04)
@@ -148,8 +151,13 @@
};
break;
case PDEV_BUS_GET_NAME:
- if(s->current)
+ if(s->current) {
+#ifdef TARGET_I386
+ if(kvm_enabled())
+ cpu_synchronize_state(cpu_single_env, 0);
+#endif
cpu_memory_rw_debug(cpu_single_env, value, (void*)s->current->name, strlen(s->current->name), 1);
+ }
break;
default:
cpu_abort (cpu_single_env, "goldfish_bus_write: Bad offset %x\n", offset);
diff --git a/hw/goldfish_nand.c b/hw/goldfish_nand.c
index 2aff835..eb0c355 100644
--- a/hw/goldfish_nand.c
+++ b/hw/goldfish_nand.c
@@ -16,6 +16,10 @@
#include "qemu_debug.h"
#include "android/android.h"
+#ifdef TARGET_I386
+#include "kvm.h"
+#endif
+
#define DEBUG 1
#if DEBUG
# define D(...) VERBOSE_PRINT(init,__VA_ARGS__)
@@ -374,6 +378,10 @@
if(!eof) {
read_len = do_read(dev->fd, dev->data, read_len);
}
+#ifdef TARGET_I386
+ if (kvm_enabled())
+ cpu_synchronize_state(cpu_single_env, 0);
+#endif
cpu_memory_rw_debug(cpu_single_env, data, dev->data, read_len, 1);
data += read_len;
len -= read_len;
@@ -393,6 +401,10 @@
while(len > 0) {
if(len < write_len)
write_len = len;
+#ifdef TARGET_I386
+ if (kvm_enabled())
+ cpu_synchronize_state(cpu_single_env, 0);
+#endif
cpu_memory_rw_debug(cpu_single_env, data, dev->data, write_len, 0);
ret = do_write(dev->fd, dev->data, write_len);
if(ret < write_len) {
@@ -455,6 +467,10 @@
case NAND_CMD_GET_DEV_NAME:
if(size > dev->devname_len)
size = dev->devname_len;
+#ifdef TARGET_I386
+ if (kvm_enabled())
+ cpu_synchronize_state(cpu_single_env, 0);
+#endif
cpu_memory_rw_debug(cpu_single_env, s->data, (uint8_t*)dev->devname, size, 1);
return size;
case NAND_CMD_READ:
@@ -464,6 +480,10 @@
size = dev->max_size - addr;
if(dev->fd >= 0)
return nand_dev_read_file(dev, s->data, addr, size);
+#ifdef TARGET_I386
+ if (kvm_enabled())
+ cpu_synchronize_state(cpu_single_env, 0);
+#endif
cpu_memory_rw_debug(cpu_single_env,s->data, &dev->data[addr], size, 1);
return size;
case NAND_CMD_WRITE:
@@ -475,6 +495,10 @@
size = dev->max_size - addr;
if(dev->fd >= 0)
return nand_dev_write_file(dev, s->data, addr, size);
+#ifdef TARGET_I386
+ if (kvm_enabled())
+ cpu_synchronize_state(cpu_single_env, 0);
+#endif
cpu_memory_rw_debug(cpu_single_env,s->data, &dev->data[addr], size, 0);
return size;
case NAND_CMD_ERASE:
@@ -638,6 +662,8 @@
uint32_t extra_size = 64;
uint32_t erase_pages = 64;
+ VERBOSE_PRINT(init, "%s: %s", __FUNCTION__, arg);
+
while(arg) {
next_arg = strchr(arg, ',');
value = strchr(arg, '=');
@@ -662,10 +688,11 @@
if(value != NULL)
goto bad_arg_and_value;
devname_len = arg_len;
- devname = malloc(arg_len);
+ devname = malloc(arg_len+1);
if(devname == NULL)
goto out_of_memory;
memcpy(devname, arg, arg_len);
+ devname[arg_len] = 0;
}
else if(value == NULL) {
if(arg_match("readonly", arg, arg_len)) {
@@ -739,7 +766,7 @@
if(rwfilename) {
rwfd = open(rwfilename, O_BINARY | (read_only ? O_RDONLY : O_RDWR));
- if(rwfd < 0 && read_only) {
+ if(rwfd < 0) {
XLOG("could not open file %s, %s\n", rwfilename, strerror(errno));
exit(1);
}
@@ -792,7 +819,7 @@
exit(1);
}
if(do_write(rwfd, dev->data, read_size) != read_size) {
- XLOG("could not write file %s, %s\n", initfilename, strerror(errno));
+ XLOG("could not write file %s, %s\n", rwfilename, strerror(errno));
exit(1);
}
} while(read_size == dev->erase_size);
diff --git a/hw/goldfish_tty.c b/hw/goldfish_tty.c
index 904a07b..fd8eca8 100644
--- a/hw/goldfish_tty.c
+++ b/hw/goldfish_tty.c
@@ -13,6 +13,10 @@
#include "qemu-char.h"
#include "goldfish_device.h"
+#ifdef TARGET_I386
+#include "kvm.h"
+#endif
+
enum {
TTY_PUT_CHAR = 0x00,
TTY_BYTES_READY = 0x04,
@@ -126,6 +130,10 @@
if (to_write > len)
to_write = len;
+#ifdef TARGET_I386
+ if (kvm_enabled())
+ cpu_synchronize_state(cpu_single_env, 0);
+#endif
cpu_memory_rw_debug(cpu_single_env, buf, (uint8_t*)temp, to_write, 0);
qemu_chr_write(s->cs, (const uint8_t*)temp, to_write);
buf += to_write;
@@ -138,6 +146,10 @@
case TTY_CMD_READ_BUFFER:
if(s->ptr_len > s->data_count)
cpu_abort (cpu_single_env, "goldfish_tty_write: reading more data than available %d %d\n", s->ptr_len, s->data_count);
+#ifdef TARGET_I386
+ if (kvm_enabled())
+ cpu_synchronize_state(cpu_single_env, 0);
+#endif
cpu_memory_rw_debug(cpu_single_env,s->ptr, s->data, s->ptr_len,1);
//printf("goldfish_tty_write: read %d bytes to %x\n", s->ptr_len, s->ptr);
if(s->data_count > s->ptr_len)
diff --git a/hw/hw.h b/hw/hw.h
index 4f9b650..efcbe1e 100644
--- a/hw/hw.h
+++ b/hw/hw.h
@@ -4,7 +4,10 @@
#include "qemu-common.h"
#include "irq.h"
+
+#if defined(TARGET_PHYS_ADDRESS_SPACE_BITS) && !defined(NEED_CPU_H)
#include "cpu.h"
+#endif
/* VM Load/Save */
diff --git a/hw/pc.c b/hw/pc.c
index 72b6813..ff7670e 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -788,6 +788,7 @@
static int parallel_irq[MAX_PARALLEL_PORTS] = { 7, 7, 7 }; */
#ifdef HAS_AUDIO
+#ifndef CONFIG_ANDROID
static void audio_init (PCIBus *pci_bus, qemu_irq *pic)
{
struct soundhw *c;
@@ -805,6 +806,7 @@
}
}
#endif
+#endif
static void pc_init_ne2k_isa(NICInfo *nd, qemu_irq *pic)
{
@@ -1184,7 +1186,11 @@
events_dev_init(event0_device.base, i8259[event0_device.irq]);
#ifdef HAS_AUDIO
+#ifndef CONFIG_ANDROID
audio_init(pci_enabled ? pci_bus : NULL, i8259);
+#else
+ goldfish_audio_init(0xff004000, 0, audio_input_source);
+#endif
#endif
#ifndef CONFIG_ANDROID
diff --git a/kvm-all.c b/kvm-all.c
new file mode 100644
index 0000000..f620417
--- /dev/null
+++ b/kvm-all.c
@@ -0,0 +1,1039 @@
+/*
+ * QEMU KVM support
+ *
+ * Copyright IBM, Corp. 2008
+ * Red Hat, Inc. 2008
+ *
+ * Authors:
+ * Anthony Liguori <aliguori@us.ibm.com>
+ * Glauber Costa <gcosta@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <stdarg.h>
+
+#include <linux/kvm.h>
+
+#include "qemu-common.h"
+#include "sysemu.h"
+#include "hw/hw.h"
+#include "gdbstub.h"
+#include "kvm.h"
+
+/* KVM uses PAGE_SIZE in it's definition of COALESCED_MMIO_MAX */
+#define PAGE_SIZE TARGET_PAGE_SIZE
+
+//#define DEBUG_KVM
+
+#ifdef DEBUG_KVM
+#define dprintf(fmt, ...) \
+ do { fprintf(stderr, fmt, ## __VA_ARGS__); } while (0)
+#else
+#define dprintf(fmt, ...) \
+ do { } while (0)
+#endif
+
+typedef struct KVMSlot
+{
+ target_phys_addr_t start_addr;
+ ram_addr_t memory_size;
+ ram_addr_t phys_offset;
+ int slot;
+ int flags;
+} KVMSlot;
+
+typedef struct kvm_dirty_log KVMDirtyLog;
+
+int kvm_allowed = 0;
+
+struct KVMState
+{
+ KVMSlot slots[32];
+ int fd;
+ int vmfd;
+ int coalesced_mmio;
+ int broken_set_mem_region;
+ int migration_log;
+#ifdef KVM_CAP_SET_GUEST_DEBUG
+ struct kvm_sw_breakpoint_head kvm_sw_breakpoints;
+#endif
+};
+
+static KVMState *kvm_state;
+
+static KVMSlot *kvm_alloc_slot(KVMState *s)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(s->slots); i++) {
+ /* KVM private memory slots */
+ if (i >= 8 && i < 12)
+ continue;
+ if (s->slots[i].memory_size == 0)
+ return &s->slots[i];
+ }
+
+ fprintf(stderr, "%s: no free slot available\n", __func__);
+ abort();
+}
+
+static KVMSlot *kvm_lookup_matching_slot(KVMState *s,
+ target_phys_addr_t start_addr,
+ target_phys_addr_t end_addr)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(s->slots); i++) {
+ KVMSlot *mem = &s->slots[i];
+
+ if (start_addr == mem->start_addr &&
+ end_addr == mem->start_addr + mem->memory_size) {
+ return mem;
+ }
+ }
+
+ return NULL;
+}
+
+/*
+ * Find overlapping slot with lowest start address
+ */
+static KVMSlot *kvm_lookup_overlapping_slot(KVMState *s,
+ target_phys_addr_t start_addr,
+ target_phys_addr_t end_addr)
+{
+ KVMSlot *found = NULL;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(s->slots); i++) {
+ KVMSlot *mem = &s->slots[i];
+
+ if (mem->memory_size == 0 ||
+ (found && found->start_addr < mem->start_addr)) {
+ continue;
+ }
+
+ if (end_addr > mem->start_addr &&
+ start_addr < mem->start_addr + mem->memory_size) {
+ found = mem;
+ }
+ }
+
+ return found;
+}
+
+static int kvm_set_user_memory_region(KVMState *s, KVMSlot *slot)
+{
+ struct kvm_userspace_memory_region mem;
+
+ mem.slot = slot->slot;
+ mem.guest_phys_addr = slot->start_addr;
+ mem.memory_size = slot->memory_size;
+ mem.userspace_addr = (unsigned long)qemu_get_ram_ptr(slot->phys_offset);
+ mem.flags = slot->flags;
+ if (s->migration_log) {
+ mem.flags |= KVM_MEM_LOG_DIRTY_PAGES;
+ }
+ return kvm_vm_ioctl(s, KVM_SET_USER_MEMORY_REGION, &mem);
+}
+
+
+int kvm_init_vcpu(CPUState *env)
+{
+ KVMState *s = kvm_state;
+ long mmap_size;
+ int ret;
+
+ dprintf("kvm_init_vcpu\n");
+
+ ret = kvm_vm_ioctl(s, KVM_CREATE_VCPU, env->cpu_index);
+ if (ret < 0) {
+ dprintf("kvm_create_vcpu failed\n");
+ goto err;
+ }
+
+ env->kvm_fd = ret;
+ env->kvm_state = s;
+
+ mmap_size = kvm_ioctl(s, KVM_GET_VCPU_MMAP_SIZE, 0);
+ if (mmap_size < 0) {
+ dprintf("KVM_GET_VCPU_MMAP_SIZE failed\n");
+ goto err;
+ }
+
+ env->kvm_run = mmap(NULL, mmap_size, PROT_READ | PROT_WRITE, MAP_SHARED,
+ env->kvm_fd, 0);
+ if (env->kvm_run == MAP_FAILED) {
+ ret = -errno;
+ dprintf("mmap'ing vcpu state failed\n");
+ goto err;
+ }
+
+ ret = kvm_arch_init_vcpu(env);
+
+err:
+ return ret;
+}
+
+int kvm_put_mp_state(CPUState *env)
+{
+ struct kvm_mp_state mp_state = { .mp_state = env->mp_state };
+
+ return kvm_vcpu_ioctl(env, KVM_SET_MP_STATE, &mp_state);
+}
+
+int kvm_get_mp_state(CPUState *env)
+{
+ struct kvm_mp_state mp_state;
+ int ret;
+
+ ret = kvm_vcpu_ioctl(env, KVM_GET_MP_STATE, &mp_state);
+ if (ret < 0) {
+ return ret;
+ }
+ env->mp_state = mp_state.mp_state;
+ return 0;
+}
+
+int kvm_sync_vcpus(void)
+{
+ CPUState *env;
+
+ for (env = first_cpu; env != NULL; env = env->next_cpu) {
+ int ret;
+
+ ret = kvm_arch_put_registers(env);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+/*
+ * dirty pages logging control
+ */
+static int kvm_dirty_pages_log_change(target_phys_addr_t phys_addr,
+ ram_addr_t size, int flags, int mask)
+{
+ KVMState *s = kvm_state;
+ KVMSlot *mem = kvm_lookup_matching_slot(s, phys_addr, phys_addr + size);
+ int old_flags;
+
+ if (mem == NULL) {
+ fprintf(stderr, "BUG: %s: invalid parameters " TARGET_FMT_plx "-"
+ TARGET_FMT_plx "\n", __func__, phys_addr,
+ phys_addr + size - 1);
+ return -EINVAL;
+ }
+
+ old_flags = mem->flags;
+
+ flags = (mem->flags & ~mask) | flags;
+ mem->flags = flags;
+
+ /* If nothing changed effectively, no need to issue ioctl */
+ if (s->migration_log) {
+ flags |= KVM_MEM_LOG_DIRTY_PAGES;
+ }
+ if (flags == old_flags) {
+ return 0;
+ }
+
+ return kvm_set_user_memory_region(s, mem);
+}
+
+int kvm_log_start(target_phys_addr_t phys_addr, ram_addr_t size)
+{
+ return kvm_dirty_pages_log_change(phys_addr, size,
+ KVM_MEM_LOG_DIRTY_PAGES,
+ KVM_MEM_LOG_DIRTY_PAGES);
+}
+
+int kvm_log_stop(target_phys_addr_t phys_addr, ram_addr_t size)
+{
+ return kvm_dirty_pages_log_change(phys_addr, size,
+ 0,
+ KVM_MEM_LOG_DIRTY_PAGES);
+}
+
+int kvm_set_migration_log(int enable)
+{
+ KVMState *s = kvm_state;
+ KVMSlot *mem;
+ int i, err;
+
+ s->migration_log = enable;
+
+ for (i = 0; i < ARRAY_SIZE(s->slots); i++) {
+ mem = &s->slots[i];
+
+ if (!!(mem->flags & KVM_MEM_LOG_DIRTY_PAGES) == enable) {
+ continue;
+ }
+ err = kvm_set_user_memory_region(s, mem);
+ if (err) {
+ return err;
+ }
+ }
+ return 0;
+}
+
+/**
+ * kvm_physical_sync_dirty_bitmap - Grab dirty bitmap from kernel space
+ * This function updates qemu's dirty bitmap using cpu_physical_memory_set_dirty().
+ * This means all bits are set to dirty.
+ *
+ * @start_add: start of logged region.
+ * @end_addr: end of logged region.
+ */
+int kvm_physical_sync_dirty_bitmap(target_phys_addr_t start_addr,
+ target_phys_addr_t end_addr)
+{
+ KVMState *s = kvm_state;
+ unsigned long size, allocated_size = 0;
+ target_phys_addr_t phys_addr;
+ ram_addr_t addr;
+ KVMDirtyLog d;
+ KVMSlot *mem;
+ int ret = 0;
+
+ d.dirty_bitmap = NULL;
+ while (start_addr < end_addr) {
+ mem = kvm_lookup_overlapping_slot(s, start_addr, end_addr);
+ if (mem == NULL) {
+ break;
+ }
+
+ size = ((mem->memory_size >> TARGET_PAGE_BITS) + 7) / 8;
+ if (!d.dirty_bitmap) {
+ d.dirty_bitmap = qemu_malloc(size);
+ } else if (size > allocated_size) {
+ d.dirty_bitmap = qemu_realloc(d.dirty_bitmap, size);
+ }
+ allocated_size = size;
+ memset(d.dirty_bitmap, 0, allocated_size);
+
+ d.slot = mem->slot;
+
+ if (kvm_vm_ioctl(s, KVM_GET_DIRTY_LOG, &d) == -1) {
+ dprintf("ioctl failed %d\n", errno);
+ ret = -1;
+ break;
+ }
+
+ for (phys_addr = mem->start_addr, addr = mem->phys_offset;
+ phys_addr < mem->start_addr + mem->memory_size;
+ phys_addr += TARGET_PAGE_SIZE, addr += TARGET_PAGE_SIZE) {
+ unsigned long *bitmap = (unsigned long *)d.dirty_bitmap;
+ unsigned nr = (phys_addr - mem->start_addr) >> TARGET_PAGE_BITS;
+ unsigned word = nr / (sizeof(*bitmap) * 8);
+ unsigned bit = nr % (sizeof(*bitmap) * 8);
+
+ if ((bitmap[word] >> bit) & 1) {
+ cpu_physical_memory_set_dirty(addr);
+ }
+ }
+ start_addr = phys_addr;
+ }
+ qemu_free(d.dirty_bitmap);
+
+ return ret;
+}
+
+int kvm_coalesce_mmio_region(target_phys_addr_t start, ram_addr_t size)
+{
+ int ret = -ENOSYS;
+#ifdef KVM_CAP_COALESCED_MMIO
+ KVMState *s = kvm_state;
+
+ if (s->coalesced_mmio) {
+ struct kvm_coalesced_mmio_zone zone;
+
+ zone.addr = start;
+ zone.size = size;
+
+ ret = kvm_vm_ioctl(s, KVM_REGISTER_COALESCED_MMIO, &zone);
+ }
+#endif
+
+ return ret;
+}
+
+int kvm_uncoalesce_mmio_region(target_phys_addr_t start, ram_addr_t size)
+{
+ int ret = -ENOSYS;
+#ifdef KVM_CAP_COALESCED_MMIO
+ KVMState *s = kvm_state;
+
+ if (s->coalesced_mmio) {
+ struct kvm_coalesced_mmio_zone zone;
+
+ zone.addr = start;
+ zone.size = size;
+
+ ret = kvm_vm_ioctl(s, KVM_UNREGISTER_COALESCED_MMIO, &zone);
+ }
+#endif
+
+ return ret;
+}
+
+int kvm_check_extension(KVMState *s, unsigned int extension)
+{
+ int ret;
+
+ ret = kvm_ioctl(s, KVM_CHECK_EXTENSION, extension);
+ if (ret < 0) {
+ ret = 0;
+ }
+
+ return ret;
+}
+
+static void kvm_reset_vcpus(void *opaque)
+{
+ kvm_sync_vcpus();
+}
+
+int kvm_init(int smp_cpus)
+{
+ static const char upgrade_note[] =
+ "Please upgrade to at least kernel 2.6.29 or recent kvm-kmod\n"
+ "(see http://sourceforge.net/projects/kvm).\n";
+ KVMState *s;
+ int ret;
+ int i;
+
+ if (smp_cpus > 1) {
+ fprintf(stderr, "No SMP KVM support, use '-smp 1'\n");
+ return -EINVAL;
+ }
+
+ s = qemu_mallocz(sizeof(KVMState));
+
+#ifdef KVM_CAP_SET_GUEST_DEBUG
+ QTAILQ_INIT(&s->kvm_sw_breakpoints);
+#endif
+ for (i = 0; i < ARRAY_SIZE(s->slots); i++)
+ s->slots[i].slot = i;
+
+ s->vmfd = -1;
+ s->fd = open("/dev/kvm", O_RDWR);
+ if (s->fd == -1) {
+ fprintf(stderr, "Could not access KVM kernel module: %m\n");
+ ret = -errno;
+ goto err;
+ }
+
+ ret = kvm_ioctl(s, KVM_GET_API_VERSION, 0);
+ if (ret < KVM_API_VERSION) {
+ if (ret > 0)
+ ret = -EINVAL;
+ fprintf(stderr, "kvm version too old\n");
+ goto err;
+ }
+
+ if (ret > KVM_API_VERSION) {
+ ret = -EINVAL;
+ fprintf(stderr, "kvm version not supported\n");
+ goto err;
+ }
+
+ s->vmfd = kvm_ioctl(s, KVM_CREATE_VM, 0);
+ if (s->vmfd < 0)
+ goto err;
+
+ /* initially, KVM allocated its own memory and we had to jump through
+ * hooks to make phys_ram_base point to this. Modern versions of KVM
+ * just use a user allocated buffer so we can use regular pages
+ * unmodified. Make sure we have a sufficiently modern version of KVM.
+ */
+ if (!kvm_check_extension(s, KVM_CAP_USER_MEMORY)) {
+ ret = -EINVAL;
+ fprintf(stderr, "kvm does not support KVM_CAP_USER_MEMORY\n%s",
+ upgrade_note);
+ goto err;
+ }
+
+ /* There was a nasty bug in < kvm-80 that prevents memory slots from being
+ * destroyed properly. Since we rely on this capability, refuse to work
+ * with any kernel without this capability. */
+ if (!kvm_check_extension(s, KVM_CAP_DESTROY_MEMORY_REGION_WORKS)) {
+ ret = -EINVAL;
+
+ fprintf(stderr,
+ "KVM kernel module broken (DESTROY_MEMORY_REGION).\n%s",
+ upgrade_note);
+ goto err;
+ }
+
+#ifdef KVM_CAP_COALESCED_MMIO
+ s->coalesced_mmio = kvm_check_extension(s, KVM_CAP_COALESCED_MMIO);
+#else
+ s->coalesced_mmio = 0;
+#endif
+
+ s->broken_set_mem_region = 1;
+#ifdef KVM_CAP_JOIN_MEMORY_REGIONS_WORKS
+ ret = kvm_ioctl(s, KVM_CHECK_EXTENSION, KVM_CAP_JOIN_MEMORY_REGIONS_WORKS);
+ if (ret > 0) {
+ s->broken_set_mem_region = 0;
+ }
+#endif
+
+ ret = kvm_arch_init(s, smp_cpus);
+ if (ret < 0)
+ goto err;
+
+ qemu_register_reset(kvm_reset_vcpus, INT_MAX, NULL);
+
+ kvm_state = s;
+
+ return 0;
+
+err:
+ if (s) {
+ if (s->vmfd != -1)
+ close(s->vmfd);
+ if (s->fd != -1)
+ close(s->fd);
+ }
+ qemu_free(s);
+
+ return ret;
+}
+
+static int kvm_handle_io(CPUState *env, uint16_t port, void *data,
+ int direction, int size, uint32_t count)
+{
+ int i;
+ uint8_t *ptr = data;
+
+ for (i = 0; i < count; i++) {
+ if (direction == KVM_EXIT_IO_IN) {
+ switch (size) {
+ case 1:
+ stb_p(ptr, cpu_inb(port));
+ break;
+ case 2:
+ stw_p(ptr, cpu_inw(port));
+ break;
+ case 4:
+ stl_p(ptr, cpu_inl(port));
+ break;
+ }
+ } else {
+ switch (size) {
+ case 1:
+ cpu_outb(port, ldub_p(ptr));
+ break;
+ case 2:
+ cpu_outw(port, lduw_p(ptr));
+ break;
+ case 4:
+ cpu_outl(port, ldl_p(ptr));
+ break;
+ }
+ }
+
+ ptr += size;
+ }
+
+ return 1;
+}
+
+static void kvm_run_coalesced_mmio(CPUState *env, struct kvm_run *run)
+{
+#ifdef KVM_CAP_COALESCED_MMIO
+ KVMState *s = kvm_state;
+ if (s->coalesced_mmio) {
+ struct kvm_coalesced_mmio_ring *ring;
+
+ ring = (void *)run + (s->coalesced_mmio * TARGET_PAGE_SIZE);
+ while (ring->first != ring->last) {
+ struct kvm_coalesced_mmio *ent;
+
+ ent = &ring->coalesced_mmio[ring->first];
+
+ cpu_physical_memory_write(ent->phys_addr, ent->data, ent->len);
+ /* FIXME smp_wmb() */
+ ring->first = (ring->first + 1) % KVM_COALESCED_MMIO_MAX;
+ }
+ }
+#endif
+}
+
+int kvm_cpu_exec(CPUState *env)
+{
+ struct kvm_run *run = env->kvm_run;
+ int ret;
+
+ dprintf("kvm_cpu_exec()\n");
+
+ do {
+ if (env->exit_request) {
+ dprintf("interrupt exit requested\n");
+ ret = 0;
+ break;
+ }
+
+ kvm_arch_pre_run(env, run);
+ ret = kvm_vcpu_ioctl(env, KVM_RUN, 0);
+ kvm_arch_post_run(env, run);
+
+ if (ret == -EINTR || ret == -EAGAIN) {
+ dprintf("io window exit\n");
+ ret = 0;
+ break;
+ }
+
+ if (ret < 0) {
+ dprintf("kvm run failed %s\n", strerror(-ret));
+ abort();
+ }
+
+ kvm_run_coalesced_mmio(env, run);
+
+ ret = 0; /* exit loop */
+ switch (run->exit_reason) {
+ case KVM_EXIT_IO:
+ dprintf("handle_io\n");
+ ret = kvm_handle_io(env, run->io.port,
+ (uint8_t *)run + run->io.data_offset,
+ run->io.direction,
+ run->io.size,
+ run->io.count);
+ break;
+ case KVM_EXIT_MMIO:
+ dprintf("handle_mmio\n");
+ cpu_physical_memory_rw(run->mmio.phys_addr,
+ run->mmio.data,
+ run->mmio.len,
+ run->mmio.is_write);
+ ret = 1;
+ break;
+ case KVM_EXIT_IRQ_WINDOW_OPEN:
+ dprintf("irq_window_open\n");
+ break;
+ case KVM_EXIT_SHUTDOWN:
+ dprintf("shutdown\n");
+ qemu_system_reset_request();
+ ret = 1;
+ break;
+ case KVM_EXIT_UNKNOWN:
+ dprintf("kvm_exit_unknown\n");
+ break;
+ case KVM_EXIT_FAIL_ENTRY:
+ dprintf("kvm_exit_fail_entry\n");
+ break;
+ case KVM_EXIT_EXCEPTION:
+ dprintf("kvm_exit_exception\n");
+ break;
+ case KVM_EXIT_DEBUG:
+ dprintf("kvm_exit_debug\n");
+#ifdef KVM_CAP_SET_GUEST_DEBUG
+ if (kvm_arch_debug(&run->debug.arch)) {
+ gdb_set_stop_cpu(env);
+ vm_stop(EXCP_DEBUG);
+ env->exception_index = EXCP_DEBUG;
+ return 0;
+ }
+ /* re-enter, this exception was guest-internal */
+ ret = 1;
+#endif /* KVM_CAP_SET_GUEST_DEBUG */
+ break;
+ default:
+ dprintf("kvm_arch_handle_exit\n");
+ ret = kvm_arch_handle_exit(env, run);
+ break;
+ }
+ } while (ret > 0);
+
+ if (env->exit_request) {
+ env->exit_request = 0;
+ env->exception_index = EXCP_INTERRUPT;
+ }
+
+ return ret;
+}
+
+void kvm_set_phys_mem(target_phys_addr_t start_addr,
+ ram_addr_t size,
+ ram_addr_t phys_offset)
+{
+ KVMState *s = kvm_state;
+ ram_addr_t flags = phys_offset & ~TARGET_PAGE_MASK;
+ KVMSlot *mem, old;
+ int err;
+
+ if (start_addr & ~TARGET_PAGE_MASK) {
+ if (flags >= IO_MEM_UNASSIGNED) {
+ if (!kvm_lookup_overlapping_slot(s, start_addr,
+ start_addr + size)) {
+ return;
+ }
+ fprintf(stderr, "Unaligned split of a KVM memory slot\n");
+ } else {
+ fprintf(stderr, "Only page-aligned memory slots supported\n");
+ }
+ abort();
+ }
+
+ /* KVM does not support read-only slots */
+ phys_offset &= ~IO_MEM_ROM;
+
+ while (1) {
+ mem = kvm_lookup_overlapping_slot(s, start_addr, start_addr + size);
+ if (!mem) {
+ break;
+ }
+
+ if (flags < IO_MEM_UNASSIGNED && start_addr >= mem->start_addr &&
+ (start_addr + size <= mem->start_addr + mem->memory_size) &&
+ (phys_offset - start_addr == mem->phys_offset - mem->start_addr)) {
+ /* The new slot fits into the existing one and comes with
+ * identical parameters - nothing to be done. */
+ return;
+ }
+
+ old = *mem;
+
+ /* unregister the overlapping slot */
+ mem->memory_size = 0;
+ err = kvm_set_user_memory_region(s, mem);
+ if (err) {
+ fprintf(stderr, "%s: error unregistering overlapping slot: %s\n",
+ __func__, strerror(-err));
+ abort();
+ }
+
+ /* Workaround for older KVM versions: we can't join slots, even not by
+ * unregistering the previous ones and then registering the larger
+ * slot. We have to maintain the existing fragmentation. Sigh.
+ *
+ * This workaround assumes that the new slot starts at the same
+ * address as the first existing one. If not or if some overlapping
+ * slot comes around later, we will fail (not seen in practice so far)
+ * - and actually require a recent KVM version. */
+ if (s->broken_set_mem_region &&
+ old.start_addr == start_addr && old.memory_size < size &&
+ flags < IO_MEM_UNASSIGNED) {
+ mem = kvm_alloc_slot(s);
+ mem->memory_size = old.memory_size;
+ mem->start_addr = old.start_addr;
+ mem->phys_offset = old.phys_offset;
+ mem->flags = 0;
+
+ err = kvm_set_user_memory_region(s, mem);
+ if (err) {
+ fprintf(stderr, "%s: error updating slot: %s\n", __func__,
+ strerror(-err));
+ abort();
+ }
+
+ start_addr += old.memory_size;
+ phys_offset += old.memory_size;
+ size -= old.memory_size;
+ continue;
+ }
+
+ /* register prefix slot */
+ if (old.start_addr < start_addr) {
+ mem = kvm_alloc_slot(s);
+ mem->memory_size = start_addr - old.start_addr;
+ mem->start_addr = old.start_addr;
+ mem->phys_offset = old.phys_offset;
+ mem->flags = 0;
+
+ err = kvm_set_user_memory_region(s, mem);
+ if (err) {
+ fprintf(stderr, "%s: error registering prefix slot: %s\n",
+ __func__, strerror(-err));
+ abort();
+ }
+ }
+
+ /* register suffix slot */
+ if (old.start_addr + old.memory_size > start_addr + size) {
+ ram_addr_t size_delta;
+
+ mem = kvm_alloc_slot(s);
+ mem->start_addr = start_addr + size;
+ size_delta = mem->start_addr - old.start_addr;
+ mem->memory_size = old.memory_size - size_delta;
+ mem->phys_offset = old.phys_offset + size_delta;
+ mem->flags = 0;
+
+ err = kvm_set_user_memory_region(s, mem);
+ if (err) {
+ fprintf(stderr, "%s: error registering suffix slot: %s\n",
+ __func__, strerror(-err));
+ abort();
+ }
+ }
+ }
+
+ /* in case the KVM bug workaround already "consumed" the new slot */
+ if (!size)
+ return;
+
+ /* KVM does not need to know about this memory */
+ if (flags >= IO_MEM_UNASSIGNED)
+ return;
+
+ mem = kvm_alloc_slot(s);
+ mem->memory_size = size;
+ mem->start_addr = start_addr;
+ mem->phys_offset = phys_offset;
+ mem->flags = 0;
+
+ err = kvm_set_user_memory_region(s, mem);
+ if (err) {
+ fprintf(stderr, "%s: error registering slot: %s\n", __func__,
+ strerror(-err));
+ abort();
+ }
+}
+
+int kvm_ioctl(KVMState *s, int type, ...)
+{
+ int ret;
+ void *arg;
+ va_list ap;
+
+ va_start(ap, type);
+ arg = va_arg(ap, void *);
+ va_end(ap);
+
+ ret = ioctl(s->fd, type, arg);
+ if (ret == -1)
+ ret = -errno;
+
+ return ret;
+}
+
+int kvm_vm_ioctl(KVMState *s, int type, ...)
+{
+ int ret;
+ void *arg;
+ va_list ap;
+
+ va_start(ap, type);
+ arg = va_arg(ap, void *);
+ va_end(ap);
+
+ ret = ioctl(s->vmfd, type, arg);
+ if (ret == -1)
+ ret = -errno;
+
+ return ret;
+}
+
+int kvm_vcpu_ioctl(CPUState *env, int type, ...)
+{
+ int ret;
+ void *arg;
+ va_list ap;
+
+ va_start(ap, type);
+ arg = va_arg(ap, void *);
+ va_end(ap);
+
+ ret = ioctl(env->kvm_fd, type, arg);
+ if (ret == -1)
+ ret = -errno;
+
+ return ret;
+}
+
+int kvm_has_sync_mmu(void)
+{
+#ifdef KVM_CAP_SYNC_MMU
+ KVMState *s = kvm_state;
+
+ return kvm_check_extension(s, KVM_CAP_SYNC_MMU);
+#else
+ return 0;
+#endif
+}
+
+void kvm_setup_guest_memory(void *start, size_t size)
+{
+ if (!kvm_has_sync_mmu()) {
+#ifdef MADV_DONTFORK
+ int ret = madvise(start, size, MADV_DONTFORK);
+
+ if (ret) {
+ perror("madvice");
+ exit(1);
+ }
+#else
+ fprintf(stderr,
+ "Need MADV_DONTFORK in absence of synchronous KVM MMU\n");
+ exit(1);
+#endif
+ }
+}
+
+#ifdef KVM_CAP_SET_GUEST_DEBUG
+struct kvm_sw_breakpoint *kvm_find_sw_breakpoint(CPUState *env,
+ target_ulong pc)
+{
+ struct kvm_sw_breakpoint *bp;
+
+ QTAILQ_FOREACH(bp, &env->kvm_state->kvm_sw_breakpoints, entry) {
+ if (bp->pc == pc)
+ return bp;
+ }
+ return NULL;
+}
+
+int kvm_sw_breakpoints_active(CPUState *env)
+{
+ return !QTAILQ_EMPTY(&env->kvm_state->kvm_sw_breakpoints);
+}
+
+int kvm_update_guest_debug(CPUState *env, unsigned long reinject_trap)
+{
+ struct kvm_guest_debug dbg;
+
+ dbg.control = 0;
+ if (env->singlestep_enabled)
+ dbg.control = KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_SINGLESTEP;
+
+ kvm_arch_update_guest_debug(env, &dbg);
+ dbg.control |= reinject_trap;
+
+ return kvm_vcpu_ioctl(env, KVM_SET_GUEST_DEBUG, &dbg);
+}
+
+int kvm_insert_breakpoint(CPUState *current_env, target_ulong addr,
+ target_ulong len, int type)
+{
+ struct kvm_sw_breakpoint *bp;
+ CPUState *env;
+ int err;
+
+ if (type == GDB_BREAKPOINT_SW) {
+ bp = kvm_find_sw_breakpoint(current_env, addr);
+ if (bp) {
+ bp->use_count++;
+ return 0;
+ }
+
+ bp = qemu_malloc(sizeof(struct kvm_sw_breakpoint));
+ if (!bp)
+ return -ENOMEM;
+
+ bp->pc = addr;
+ bp->use_count = 1;
+ err = kvm_arch_insert_sw_breakpoint(current_env, bp);
+ if (err) {
+ free(bp);
+ return err;
+ }
+
+ QTAILQ_INSERT_HEAD(¤t_env->kvm_state->kvm_sw_breakpoints,
+ bp, entry);
+ } else {
+ err = kvm_arch_insert_hw_breakpoint(addr, len, type);
+ if (err)
+ return err;
+ }
+
+ for (env = first_cpu; env != NULL; env = env->next_cpu) {
+ err = kvm_update_guest_debug(env, 0);
+ if (err)
+ return err;
+ }
+ return 0;
+}
+
+int kvm_remove_breakpoint(CPUState *current_env, target_ulong addr,
+ target_ulong len, int type)
+{
+ struct kvm_sw_breakpoint *bp;
+ CPUState *env;
+ int err;
+
+ if (type == GDB_BREAKPOINT_SW) {
+ bp = kvm_find_sw_breakpoint(current_env, addr);
+ if (!bp)
+ return -ENOENT;
+
+ if (bp->use_count > 1) {
+ bp->use_count--;
+ return 0;
+ }
+
+ err = kvm_arch_remove_sw_breakpoint(current_env, bp);
+ if (err)
+ return err;
+
+ QTAILQ_REMOVE(¤t_env->kvm_state->kvm_sw_breakpoints, bp, entry);
+ qemu_free(bp);
+ } else {
+ err = kvm_arch_remove_hw_breakpoint(addr, len, type);
+ if (err)
+ return err;
+ }
+
+ for (env = first_cpu; env != NULL; env = env->next_cpu) {
+ err = kvm_update_guest_debug(env, 0);
+ if (err)
+ return err;
+ }
+ return 0;
+}
+
+void kvm_remove_all_breakpoints(CPUState *current_env)
+{
+ struct kvm_sw_breakpoint *bp, *next;
+ KVMState *s = current_env->kvm_state;
+ CPUState *env;
+
+ QTAILQ_FOREACH_SAFE(bp, &s->kvm_sw_breakpoints, entry, next) {
+ if (kvm_arch_remove_sw_breakpoint(current_env, bp) != 0) {
+ /* Try harder to find a CPU that currently sees the breakpoint. */
+ for (env = first_cpu; env != NULL; env = env->next_cpu) {
+ if (kvm_arch_remove_sw_breakpoint(env, bp) == 0)
+ break;
+ }
+ }
+ }
+ kvm_arch_remove_all_hw_breakpoints();
+
+ for (env = first_cpu; env != NULL; env = env->next_cpu)
+ kvm_update_guest_debug(env, 0);
+}
+
+#else /* !KVM_CAP_SET_GUEST_DEBUG */
+
+int kvm_update_guest_debug(CPUState *env, unsigned long reinject_trap)
+{
+ return -EINVAL;
+}
+
+int kvm_insert_breakpoint(CPUState *current_env, target_ulong addr,
+ target_ulong len, int type)
+{
+ return -EINVAL;
+}
+
+int kvm_remove_breakpoint(CPUState *current_env, target_ulong addr,
+ target_ulong len, int type)
+{
+ return -EINVAL;
+}
+
+void kvm_remove_all_breakpoints(CPUState *current_env)
+{
+}
+#endif /* !KVM_CAP_SET_GUEST_DEBUG */
diff --git a/kvm.h b/kvm.h
index f5f5a55..e1fc986 100644
--- a/kvm.h
+++ b/kvm.h
@@ -18,6 +18,8 @@
#include "qemu-queue.h"
#ifdef CONFIG_KVM
+
+#ifdef TARGET_I386
extern int kvm_allowed;
#define kvm_enabled() (kvm_allowed)
@@ -25,6 +27,10 @@
#define kvm_enabled() (0)
#endif
+#else
+#define kvm_enabled() (0)
+#endif
+
struct kvm_run;
/* external API */
diff --git a/memcheck/memcheck.c b/memcheck/memcheck.c
index 3c8194a..3ccb196 100644
--- a/memcheck/memcheck.c
+++ b/memcheck/memcheck.c
@@ -14,12 +14,6 @@
* Contains implementation of memory checking framework in the emulator.
*/
-/* This file should compile iff qemu is built with memory checking
- * configuration turned on. */
-#ifndef CONFIG_MEMCHECK
-#error CONFIG_MEMCHECK is not defined.
-#endif // CONFIG_MEMCHECK
-
#include "qemu-queue.h"
#include "qemu_file.h"
#include "elff_api.h"
diff --git a/memcheck/memcheck.h b/memcheck/memcheck.h
index a9a6422..a7761a9 100644
--- a/memcheck/memcheck.h
+++ b/memcheck/memcheck.h
@@ -18,12 +18,6 @@
#ifndef QEMU_MEMCHECK_MEMCHECK_H
#define QEMU_MEMCHECK_MEMCHECK_H
-/* This file should compile iff qemu is built with memory checking
- * configuration turned on. */
-#ifndef CONFIG_MEMCHECK
-#error CONFIG_MEMCHECK is not defined.
-#endif // CONFIG_MEMCHECK
-
#include "memcheck_common.h"
#ifdef __cplusplus
diff --git a/memcheck/memcheck_common.h b/memcheck/memcheck_common.h
index e6d12db..e753094 100644
--- a/memcheck/memcheck_common.h
+++ b/memcheck/memcheck_common.h
@@ -18,12 +18,6 @@
#ifndef QEMU_MEMCHECK_MEMCHECK_COMMON_H
#define QEMU_MEMCHECK_MEMCHECK_COMMON_H
-/* This file should compile iff qemu is built with memory checking
- * configuration turned on. */
-#ifndef CONFIG_MEMCHECK
-#error CONFIG_MEMCHECK is not defined.
-#endif // CONFIG_MEMCHECK
-
#include "qemu-common.h"
#include "cpu.h"
diff --git a/memcheck/memcheck_logging.h b/memcheck/memcheck_logging.h
index c2ae6e9..94a3c09 100644
--- a/memcheck/memcheck_logging.h
+++ b/memcheck/memcheck_logging.h
@@ -17,12 +17,6 @@
#ifndef QEMU_MEMCHECK_MEMCHECK_LOGGING_H
#define QEMU_MEMCHECK_MEMCHECK_LOGGING_H
-/* This file should compile iff qemu is built with memory checking
- * configuration turned on. */
-#ifndef CONFIG_MEMCHECK
-#error CONFIG_MEMCHECK is not defined.
-#endif // CONFIG_MEMCHECK
-
#include "qemu-common.h"
#include "android/utils/debug.h"
diff --git a/memcheck/memcheck_malloc_map.c b/memcheck/memcheck_malloc_map.c
index 07ae889..d7e8032 100644
--- a/memcheck/memcheck_malloc_map.c
+++ b/memcheck/memcheck_malloc_map.c
@@ -15,12 +15,6 @@
* memory blocks allocated by the guest system.
*/
-/* This file should compile iff qemu is built with memory checking
- * configuration turned on. */
-#ifndef CONFIG_MEMCHECK
-#error CONFIG_MEMCHECK is not defined.
-#endif // CONFIG_MEMCHECK
-
#include "memcheck_malloc_map.h"
#include "memcheck_util.h"
#include "memcheck_logging.h"
diff --git a/memcheck/memcheck_malloc_map.h b/memcheck/memcheck_malloc_map.h
index b356180..1c25738 100644
--- a/memcheck/memcheck_malloc_map.h
+++ b/memcheck/memcheck_malloc_map.h
@@ -24,12 +24,6 @@
#ifndef QEMU_MEMCHECK_MEMCHECK_MALLOC_MAP_H
#define QEMU_MEMCHECK_MEMCHECK_MALLOC_MAP_H
-/* This file should compile iff qemu is built with memory checking
- * configuration turned on. */
-#ifndef CONFIG_MEMCHECK
-#error CONFIG_MEMCHECK is not defined.
-#endif // CONFIG_MEMCHECK
-
#include "sys-tree.h"
#include "memcheck_common.h"
diff --git a/memcheck/memcheck_mmrange_map.c b/memcheck/memcheck_mmrange_map.c
index f2609df..d9a1211 100644
--- a/memcheck/memcheck_mmrange_map.c
+++ b/memcheck/memcheck_mmrange_map.c
@@ -15,12 +15,6 @@
* memory mappings in the guest system.
*/
-/* This file should compile iff qemu is built with memory checking
- * configuration turned on. */
-#ifndef CONFIG_MEMCHECK
-#error CONFIG_MEMCHECK is not defined.
-#endif // CONFIG_MEMCHECK
-
#include "memcheck_mmrange_map.h"
#include "memcheck_logging.h"
diff --git a/memcheck/memcheck_mmrange_map.h b/memcheck/memcheck_mmrange_map.h
index f2c9701..f291c95 100644
--- a/memcheck/memcheck_mmrange_map.h
+++ b/memcheck/memcheck_mmrange_map.h
@@ -22,12 +22,6 @@
#ifndef QEMU_MEMCHECK_MEMCHECK_MMRANGE_MAP_H
#define QEMU_MEMCHECK_MEMCHECK_MMRANGE_MAP_H
-/* This file should compile iff qemu is built with memory checking
- * configuration turned on. */
-#ifndef CONFIG_MEMCHECK
-#error CONFIG_MEMCHECK is not defined.
-#endif // CONFIG_MEMCHECK
-
#include "sys-tree.h"
#include "memcheck_common.h"
diff --git a/memcheck/memcheck_proc_management.c b/memcheck/memcheck_proc_management.c
index 593ba32..45cf141 100644
--- a/memcheck/memcheck_proc_management.c
+++ b/memcheck/memcheck_proc_management.c
@@ -15,12 +15,6 @@
* memchecker framework.
*/
-/* This file should compile iff qemu is built with memory checking
- * configuration turned on. */
-#ifndef CONFIG_MEMCHECK
-#error CONFIG_MEMCHECK is not defined.
-#endif // CONFIG_MEMCHECK
-
#include "elff/elff_api.h"
#include "memcheck.h"
#include "memcheck_proc_management.h"
diff --git a/memcheck/memcheck_proc_management.h b/memcheck/memcheck_proc_management.h
index 68b6181..7f489cf 100644
--- a/memcheck/memcheck_proc_management.h
+++ b/memcheck/memcheck_proc_management.h
@@ -18,12 +18,6 @@
#ifndef QEMU_MEMCHECK_MEMCHECK_PROC_MANAGEMENT_H
#define QEMU_MEMCHECK_MEMCHECK_PROC_MANAGEMENT_H
-/* This file should compile iff qemu is built with memory checking
- * configuration turned on. */
-#ifndef CONFIG_MEMCHECK
-#error CONFIG_MEMCHECK is not defined.
-#endif // CONFIG_MEMCHECK
-
#include "qemu-queue.h"
#include "memcheck_common.h"
#include "memcheck_malloc_map.h"
diff --git a/memcheck/memcheck_util.c b/memcheck/memcheck_util.c
index 5449488..8a59914 100644
--- a/memcheck/memcheck_util.c
+++ b/memcheck/memcheck_util.c
@@ -14,12 +14,6 @@
* Contains implementation of utility routines for memchecker framework.
*/
-/* This file should compile iff qemu is built with memory checking
- * configuration turned on. */
-#ifndef CONFIG_MEMCHECK
-#error CONFIG_MEMCHECK is not defined.
-#endif // CONFIG_MEMCHECK
-
#include "stdio.h"
#include "qemu-common.h"
#include "android/utils/path.h"
diff --git a/memcheck/memcheck_util.h b/memcheck/memcheck_util.h
index b75ee53..2a9907e 100644
--- a/memcheck/memcheck_util.h
+++ b/memcheck/memcheck_util.h
@@ -17,12 +17,6 @@
#ifndef QEMU_MEMCHECK_MEMCHECK_UTIL_H
#define QEMU_MEMCHECK_MEMCHECK_UTIL_H
-/* This file should compile iff qemu is built with memory checking
- * configuration turned on. */
-#ifndef CONFIG_MEMCHECK
-#error CONFIG_MEMCHECK is not defined.
-#endif // CONFIG_MEMCHECK
-
#include "memcheck_common.h"
#include "elff/elff_api.h"
diff --git a/net-android.c b/net-android.c
index 234235b..6459eff 100644
--- a/net-android.c
+++ b/net-android.c
@@ -126,7 +126,7 @@
#include "libslirp.h"
#endif
-#if defined(CONFIG_SHAPER)
+#if defined(CONFIG_ANDROID)
#include "shaper.h"
#endif
@@ -730,7 +730,7 @@
return ( data[12] == 10 && data[16] == 10);
}
-#ifdef CONFIG_SHAPER
+#ifdef CONFIG_ANDROID
NetShaper slirp_shaper_in;
NetShaper slirp_shaper_out;
@@ -773,12 +773,12 @@
netshaper_set_rate( slirp_shaper_in, qemu_net_upload_speed );
}
-#endif /* CONFIG_SHAPER */
+#endif /* CONFIG_ANDROID */
int slirp_can_output(void)
{
-#ifdef CONFIG_SHAPER
+#ifdef CONFIG_ANDROID
return !slirp_vc ||
( netshaper_can_send(slirp_shaper_out) &&
qemu_can_send_packet(slirp_vc) );
@@ -799,7 +799,7 @@
if (!slirp_vc)
return;
-#ifdef CONFIG_SHAPER
+#ifdef CONFIG_ANDROID
netshaper_send(slirp_shaper_out, (void*)pkt, pkt_len);
#else
qemu_send_packet(slirp_vc, pkt, pkt_len);
@@ -820,7 +820,7 @@
if (qemu_tcpdump_active)
qemu_tcpdump_packet(buf, size);
-#ifdef CONFIG_SHAPER
+#ifdef CONFIG_ANDROID
netshaper_send(slirp_shaper_in, (char*)buf, size);
#else
slirp_input(buf, size);
diff --git a/qemu-options.hx b/qemu-options.hx
index baae81b..f35b4d0 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -1440,6 +1440,95 @@
@code{2006-06-17}. The default value is @code{now}.
ETEXI
+/* Start user mode network stack restrictions */
+DEF("drop-udp", 0, QEMU_OPTION_drop_udp, \
+ "-drop-udp starts filtering all UDP packets\n")
+STEXI
+
+@item -drop-udp
+Enable dropping of all UDP packets.
+ETEXI
+
+
+DEF("drop-tcp", 0, QEMU_OPTION_drop_tcp, \
+ "-drop-tcp starts filtering all TCP packets\n")
+STEXI
+
+@item -drop-tcp
+Enable dropping of all TCP packets.
+ETEXI
+
+
+DEF("allow-tcp", HAS_ARG, QEMU_OPTION_allow_tcp, \
+ "-allow-tcp Only allows TCP packets for host:port\n")
+STEXI
+
+@item -allow-tcp @var{host}:@var{port}
+Allows communication with the host named @code{host} and with
+the port @code{port}.
+ETEXI
+
+
+DEF("drop-log", 0, QEMU_OPTION_drop_log, \
+ "-drop-log Creates a log for dropped connections\n")
+STEXI
+
+@item -drop-log @var{file}
+Creates a log for dropped connections in the file @code{file}.
+ETEXI
+
+/* Additional network restriction options */
+
+DEF("max-dns-conns", HAS_ARG, QEMU_OPTION_max_dns_conns, \
+ "-max-dns-conns limit \n"
+ " Limits the maximum DNS connections\n")
+STEXI
+@item -max-dns-conns @var{limit}
+Limits the maximum DNS connections to @var{limit}.
+ETEXI
+
+DEF("allow-udp", HAS_ARG, QEMU_OPTION_allow_udp, \
+ "-allow-udp host:port \n"
+ " Allows udp connections to go through to host:port\n")
+STEXI
+@item -allow-udp @var{host}:@var{port}
+Allows udp connections to go through to @var{host}:@var{port}.
+ETEXI
+
+DEF("dns-log", HAS_ARG, QEMU_OPTION_dns_log, \
+ "-dns-log file Creates a log of DNS lookups\n")
+STEXI
+@item -dns-log @var{file}
+Creates a log of DNS lookups as @var{file}.
+ETEXI
+
+
+DEF("net-forward", HAS_ARG, QEMU_OPTION_net_forward, \
+"-net-forward dst_net:dst_mask:dst_port:redirect_ip:redirect_port:\n"
+" Forwards guest network traffic sent to dst_net(dst_mask):dst_port\n"
+" to redirect_ip:redirect_port\n")
+
+STEXI
+@item -net-forward @var{settings}
+Forwards network traffic using the settings @code{settings}.
+ETEXI
+
+
+DEF("net-forward-tcp2sink", HAS_ARG, QEMU_OPTION_net_forward_tcp2sink, \
+"-net-forward-tcp2sink sink_ip:sink_port\n"
+" Forwards all dropped and non-forwarded guest network traffic\n"
+" to specified ip:port. \n")
+
+STEXI
+@item -net-forward-tcp2sink @var{settings}
+Forwards all dropped and non-forwarded network traffic to sink ip:port.
+ETEXI
+
+
+
+/* End User mode network stack restrictions */
+
+
DEF("icount", HAS_ARG, QEMU_OPTION_icount, \
"-icount [N|auto]\n" \
" enable virtual instruction counter with 2^N clock ticks per\n" \
@@ -1631,10 +1720,6 @@
"-charmap <file>"
" use specific key character map\n")
-DEF("android-gui", HAS_ARG, QEMU_OPTION_android_gui, \
- "-android-gui width=<width>,height=<height>,bpp=<bits per pixel>"
- " width, height, and bits per pixel for the graphic console\n")
-
DEF("android-hw", HAS_ARG, QEMU_OPTION_android_hw, \
"-android-hw <file> read hardware initialization from ini file\n")
@@ -1697,4 +1782,7 @@
DEF("audio-test-out", 0, QEMU_OPTION_audio_test_out, \
"-audio-test-out Test audio output\n")
+DEF("snapshot-no-time-update", 0, QEMU_OPTION_snapshot_no_time_update, \
+ "-snapshot-no-time-update Disable time update when restoring snapshots\n")
+
#endif /* ANDROID */
diff --git a/qemu-timer.c b/qemu-timer.c
index 0ed5ba9..82a5de3 100644
--- a/qemu-timer.c
+++ b/qemu-timer.c
@@ -394,14 +394,20 @@
static struct qemu_alarm_timer alarm_timers[] = {
#ifndef _WIN32
#ifdef __linux__
- {"dynticks", dynticks_start_timer,
- dynticks_stop_timer, dynticks_rearm_timer, NULL},
/* HPET - if available - is preferred */
{"hpet", hpet_start_timer, hpet_stop_timer, NULL, NULL},
/* ...otherwise try RTC */
{"rtc", rtc_start_timer, rtc_stop_timer, NULL, NULL},
#endif
{"unix", unix_start_timer, unix_stop_timer, NULL, NULL},
+#ifdef __linux__
+ /* on Linux, the 'dynticks' clock sometimes doesn't work
+ * properly. this results in the UI freezing while emulation
+ * continues, for several seconds... So move it to the end
+ * of the list. */
+ {"dynticks", dynticks_start_timer,
+ dynticks_stop_timer, dynticks_rearm_timer, NULL},
+#endif
#else
{"dynticks", win32_start_timer,
win32_stop_timer, win32_rearm_timer, &alarm_win32_data},
diff --git a/slirp-android/libslirp.h b/slirp-android/libslirp.h
index 6086384..e8b63a8 100644
--- a/slirp-android/libslirp.h
+++ b/slirp-android/libslirp.h
@@ -2,7 +2,9 @@
#define _LIBSLIRP_H
#include <stdint.h>
+#include <stdio.h>
#include "sockets.h"
+#include "slirp.h"
#ifdef _WIN32
# define WIN32_LEAN_AND_MEAN
# define socket_close winsock2_socket_close3
@@ -16,6 +18,8 @@
extern "C" {
#endif
+struct mbuf;
+
int inet_strtoip(const char* str, uint32_t *ip);
char* inet_iptostr(uint32_t ip);
@@ -32,6 +36,64 @@
int slirp_can_output(void);
void slirp_output(const uint8_t *pkt, int pkt_len);
+/* ---------------------------------------------------*/
+/* User mode network stack restrictions */
+void slirp_drop_udp();
+void slirp_drop_tcp();
+void slirp_add_allow(unsigned long dst_addr, int dst_lport,
+ int dst_hport, u_int8_t proto);
+void slirp_drop_log_fd(FILE* fd);
+
+/** Get the drop log fd */
+FILE* get_slirp_drop_log_fd(void);
+int slirp_should_drop(unsigned long dst_addr,
+ int dst_port,
+ u_int8_t proto);
+int slirp_drop_log(const char* format, ...);
+
+/* for network forwards */
+void slirp_add_net_forward(unsigned long dest_ip, unsigned long dest_mask,
+ int dest_lport, int dest_hport,
+ unsigned long redirect_ip, int redirect_port);
+
+int slirp_should_net_forward(unsigned long remote_ip, int remote_port,
+ unsigned long *redirect_ip, int *redirect_port);
+/* ---------------------------------------------------*/
+
+/**
+ * Additional network stack modifications, aiming to detect and log
+ * any network activity initiated by any binary outisde the context of
+ * the running browser.
+ */
+
+void slirp_dns_log_fd(FILE* fd);
+/** Get the dns log fd */
+FILE* get_slirp_dns_log_fd(void);
+/** Logs the DNS name in DNS query issued by the VM. */
+int slirp_log_dns(struct mbuf* m, int dropped);
+/** IP packet dump of DNS queris and responses. */
+int slirp_dump_dns(struct mbuf* m);
+/** Sets an upper limit for the number of allowed DNS requests from
+ * the VM.
+ */
+void slirp_set_max_dns_conns(int max_dns_conns);
+/* Returns the max number of allowed DNS requests.*/
+int slirp_get_max_dns_conns();
+
+/**
+ * Modifications for implementing "-net-forward-tcp2sink' option.
+ */
+
+void slirp_forward_dropped_tcp2sink(unsigned long sink_ip, int sink_port);
+int slirp_should_forward_dropped_tcp2sink();
+unsigned long slirp_get_tcp_sink_ip();
+int slirp_get_tcp_sink_port();
+
+
+
+
+/* ---------------------------------------------------*/
+
void slirp_redir_loop(void (*func)(void *opaque, int is_udp,
const SockAddress *laddr,
const SockAddress *faddr),
diff --git a/slirp-android/slirp.c b/slirp-android/slirp.c
index dc94a99..6a62e4b 100644
--- a/slirp-android/slirp.c
+++ b/slirp-android/slirp.c
@@ -32,6 +32,12 @@
#include "android/android.h"
#include "sockets.h"
+#include "qemu-queue.h"
+
+/* proto types */
+static void slirp_net_forward_init(void);
+
+
#define D(...) VERBOSE_PRINT(slirp,__VA_ARGS__)
#define DN(...) do { if (VERBOSE_CHECK(slirp)) dprintn(__VA_ARGS__); } while (0)
@@ -81,7 +87,7 @@
return -1;
dns_ip = sock_address_get_ip(new_dns_addr);
- if (dns_ip < 0)
+ if (dns_ip == -1)
return -1;
dns_addr[dns_addr_count++] = dns_ip;
@@ -259,6 +265,8 @@
alias_addr_ip = special_addr_ip | CTL_ALIAS;
getouraddr();
register_savevm("slirp", 0, 1, slirp_state_save, slirp_state_load, NULL);
+
+ slirp_net_forward_init();
}
#define CONN_CANFSEND(so) (((so)->so_state & (SS_FCANTSENDMORE|SS_ISFCONNECTED)) == SS_ISFCONNECTED)
@@ -819,6 +827,306 @@
}
}
+
+/*---------------------------------------------------*/
+/* User mode network stack restrictions */
+struct fw_allow_entry {
+ struct fw_allow_entry* next;
+ unsigned long dst_addr; /* host byte order */
+ /* Allowed port range. dst_lport should be the same as dst_hport for a
+ * single port. */
+ unsigned short dst_lport; /* host byte order */
+ unsigned short dst_hport; /* host byte order */
+};
+
+static int drop_udp = 0;
+static int drop_tcp = 0;
+static struct fw_allow_entry* allow_tcp_entries = NULL;
+static struct fw_allow_entry* allow_udp_entries = NULL;
+static FILE* drop_log_fd = NULL;
+static FILE* dns_log_fd = NULL;
+static int max_dns_conns = -1; /* unlimited max DNS connections by default */
+static int slirp_net_forward_inited = 0;
+
+void slirp_drop_udp() {
+ drop_udp = 1;
+}
+
+void slirp_drop_tcp() {
+ drop_tcp = 1;
+}
+
+/* TCP traffic forwarding to a sink - If enabled, all TCP traffic to any
+ * ip/port that is not explicitly forwared using '-net-forward', and which would
+ * otherwise be dropped if '-drop-tcp' has been specified, is redirected to the
+ * specified ip:port
+ */
+int forward_dropped_tcp2sink = 0;
+static unsigned long tcp_sink_ip;
+int tcp_sink_port;
+
+void slirp_forward_dropped_tcp2sink(unsigned long sink_ip, int sink_port) {
+ tcp_sink_ip = sink_ip;
+ tcp_sink_port = sink_port;
+ forward_dropped_tcp2sink = 1;
+}
+
+int slirp_should_forward_dropped_tcp2sink() {
+ return forward_dropped_tcp2sink;
+}
+
+unsigned long slirp_get_tcp_sink_ip() {
+ return tcp_sink_ip;
+}
+int slirp_get_tcp_sink_port() {
+ return tcp_sink_port;
+}
+
+/* Fill in the firewall rules. dst_lport and dst_hport are in host byte order */
+void slirp_add_allow(unsigned long dst_addr,
+ int dst_lport, int dst_hport,
+ u_int8_t proto) {
+
+ struct fw_allow_entry** ate;
+ switch (proto) {
+ case IPPROTO_TCP:
+ ate = &allow_tcp_entries;
+ break;
+ case IPPROTO_UDP:
+ ate = &allow_udp_entries;
+ break;
+ default:
+ return; // unknown protocol for the FW
+ }
+
+ while(*ate != NULL)
+ ate = &(*ate)->next;
+
+ *ate = malloc(sizeof(**ate));
+ if (*ate == NULL) {
+ DEBUG_MISC((dfd,
+ "Unable to create new firewall record, malloc failed\n"));
+ exit(-1);
+ }
+
+ (*ate)->next = NULL;
+ (*ate)->dst_addr = dst_addr;
+ (*ate)->dst_lport = dst_lport;
+ (*ate)->dst_hport = dst_hport;
+}
+
+void slirp_drop_log_fd(FILE* fd) {
+ drop_log_fd = fd;
+}
+
+void slirp_dns_log_fd(FILE* fd) {
+ dns_log_fd = fd;
+}
+
+FILE* get_slirp_drop_log_fd(void) {
+ return drop_log_fd;
+}
+
+FILE* get_slirp_dns_log_fd(void) {
+ return dns_log_fd;
+}
+
+/* Address and ports are in host byte order */
+int slirp_should_drop(unsigned long dst_addr,
+ int dst_port,
+ u_int8_t proto) {
+
+ struct fw_allow_entry* ate;
+
+ switch (proto) {
+ case IPPROTO_TCP:
+ if (drop_tcp != 0)
+ ate = allow_tcp_entries;
+ else
+ return 0;
+ break;
+ case IPPROTO_UDP:
+ if (drop_udp != 0)
+ ate = allow_udp_entries;
+ else
+ return 0;
+ break;
+ default:
+ return 1; // unknown protocol for the FW
+ }
+
+ while(ate) {
+ if ((ate->dst_lport <= dst_port) && (dst_port <= ate->dst_hport)) {
+ // allow any destination if 0
+ if (ate->dst_addr == 0 || ate->dst_addr == dst_addr)
+ return 0;
+ }
+ ate = ate->next;
+ }
+
+ return 1;
+}
+
+/*
+ * log DNS requests in a separate log
+ */
+int
+slirp_log_dns(struct mbuf* m, int dropped) {
+ char dns_query[256]; // max allowable dns name size
+ int c = 0;
+ int i= 0;
+ int index = 0;
+ int offset = 40 + 1; // udp/ip headers length + 1;
+ int trim_bytes = 4;
+
+ if (!dns_log_fd)
+ return -1;
+
+ /* We assume one DNS name per query: 300 = 255 (max dns name length)
+ * + 40 (udp/ip hdr) + 1 byte DNS peamble + 4 bytes DNS suffix
+ */
+ if (m->m_len < offset || m->m_len > 300) {
+ DEBUG_MISC((dfd,"Malformed DNS qeury, length %d \n", (int)m->m_len));
+ return -1;
+ }
+ for (i = offset; i < m->m_len - trim_bytes && index < sizeof(dns_query); i++, index++) {
+ c = m->m_data[i];
+ if (c < ' ' || c > '~')
+ c = '.';
+
+ dns_query[index] = (char)c;
+ }
+ dns_query[index] = '\0';
+ if (!dropped) {
+ fprintf(dns_log_fd, "Sent DNS query for, %s\n" , dns_query);
+ } else {
+ fprintf(dns_log_fd, "Dropped DNS query for, %s\n" , dns_query);
+ }
+ fflush(dns_log_fd);
+ return 1;
+}
+
+/*
+ * log DNS requests in a separate log
+ */
+int
+slirp_dump_dns(struct mbuf* m) {
+
+ if (!dns_log_fd)
+ return 0;
+ // first we write the length of the record then the record (IP packet)
+ if (!fwrite(&(m->m_len), sizeof(int), 1, dns_log_fd) ||
+ !fwrite(m->m_data, m->m_len, 1, dns_log_fd)) {
+ return 0;
+ }
+
+ fflush(dns_log_fd);
+ return 1;
+}
+
+/* Log dropped/accepted packet info */
+int slirp_drop_log(const char* format, ...) {
+ va_list args;
+
+ if (!drop_log_fd)
+ return 0;
+
+ va_start(args, format);
+ vfprintf(drop_log_fd, format, args);
+ va_end(args);
+
+ fflush(drop_log_fd);
+
+ return 1;
+}
+
+
+/* Set max DNS requests allowed to be issued from the VM */
+void slirp_set_max_dns_conns(int num_conns) {
+ max_dns_conns = num_conns;
+}
+
+int slirp_get_max_dns_conns() {
+ return max_dns_conns;
+}
+
+/* generic guest network redirection functionality for ipv4 */
+struct net_forward_entry {
+ QTAILQ_ENTRY(net_forward_entry) next;
+ /* ip addresses are also in host byte order */
+ unsigned long dest_ip; /* the destination address they try to contact */
+ unsigned long dest_mask; /* the mask to apply to the address for matching */
+ /* Range of ports they were trying to contact. In case of a single port,
+ * dest_lport should be the same as dest_hport */
+ int dest_lport; /* Host byte order */
+ int dest_hport; /* Host byte order */
+
+ unsigned long redirect_ip;
+ int redirect_port; /* Host byte order */
+};
+
+static QTAILQ_HEAD(net_forwardq, net_forward_entry) net_forwards;
+
+static void slirp_net_forward_init(void)
+{
+ if (!slirp_net_forward_inited) {
+ QTAILQ_INIT(&net_forwards);
+ slirp_net_forward_inited = 1;
+ }
+}
+
+/* all addresses and ports ae in host byte order */
+void slirp_add_net_forward(unsigned long dest_ip, unsigned long dest_mask,
+ int dest_lport, int dest_hport,
+ unsigned long redirect_ip, int redirect_port)
+{
+ slirp_net_forward_init();
+
+ struct net_forward_entry *entry = malloc(sizeof(*entry));
+ if (entry == NULL) {
+ DEBUG_MISC((dfd, "Unable to create new forwarding entry, malloc failed\n"));
+ exit(-1);
+ }
+
+ entry->dest_ip = dest_ip;
+ entry->dest_mask = dest_mask;
+ entry->dest_lport = dest_lport;
+ entry->dest_hport = dest_hport;
+ entry->redirect_ip = redirect_ip;
+ entry->redirect_port = redirect_port;
+
+ QTAILQ_INSERT_TAIL(&net_forwards, entry, next);
+}
+
+/* remote_port and redir_port arguments
+ * are in network byte order (tcp_subr.c) */
+int slirp_should_net_forward(unsigned long remote_ip, int remote_port,
+ unsigned long *redirect_ip, int *redirect_port)
+{
+ struct net_forward_entry *entry;
+
+ for (entry = net_forwards.tqh_first;
+ entry != NULL; entry = entry->next.tqe_next) {
+
+ if ((entry->dest_lport <= remote_port)
+ && (remote_port <= entry->dest_hport)) {
+ if ((entry->dest_ip & entry->dest_mask)
+ == (remote_ip & entry->dest_mask)) {
+ *redirect_ip = entry->redirect_ip;
+ *redirect_port = entry->redirect_port;
+ return 1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+/*---------------------------------------------------*/
+
+
+
+
static void _slirp_redir_loop(void (*func)(void *opaque, int is_udp,
const SockAddress *laddr,
const SockAddress *faddr),
diff --git a/slirp-android/socket.c b/slirp-android/socket.c
index 44640a8..439590a 100644
--- a/slirp-android/socket.c
+++ b/slirp-android/socket.c
@@ -570,6 +570,27 @@
addr_port = so->so_faddr_port;
+ /*
+ * test for generic forwarding; this function replaces the arguments
+ * only on success
+ */
+ unsigned long faddr = addr_ip;
+ int fport = addr_port;
+
+ if (slirp_should_net_forward(faddr, fport, &faddr, &fport)) {
+ time_t timestamp = time(NULL);
+ slirp_drop_log(
+ "Redirected UDP: src: 0x%08lx:0x%04x org dst: 0x%08lx:0x%04x "
+ "new dst: 0x%08lx:0x%04x %ld\n",
+ so->so_laddr_ip, so->so_laddr_port,
+ addr_ip, addr_port,
+ faddr, fport, timestamp
+ );
+ }
+ addr_ip = faddr;
+ addr_port = fport;
+
+
sock_address_init_inet(&addr, addr_ip, addr_port);
DEBUG_MISC((dfd, " sendto()ing, addr.sin_port=%d, addr.sin_addr.s_addr=%08x\n", addr_port, addr_ip));
@@ -779,4 +800,3 @@
else
sofcantsendmore(so);
}
-
diff --git a/slirp-android/tcp_subr.c b/slirp-android/tcp_subr.c
index b8b680c..cfcc3cb 100644
--- a/slirp-android/tcp_subr.c
+++ b/slirp-android/tcp_subr.c
@@ -377,6 +377,29 @@
tcp_input(NULL, sizeof(struct ip), so);
}
+
+/* Tests if an IP address corresponds to a special Qemu service (eg, the DNS
+ * server or the gateway - see ctl.h) and if so, rewrites it with the real
+ * address of the service.
+ */
+int is_qemu_special_address(unsigned long dst_addr, unsigned long *redir_addr)
+{
+ if ((dst_addr & 0xffffff00) == special_addr_ip) {
+ /* It's an alias */
+
+ int last_byte = dst_addr & 0xff;
+
+ if (CTL_IS_DNS(last_byte))
+ *redir_addr = dns_addr[last_byte - CTL_DNS];
+ else
+ *redir_addr = loopback_addr_ip;
+
+ return 1;
+ }
+ return 0;
+}
+
+
/*
* Connect to a host on the Internet
* Called by tcp_input
@@ -390,41 +413,60 @@
int tcp_fconnect(struct socket *so)
{
int ret=0;
- int try_proxy = 1;
SockAddress sockaddr;
- uint32_t sock_ip;
- uint16_t sock_port;
+ unsigned long sock_ip;
+ int sock_port;
+ int redirect_happened = 0; /* for logging new src ip/port after connect */
DEBUG_CALL("tcp_fconnect");
DEBUG_ARG("so = %lx", (long )so);
- sock_ip = so->so_faddr_ip;
- sock_port = so->so_faddr_port;
+ /* when true, a connection that otherwise would be dropped will instead be
+ * redirected to the sink ('-net-forward-tcp2sink') */
+ int forward_dropped_to_sink = 0;
+ time_t timestamp = time(NULL);
- if ((sock_ip & 0xffffff00) == special_addr_ip) {
- /* It's an alias */
- int last_byte = sock_ip & 0xff;
+ /*-------------------------------------------------------------*/
+ /* User mode network stack restrictions */
+ if (slirp_should_drop(so->so_faddr_ip, so->so_faddr_port, IPPROTO_TCP)) {
- if (CTL_IS_DNS(last_byte))
- sock_ip = dns_addr[last_byte - CTL_DNS];
- else
- sock_ip = loopback_addr_ip;
- try_proxy = 0;
+ /* If forwarding to sink is enabled, don't actually drop it */
+ if (slirp_should_forward_dropped_tcp2sink()) {
+ slirp_drop_log(
+ "About to be dropped TCP allowed to sink: "
+ "0x%08lx:0x%04x -> 0x%08lx:0x%04x %ld\n",
+ so->so_laddr_ip,
+ so->so_laddr_port,
+ so->so_faddr_ip,
+ so->so_faddr_port,
+ timestamp
+ );
+ forward_dropped_to_sink = 1;
+ }
+ else {
+ slirp_drop_log(
+ "Dropped TCP: 0x%08lx:0x%04x -> 0x%08lx:0x%04x %ld\n",
+ so->so_laddr_ip,
+ so->so_laddr_port,
+ so->so_faddr_ip,
+ so->so_faddr_port,
+ timestamp
+ );
+ //errno = ENETUNREACH;
+ errno = ECONNREFUSED;
+ return -1;
+ }
+ } else {
+ slirp_drop_log(
+ "Allowed TCP: 0x%08lx:0x%04x -> 0x%08lx:0x%04x %ld\n",
+ so->so_laddr_ip,
+ so->so_laddr_port,
+ so->so_faddr_ip,
+ so->so_faddr_port,
+ timestamp
+ );
}
-
- sock_address_init_inet( &sockaddr, sock_ip, sock_port );
-
- DEBUG_MISC((dfd, " connect()ing, addr=%s, proxy=%d\n",
- sock_address_to_string(&sockaddr), try_proxy));
-
- if (try_proxy) {
- if (!proxy_manager_add(&sockaddr, SOCKET_STREAM, (ProxyEventFunc) tcp_proxy_event, so)) {
- soisfconnecting(so);
- so->s = -1;
- so->so_state |= SS_PROXIFIED;
- return 0;
- }
- }
+ /*-------------------------------------------------------------*/
if ((ret=so->s=socket_create_inet(SOCKET_STREAM)) >= 0)
{
@@ -434,10 +476,87 @@
socket_set_xreuseaddr(s);
socket_set_oobinline(s);
+
+ if (forward_dropped_to_sink) {
+
+ /* This connection would normally be dropped, but since forwarding of
+ * dropped connections is enabled, redirect it to the sink */
+ sock_ip = slirp_get_tcp_sink_ip();
+ sock_port= slirp_get_tcp_sink_port();
+ redirect_happened = 1;
+ }
+ else { /* An allowed connection */
+
+ unsigned long faddr;
+ int fport;
+
+ /* Determine if the connection should be redirected
+ * due to a -net-forward rule */
+ /* faddr and fport are modified only on success */
+ if (slirp_should_net_forward(so->so_faddr_ip, so->so_faddr_port,
+ &faddr, &fport)) {
+ redirect_happened = 1;
+ sock_ip = faddr; /* forced dst addr */
+ sock_port= fport; /* forced dst port */
+ }
+ /* Determine if this is a connection to a special qemu service,
+ * and change the destination address accordingly.
+ * 'faddr' is modified only on success */
+ else if (is_qemu_special_address(so->so_faddr_ip, &faddr)) {
+
+ /* We keep the original destination port. If a special service
+ * listens on a different port than the standard, then appropriate
+ * forwarding should be set up using -net-forward, e.g., as it is
+ * the case with Mawler's DNS traffic, which is redirected to the
+ * special DNS port:
+ * -net-forward 0.0.0.0:0.0.0.0:53:127.0.0.1:21737 */
+
+ sock_ip = faddr; /* real DNS/gateway addr */
+ sock_port= so->so_faddr_port;/* original dst port */
+
+ }
+ /* A normal connection - keep the original destination addr/port */
+ else {
+
+ if (!proxy_manager_add(&sockaddr, SOCKET_STREAM,
+ (ProxyEventFunc) tcp_proxy_event, so)) {
+ soisfconnecting(so);
+ so->s = -1;
+ so->so_state |= SS_PROXIFIED;
+ return 0;
+ }
+
+ sock_ip = so->so_faddr_ip; /* original dst addr */
+ sock_port= so->so_faddr_port; /* original dst port */
+ }
+ }
+
+ DEBUG_MISC((dfd, " connect()ing, addr=%s, proxy=%d\n",
+ sock_address_to_string(&sockaddr), try_proxy));
+
+ sock_address_init_inet( &sockaddr, sock_ip, sock_port );
+
/* We don't care what port we get */
socket_connect(s, &sockaddr);
- /*
+ if (redirect_happened) {
+ SockAddress local_addr;
+ if (socket_get_address(s, &local_addr)) {
+ fprintf (stderr,
+ "Warning: tcp_fconnect: could not get socket name\n");
+ }
+ slirp_drop_log(
+ "Redirected TCP: orig 0x%08lx:0x%04x -> 0x%08lx:0x%04x "
+ "new 0x%08lx:0x%04x -> 0x%08lx:0x%04x %ld\n",
+ so->so_laddr_ip, so->so_laddr_port,
+ so->so_faddr_ip, so->so_laddr_port,
+ sock_address_get_ip(&local_addr),
+ sock_address_get_port(&local_addr),
+ sock_ip, sock_port, timestamp
+ );
+ }
+
+ /*
* If it's not in progress, it failed, so we just return 0,
* without clearing SS_NOFDREF
*/
diff --git a/slirp-android/udp.c b/slirp-android/udp.c
index 9091505..1de938a 100644
--- a/slirp-android/udp.c
+++ b/slirp-android/udp.c
@@ -47,6 +47,10 @@
struct udpstat udpstat;
#endif
+/* Keeps track of the number of DNS requests. Used to implement the firewall
+ * option that restricts the number of DNS requests (-max_dns_conns). */
+u_int dns_num_conns;
+
struct socket udb;
static u_int8_t udp_tos(struct socket *so);
@@ -68,6 +72,7 @@
udp_init(void)
{
udb.so_next = udb.so_prev = &udb;
+ dns_num_conns = 0;
}
/* m->m_data points at ip packet header
* m->m_len length ip packet
@@ -121,6 +126,37 @@
ip->ip_len = len;
}
+ /* ------------------------------------------------------*/
+ /* User mode network stack restrictions */
+ /* slirp_should_drop requires host byte ordering in arguments */
+ time_t timestamp = time(NULL);
+
+ if (slirp_should_drop(ntohl(ip->ip_dst.addr), ntohs(uh->uh_dport.port),
+ IPPROTO_UDP)) {
+ slirp_drop_log(
+ "Dropped UDP: src: 0x%08lx:0x%04x dst: 0x%08lx:0x%04x %ld\n",
+ ntohl(ip->ip_src.addr),
+ ntohs(uh->uh_sport.port),
+ ntohl(ip->ip_dst.addr),
+ ntohs(uh->uh_dport.port),
+ timestamp
+ );
+ goto bad; /* drop the packet */
+ }
+ else {
+ slirp_drop_log(
+ "Allowed UDP: src: 0x%08lx:0x%04x dst: 0x%08lx:0x%04x %ld\n",
+ ntohl(ip->ip_src.addr),
+ ntohs(uh->uh_sport.port),
+ ntohl(ip->ip_dst.addr),
+ ntohs(uh->uh_dport.port),
+ timestamp
+ );
+ }
+ /* ------------------------------------------------------*/
+
+
+
/*
* Save a copy of the IP header in case we want restore it
* for sending an ICMP error message in response.
@@ -164,6 +200,18 @@
goto bad;
}
+ // DNS logging and FW rules
+ if (ntohs(uh->uh_dport.port) == 53) {
+ if (!slirp_dump_dns(m)) {
+ DEBUG_MISC((dfd,"Error logging DNS packet"));
+ }
+ dns_num_conns++;
+ if (slirp_get_max_dns_conns() != -1 &&
+ dns_num_conns > slirp_get_max_dns_conns())
+ goto bad;
+ }
+
+
/*
* Locate pcb for datagram.
*/
@@ -309,6 +357,13 @@
STAT(udpstat.udps_opackets++);
+ // DNS logging
+ if (so != NULL && so->so_faddr_port == 53) { /*so has host byte order */
+ if (!slirp_dump_dns(m)) {
+ DEBUG_MISC((dfd,"Error logging DNS packet"));
+ }
+ }
+
error = ip_output(so, m);
return (error);
diff --git a/slirp-android/udp.h b/slirp-android/udp.h
index 4350ec3..2224181 100644
--- a/slirp-android/udp.h
+++ b/slirp-android/udp.h
@@ -69,7 +69,6 @@
#define ui_ulen ui_u.uh_ulen
#define ui_sum ui_u.uh_sum
-#ifdef LOG_ENABLED
struct udpstat {
/* input statistics: */
u_long udps_ipackets; /* total input packets */
@@ -83,7 +82,6 @@
/* output statistics: */
u_long udps_opackets; /* total output packets */
};
-#endif
/*
* Names for UDP sysctl objects
@@ -91,9 +89,7 @@
#define UDPCTL_CHECKSUM 1 /* checksum UDP packets */
#define UDPCTL_MAXID 2
-#ifdef LOG_ENABLED
extern struct udpstat udpstat;
-#endif
extern struct socket udb;
struct mbuf;
diff --git a/sockets.c b/sockets.c
index e1f7ad3..1063339 100644
--- a/sockets.c
+++ b/sockets.c
@@ -130,7 +130,7 @@
const WinsockError* werr = _winsock_errors;
int unix = EINVAL; /* generic error code */
- winsock_error = WSAGetLastError();
+ winsock_error = WSAGetLastError();
for ( ; werr->string != NULL; werr++ ) {
if (werr->winsock == winsock_error) {
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 258e2cb..f595b2c 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -1214,7 +1214,7 @@
int cpu_arm_handle_mmu_fault (CPUState *env, target_ulong address,
int access_type, int mmu_idx, int is_softmmu)
{
- uint32_t phys_addr;
+ uint32_t phys_addr = 0;
int prot;
int ret, is_user;
@@ -1244,7 +1244,7 @@
target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
{
- uint32_t phys_addr;
+ uint32_t phys_addr = 0;
int prot;
int ret;
diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index 4e7eb58..88547cb 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -181,7 +181,7 @@
#define HF2_VINTR_SHIFT 3 /* value of V_INTR_MASKING bit */
#define HF2_GIF_MASK (1 << HF2_GIF_SHIFT)
-#define HF2_HIF_MASK (1 << HF2_HIF_SHIFT)
+#define HF2_HIF_MASK (1 << HF2_HIF_SHIFT)
#define HF2_NMI_MASK (1 << HF2_NMI_SHIFT)
#define HF2_VINTR_MASK (1 << HF2_VINTR_SHIFT)
@@ -409,7 +409,7 @@
#define CPUID_VENDOR_INTEL_3 0x6c65746e /* "ntel" */
#define CPUID_VENDOR_AMD_1 0x68747541 /* "Auth" */
-#define CPUID_VENDOR_AMD_2 0x69746e65 /* "enti" */
+#define CPUID_VENDOR_AMD_2 0x69746e65 /* "enti" */
#define CPUID_VENDOR_AMD_3 0x444d4163 /* "cAMD" */
#define CPUID_MWAIT_IBE (1 << 1) /* Interrupts can exit capability */
diff --git a/target-i386/helper.c b/target-i386/helper.c
index 5a81cb2..550b348 100644
--- a/target-i386/helper.c
+++ b/target-i386/helper.c
@@ -211,7 +211,7 @@
.model = 3,
.stepping = 3,
.features = PPRO_FEATURES,
- .ext_features = CPUID_EXT_SSE3,
+ .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_SSSE3,
.xlevel = 0,
.model_id = "QEMU Virtual CPU version " QEMU_VERSION,
},
diff --git a/telephony/android_modem.c b/telephony/android_modem.c
index 26276bb..437035d 100644
--- a/telephony/android_modem.c
+++ b/telephony/android_modem.c
@@ -2199,16 +2199,14 @@
return NULL;
}
-#if CONFIG_ANDROID_SNAPSHOTS
int android_snapshot_update_time = 1;
int android_snapshot_update_time_request = 0;
-#endif
static const char*
handleSignalStrength( const char* cmd, AModem modem )
{
amodem_begin_line( modem );
-#if CONFIG_ANDROID_SNAPSHOTS
+
/* Sneak time updates into the SignalStrength request, because it's periodic.
* Ideally, we'd be able to prod the guest into asking immediately on restore
* from snapshot, but that'd require a driver.
@@ -2217,7 +2215,7 @@
amodem_addTimeUpdate( modem );
android_snapshot_update_time_request = 0;
}
-#endif
+
// rssi = 0 (<-113dBm) 1 (<-111) 2-30 (<-109--53) 31 (>=-51) 99 (?!)
// ber (bit error rate) - always 99 (unknown), apparently.
// TODO: return 99 if modem->radio_state==A_RADIO_STATE_OFF, once radio_state is in snapshot.
diff --git a/vl-android.c b/vl-android.c
index caef03d..e140cb2 100644
--- a/vl-android.c
+++ b/vl-android.c
@@ -56,8 +56,14 @@
#include "android/charmap.h"
#include "android/globals.h"
#include "android/utils/bufprint.h"
+#include "android/utils/debug.h"
+#include "android/utils/filelock.h"
+#include "android/utils/path.h"
+#include "android/utils/stralloc.h"
+#include "android/utils/tempfile.h"
#include "android/display-core.h"
#include "android/utils/timezone.h"
+#include "android/snapshot.h"
#include "targphys.h"
#include "tcpdump.h"
@@ -278,6 +284,8 @@
#endif
int no_quit = 0;
CharDriverState *serial_hds[MAX_SERIAL_PORTS];
+int serial_hds_count;
+
CharDriverState *parallel_hds[MAX_PARALLEL_PORTS];
CharDriverState *virtcon_hds[MAX_VIRTIO_CONSOLES];
#ifdef TARGET_I386
@@ -338,9 +346,6 @@
// Path to the file containing specific key character map.
char* op_charmap_file = NULL;
-/* Framebuffer dimensions, passed with -android-gui option. */
-char* android_op_gui = NULL;
-
/* Path to hardware initialization file passed with -android-hw option. */
char* android_op_hwini = NULL;
@@ -401,9 +406,11 @@
extern void dprint( const char* format, ... );
-#if CONFIG_ANDROID_SNAPSHOTS
+const char* dns_log_filename = NULL;
+const char* drop_log_filename = NULL;
+static int rotate_logs_requested = 0;
+
const char* savevm_on_exit = NULL;
-#endif
#define TFR(expr) do { if ((expr) != -1) break; } while (errno == EINTR)
@@ -509,40 +516,50 @@
#endif
}
-/* Parses -android-gui command line option, extracting width, height and bits
- * per pixel parameters for the GUI console used in this session of the
- * emulator. -android-gui option contains exactly three comma-separated positive
- * integer numbers in strict order: width goes first, width goes next, and bits
- * per pixel goes third. This routine verifies that format and return 0 if all
- * three numbers were extracted, or -1 if string format was incorrect for that
- * option. Note that this routine does not verify that extracted values are
- * correct!
+/*
+ * Sets a flag (rotate_logs_requested) to clear both the DNS and the
+ * drop logs upon receiving a SIGUSR1 signal. We need to clear the logs
+ * between the tasks that do not require restarting Qemu.
*/
-static int
-parse_androig_gui_option(const char* op, int* width, int* height, int* bpp)
-{
- char val[128];
+void rotate_qemu_logs_handler(int signum) {
+ rotate_logs_requested = 1;
+}
- if (get_param_value(val, 128, "width", op)) {
- *width = strtol(val, NULL, 0);
- } else {
- fprintf(stderr, "option -android-gui is missing width parameter\n");
- return -1;
- }
- if (get_param_value(val, 128, "height", op)) {
- *height = strtol(val, NULL, 0);
- } else {
- fprintf(stderr, "option -android-gui is missing height parameter\n");
- return -1;
- }
- if (get_param_value(val, 128, "bpp", op)) {
- *bpp = strtol(val, NULL, 0);
- } else {
- fprintf(stderr, "option -android-gui is missing bpp parameter\n");
- return -1;
- }
+/*
+ * Resets the rotate_log_requested_flag. Normally called after qemu
+ * logs has been rotated.
+ */
+void reset_rotate_qemu_logs_request(void) {
+ rotate_logs_requested = 0;
+}
- return 0;
+/*
+ * Clears the passed qemu log when the rotate_logs_requested
+ * is set. We need to clear the logs between the tasks that do not
+ * require restarting Qemu.
+ */
+FILE* rotate_qemu_log(FILE* old_log_fd, const char* filename) {
+ FILE* new_log_fd = NULL;
+ if (old_log_fd) {
+ if (fclose(old_log_fd) == -1) {
+ fprintf(stderr, "Cannot close old_log fd\n");
+ exit(errno);
+ }
+ }
+
+ if (!filename) {
+ fprintf(stderr, "The log filename to be rotated is not provided");
+ exit(-1);
+ }
+
+ new_log_fd = fopen(filename , "wb+");
+ if (new_log_fd == NULL) {
+ fprintf(stderr, "Cannot open the log file: %s for write.\n",
+ filename);
+ exit(1);
+ }
+
+ return new_log_fd;
}
/***********************************************************/
@@ -3155,6 +3172,17 @@
#ifdef CONFIG_PROFILER
dev_time += profile_getclock() - ti;
#endif
+
+ if (rotate_logs_requested) {
+ FILE* new_dns_log_fd = rotate_qemu_log(get_slirp_dns_log_fd(),
+ dns_log_filename);
+ FILE* new_drop_log_fd = rotate_qemu_log(get_slirp_drop_log_fd(),
+ drop_log_filename);
+ slirp_dns_log_fd(new_dns_log_fd);
+ slirp_drop_log_fd(new_drop_log_fd);
+ reset_rotate_qemu_logs_request();
+ }
+
} while (vm_can_run());
if (qemu_debug_requested())
@@ -3164,11 +3192,9 @@
vm_stop(0);
no_shutdown = 0;
} else {
-#if CONFIG_ANDROID_SNAPSHOTS
if (savevm_on_exit != NULL) {
do_savevm(cur_mon, savevm_on_exit);
}
-#endif
break;
}
}
@@ -3521,9 +3547,11 @@
/* Find a likely location for support files using the location of the binary.
For installed binaries this will be "$bindir/../share/qemu". When
- running from the build tree this will be "$bindir/../pc-bios". */
+ running from the build tree this will be "$bindir/../pc-bios".
+ The emulator running from the SDK will find the support files in $bindir/lib/pc-bios. */
#define SHARE_SUFFIX "/share/qemu"
#define BUILD_SUFFIX "/pc-bios"
+#define SDK_SUFFIX "/lib/pc-bios"
static char *find_datadir(const char *argv0)
{
char *dir;
@@ -3564,19 +3592,25 @@
return NULL;
}
}
- dir = dirname(p);
- dir = dirname(dir);
- max_len = strlen(dir) +
- MAX(strlen(SHARE_SUFFIX), strlen(BUILD_SUFFIX)) + 1;
+#define STRLEN_CONST(str) (sizeof(str)-1)
+ dir = dirname(p);
+ max_len = strlen(dir) + 1 +
+ MAX(STRLEN_CONST(SDK_SUFFIX), MAX(STRLEN_CONST(SHARE_SUFFIX), STRLEN_CONST(BUILD_SUFFIX)));
res = qemu_mallocz(max_len);
- snprintf(res, max_len, "%s%s", dir, SHARE_SUFFIX);
+
+ snprintf(res, max_len, "%s%s", dir, SDK_SUFFIX);
if (access(res, R_OK)) {
- snprintf(res, max_len, "%s%s", dir, BUILD_SUFFIX);
- if (access(res, R_OK)) {
- qemu_free(res);
- res = NULL;
- }
+ dir = dirname(dir);
+
+ snprintf(res, max_len, "%s%s", dir, SHARE_SUFFIX);
+ if (access(res, R_OK)) {
+ snprintf(res, max_len, "%s%s", dir, BUILD_SUFFIX);
+ if (access(res, R_OK)) {
+ qemu_free(res);
+ res = NULL;
+ }
+ }
}
#ifndef PATH_MAX
free(p);
@@ -3641,22 +3675,226 @@
return 0;
}
-/* Appends a parameter to a string of parameters separated with space.
+/* Parses an integer
* Pararm:
- * param_str String containing parameters separated with space.
- * param Parameter to append to the string.
- * size - Size (in characters) of the buffer addressed by param_str.
+ * str String containing a number to be parsed.
+ * result Passes the parsed integer in this argument
+ * returns 0 if ok, -1 if failed
+ */
+int
+parse_int(const char *str, int *result)
+{
+ char* r;
+ *result = strtol(str, &r, 0);
+ if (r == NULL || *r != '\0')
+ return -1;
+
+ return 0;
+}
+
+#ifndef _WIN32
+/*
+ * Initializes the SIGUSR1 signal handler to clear Qemu logs.
+ */
+void init_qemu_clear_logs_sig() {
+ struct sigaction act;
+ sigfillset(&act.sa_mask);
+ act.sa_flags = 0;
+ act.sa_handler = rotate_qemu_logs_handler;
+ if (sigaction(SIGUSR1, &act, NULL) == -1) {
+ fprintf(stderr, "Failed to setup SIGUSR1 handler to clear Qemu logs\n");
+ exit(-1);
+ }
+}
+#endif
+
+
+
+/* parses a null-terminated string specifying a network port (e.g., "80") or
+ * port range (e.g., "[6666-7000]"). In case of a single port, lport and hport
+ * are the same. Returns 0 on success, -1 on error. */
+
+int parse_port_range(const char *str, unsigned short *lport,
+ unsigned short *hport) {
+
+ unsigned int low = 0, high = 0;
+ char *p, *arg = strdup(str);
+
+ if ((*arg == '[') && ((p = strrchr(arg, ']')) != NULL)) {
+ p = arg + 1; /* skip '[' */
+ low = atoi(strtok(p, "-"));
+ high = atoi(strtok(NULL, "-"));
+ if ((low > 0) && (high > 0) && (low < high) && (high < 65535)) {
+ *lport = low;
+ *hport = high;
+ }
+ }
+ else {
+ low = atoi(arg);
+ if ((0 < low) && (low < 65535)) {
+ *lport = low;
+ *hport = low;
+ }
+ }
+ free(arg);
+ if (low != 0)
+ return 0;
+ return -1;
+}
+
+/*
+ * Implements the generic port forwarding option
+ */
+void
+net_slirp_forward(const char *optarg)
+{
+ /*
+ * we expect the following format:
+ * dst_net:dst_mask:dst_port:redirect_ip:redirect_port OR
+ * dst_net:dst_mask:[dp_range_start-dp_range_end]:redirect_ip:redirect_port
+ */
+ char *argument = strdup(optarg), *p = argument;
+ char *dst_net, *dst_mask, *dst_port;
+ char *redirect_ip, *redirect_port;
+ uint32_t dnet, dmask, rip;
+ unsigned short dlport, dhport, rport;
+
+
+ dst_net = strtok(p, ":");
+ dst_mask = strtok(NULL, ":");
+ dst_port = strtok(NULL, ":");
+ redirect_ip = strtok(NULL, ":");
+ redirect_port = strtok(NULL, ":");
+
+ if (dst_net == NULL || dst_mask == NULL || dst_port == NULL ||
+ redirect_ip == NULL || redirect_port == NULL) {
+ fprintf(stderr,
+ "Invalid argument for -net-forward, we expect "
+ "dst_net:dst_mask:dst_port:redirect_ip:redirect_port or "
+ "dst_net:dst_mask:[dp_range_start-dp_range_end]"
+ ":redirect_ip:redirect_port: %s\n",
+ optarg);
+ exit(1);
+ }
+
+ /* inet_strtoip converts dotted address to host byte order */
+ if (inet_strtoip(dst_net, &dnet) == -1) {
+ fprintf(stderr, "Invalid destination IP net: %s\n", dst_net);
+ exit(1);
+ }
+ if (inet_strtoip(dst_mask, &dmask) == -1) {
+ fprintf(stderr, "Invalid destination IP mask: %s\n", dst_mask);
+ exit(1);
+ }
+ if (inet_strtoip(redirect_ip, &rip) == -1) {
+ fprintf(stderr, "Invalid redirect IP address: %s\n", redirect_ip);
+ exit(1);
+ }
+
+ if (parse_port_range(dst_port, &dlport, &dhport) == -1) {
+ fprintf(stderr, "Invalid destination port or port range\n");
+ exit(1);
+ }
+
+ rport = atoi(redirect_port);
+ if (!rport) {
+ fprintf(stderr, "Invalid redirect port: %s\n", redirect_port);
+ exit(1);
+ }
+
+ dnet &= dmask;
+
+ slirp_add_net_forward(dnet, dmask, dlport, dhport,
+ rip, rport);
+
+ free(argument);
+}
+
+
+/* Parses an -allow-tcp or -allow-udp argument and inserts a corresponding
+ * entry in the allows list */
+void
+slirp_allow(const char *optarg, u_int8_t proto)
+{
+ /*
+ * we expect the following format:
+ * dst_ip:dst_port OR dst_ip:[dst_lport-dst_hport]
+ */
+ char *argument = strdup(optarg), *p = argument;
+ char *dst_ip_str, *dst_port_str;
+ uint32_t dst_ip;
+ unsigned short dst_lport, dst_hport;
+
+ dst_ip_str = strtok(p, ":");
+ dst_port_str = strtok(NULL, ":");
+
+ if (dst_ip_str == NULL || dst_port_str == NULL) {
+ fprintf(stderr,
+ "Invalid argument %s for -allow. We expect "
+ "dst_ip:dst_port or dst_ip:[dst_lport-dst_hport]\n",
+ optarg);
+ exit(1);
+ }
+
+ if (inet_strtoip(dst_ip_str, &dst_ip) == -1) {
+ fprintf(stderr, "Invalid destination IP address: %s\n", dst_ip_str);
+ exit(1);
+ }
+ if (parse_port_range(dst_port_str, &dst_lport, &dst_hport) == -1) {
+ fprintf(stderr, "Invalid destination port or port range\n");
+ exit(1);
+ }
+
+ slirp_add_allow(dst_ip, dst_lport, dst_hport, proto);
+
+ free(argument);
+}
+
+/* Add a serial device at a given location in the emulated hardware table.
+ * On failure, this function aborts the program with an error message.
*/
static void
-append_param(char* param_str, const char* arg, int size)
+serial_hds_add_at(int index, const char* devname)
{
- if (*param_str) {
- strncat(param_str, " ", size);
- strncat(param_str, arg, size);
- } else {
- strncpy(param_str, arg, size);
- param_str[size - 1] = '\0';
+ char label[32];
+
+ if (!devname || !strcmp(devname,"none"))
+ return;
+
+ if (index >= MAX_SERIAL_PORTS) {
+ PANIC("qemu: invalid serial index for %s (%d >= %d)",
+ devname, index, MAX_SERIAL_PORTS);
}
+ if (serial_hds[index] != NULL) {
+ PANIC("qemu: invalid serial index for %s (%d: already taken!)",
+ devname, index);
+ }
+ snprintf(label, sizeof(label), "serial%d", index);
+ serial_hds[index] = qemu_chr_open(label, devname, NULL);
+ if (!serial_hds[index]) {
+ PANIC("qemu: could not open serial device '%s'", devname);
+ }
+}
+
+
+/* Find a free slot in the emulated serial device table, and register
+ * it. Return the allocated table index.
+ */
+static int
+serial_hds_add(const char* devname)
+{
+ int index;
+
+ /* Find first free slot */
+ for (index = 0; index < MAX_SERIAL_PORTS; index++) {
+ if (serial_hds[index] == NULL) {
+ serial_hds_add_at(index, devname);
+ return index;
+ }
+ }
+
+ PANIC("qemu: too many serial devices registered (%d)", index);
+ return -1; /* shouldn't happen */
}
int main(int argc, char **argv, char **envp)
@@ -3673,6 +3911,7 @@
DisplayChangeListener *dcl;
int cyls, heads, secs, translation;
QemuOpts *hda_opts = NULL;
+ QemuOpts *hdb_opts = NULL;
const char *net_clients[MAX_NET_CLIENTS];
int nb_net_clients;
const char *bt_opts[MAX_BT_CMDLINE];
@@ -3706,16 +3945,9 @@
#endif
CPUState *env;
int show_vnc_port = 0;
-#ifdef CONFIG_STANDALONE_CORE
IniFile* hw_ini = NULL;
-#endif // CONFIG_STANDALONE_CORE
- /* Container for the kernel initialization parameters collected in this
- * routine. */
- char kernel_cmdline_append[1024];
- /* Combines kernel initialization parameters passed from the UI with
- * the parameters collected in this routine. */
- char kernel_cmdline_full[1024];
- char tmp_str[1024];
+ STRALLOC_DEFINE(kernel_params);
+ STRALLOC_DEFINE(kernel_config);
int dns_count = 0;
/* Initialize sockets before anything else, so we can properly report
@@ -3767,8 +3999,7 @@
snapshot = 0;
kernel_filename = NULL;
kernel_cmdline = "";
- kernel_cmdline_append[0] = '\0';
- kernel_cmdline_full[0] = '\0';
+
cyls = heads = secs = 0;
translation = BIOS_ATA_TRANSLATION_AUTO;
monitor_device = "vc:80Cx24C";
@@ -3893,6 +4124,9 @@
",trans=none" : "");
break;
case QEMU_OPTION_hdb:
+ hdb_opts = drive_add(optarg, HD_ALIAS, 1);
+ break;
+
case QEMU_OPTION_hdc:
case QEMU_OPTION_hdd:
drive_add(optarg, HD_ALIAS, popt->index - QEMU_OPTION_hda);
@@ -4235,11 +4469,9 @@
case QEMU_OPTION_loadvm:
loadvm = optarg;
break;
-#if CONFIG_ANDROID_SNAPSHOTS
case QEMU_OPTION_savevm_on_exit:
savevm_on_exit = optarg;
break;
-#endif
case QEMU_OPTION_full_screen:
full_screen = 1;
break;
@@ -4288,6 +4520,7 @@
kqemu_allowed = 2;
break;
#endif
+#ifdef TARGET_I386
#ifdef CONFIG_KVM
case QEMU_OPTION_enable_kvm:
kvm_allowed = 1;
@@ -4296,6 +4529,7 @@
#endif
break;
#endif
+#endif /* TARGET_I386 */
case QEMU_OPTION_usb:
usb_enabled = 1;
break;
@@ -4416,6 +4650,91 @@
}
}
break;
+
+ /* -------------------------------------------------------*/
+ /* User mode network stack restrictions */
+ case QEMU_OPTION_drop_udp:
+ slirp_drop_udp();
+ break;
+ case QEMU_OPTION_drop_tcp:
+ slirp_drop_tcp();
+ break;
+ case QEMU_OPTION_allow_tcp:
+ slirp_allow(optarg, IPPROTO_TCP);
+ break;
+ case QEMU_OPTION_allow_udp:
+ slirp_allow(optarg, IPPROTO_UDP);
+ break;
+ case QEMU_OPTION_drop_log:
+ {
+ FILE* drop_log_fd;
+ drop_log_filename = optarg;
+ drop_log_fd = fopen(optarg, "w+");
+
+ if (!drop_log_fd) {
+ fprintf(stderr, "Cannot open drop log: %s\n", optarg);
+ exit(1);
+ }
+
+ slirp_drop_log_fd(drop_log_fd);
+ }
+ break;
+
+ case QEMU_OPTION_dns_log:
+ {
+ FILE* dns_log_fd;
+ dns_log_filename = optarg;
+ dns_log_fd = fopen(optarg, "wb+");
+
+ if (dns_log_fd == NULL) {
+ fprintf(stderr, "Cannot open dns log: %s\n", optarg);
+ exit(1);
+ }
+
+ slirp_dns_log_fd(dns_log_fd);
+ }
+ break;
+
+
+ case QEMU_OPTION_max_dns_conns:
+ {
+ int max_dns_conns = 0;
+ if (parse_int(optarg, &max_dns_conns)) {
+ fprintf(stderr,
+ "qemu: syntax: -max-dns-conns max_connections\n");
+ exit(1);
+ }
+ if (max_dns_conns <= 0 || max_dns_conns == LONG_MAX) {
+ fprintf(stderr,
+ "Invalid arg for max dns connections: %s\n",
+ optarg);
+ exit(1);
+ }
+ slirp_set_max_dns_conns(max_dns_conns);
+ }
+ break;
+
+ case QEMU_OPTION_net_forward:
+ net_slirp_forward(optarg);
+ break;
+ case QEMU_OPTION_net_forward_tcp2sink:
+ {
+ SockAddress saddr;
+
+ if (parse_host_port(&saddr, optarg)) {
+ fprintf(stderr,
+ "Invalid ip/port %s for "
+ "-forward-dropped-tcp2sink. "
+ "We expect 'sink_ip:sink_port'\n",
+ optarg);
+ exit(1);
+ }
+ slirp_forward_dropped_tcp2sink(saddr.u.inet.address,
+ saddr.u.inet.port);
+ }
+ break;
+ /* -------------------------------------------------------*/
+
case QEMU_OPTION_tb_size:
tb_size = strtol(optarg, NULL, 0);
if (tb_size < 0)
@@ -4508,10 +4827,6 @@
op_charmap_file = (char*)optarg;
break;
- case QEMU_OPTION_android_gui:
- android_op_gui = (char*)optarg;
- break;
-
case QEMU_OPTION_android_hw:
android_op_hwini = (char*)optarg;
break;
@@ -4596,26 +4911,16 @@
#ifdef CONFIG_MEMCHECK
case QEMU_OPTION_android_memcheck:
android_op_memcheck = (char*)optarg;
- snprintf(tmp_str, sizeof(tmp_str), "memcheck=%s",
- android_op_memcheck);
- tmp_str[sizeof(tmp_str) - 1] = '\0';
/* This will set ro.kernel.memcheck system property
* to memcheck's tracing flags. */
- append_param(kernel_cmdline_append, tmp_str, sizeof(kernel_cmdline_append));
+ stralloc_add_format(kernel_config, " memcheck=%s", android_op_memcheck);
break;
#endif // CONFIG_MEMCHECK
- }
- }
- }
- /* Parse GUI option early, so when we init framebuffer in goldfish we have
- * saved display parameters. */
- if (android_op_gui) {
- if (parse_androig_gui_option(android_op_gui,
- &android_display_width,
- &android_display_height,
- &android_display_bpp)) {
- PANIC("Unable to parse -android-gui parameter: %s", android_op_gui);
+ case QEMU_OPTION_snapshot_no_time_update:
+ android_snapshot_update_time = 0;
+ break;
+ }
}
}
@@ -4641,20 +4946,33 @@
data_dir = CONFIG_QEMU_SHAREDIR;
}
-#ifdef CONFIG_STANDALONE_CORE
- /* Initialize hardware configuration. */
- if (android_op_hwini) {
- hw_ini = iniFile_newFromFile(android_op_hwini);
- if (hw_ini == NULL) {
- PANIC("Could not find %s file.", android_op_hwini);
- }
- } else {
- hw_ini = iniFile_newFromMemory("", 0);
+ if (!android_op_hwini) {
+ PANIC("Missing -android-hw <file> option!");
}
-
+ hw_ini = iniFile_newFromFile(android_op_hwini);
+ if (hw_ini == NULL) {
+ PANIC("Could not find %s file.", android_op_hwini);
+ }
androidHwConfig_read(android_hw, hw_ini);
iniFile_free(hw_ini);
-#endif // CONFIG_STANDALONE_CORE
+
+ {
+ int width = android_hw->hw_lcd_width;
+ int height = android_hw->hw_lcd_height;
+ int depth = android_hw->hw_lcd_depth;
+
+ /* A bit of sanity checking */
+ if (width <= 0 || height <= 0 ||
+ (depth != 16 && depth != 32) ||
+ (((width|height) & 3) != 0) )
+ {
+ PANIC("Invalid display configuration (%d,%d,%d)",
+ width, height, depth);
+ }
+ android_display_width = width;
+ android_display_height = height;
+ android_display_bpp = depth;
+ }
#ifdef CONFIG_NAND_LIMITS
/* Init nand stuff. */
@@ -4663,6 +4981,114 @@
}
#endif // CONFIG_NAND_LIMITS
+ /* Initialize AVD name from hardware configuration if needed */
+ if (!android_op_avd_name) {
+ if (android_hw->avd_name && *android_hw->avd_name) {
+ android_op_avd_name = android_hw->avd_name;
+ VERBOSE_PRINT(init,"AVD Name: %s", android_op_avd_name);
+ }
+ }
+
+ /* Initialize system partition image */
+ {
+ char tmp[PATH_MAX+32];
+ const char* sysImage = android_hw->disk_systemPartition_path;
+ const char* initImage = android_hw->disk_systemPartition_initPath;
+ uint64_t sysBytes = android_hw->disk_systemPartition_size;
+
+ if (sysBytes == 0) {
+ PANIC("Invalid system partition size: %" PRUd64, sysBytes);
+ }
+
+ snprintf(tmp,sizeof(tmp),"system,size=0x%" PRUx64, sysBytes);
+
+ if (sysImage && *sysImage) {
+ if (filelock_create(sysImage) == NULL) {
+ fprintf(stderr,"WARNING: System image already in use, changes will not persist!\n");
+ /* If there is no file= parameters, nand_add_dev will create
+ * a temporary file to back the partition image. */
+ } else {
+ pstrcat(tmp,sizeof(tmp),",file=");
+ pstrcat(tmp,sizeof(tmp),sysImage);
+ }
+ }
+ if (initImage && *initImage) {
+ if (!path_exists(initImage)) {
+ PANIC("Invalid initial system image path: %s", initImage);
+ }
+ pstrcat(tmp,sizeof(tmp),",initfile=");
+ pstrcat(tmp,sizeof(tmp),initImage);
+ } else {
+ PANIC("Missing initial system image path!");
+ }
+ nand_add_dev(tmp);
+ }
+
+ /* Initialize data partition image */
+ {
+ char tmp[PATH_MAX+32];
+ const char* dataImage = android_hw->disk_dataPartition_path;
+ const char* initImage = android_hw->disk_dataPartition_initPath;
+ uint64_t dataBytes = android_hw->disk_dataPartition_size;
+
+ if (dataBytes == 0) {
+ PANIC("Invalid data partition size: %" PRUd64, dataBytes);
+ }
+
+ snprintf(tmp,sizeof(tmp),"userdata,size=0x%" PRUx64, dataBytes);
+
+ if (dataImage && *dataImage) {
+ if (filelock_create(dataImage) == NULL) {
+ fprintf(stderr, "WARNING: Data partition already in use. Changes will not persist!\n");
+ /* Note: if there is no file= parameters, nand_add_dev() will
+ * create a temporary file to back the partition image. */
+ } else {
+ /* Create the file if needed */
+ if (!path_exists(dataImage)) {
+ if (path_empty_file(dataImage) < 0) {
+ PANIC("Could not create data image file %s: %s", dataImage, strerror(errno));
+ }
+ }
+ pstrcat(tmp, sizeof(tmp), ",file=");
+ pstrcat(tmp, sizeof(tmp), dataImage);
+ }
+ }
+ if (initImage && *initImage) {
+ pstrcat(tmp, sizeof(tmp), ",initfile=");
+ pstrcat(tmp, sizeof(tmp), initImage);
+ }
+ nand_add_dev(tmp);
+ }
+
+ /* Init SD-Card stuff. For Android, it is always hda */
+ /* If the -hda option was used, ignore the Android-provided one */
+ if (hda_opts == NULL) {
+ const char* sdPath = android_hw->hw_sdCard_path;
+ if (sdPath && *sdPath) {
+ if (!path_exists(sdPath)) {
+ fprintf(stderr, "WARNING: SD Card image is missing: %s\n", sdPath);
+ } else if (filelock_create(sdPath) == NULL) {
+ fprintf(stderr, "WARNING: SD Card image already in use: %s\n", sdPath);
+ } else {
+ /* Successful locking */
+ hda_opts = drive_add(sdPath, HD_ALIAS, 0);
+ }
+ }
+ }
+
+ if (hdb_opts == NULL) {
+ const char* spath = android_hw->disk_snapStorage_path;
+ if (spath && *spath) {
+ if (!path_exists(spath)) {
+ PANIC("Snapshot storage file does not exist: %s", spath);
+ }
+ if (filelock_create(spath) == NULL) {
+ PANIC("Snapshot storag already in use: %s", spath);
+ }
+ hdb_opts = drive_add(spath, HD_ALIAS, 1);
+ }
+ }
+
/* Set the VM's max heap size, passed as a boot property */
if (android_hw->vm_heapSize > 0) {
char tmp[64];
@@ -4689,11 +5115,10 @@
}
/* Initialize LCD density */
- if (android_op_lcd_density) {
- char* end;
- long density = strtol(android_op_lcd_density, &end, 0);
- if (end == NULL || *end || density < 0) {
- PANIC("option -lcd-density must be a positive integer");
+ if (android_hw->hw_lcd_density) {
+ long density = android_hw->hw_lcd_density;
+ if (density <= 0) {
+ PANIC("Invalid hw.lcd.density value: %ld", density);
}
hwLcd_setBootProperty(density);
}
@@ -4789,8 +5214,7 @@
if (dns_count == 0)
dns_count = slirp_get_system_dns_servers();
if (dns_count) {
- snprintf(tmp_str, sizeof(tmp_str), "ndns=%d", dns_count);
- append_param(kernel_cmdline_append, tmp_str, sizeof(kernel_cmdline_append));
+ stralloc_add_format(kernel_config, " ndns=%d", dns_count);
}
#ifdef CONFIG_MEMCHECK
@@ -4799,6 +5223,46 @@
}
#endif // CONFIG_MEMCHECK
+ /* Initialize cache partition, if any */
+ if (android_hw->disk_cachePartition != 0) {
+ char tmp[PATH_MAX+32];
+ const char* partPath = android_hw->disk_cachePartition_path;
+ uint64_t partSize = android_hw->disk_cachePartition_size;
+
+ snprintf(tmp,sizeof(tmp),"cache,size=0x%" PRUx64, partSize);
+
+ if (partPath && *partPath && strcmp(partPath, "<temp>") != 0) {
+ if (filelock_create(partPath) == NULL) {
+ fprintf(stderr, "WARNING: Cache partition already in use. Changes will not persist!\n");
+ /* Note: if there is no file= parameters, nand_add_dev() will
+ * create a temporary file to back the partition image. */
+ } else {
+ /* Create the file if needed */
+ if (!path_exists(partPath)) {
+ if (path_empty_file(partPath) < 0) {
+ PANIC("Could not create cache image file %s: %s", partPath, strerror(errno));
+ }
+ }
+ pstrcat(tmp, sizeof(tmp), ",file=");
+ pstrcat(tmp, sizeof(tmp), partPath);
+ }
+ }
+ nand_add_dev(tmp);
+ }
+
+ /* We always force qemu=1 when running inside QEMU */
+ stralloc_add_str(kernel_params, " qemu=1");
+
+ /* We always initialize the first serial port for the android-kmsg
+ * character device (used to send kernel messages) */
+ serial_hds_add_at(0, "android-kmsg");
+ stralloc_add_str(kernel_params, " console=ttyS0");
+
+ /* We always initialize the second serial port for the android-qemud
+ * character device as well */
+ serial_hds_add_at(1, "android-qemud");
+ stralloc_add_str(kernel_params, " android.qemud=ttyS1");
+
#if defined(CONFIG_KVM) && defined(CONFIG_KQEMU)
if (kvm_allowed && kqemu_allowed) {
PANIC(
@@ -4891,6 +5355,14 @@
if (qemu_init_main_loop()) {
PANIC("qemu_init_main_loop failed");
}
+
+ if (kernel_filename == NULL) {
+ kernel_filename = android_hw->kernel_path;
+ }
+ if (initrd_filename == NULL) {
+ initrd_filename = android_hw->disk_ramdisk_path;
+ }
+
linux_boot = (kernel_filename != NULL);
net_boot = (boot_devices_bitmap >> ('n' - 'a')) & 0xF;
@@ -4968,8 +5440,12 @@
}
/* init the memory */
- if (ram_size == 0)
- ram_size = DEFAULT_RAM_SIZE * 1024 * 1024;
+ if (ram_size == 0) {
+ ram_size = android_hw->hw_ramSize * 1024LL * 1024;
+ if (ram_size == 0) {
+ ram_size = DEFAULT_RAM_SIZE * 1024 * 1024;
+ }
+ }
#ifdef CONFIG_KQEMU
/* FIXME: This is a nasty hack because kqemu can't cope with dynamic
@@ -4983,6 +5459,10 @@
}
#endif
+#ifndef _WIN32
+ init_qemu_clear_logs_sig();
+#endif
+
/* init the dynamic translator */
cpu_exec_init_all(tb_size * 1024 * 1024);
@@ -5093,16 +5573,7 @@
}
for(i = 0; i < MAX_SERIAL_PORTS; i++) {
- const char *devname = serial_devices[i];
- if (devname && strcmp(devname, "none")) {
- char label[32];
- snprintf(label, sizeof(label), "serial%d", i);
- serial_hds[i] = qemu_chr_open(label, devname, NULL);
- if (!serial_hds[i]) {
- PANIC("qemu: could not open serial device '%s'",
- devname);
- }
- }
+ serial_hds_add(serial_devices[i]);
}
for(i = 0; i < MAX_PARALLEL_PORTS; i++) {
@@ -5149,21 +5620,45 @@
#endif
/* Combine kernel command line passed from the UI with parameters
- * collected during initialization. */
- if (*kernel_cmdline) {
- if (kernel_cmdline_append[0]) {
- snprintf(kernel_cmdline_full, sizeof(kernel_cmdline_full), "%s %s",
- kernel_cmdline, kernel_cmdline_append);
- } else {
- strncpy(kernel_cmdline_full, kernel_cmdline, sizeof(kernel_cmdline_full));
- kernel_cmdline_full[sizeof(kernel_cmdline_full) - 1] = '\0';
- }
- } else if (kernel_cmdline_append[0]) {
- strncpy(kernel_cmdline_full, kernel_cmdline_append, sizeof(kernel_cmdline_full));
- }
+ * collected during initialization.
+ *
+ * The order is the following:
+ * - parameters from the hw configuration (kernel.parameters)
+ * - additionnal parameters from options (e.g. -memcheck)
+ * - the -append parameters.
+ */
+ {
+ const char* kernel_parameters;
- machine->init(ram_size, boot_devices,
- kernel_filename, kernel_cmdline_full, initrd_filename, cpu_model);
+ if (android_hw->kernel_parameters) {
+ stralloc_add_c(kernel_params, ' ');
+ stralloc_add_str(kernel_params, android_hw->kernel_parameters);
+ }
+
+ /* If not empty, kernel_config always contains a leading space */
+ stralloc_append(kernel_params, kernel_config);
+
+ if (*kernel_cmdline) {
+ stralloc_add_c(kernel_params, ' ');
+ stralloc_add_str(kernel_params, kernel_cmdline);
+ }
+
+ /* Remove any leading/trailing spaces */
+ stralloc_strip(kernel_params);
+
+ kernel_parameters = stralloc_cstr(kernel_params);
+ VERBOSE_PRINT(init, "Kernel parameters: %s", kernel_parameters);
+
+ machine->init(ram_size,
+ boot_devices,
+ kernel_filename,
+ kernel_parameters,
+ initrd_filename,
+ cpu_model);
+
+ stralloc_reset(kernel_params);
+ stralloc_reset(kernel_config);
+ }
for (env = first_cpu; env != NULL; env = env->next_cpu) {
@@ -5199,16 +5694,11 @@
/* just use the first displaystate for the moment */
ds = get_displaystate();
- if (android_op_gui) {
- /* Initialize display from the command line parameters. */
- android_display_reset(ds,
- android_display_width,
- android_display_height,
- android_display_bpp);
- } else {
- /* By default, use 320x480x16 */
- android_display_reset(ds, 320, 480, 16);
- }
+ /* Initialize display from the command line parameters. */
+ android_display_reset(ds,
+ android_display_width,
+ android_display_height,
+ android_display_bpp);
if (display_type == DT_DEFAULT) {
#if defined(CONFIG_SDL) || defined(CONFIG_COCOA)