TWRP-ify AOSP code
Pull in most TWRP sources Stub out partition management code Make it compile -- probably will not boot Kind of a mess but have to start somewhere
192
Android.mk
@ -14,6 +14,7 @@
|
|||||||
|
|
||||||
LOCAL_PATH := $(call my-dir)
|
LOCAL_PATH := $(call my-dir)
|
||||||
|
|
||||||
|
TARGET_RECOVERY_GUI := true
|
||||||
|
|
||||||
include $(CLEAR_VARS)
|
include $(CLEAR_VARS)
|
||||||
|
|
||||||
@ -27,32 +28,50 @@ LOCAL_SRC_FILES := \
|
|||||||
verifier.cpp \
|
verifier.cpp \
|
||||||
adb_install.cpp
|
adb_install.cpp
|
||||||
|
|
||||||
|
LOCAL_SRC_FILES += \
|
||||||
|
extra-functions.c \
|
||||||
|
data.cpp \
|
||||||
|
makelist.c \
|
||||||
|
firmware.c \
|
||||||
|
partition.cpp \
|
||||||
|
partitionmanager.cpp \
|
||||||
|
mtdutils/mtdutils.c
|
||||||
|
|
||||||
|
ifeq ($(TARGET_RECOVERY_REBOOT_SRC),)
|
||||||
|
LOCAL_SRC_FILES += reboot.c
|
||||||
|
else
|
||||||
|
LOCAL_SRC_FILES += $(TARGET_RECOVERY_REBOOT_SRC)
|
||||||
|
endif
|
||||||
|
|
||||||
LOCAL_MODULE := recovery
|
LOCAL_MODULE := recovery
|
||||||
|
|
||||||
LOCAL_FORCE_STATIC_EXECUTABLE := true
|
#LOCAL_FORCE_STATIC_EXECUTABLE := true
|
||||||
|
|
||||||
RECOVERY_API_VERSION := 3
|
RECOVERY_API_VERSION := 3
|
||||||
LOCAL_CFLAGS += -DRECOVERY_API_VERSION=$(RECOVERY_API_VERSION)
|
LOCAL_CFLAGS += -DRECOVERY_API_VERSION=$(RECOVERY_API_VERSION)
|
||||||
|
|
||||||
LOCAL_STATIC_LIBRARIES := \
|
#LOCAL_STATIC_LIBRARIES := \
|
||||||
libext4_utils_static \
|
# libext4_utils \
|
||||||
libsparse_static \
|
# libminzip \
|
||||||
libminzip \
|
# libmtdutils \
|
||||||
libz \
|
# libmincrypt \
|
||||||
libmtdutils \
|
# libminadbd \
|
||||||
libmincrypt \
|
# libpixelflinger_static
|
||||||
libminadbd \
|
|
||||||
libminui \
|
LOCAL_C_INCLUDES += bionic external/stlport/stlport
|
||||||
libpixelflinger_static \
|
|
||||||
libpng \
|
LOCAL_STATIC_LIBRARIES :=
|
||||||
libcutils \
|
LOCAL_SHARED_LIBRARIES :=
|
||||||
libstdc++ \
|
|
||||||
libc
|
LOCAL_STATIC_LIBRARIES += libmtdutils
|
||||||
|
LOCAL_STATIC_LIBRARIES += libext4_utils libminadbd libminzip libunz libmincrypt
|
||||||
|
LOCAL_STATIC_LIBRARIES += libminuitwrp libpixelflinger_static libpng libjpegtwrp
|
||||||
|
LOCAL_SHARED_LIBRARIES += libz libc libstlport libcutils libstdc++
|
||||||
|
|
||||||
ifeq ($(TARGET_USERIMAGES_USE_EXT4), true)
|
ifeq ($(TARGET_USERIMAGES_USE_EXT4), true)
|
||||||
LOCAL_CFLAGS += -DUSE_EXT4
|
LOCAL_CFLAGS += -DUSE_EXT4
|
||||||
LOCAL_C_INCLUDES += system/extras/ext4_utils
|
LOCAL_C_INCLUDES += system/extras/ext4_utils
|
||||||
LOCAL_STATIC_LIBRARIES += libext4_utils_static libz
|
LOCAL_STATIC_LIBRARIES += libext4_utils
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(HAVE_SELINUX), true)
|
ifeq ($(HAVE_SELINUX), true)
|
||||||
@ -73,14 +92,118 @@ else
|
|||||||
LOCAL_STATIC_LIBRARIES += $(TARGET_RECOVERY_UI_LIB)
|
LOCAL_STATIC_LIBRARIES += $(TARGET_RECOVERY_UI_LIB)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(HAVE_SELINUX),true)
|
|
||||||
LOCAL_C_INCLUDES += external/libselinux/include
|
|
||||||
LOCAL_STATIC_LIBRARIES += libselinux
|
|
||||||
LOCAL_CFLAGS += -DHAVE_SELINUX
|
|
||||||
endif # HAVE_SELINUX
|
|
||||||
|
|
||||||
LOCAL_C_INCLUDES += system/extras/ext4_utils
|
LOCAL_C_INCLUDES += system/extras/ext4_utils
|
||||||
|
|
||||||
|
#TWRP Build Flags
|
||||||
|
ifeq ($(BOARD_HAS_NO_REAL_SDCARD), true)
|
||||||
|
LOCAL_CFLAGS += -DBOARD_HAS_NO_REAL_SDCARD
|
||||||
|
endif
|
||||||
|
ifneq ($(SP1_NAME),)
|
||||||
|
LOCAL_CFLAGS += -DSP1_NAME=$(SP1_NAME) -DSP1_BACKUP_METHOD=$(SP1_BACKUP_METHOD) -DSP1_MOUNTABLE=$(SP1_MOUNTABLE)
|
||||||
|
endif
|
||||||
|
ifneq ($(SP1_DISPLAY_NAME),)
|
||||||
|
LOCAL_CFLAGS += -DSP1_DISPLAY_NAME=$(SP1_DISPLAY_NAME)
|
||||||
|
endif
|
||||||
|
ifneq ($(SP2_NAME),)
|
||||||
|
LOCAL_CFLAGS += -DSP2_NAME=$(SP2_NAME) -DSP2_BACKUP_METHOD=$(SP2_BACKUP_METHOD) -DSP2_MOUNTABLE=$(SP2_MOUNTABLE)
|
||||||
|
endif
|
||||||
|
ifneq ($(SP2_DISPLAY_NAME),)
|
||||||
|
LOCAL_CFLAGS += -DSP2_DISPLAY_NAME=$(SP2_DISPLAY_NAME)
|
||||||
|
endif
|
||||||
|
ifneq ($(SP3_NAME),)
|
||||||
|
LOCAL_CFLAGS += -DSP3_NAME=$(SP3_NAME) -DSP3_BACKUP_METHOD=$(SP3_BACKUP_METHOD) -DSP3_MOUNTABLE=$(SP3_MOUNTABLE)
|
||||||
|
endif
|
||||||
|
ifneq ($(SP3_DISPLAY_NAME),)
|
||||||
|
LOCAL_CFLAGS += -DSP3_DISPLAY_NAME=$(SP3_DISPLAY_NAME)
|
||||||
|
endif
|
||||||
|
ifneq ($(RECOVERY_SDCARD_ON_DATA),)
|
||||||
|
LOCAL_CFLAGS += -DRECOVERY_SDCARD_ON_DATA
|
||||||
|
endif
|
||||||
|
ifneq ($(TW_INCLUDE_DUMLOCK),)
|
||||||
|
LOCAL_CFLAGS += -DTW_INCLUDE_DUMLOCK
|
||||||
|
endif
|
||||||
|
ifneq ($(TW_INTERNAL_STORAGE_PATH),)
|
||||||
|
LOCAL_CFLAGS += -DTW_INTERNAL_STORAGE_PATH=$(TW_INTERNAL_STORAGE_PATH)
|
||||||
|
endif
|
||||||
|
ifneq ($(TW_INTERNAL_STORAGE_MOUNT_POINT),)
|
||||||
|
LOCAL_CFLAGS += -DTW_INTERNAL_STORAGE_MOUNT_POINT=$(TW_INTERNAL_STORAGE_MOUNT_POINT)
|
||||||
|
endif
|
||||||
|
ifneq ($(TW_EXTERNAL_STORAGE_PATH),)
|
||||||
|
LOCAL_CFLAGS += -DTW_EXTERNAL_STORAGE_PATH=$(TW_EXTERNAL_STORAGE_PATH)
|
||||||
|
endif
|
||||||
|
ifneq ($(TW_EXTERNAL_STORAGE_MOUNT_POINT),)
|
||||||
|
LOCAL_CFLAGS += -DTW_EXTERNAL_STORAGE_MOUNT_POINT=$(TW_EXTERNAL_STORAGE_MOUNT_POINT)
|
||||||
|
endif
|
||||||
|
ifeq ($(TW_HAS_NO_RECOVERY_PARTITION), true)
|
||||||
|
LOCAL_CFLAGS += -DTW_HAS_NO_RECOVERY_PARTITION
|
||||||
|
endif
|
||||||
|
ifeq ($(TW_NO_REBOOT_BOOTLOADER), true)
|
||||||
|
LOCAL_CFLAGS += -DTW_NO_REBOOT_BOOTLOADER
|
||||||
|
endif
|
||||||
|
ifeq ($(TW_NO_REBOOT_RECOVERY), true)
|
||||||
|
LOCAL_CFLAGS += -DTW_NO_REBOOT_RECOVERY
|
||||||
|
endif
|
||||||
|
ifeq ($(TW_NO_BATT_PERCENT), true)
|
||||||
|
LOCAL_CFLAGS += -DTW_NO_BATT_PERCENT
|
||||||
|
endif
|
||||||
|
ifneq ($(TW_CUSTOM_POWER_BUTTON),)
|
||||||
|
LOCAL_CFLAGS += -DTW_CUSTOM_POWER_BUTTON=$(TW_CUSTOM_POWER_BUTTON)
|
||||||
|
endif
|
||||||
|
ifeq ($(TW_ALWAYS_RMRF), true)
|
||||||
|
LOCAL_CFLAGS += -DTW_ALWAYS_RMRF
|
||||||
|
endif
|
||||||
|
ifeq ($(TW_NEVER_UNMOUNT_SYSTEM), true)
|
||||||
|
LOCAL_CFLAGS += -DTW_NEVER_UNMOUNT_SYSTEM
|
||||||
|
endif
|
||||||
|
ifeq ($(TW_NO_USB_STORAGE), true)
|
||||||
|
LOCAL_CFLAGS += -DTW_NO_USB_STORAGE
|
||||||
|
endif
|
||||||
|
ifeq ($(TW_INCLUDE_INJECTTWRP), true)
|
||||||
|
LOCAL_CFLAGS += -DTW_INCLUDE_INJECTTWRP
|
||||||
|
endif
|
||||||
|
ifeq ($(TW_INCLUDE_BLOBPACK), true)
|
||||||
|
LOCAL_CFLAGS += -DTW_INCLUDE_BLOBPACK
|
||||||
|
endif
|
||||||
|
ifeq ($(TW_DEFAULT_EXTERNAL_STORAGE), true)
|
||||||
|
LOCAL_CFLAGS += -DTW_DEFAULT_EXTERNAL_STORAGE
|
||||||
|
endif
|
||||||
|
ifneq ($(TARGET_USE_CUSTOM_LUN_FILE_PATH),)
|
||||||
|
LOCAL_CFLAGS += -DCUSTOM_LUN_FILE=\"$(TARGET_USE_CUSTOM_LUN_FILE_PATH)\"
|
||||||
|
endif
|
||||||
|
ifneq ($(BOARD_UMS_LUNFILE),)
|
||||||
|
LOCAL_CFLAGS += -DCUSTOM_LUN_FILE=\"$(BOARD_UMS_LUNFILE)\"
|
||||||
|
endif
|
||||||
|
#ifeq ($(TW_FLASH_FROM_STORAGE), true) Making this the default behavior
|
||||||
|
LOCAL_CFLAGS += -DTW_FLASH_FROM_STORAGE
|
||||||
|
#endif
|
||||||
|
ifeq ($(TW_HAS_DOWNLOAD_MODE), true)
|
||||||
|
LOCAL_CFLAGS += -DTW_HAS_DOWNLOAD_MODE
|
||||||
|
endif
|
||||||
|
ifeq ($(TW_SDEXT_NO_EXT4), true)
|
||||||
|
LOCAL_CFLAGS += -DTW_SDEXT_NO_EXT4
|
||||||
|
endif
|
||||||
|
ifeq ($(TW_INCLUDE_CRYPTO), true)
|
||||||
|
LOCAL_CFLAGS += -DTW_INCLUDE_CRYPTO
|
||||||
|
LOCAL_CFLAGS += -DCRYPTO_FS_TYPE=\"$(TW_CRYPTO_FS_TYPE)\"
|
||||||
|
LOCAL_CFLAGS += -DCRYPTO_REAL_BLKDEV=\"$(TW_CRYPTO_REAL_BLKDEV)\"
|
||||||
|
LOCAL_CFLAGS += -DCRYPTO_MNT_POINT=\"$(TW_CRYPTO_MNT_POINT)\"
|
||||||
|
LOCAL_CFLAGS += -DCRYPTO_FS_OPTIONS=\"$(TW_CRYPTO_FS_OPTIONS)\"
|
||||||
|
LOCAL_CFLAGS += -DCRYPTO_FS_FLAGS=\"$(TW_CRYPTO_FS_FLAGS)\"
|
||||||
|
LOCAL_CFLAGS += -DCRYPTO_KEY_LOC=\"$(TW_CRYPTO_KEY_LOC)\"
|
||||||
|
LOCAL_SHARED_LIBRARIES += libcrypto
|
||||||
|
LOCAL_SRC_FILES += crypto/ics/cryptfs.c
|
||||||
|
LOCAL_C_INCLUDES += system/extras/ext4_utils external/openssl/include
|
||||||
|
endif
|
||||||
|
ifeq ($(TW_INCLUDE_JB_CRYPTO), true)
|
||||||
|
LOCAL_CFLAGS += -DTW_INCLUDE_CRYPTO
|
||||||
|
LOCAL_CFLAGS += -DTW_INCLUDE_JB_CRYPTO
|
||||||
|
LOCAL_SHARED_LIBRARIES += libcrypto
|
||||||
|
LOCAL_STATIC_LIBRARIES += libfs_mgrtwrp
|
||||||
|
LOCAL_SRC_FILES += crypto/jb/cryptfs.c
|
||||||
|
LOCAL_C_INCLUDES += system/extras/ext4_utils external/openssl/include
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
include $(BUILD_EXECUTABLE)
|
include $(BUILD_EXECUTABLE)
|
||||||
|
|
||||||
|
|
||||||
@ -101,13 +224,34 @@ LOCAL_STATIC_LIBRARIES := \
|
|||||||
libc
|
libc
|
||||||
include $(BUILD_EXECUTABLE)
|
include $(BUILD_EXECUTABLE)
|
||||||
|
|
||||||
|
commands_recovery_local_path := $(LOCAL_PATH)
|
||||||
include $(LOCAL_PATH)/minui/Android.mk \
|
include $(LOCAL_PATH)/minui/Android.mk \
|
||||||
$(LOCAL_PATH)/minelf/Android.mk \
|
$(LOCAL_PATH)/minelf/Android.mk \
|
||||||
$(LOCAL_PATH)/minzip/Android.mk \
|
$(LOCAL_PATH)/minzip/Android.mk \
|
||||||
$(LOCAL_PATH)/minadbd/Android.mk \
|
$(LOCAL_PATH)/minadbd/Android.mk \
|
||||||
$(LOCAL_PATH)/mtdutils/Android.mk \
|
|
||||||
$(LOCAL_PATH)/tools/Android.mk \
|
$(LOCAL_PATH)/tools/Android.mk \
|
||||||
$(LOCAL_PATH)/edify/Android.mk \
|
$(LOCAL_PATH)/edify/Android.mk \
|
||||||
$(LOCAL_PATH)/updater/Android.mk \
|
$(LOCAL_PATH)/updater/Android.mk \
|
||||||
$(LOCAL_PATH)/applypatch/Android.mk
|
$(LOCAL_PATH)/applypatch/Android.mk
|
||||||
|
|
||||||
|
#includes for TWRP
|
||||||
|
include $(commands_recovery_local_path)/libjpegtwrp/Android.mk \
|
||||||
|
$(commands_recovery_local_path)/injecttwrp/Android.mk \
|
||||||
|
$(commands_recovery_local_path)/htcdumlock/Android.mk \
|
||||||
|
$(commands_recovery_local_path)/minuitwrp/Android.mk \
|
||||||
|
$(commands_recovery_local_path)/gui/Android.mk \
|
||||||
|
$(commands_recovery_local_path)/mmcutils/Android.mk \
|
||||||
|
$(commands_recovery_local_path)/bmlutils/Android.mk \
|
||||||
|
$(commands_recovery_local_path)/flashutils/Android.mk \
|
||||||
|
$(commands_recovery_local_path)/prebuilt/Android.mk \
|
||||||
|
$(commands_recovery_local_path)/mtdutils/Android.mk \
|
||||||
|
$(commands_recovery_local_path)/pigz/Android.mk \
|
||||||
|
$(commands_recovery_local_path)/crypto/cryptsettings/Android.mk \
|
||||||
|
$(commands_recovery_local_path)/libcrecovery/Android.mk
|
||||||
|
|
||||||
|
ifeq ($(TW_INCLUDE_JB_CRYPTO), true)
|
||||||
|
include $(commands_recovery_local_path)/crypto/fs_mgr/Android.mk
|
||||||
|
endif
|
||||||
|
|
||||||
|
commands_recovery_local_path :=
|
||||||
|
|
||||||
|
@ -52,5 +52,6 @@ LOCAL_MODULE := imgdiff
|
|||||||
LOCAL_FORCE_STATIC_EXECUTABLE := true
|
LOCAL_FORCE_STATIC_EXECUTABLE := true
|
||||||
LOCAL_C_INCLUDES += external/zlib external/bzip2
|
LOCAL_C_INCLUDES += external/zlib external/bzip2
|
||||||
LOCAL_STATIC_LIBRARIES += libz libbz
|
LOCAL_STATIC_LIBRARIES += libz libbz
|
||||||
|
LOCAL_MODULE_TAGS := eng
|
||||||
|
|
||||||
include $(BUILD_HOST_EXECUTABLE)
|
include $(BUILD_HOST_EXECUTABLE)
|
||||||
|
35
bmlutils/Android.mk
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
LOCAL_PATH := $(call my-dir)
|
||||||
|
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
|
||||||
|
BOARD_RECOVERY_DEFINES := BOARD_BML_BOOT BOARD_BML_RECOVERY
|
||||||
|
|
||||||
|
$(foreach board_define,$(BOARD_RECOVERY_DEFINES), \
|
||||||
|
$(if $($(board_define)), \
|
||||||
|
$(eval LOCAL_CFLAGS += -D$(board_define)=\"$($(board_define))\") \
|
||||||
|
) \
|
||||||
|
)
|
||||||
|
|
||||||
|
LOCAL_STATIC_LIBRARIES := libcrecovery
|
||||||
|
LOCAL_C_INCLUDES := bootable/recovery/libcrecovery
|
||||||
|
|
||||||
|
LOCAL_SRC_FILES := bmlutils.c
|
||||||
|
LOCAL_MODULE := libbmlutils
|
||||||
|
LOCAL_MODULE_TAGS := eng
|
||||||
|
include $(BUILD_STATIC_LIBRARY)
|
||||||
|
|
||||||
|
#Added for building TWRP dynamic:
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
|
||||||
|
BOARD_RECOVERY_DEFINES := BOARD_BML_BOOT BOARD_BML_RECOVERY
|
||||||
|
|
||||||
|
$(foreach board_define,$(BOARD_RECOVERY_DEFINES), \
|
||||||
|
$(if $($(board_define)), \
|
||||||
|
$(eval LOCAL_CFLAGS += -D$(board_define)=\"$($(board_define))\") \
|
||||||
|
) \
|
||||||
|
)
|
||||||
|
|
||||||
|
LOCAL_SRC_FILES := bmlutils.c
|
||||||
|
LOCAL_MODULE := libbmlutils
|
||||||
|
LOCAL_MODULE_TAGS := eng
|
||||||
|
include $(BUILD_SHARED_LIBRARY)
|
251
bmlutils/bmlutils.c
Normal file
@ -0,0 +1,251 @@
|
|||||||
|
#include <ctype.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <getopt.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <linux/input.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/reboot.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#include <sys/limits.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#include <signal.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#include "../extra-functions.h"
|
||||||
|
|
||||||
|
//extern int __system(const char *command);
|
||||||
|
#define BML_UNLOCK_ALL 0x8A29 ///< unlock all partition RO -> RW
|
||||||
|
|
||||||
|
#ifndef BOARD_BML_BOOT
|
||||||
|
#define BOARD_BML_BOOT "/dev/block/bml7"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef BOARD_BML_RECOVERY
|
||||||
|
#define BOARD_BML_RECOVERY "/dev/block/bml8"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#undef _PATH_BSHELL
|
||||||
|
#define _PATH_BSHELL "/sbin/sh"
|
||||||
|
|
||||||
|
int __system(const char *command)
|
||||||
|
{
|
||||||
|
pid_t pid;
|
||||||
|
sig_t intsave, quitsave;
|
||||||
|
sigset_t mask, omask;
|
||||||
|
int pstat;
|
||||||
|
char *argp[] = {"sh", "-c", NULL, NULL};
|
||||||
|
|
||||||
|
if (!command) /* just checking... */
|
||||||
|
return(1);
|
||||||
|
|
||||||
|
argp[2] = (char *)command;
|
||||||
|
|
||||||
|
sigemptyset(&mask);
|
||||||
|
sigaddset(&mask, SIGCHLD);
|
||||||
|
sigprocmask(SIG_BLOCK, &mask, &omask);
|
||||||
|
switch (pid = vfork()) {
|
||||||
|
case -1: /* error */
|
||||||
|
sigprocmask(SIG_SETMASK, &omask, NULL);
|
||||||
|
return(-1);
|
||||||
|
case 0: /* child */
|
||||||
|
sigprocmask(SIG_SETMASK, &omask, NULL);
|
||||||
|
execve(_PATH_BSHELL, argp, environ);
|
||||||
|
_exit(127);
|
||||||
|
}
|
||||||
|
|
||||||
|
intsave = (sig_t) bsd_signal(SIGINT, SIG_IGN);
|
||||||
|
quitsave = (sig_t) bsd_signal(SIGQUIT, SIG_IGN);
|
||||||
|
pid = waitpid(pid, (int *)&pstat, 0);
|
||||||
|
sigprocmask(SIG_SETMASK, &omask, NULL);
|
||||||
|
(void)bsd_signal(SIGINT, intsave);
|
||||||
|
(void)bsd_signal(SIGQUIT, quitsave);
|
||||||
|
return (pid == -1 ? -1 : pstat);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct pid {
|
||||||
|
struct pid *next;
|
||||||
|
FILE *fp;
|
||||||
|
pid_t pid;
|
||||||
|
} *pidlist;
|
||||||
|
|
||||||
|
|
||||||
|
static int restore_internal(const char* bml, const char* filename)
|
||||||
|
{
|
||||||
|
char buf[4096];
|
||||||
|
int dstfd, srcfd, bytes_read, bytes_written, total_read = 0;
|
||||||
|
if (filename == NULL)
|
||||||
|
srcfd = 0;
|
||||||
|
else {
|
||||||
|
srcfd = open(filename, O_RDONLY | O_LARGEFILE);
|
||||||
|
if (srcfd < 0)
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
dstfd = open(bml, O_RDWR | O_LARGEFILE);
|
||||||
|
if (dstfd < 0)
|
||||||
|
return 3;
|
||||||
|
if (ioctl(dstfd, BML_UNLOCK_ALL, 0))
|
||||||
|
return 4;
|
||||||
|
do {
|
||||||
|
total_read += bytes_read = read(srcfd, buf, 4096);
|
||||||
|
if (!bytes_read)
|
||||||
|
break;
|
||||||
|
if (bytes_read < 4096)
|
||||||
|
memset(&buf[bytes_read], 0, 4096 - bytes_read);
|
||||||
|
if (write(dstfd, buf, 4096) < 4096)
|
||||||
|
return 5;
|
||||||
|
} while(bytes_read == 4096);
|
||||||
|
|
||||||
|
close(dstfd);
|
||||||
|
close(srcfd);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cmd_bml_restore_raw_partition(const char *partition, const char *filename)
|
||||||
|
{
|
||||||
|
if (strcmp(partition, "boot") != 0 && strcmp(partition, "recovery") != 0 && strcmp(partition, "recoveryonly") != 0 && partition[0] != '/')
|
||||||
|
return 6;
|
||||||
|
|
||||||
|
int ret = -1;
|
||||||
|
if (strcmp(partition, "recoveryonly") != 0) {
|
||||||
|
// always restore boot, regardless of whether recovery or boot is flashed.
|
||||||
|
// this is because boot and recovery are the same on some samsung phones.
|
||||||
|
// unless of course, recoveryonly is explictly chosen (bml8)
|
||||||
|
ret = restore_internal(BOARD_BML_BOOT, filename);
|
||||||
|
if (ret != 0)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp(partition, "recovery") == 0 || strcmp(partition, "recoveryonly") == 0)
|
||||||
|
ret = restore_internal(BOARD_BML_RECOVERY, filename);
|
||||||
|
|
||||||
|
// support explicitly provided device paths
|
||||||
|
if (partition[0] == '/')
|
||||||
|
ret = restore_internal(partition, filename);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cmd_bml_backup_raw_partition(const char *partition, const char *out_file)
|
||||||
|
{
|
||||||
|
char* bml;
|
||||||
|
if (strcmp("boot", partition) == 0)
|
||||||
|
bml = BOARD_BML_BOOT;
|
||||||
|
else if (strcmp("recovery", partition) == 0)
|
||||||
|
bml = BOARD_BML_RECOVERY;
|
||||||
|
else if (partition[0] == '/') {
|
||||||
|
// support explicitly provided device paths
|
||||||
|
bml = partition;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
printf("Invalid partition.\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ch;
|
||||||
|
FILE *in;
|
||||||
|
FILE *out;
|
||||||
|
int val = 0;
|
||||||
|
char buf[512];
|
||||||
|
unsigned sz = 0;
|
||||||
|
unsigned i;
|
||||||
|
int ret = -1;
|
||||||
|
char *in_file = bml;
|
||||||
|
|
||||||
|
in = fopen ( in_file, "r" );
|
||||||
|
if (in == NULL)
|
||||||
|
goto ERROR3;
|
||||||
|
|
||||||
|
out = fopen ( out_file, "w" );
|
||||||
|
if (out == NULL)
|
||||||
|
goto ERROR2;
|
||||||
|
|
||||||
|
fseek(in, 0L, SEEK_END);
|
||||||
|
sz = ftell(in);
|
||||||
|
fseek(in, 0L, SEEK_SET);
|
||||||
|
|
||||||
|
if (sz % 512)
|
||||||
|
{
|
||||||
|
while ( ( ch = fgetc ( in ) ) != EOF )
|
||||||
|
fputc ( ch, out );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (i=0; i< (sz/512); i++)
|
||||||
|
{
|
||||||
|
if ((fread(buf, 512, 1, in)) != 1)
|
||||||
|
goto ERROR1;
|
||||||
|
if ((fwrite(buf, 512, 1, out)) != 1)
|
||||||
|
goto ERROR1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fsync(out);
|
||||||
|
ret = 0;
|
||||||
|
ERROR1:
|
||||||
|
fclose ( out );
|
||||||
|
ERROR2:
|
||||||
|
fclose ( in );
|
||||||
|
ERROR3:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cmd_bml_erase_raw_partition(const char *partition)
|
||||||
|
{
|
||||||
|
// TODO: implement raw wipe
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cmd_bml_erase_partition(const char *partition, const char *filesystem)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cmd_bml_mount_partition(const char *partition, const char *mount_point, const char *filesystem, int read_only)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cmd_bml_get_partition_device(const char *partition, char *device)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int format_rfs_device (const char *device, const char *path) {
|
||||||
|
const char *fatsize = "32";
|
||||||
|
const char *sectorsize = "1";
|
||||||
|
|
||||||
|
if (strcmp(path, "/datadata") == 0 || strcmp(path, "/cache") == 0) {
|
||||||
|
fatsize = "16";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Just in case /data sector size needs to be altered
|
||||||
|
else if (strcmp(path, "/data") == 0 ) {
|
||||||
|
sectorsize = "1";
|
||||||
|
}
|
||||||
|
|
||||||
|
// dump 10KB of zeros to partition before format due to fat.format bug
|
||||||
|
char cmd[PATH_MAX];
|
||||||
|
|
||||||
|
sprintf(cmd, "/sbin/dd if=/dev/zero of=%s bs=4096 count=10", device);
|
||||||
|
if(__system(cmd)) {
|
||||||
|
printf("failure while zeroing rfs partition.\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run fat.format
|
||||||
|
sprintf(cmd, "/sbin/fat.format -F %s -S 4096 -s %s %s", fatsize, sectorsize, device);
|
||||||
|
if(__system(cmd)) {
|
||||||
|
printf("failure while running fat.format\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
6
bmlutils/bmlutils.h
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#ifndef BMLUTILS_H_
|
||||||
|
#define BMLUTILS_H_
|
||||||
|
|
||||||
|
int format_rfs_device (const char *device, const char *path);
|
||||||
|
|
||||||
|
#endif // BMLUTILS_H_
|
@ -16,7 +16,9 @@
|
|||||||
|
|
||||||
#include "bootloader.h"
|
#include "bootloader.h"
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
extern "C" {
|
||||||
#include "mtdutils/mtdutils.h"
|
#include "mtdutils/mtdutils.h"
|
||||||
|
}
|
||||||
#include "roots.h"
|
#include "roots.h"
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
3
common.h
@ -23,6 +23,9 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define ui_print(...) fprintf(stdout, __VA_ARGS__)
|
||||||
|
#define ui_print_overwrite(...) fprintf(stdout, __VA_ARGS__)
|
||||||
|
|
||||||
// TODO: restore ui_print for LOGE
|
// TODO: restore ui_print for LOGE
|
||||||
#define LOGE(...) fprintf(stdout, "E:" __VA_ARGS__)
|
#define LOGE(...) fprintf(stdout, "E:" __VA_ARGS__)
|
||||||
#define LOGW(...) fprintf(stdout, "W:" __VA_ARGS__)
|
#define LOGW(...) fprintf(stdout, "W:" __VA_ARGS__)
|
||||||
|
13
crypto/cryptsettings/Android.mk
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
LOCAL_PATH:= $(call my-dir)
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
|
||||||
|
LOCAL_SRC_FILES:= \
|
||||||
|
cryptsettings.c
|
||||||
|
LOCAL_CFLAGS:= -g -c -W
|
||||||
|
LOCAL_MODULE:=cryptsettings
|
||||||
|
LOCAL_MODULE_TAGS:= eng
|
||||||
|
LOCAL_SHARED_LIBRARIES += libc libcutils
|
||||||
|
LOCAL_STATIC_LIBRARIES += libfs_mgrtwrp
|
||||||
|
LOCAL_MODULE_CLASS := UTILITY_EXECUTABLES
|
||||||
|
LOCAL_MODULE_PATH := $(PRODUCT_OUT)/utilities
|
||||||
|
include $(BUILD_EXECUTABLE)
|
51
crypto/cryptsettings/cryptsettings.c
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
#include <sys/types.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include "../crypto/fs_mgr/include/fs_mgr.h"
|
||||||
|
|
||||||
|
#include "cutils/properties.h"
|
||||||
|
|
||||||
|
#ifndef PROPERTY_VALUE_MAX
|
||||||
|
#define PROPERTY_VALUE_MAX 255
|
||||||
|
#endif
|
||||||
|
#ifndef FSTAB_PREFIX
|
||||||
|
#define FSTAB_PREFIX "/fstab."
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
char prop[PROPERTY_VALUE_MAX];
|
||||||
|
char key_loc[PROPERTY_VALUE_MAX];
|
||||||
|
char blk_dev[PROPERTY_VALUE_MAX];
|
||||||
|
char fstab_filename[PROPERTY_VALUE_MAX + sizeof(FSTAB_PREFIX)];
|
||||||
|
|
||||||
|
printf("This tool will gather the build flags needed for decryption support for TWRP.\n");
|
||||||
|
printf("This tool comes with no warranties whatsoever.\n");
|
||||||
|
printf("http://teamw.in\n\n");
|
||||||
|
property_get("ro.crypto.state", prop, "encrypted");
|
||||||
|
if (strcmp(prop, "encrypted") != 0)
|
||||||
|
printf("Your device is not encrypted, continuing anyway.\n\nTW_INCLUDE_CRYPTO := true\n");
|
||||||
|
property_get("ro.crypto.fs_type", prop, "ERROR");
|
||||||
|
printf("TW_CRYPTO_FS_TYPE := \"%s\"\n", prop);
|
||||||
|
property_get("ro.crypto.fs_real_blkdev", prop, "ERROR");
|
||||||
|
printf("TW_CRYPTO_REAL_BLKDEV := \"%s\"\n", prop);
|
||||||
|
property_get("ro.crypto.fs_mnt_point", prop, "ERROR");
|
||||||
|
printf("TW_CRYPTO_MNT_POINT := \"%s\"\n", prop);
|
||||||
|
property_get("ro.crypto.fs_options", prop, "ERROR");
|
||||||
|
printf("TW_CRYPTO_FS_OPTIONS := \"%s\"\n", prop);
|
||||||
|
property_get("ro.crypto.fs_flags", prop, "ERROR");
|
||||||
|
printf("TW_CRYPTO_FS_FLAGS := \"%s\"\n", prop);
|
||||||
|
property_get("ro.crypto.keyfile.userdata", prop, "footer");
|
||||||
|
printf("TW_CRYPTO_KEY_LOC := \"%s\"\n", prop);
|
||||||
|
printf("\n*** NEW FOR JELLY BEAN:\n");
|
||||||
|
strcpy(fstab_filename, FSTAB_PREFIX);
|
||||||
|
property_get("ro.hardware", fstab_filename + sizeof(FSTAB_PREFIX) - 1, "");
|
||||||
|
fs_mgr_get_crypt_info(fstab_filename, key_loc, blk_dev, sizeof(key_loc));
|
||||||
|
printf("fstab file location: '%s'\n\nTW_INCLUDE_JB_CRYPTO := true\n", fstab_filename);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
33
crypto/fs_mgr/Android.mk
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
# Copyright 2011 The Android Open Source Project
|
||||||
|
|
||||||
|
LOCAL_PATH:= $(call my-dir)
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
|
||||||
|
LOCAL_SRC_FILES:= fs_mgr.c
|
||||||
|
|
||||||
|
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
|
||||||
|
|
||||||
|
LOCAL_MODULE:= libfs_mgrtwrp
|
||||||
|
LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
|
||||||
|
|
||||||
|
include $(BUILD_STATIC_LIBRARY)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include $(CLEAR_VARS)
|
||||||
|
|
||||||
|
#LOCAL_SRC_FILES:= fs_mgr_main.c
|
||||||
|
|
||||||
|
#LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
|
||||||
|
|
||||||
|
#LOCAL_MODULE:= fs_mgr
|
||||||
|
|
||||||
|
#LOCAL_MODULE_TAGS := optional
|
||||||
|
#LOCAL_FORCE_STATIC_EXECUTABLE := true
|
||||||
|
#LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT)/sbin
|
||||||
|
#LOCAL_UNSTRIPPED_PATH := $(TARGET_ROOT_OUT_UNSTRIPPED)
|
||||||
|
|
||||||
|
#LOCAL_STATIC_LIBRARIES := libfs_mgr libcutils libc
|
||||||
|
|
||||||
|
#include $(BUILD_EXECUTABLE)
|
||||||
|
|
611
crypto/fs_mgr/fs_mgr.c
Normal file
@ -0,0 +1,611 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2012 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* TO DO:
|
||||||
|
* 1. Re-direct fsck output to the kernel log?
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <sys/mount.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#include <libgen.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#include <private/android_filesystem_config.h>
|
||||||
|
#include <cutils/partition_utils.h>
|
||||||
|
#include <cutils/properties.h>
|
||||||
|
|
||||||
|
#include "fs_mgr_priv.h"
|
||||||
|
|
||||||
|
#define KEY_LOC_PROP "ro.crypto.keyfile.userdata"
|
||||||
|
#define KEY_IN_FOOTER "footer"
|
||||||
|
|
||||||
|
#define E2FSCK_BIN "/system/bin/e2fsck"
|
||||||
|
|
||||||
|
struct flag_list {
|
||||||
|
const char *name;
|
||||||
|
unsigned flag;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct flag_list mount_flags[] = {
|
||||||
|
{ "noatime", MS_NOATIME },
|
||||||
|
{ "noexec", MS_NOEXEC },
|
||||||
|
{ "nosuid", MS_NOSUID },
|
||||||
|
{ "nodev", MS_NODEV },
|
||||||
|
{ "nodiratime", MS_NODIRATIME },
|
||||||
|
{ "ro", MS_RDONLY },
|
||||||
|
{ "rw", 0 },
|
||||||
|
{ "remount", MS_REMOUNT },
|
||||||
|
{ "defaults", 0 },
|
||||||
|
{ 0, 0 },
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct flag_list fs_mgr_flags[] = {
|
||||||
|
{ "wait", MF_WAIT },
|
||||||
|
{ "check", MF_CHECK },
|
||||||
|
{ "encryptable=",MF_CRYPT },
|
||||||
|
{ "defaults", 0 },
|
||||||
|
{ 0, 0 },
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* gettime() - returns the time in seconds of the system's monotonic clock or
|
||||||
|
* zero on error.
|
||||||
|
*/
|
||||||
|
static time_t gettime(void)
|
||||||
|
{
|
||||||
|
struct timespec ts;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||||
|
if (ret < 0) {
|
||||||
|
ERROR("clock_gettime(CLOCK_MONOTONIC) failed: %s\n", strerror(errno));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ts.tv_sec;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int wait_for_file(const char *filename, int timeout)
|
||||||
|
{
|
||||||
|
struct stat info;
|
||||||
|
time_t timeout_time = gettime() + timeout;
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
|
while (gettime() < timeout_time && ((ret = stat(filename, &info)) < 0))
|
||||||
|
usleep(10000);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int parse_flags(char *flags, struct flag_list *fl, char **key_loc,
|
||||||
|
char *fs_options, int fs_options_len)
|
||||||
|
{
|
||||||
|
int f = 0;
|
||||||
|
int i;
|
||||||
|
char *p;
|
||||||
|
char *savep;
|
||||||
|
|
||||||
|
/* initialize key_loc to null, if we find an MF_CRYPT flag,
|
||||||
|
* then we'll set key_loc to the proper value */
|
||||||
|
if (key_loc) {
|
||||||
|
*key_loc = NULL;
|
||||||
|
}
|
||||||
|
/* initialize fs_options to the null string */
|
||||||
|
if (fs_options && (fs_options_len > 0)) {
|
||||||
|
fs_options[0] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
p = strtok_r(flags, ",", &savep);
|
||||||
|
while (p) {
|
||||||
|
/* Look for the flag "p" in the flag list "fl"
|
||||||
|
* If not found, the loop exits with fl[i].name being null.
|
||||||
|
*/
|
||||||
|
for (i = 0; fl[i].name; i++) {
|
||||||
|
if (!strncmp(p, fl[i].name, strlen(fl[i].name))) {
|
||||||
|
f |= fl[i].flag;
|
||||||
|
if ((fl[i].flag == MF_CRYPT) && key_loc) {
|
||||||
|
/* The encryptable flag is followed by an = and the
|
||||||
|
* location of the keys. Get it and return it.
|
||||||
|
*/
|
||||||
|
*key_loc = strdup(strchr(p, '=') + 1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!fl[i].name) {
|
||||||
|
if (fs_options) {
|
||||||
|
/* It's not a known flag, so it must be a filesystem specific
|
||||||
|
* option. Add it to fs_options if it was passed in.
|
||||||
|
*/
|
||||||
|
strlcat(fs_options, p, fs_options_len);
|
||||||
|
strlcat(fs_options, ",", fs_options_len);
|
||||||
|
} else {
|
||||||
|
/* fs_options was not passed in, so if the flag is unknown
|
||||||
|
* it's an error.
|
||||||
|
*/
|
||||||
|
ERROR("Warning: unknown flag %s\n", p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p = strtok_r(NULL, ",", &savep);
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
if (fs_options && fs_options[0]) {
|
||||||
|
/* remove the last trailing comma from the list of options */
|
||||||
|
fs_options[strlen(fs_options) - 1] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read a line of text till the next newline character.
|
||||||
|
* If no newline is found before the buffer is full, continue reading till a new line is seen,
|
||||||
|
* then return an empty buffer. This effectively ignores lines that are too long.
|
||||||
|
* On EOF, return null.
|
||||||
|
*/
|
||||||
|
static char *getline(char *buf, int size, FILE *file)
|
||||||
|
{
|
||||||
|
int cnt = 0;
|
||||||
|
int eof = 0;
|
||||||
|
int eol = 0;
|
||||||
|
int c;
|
||||||
|
|
||||||
|
if (size < 1) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (cnt < (size - 1)) {
|
||||||
|
c = getc(file);
|
||||||
|
if (c == EOF) {
|
||||||
|
eof = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
*(buf + cnt) = c;
|
||||||
|
cnt++;
|
||||||
|
|
||||||
|
if (c == '\n') {
|
||||||
|
eol = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Null terminate what we've read */
|
||||||
|
*(buf + cnt) = '\0';
|
||||||
|
|
||||||
|
if (eof) {
|
||||||
|
if (cnt) {
|
||||||
|
return buf;
|
||||||
|
} else {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
} else if (eol) {
|
||||||
|
return buf;
|
||||||
|
} else {
|
||||||
|
/* The line is too long. Read till a newline or EOF.
|
||||||
|
* If EOF, return null, if newline, return an empty buffer.
|
||||||
|
*/
|
||||||
|
while(1) {
|
||||||
|
c = getc(file);
|
||||||
|
if (c == EOF) {
|
||||||
|
return NULL;
|
||||||
|
} else if (c == '\n') {
|
||||||
|
*buf = '\0';
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct fstab_rec *read_fstab(char *fstab_path)
|
||||||
|
{
|
||||||
|
FILE *fstab_file;
|
||||||
|
int cnt, entries;
|
||||||
|
int len;
|
||||||
|
char line[256];
|
||||||
|
const char *delim = " \t";
|
||||||
|
char *save_ptr, *p;
|
||||||
|
struct fstab_rec *fstab;
|
||||||
|
char *key_loc;
|
||||||
|
#define FS_OPTIONS_LEN 1024
|
||||||
|
char tmp_fs_options[FS_OPTIONS_LEN];
|
||||||
|
|
||||||
|
fstab_file = fopen(fstab_path, "r");
|
||||||
|
if (!fstab_file) {
|
||||||
|
ERROR("Cannot open file %s\n", fstab_path);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
entries = 0;
|
||||||
|
while (getline(line, sizeof(line), fstab_file)) {
|
||||||
|
/* if the last character is a newline, shorten the string by 1 byte */
|
||||||
|
len = strlen(line);
|
||||||
|
if (line[len - 1] == '\n') {
|
||||||
|
line[len - 1] = '\0';
|
||||||
|
}
|
||||||
|
/* Skip any leading whitespace */
|
||||||
|
p = line;
|
||||||
|
while (isspace(*p)) {
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
/* ignore comments or empty lines */
|
||||||
|
if (*p == '#' || *p == '\0')
|
||||||
|
continue;
|
||||||
|
entries++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!entries) {
|
||||||
|
ERROR("No entries found in fstab\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
fstab = calloc(entries + 1, sizeof(struct fstab_rec));
|
||||||
|
|
||||||
|
fseek(fstab_file, 0, SEEK_SET);
|
||||||
|
|
||||||
|
cnt = 0;
|
||||||
|
while (getline(line, sizeof(line), fstab_file)) {
|
||||||
|
/* if the last character is a newline, shorten the string by 1 byte */
|
||||||
|
len = strlen(line);
|
||||||
|
if (line[len - 1] == '\n') {
|
||||||
|
line[len - 1] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Skip any leading whitespace */
|
||||||
|
p = line;
|
||||||
|
while (isspace(*p)) {
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
/* ignore comments or empty lines */
|
||||||
|
if (*p == '#' || *p == '\0')
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* If a non-comment entry is greater than the size we allocated, give an
|
||||||
|
* error and quit. This can happen in the unlikely case the file changes
|
||||||
|
* between the two reads.
|
||||||
|
*/
|
||||||
|
if (cnt >= entries) {
|
||||||
|
ERROR("Tried to process more entries than counted\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(p = strtok_r(line, delim, &save_ptr))) {
|
||||||
|
ERROR("Error parsing mount source\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
fstab[cnt].blk_dev = strdup(p);
|
||||||
|
|
||||||
|
if (!(p = strtok_r(NULL, delim, &save_ptr))) {
|
||||||
|
ERROR("Error parsing mnt_point\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
fstab[cnt].mnt_point = strdup(p);
|
||||||
|
|
||||||
|
if (!(p = strtok_r(NULL, delim, &save_ptr))) {
|
||||||
|
ERROR("Error parsing fs_type\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
fstab[cnt].type = strdup(p);
|
||||||
|
|
||||||
|
if (!(p = strtok_r(NULL, delim, &save_ptr))) {
|
||||||
|
ERROR("Error parsing mount_flags\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
tmp_fs_options[0] = '\0';
|
||||||
|
fstab[cnt].flags = parse_flags(p, mount_flags, 0, tmp_fs_options, FS_OPTIONS_LEN);
|
||||||
|
|
||||||
|
/* fs_options are optional */
|
||||||
|
if (tmp_fs_options[0]) {
|
||||||
|
fstab[cnt].fs_options = strdup(tmp_fs_options);
|
||||||
|
} else {
|
||||||
|
fstab[cnt].fs_options = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(p = strtok_r(NULL, delim, &save_ptr))) {
|
||||||
|
ERROR("Error parsing fs_mgr_options\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
fstab[cnt].fs_mgr_flags = parse_flags(p, fs_mgr_flags, &key_loc, 0, 0);
|
||||||
|
fstab[cnt].key_loc = key_loc;
|
||||||
|
|
||||||
|
cnt++;
|
||||||
|
}
|
||||||
|
fclose(fstab_file);
|
||||||
|
|
||||||
|
return fstab;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void free_fstab(struct fstab_rec *fstab)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
while (fstab[i].blk_dev) {
|
||||||
|
/* Free the pointers return by strdup(3) */
|
||||||
|
free(fstab[i].blk_dev);
|
||||||
|
free(fstab[i].mnt_point);
|
||||||
|
free(fstab[i].type);
|
||||||
|
free(fstab[i].fs_options);
|
||||||
|
free(fstab[i].key_loc);
|
||||||
|
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Free the actual fstab array created by calloc(3) */
|
||||||
|
free(fstab);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void check_fs(char *blk_dev, char *type)
|
||||||
|
{
|
||||||
|
pid_t pid;
|
||||||
|
int status;
|
||||||
|
|
||||||
|
/* Check for the types of filesystems we know how to check */
|
||||||
|
if (!strcmp(type, "ext2") || !strcmp(type, "ext3") || !strcmp(type, "ext4")) {
|
||||||
|
INFO("Running %s on %s\n", E2FSCK_BIN, blk_dev);
|
||||||
|
pid = fork();
|
||||||
|
if (pid > 0) {
|
||||||
|
/* Parent, wait for the child to return */
|
||||||
|
waitpid(pid, &status, 0);
|
||||||
|
} else if (pid == 0) {
|
||||||
|
/* child, run checker */
|
||||||
|
execlp(E2FSCK_BIN, E2FSCK_BIN, "-y", blk_dev, (char *)NULL);
|
||||||
|
|
||||||
|
/* Only gets here on error */
|
||||||
|
ERROR("Cannot run fs_mgr binary %s\n", E2FSCK_BIN);
|
||||||
|
} else {
|
||||||
|
/* No need to check for error in fork, we can't really handle it now */
|
||||||
|
ERROR("Fork failed trying to run %s\n", E2FSCK_BIN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void remove_trailing_slashes(char *n)
|
||||||
|
{
|
||||||
|
int len;
|
||||||
|
|
||||||
|
len = strlen(n) - 1;
|
||||||
|
while ((*(n + len) == '/') && len) {
|
||||||
|
*(n + len) = '\0';
|
||||||
|
len--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int fs_match(char *in1, char *in2)
|
||||||
|
{
|
||||||
|
char *n1;
|
||||||
|
char *n2;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
n1 = strdup(in1);
|
||||||
|
n2 = strdup(in2);
|
||||||
|
|
||||||
|
remove_trailing_slashes(n1);
|
||||||
|
remove_trailing_slashes(n2);
|
||||||
|
|
||||||
|
ret = !strcmp(n1, n2);
|
||||||
|
|
||||||
|
free(n1);
|
||||||
|
free(n2);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int fs_mgr_mount_all(char *fstab_file)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
int encrypted = 0;
|
||||||
|
int ret = -1;
|
||||||
|
int mret;
|
||||||
|
struct fstab_rec *fstab = 0;
|
||||||
|
|
||||||
|
if (!(fstab = read_fstab(fstab_file))) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; fstab[i].blk_dev; i++) {
|
||||||
|
if (fstab[i].fs_mgr_flags & MF_WAIT) {
|
||||||
|
wait_for_file(fstab[i].blk_dev, WAIT_TIMEOUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fstab[i].fs_mgr_flags & MF_CHECK) {
|
||||||
|
check_fs(fstab[i].blk_dev, fstab[i].type);
|
||||||
|
}
|
||||||
|
|
||||||
|
mret = mount(fstab[i].blk_dev, fstab[i].mnt_point, fstab[i].type,
|
||||||
|
fstab[i].flags, fstab[i].fs_options);
|
||||||
|
if (!mret) {
|
||||||
|
/* Success! Go get the next one */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* mount(2) returned an error, check if it's encrypted and deal with it */
|
||||||
|
if ((fstab[i].fs_mgr_flags & MF_CRYPT) && !partition_wiped(fstab[i].blk_dev)) {
|
||||||
|
/* Need to mount a tmpfs at this mountpoint for now, and set
|
||||||
|
* properties that vold will query later for decrypting
|
||||||
|
*/
|
||||||
|
if (mount("tmpfs", fstab[i].mnt_point, "tmpfs",
|
||||||
|
MS_NOATIME | MS_NOSUID | MS_NODEV, CRYPTO_TMPFS_OPTIONS) < 0) {
|
||||||
|
ERROR("Cannot mount tmpfs filesystem for encrypted fs at %s\n",
|
||||||
|
fstab[i].mnt_point);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
encrypted = 1;
|
||||||
|
} else {
|
||||||
|
ERROR("Cannot mount filesystem on %s at %s\n",
|
||||||
|
fstab[i].blk_dev, fstab[i].mnt_point);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (encrypted) {
|
||||||
|
ret = 1;
|
||||||
|
} else {
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
free_fstab(fstab);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If tmp_mnt_point is non-null, mount the filesystem there. This is for the
|
||||||
|
* tmp mount we do to check the user password
|
||||||
|
*/
|
||||||
|
int fs_mgr_do_mount(char *fstab_file, char *n_name, char *n_blk_dev, char *tmp_mnt_point)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
int ret = -1;
|
||||||
|
struct fstab_rec *fstab = 0;
|
||||||
|
char *m;
|
||||||
|
|
||||||
|
if (!(fstab = read_fstab(fstab_file))) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; fstab[i].blk_dev; i++) {
|
||||||
|
if (!fs_match(fstab[i].mnt_point, n_name)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We found our match */
|
||||||
|
/* First check the filesystem if requested */
|
||||||
|
if (fstab[i].fs_mgr_flags & MF_WAIT) {
|
||||||
|
wait_for_file(fstab[i].blk_dev, WAIT_TIMEOUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fstab[i].fs_mgr_flags & MF_CHECK) {
|
||||||
|
check_fs(fstab[i].blk_dev, fstab[i].type);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now mount it where requested */
|
||||||
|
if (tmp_mnt_point) {
|
||||||
|
m = tmp_mnt_point;
|
||||||
|
} else {
|
||||||
|
m = fstab[i].mnt_point;
|
||||||
|
}
|
||||||
|
if (mount(n_blk_dev, m, fstab[i].type,
|
||||||
|
fstab[i].flags, fstab[i].fs_options)) {
|
||||||
|
ERROR("Cannot mount filesystem on %s at %s\n",
|
||||||
|
n_blk_dev, m);
|
||||||
|
goto out;
|
||||||
|
} else {
|
||||||
|
ret = 0;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We didn't find a match, say so and return an error */
|
||||||
|
ERROR("Cannot find mount point %s in fstab\n", fstab[i].mnt_point);
|
||||||
|
|
||||||
|
out:
|
||||||
|
free_fstab(fstab);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* mount a tmpfs filesystem at the given point.
|
||||||
|
* return 0 on success, non-zero on failure.
|
||||||
|
*/
|
||||||
|
int fs_mgr_do_tmpfs_mount(char *n_name)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = mount("tmpfs", n_name, "tmpfs",
|
||||||
|
MS_NOATIME | MS_NOSUID | MS_NODEV, CRYPTO_TMPFS_OPTIONS);
|
||||||
|
if (ret < 0) {
|
||||||
|
ERROR("Cannot mount tmpfs filesystem at %s\n", n_name);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Success */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int fs_mgr_unmount_all(char *fstab_file)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
int ret = 0;
|
||||||
|
struct fstab_rec *fstab = 0;
|
||||||
|
|
||||||
|
if (!(fstab = read_fstab(fstab_file))) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (fstab[i].blk_dev) {
|
||||||
|
if (umount(fstab[i].mnt_point)) {
|
||||||
|
ERROR("Cannot unmount filesystem at %s\n", fstab[i].mnt_point);
|
||||||
|
ret = -1;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
free_fstab(fstab);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* key_loc must be at least PROPERTY_VALUE_MAX bytes long
|
||||||
|
*
|
||||||
|
* real_blk_dev must be at least PROPERTY_VALUE_MAX bytes long
|
||||||
|
*/
|
||||||
|
int fs_mgr_get_crypt_info(char *fstab_file, char *key_loc, char *real_blk_dev, int size)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
struct fstab_rec *fstab = 0;
|
||||||
|
|
||||||
|
if (!(fstab = read_fstab(fstab_file))) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
/* Initialize return values to null strings */
|
||||||
|
if (key_loc) {
|
||||||
|
*key_loc = '\0';
|
||||||
|
}
|
||||||
|
if (real_blk_dev) {
|
||||||
|
*real_blk_dev = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Look for the encryptable partition to find the data */
|
||||||
|
for (i = 0; fstab[i].blk_dev; i++) {
|
||||||
|
if (!(fstab[i].fs_mgr_flags & MF_CRYPT)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We found a match */
|
||||||
|
if (key_loc) {
|
||||||
|
strlcpy(key_loc, fstab[i].key_loc, size);
|
||||||
|
}
|
||||||
|
if (real_blk_dev) {
|
||||||
|
strlcpy(real_blk_dev, fstab[i].blk_dev, size);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
free_fstab(fstab);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
109
crypto/fs_mgr/fs_mgr_main.c
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2012 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <libgen.h>
|
||||||
|
#include "fs_mgr_priv.h"
|
||||||
|
|
||||||
|
char *me = "";
|
||||||
|
|
||||||
|
static void usage(void)
|
||||||
|
{
|
||||||
|
ERROR("%s: usage: %s <-a | -n mnt_point blk_dev | -u> <fstab_file>\n", me, me);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Parse the command line. If an error is encountered, print an error message
|
||||||
|
* and exit the program, do not return to the caller.
|
||||||
|
* Return the number of argv[] entries consumed.
|
||||||
|
*/
|
||||||
|
static void parse_options(int argc, char *argv[], int *a_flag, int *u_flag, int *n_flag,
|
||||||
|
char **n_name, char **n_blk_dev)
|
||||||
|
{
|
||||||
|
me = basename(strdup(argv[0]));
|
||||||
|
|
||||||
|
if (argc <= 1) {
|
||||||
|
usage();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strcmp(argv[1], "-a")) {
|
||||||
|
if (argc != 3) {
|
||||||
|
usage();
|
||||||
|
}
|
||||||
|
*a_flag = 1;
|
||||||
|
}
|
||||||
|
if (!strcmp(argv[1], "-n")) {
|
||||||
|
if (argc != 5) {
|
||||||
|
usage();
|
||||||
|
}
|
||||||
|
*n_flag = 1;
|
||||||
|
*n_name = argv[2];
|
||||||
|
*n_blk_dev = argv[3];
|
||||||
|
}
|
||||||
|
if (!strcmp(argv[1], "-u")) {
|
||||||
|
if (argc != 3) {
|
||||||
|
usage();
|
||||||
|
}
|
||||||
|
*u_flag = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If no flag is specified, it's an error */
|
||||||
|
if (!(*a_flag | *n_flag | *u_flag)) {
|
||||||
|
usage();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If more than one flag is specified, it's an error */
|
||||||
|
if ((*a_flag + *n_flag + *u_flag) > 1) {
|
||||||
|
usage();
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
int a_flag=0;
|
||||||
|
int u_flag=0;
|
||||||
|
int n_flag=0;
|
||||||
|
char *n_name;
|
||||||
|
char *n_blk_dev;
|
||||||
|
char *fstab;
|
||||||
|
|
||||||
|
klog_init();
|
||||||
|
klog_set_level(6);
|
||||||
|
|
||||||
|
parse_options(argc, argv, &a_flag, &u_flag, &n_flag, &n_name, &n_blk_dev);
|
||||||
|
|
||||||
|
/* The name of the fstab file is last, after the option */
|
||||||
|
fstab = argv[argc - 1];
|
||||||
|
|
||||||
|
if (a_flag) {
|
||||||
|
return fs_mgr_mount_all(fstab);
|
||||||
|
} else if (n_flag) {
|
||||||
|
return fs_mgr_do_mount(fstab, n_name, n_blk_dev, 0);
|
||||||
|
} else if (u_flag) {
|
||||||
|
return fs_mgr_unmount_all(fstab);
|
||||||
|
} else {
|
||||||
|
ERROR("%s: Internal error, unknown option\n", me);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Should not get here */
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
80
crypto/fs_mgr/fs_mgr_priv.h
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2012 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __CORE_FS_MGR_PRIV_H
|
||||||
|
#define __CORE_FS_MGR_PRIV_H
|
||||||
|
|
||||||
|
#include <cutils/klog.h>
|
||||||
|
#include <fs_mgr.h>
|
||||||
|
|
||||||
|
#define INFO(x...) KLOG_INFO("fs_mgr", x)
|
||||||
|
#define ERROR(x...) KLOG_ERROR("fs_mgr", x)
|
||||||
|
|
||||||
|
#define CRYPTO_TMPFS_OPTIONS "size=128m,mode=0771,uid=1000,gid=1000"
|
||||||
|
|
||||||
|
struct fstab_rec {
|
||||||
|
char *blk_dev;
|
||||||
|
char *mnt_point;
|
||||||
|
char *type;
|
||||||
|
unsigned long flags;
|
||||||
|
char *fs_options;
|
||||||
|
int fs_mgr_flags;
|
||||||
|
char *key_loc;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define WAIT_TIMEOUT 5
|
||||||
|
|
||||||
|
/* fstab has the following format:
|
||||||
|
*
|
||||||
|
* Any line starting with a # is a comment and ignored
|
||||||
|
*
|
||||||
|
* Any blank line is ignored
|
||||||
|
*
|
||||||
|
* All other lines must be in this format:
|
||||||
|
* <source> <mount_point> <fs_type> <mount_flags> <fs_options> <fs_mgr_options>
|
||||||
|
*
|
||||||
|
* <mount_flags> is a comma separated list of flags that can be passed to the
|
||||||
|
* mount command. The list includes noatime, nosuid, nodev, nodiratime,
|
||||||
|
* ro, rw, remount, defaults.
|
||||||
|
*
|
||||||
|
* <fs_options> is a comma separated list of options accepted by the filesystem being
|
||||||
|
* mounted. It is passed directly to mount without being parsed
|
||||||
|
*
|
||||||
|
* <fs_mgr_options> is a comma separated list of flags that control the operation of
|
||||||
|
* the fs_mgr program. The list includes "wait", which will wait till
|
||||||
|
* the <source> file exists, and "check", which requests that the fs_mgr
|
||||||
|
* run an fscheck program on the <source> before mounting the filesystem.
|
||||||
|
* If check is specifed on a read-only filesystem, it is ignored.
|
||||||
|
* Also, "encryptable" means that filesystem can be encrypted.
|
||||||
|
* The "encryptable" flag _MUST_ be followed by a : and a string which
|
||||||
|
* is the location of the encryption keys. I can either be a path
|
||||||
|
* to a file or partition which contains the keys, or the word "footer"
|
||||||
|
* which means the keys are in the last 16 Kbytes of the partition
|
||||||
|
* containing the filesystem.
|
||||||
|
*
|
||||||
|
* When the fs_mgr is requested to mount all filesystems, it will first mount all the
|
||||||
|
* filesystems that do _NOT_ specify check (including filesystems that are read-only and
|
||||||
|
* specify check, because check is ignored in that case) and then it will check and mount
|
||||||
|
* filesystem marked with check.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define MF_WAIT 0x1
|
||||||
|
#define MF_CHECK 0x2
|
||||||
|
#define MF_CRYPT 0x4
|
||||||
|
|
||||||
|
#endif /* __CORE_FS_MGR_PRIV_H */
|
||||||
|
|
27
crypto/fs_mgr/include/fs_mgr.h
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2012 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __CORE_FS_MGR_H
|
||||||
|
#define __CORE_FS_MGR_H
|
||||||
|
|
||||||
|
int fs_mgr_mount_all(char *fstab_file);
|
||||||
|
int fs_mgr_do_mount(char *fstab_file, char *n_name, char *n_blk_dev, char *tmp_mnt_point);
|
||||||
|
int fs_mgr_do_tmpfs_mount(char *n_name);
|
||||||
|
int fs_mgr_unmount_all(char *fstab_file);
|
||||||
|
int fs_mgr_get_crypt_info(char *fstab_file, char *key_loc, char *real_blk_dev, int size);
|
||||||
|
|
||||||
|
#endif /* __CORE_FS_MGR_H */
|
||||||
|
|
1164
crypto/ics/cryptfs.c
Normal file
89
crypto/ics/cryptfs.h
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2010 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* This structure starts 16,384 bytes before the end of a hardware
|
||||||
|
* partition that is encrypted.
|
||||||
|
* Immediately following this structure is the encrypted key.
|
||||||
|
* The keysize field tells how long the key is, in bytes.
|
||||||
|
* Then there is 32 bytes of padding,
|
||||||
|
* Finally there is the salt used with the user password.
|
||||||
|
* The salt is fixed at 16 bytes long.
|
||||||
|
* Obviously, the filesystem does not include the last 16 kbytes
|
||||||
|
* of the partition.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define CRYPT_FOOTER_OFFSET 0x4000
|
||||||
|
|
||||||
|
#define MAX_CRYPTO_TYPE_NAME_LEN 64
|
||||||
|
|
||||||
|
#define SALT_LEN 16
|
||||||
|
#define KEY_TO_SALT_PADDING 32
|
||||||
|
|
||||||
|
/* definitions of flags in the structure below */
|
||||||
|
#define CRYPT_MNT_KEY_UNENCRYPTED 0x1 /* The key for the partition is not encrypted. */
|
||||||
|
#define CRYPT_ENCRYPTION_IN_PROGRESS 0x2 /* Set when starting encryption,
|
||||||
|
* clear when done before rebooting */
|
||||||
|
|
||||||
|
#define CRYPT_MNT_MAGIC 0xD0B5B1C4
|
||||||
|
|
||||||
|
#define __le32 unsigned int
|
||||||
|
#define __le16 unsigned short int
|
||||||
|
|
||||||
|
struct crypt_mnt_ftr {
|
||||||
|
__le32 magic; /* See above */
|
||||||
|
__le16 major_version;
|
||||||
|
__le16 minor_version;
|
||||||
|
__le32 ftr_size; /* in bytes, not including key following */
|
||||||
|
__le32 flags; /* See above */
|
||||||
|
__le32 keysize; /* in bytes */
|
||||||
|
__le32 spare1; /* ignored */
|
||||||
|
__le64 fs_size; /* Size of the encrypted fs, in 512 byte sectors */
|
||||||
|
__le32 failed_decrypt_count; /* count of # of failed attempts to decrypt and
|
||||||
|
mount, set to 0 on successful mount */
|
||||||
|
unsigned char crypto_type_name[MAX_CRYPTO_TYPE_NAME_LEN]; /* The type of encryption
|
||||||
|
needed to decrypt this
|
||||||
|
partition, null terminated */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct volume_info {
|
||||||
|
unsigned int size;
|
||||||
|
unsigned int flags;
|
||||||
|
struct crypt_mnt_ftr crypt_ftr;
|
||||||
|
char mnt_point[256];
|
||||||
|
char blk_dev[256];
|
||||||
|
char crypto_blkdev[256];
|
||||||
|
char label[256];
|
||||||
|
};
|
||||||
|
#define VOL_NONREMOVABLE 0x1
|
||||||
|
#define VOL_ENCRYPTABLE 0x2
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
int cryptfs_crypto_complete(void);
|
||||||
|
int cryptfs_check_passwd(char *pw);
|
||||||
|
int cryptfs_verify_passwd(char *newpw);
|
||||||
|
int cryptfs_restart(void);
|
||||||
|
int cryptfs_enable(char *flag, char *passwd);
|
||||||
|
int cryptfs_changepw(char *newpw);
|
||||||
|
int cryptfs_setup_volume(const char *label, int major, int minor,
|
||||||
|
char *crypto_dev_path, unsigned int max_pathlen,
|
||||||
|
int *new_major, int *new_minor);
|
||||||
|
int cryptfs_revert_volume(const char *label);
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
1152
crypto/jb/cryptfs.c
Normal file
89
crypto/jb/cryptfs.h
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2010 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* This structure starts 16,384 bytes before the end of a hardware
|
||||||
|
* partition that is encrypted.
|
||||||
|
* Immediately following this structure is the encrypted key.
|
||||||
|
* The keysize field tells how long the key is, in bytes.
|
||||||
|
* Then there is 32 bytes of padding,
|
||||||
|
* Finally there is the salt used with the user password.
|
||||||
|
* The salt is fixed at 16 bytes long.
|
||||||
|
* Obviously, the filesystem does not include the last 16 kbytes
|
||||||
|
* of the partition.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define CRYPT_FOOTER_OFFSET 0x4000
|
||||||
|
|
||||||
|
#define MAX_CRYPTO_TYPE_NAME_LEN 64
|
||||||
|
|
||||||
|
#define SALT_LEN 16
|
||||||
|
#define KEY_TO_SALT_PADDING 32
|
||||||
|
|
||||||
|
/* definitions of flags in the structure below */
|
||||||
|
#define CRYPT_MNT_KEY_UNENCRYPTED 0x1 /* The key for the partition is not encrypted. */
|
||||||
|
#define CRYPT_ENCRYPTION_IN_PROGRESS 0x2 /* Set when starting encryption,
|
||||||
|
* clear when done before rebooting */
|
||||||
|
|
||||||
|
#define CRYPT_MNT_MAGIC 0xD0B5B1C4
|
||||||
|
|
||||||
|
#define __le32 unsigned int
|
||||||
|
#define __le16 unsigned short int
|
||||||
|
|
||||||
|
struct crypt_mnt_ftr {
|
||||||
|
__le32 magic; /* See above */
|
||||||
|
__le16 major_version;
|
||||||
|
__le16 minor_version;
|
||||||
|
__le32 ftr_size; /* in bytes, not including key following */
|
||||||
|
__le32 flags; /* See above */
|
||||||
|
__le32 keysize; /* in bytes */
|
||||||
|
__le32 spare1; /* ignored */
|
||||||
|
__le64 fs_size; /* Size of the encrypted fs, in 512 byte sectors */
|
||||||
|
__le32 failed_decrypt_count; /* count of # of failed attempts to decrypt and
|
||||||
|
mount, set to 0 on successful mount */
|
||||||
|
unsigned char crypto_type_name[MAX_CRYPTO_TYPE_NAME_LEN]; /* The type of encryption
|
||||||
|
needed to decrypt this
|
||||||
|
partition, null terminated */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct volume_info {
|
||||||
|
unsigned int size;
|
||||||
|
unsigned int flags;
|
||||||
|
struct crypt_mnt_ftr crypt_ftr;
|
||||||
|
char mnt_point[256];
|
||||||
|
char blk_dev[256];
|
||||||
|
char crypto_blkdev[256];
|
||||||
|
char label[256];
|
||||||
|
};
|
||||||
|
#define VOL_NONREMOVABLE 0x1
|
||||||
|
#define VOL_ENCRYPTABLE 0x2
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
int cryptfs_crypto_complete(void);
|
||||||
|
int cryptfs_check_passwd(char *pw);
|
||||||
|
int cryptfs_verify_passwd(char *newpw);
|
||||||
|
int cryptfs_restart(void);
|
||||||
|
int cryptfs_enable(char *flag, char *passwd);
|
||||||
|
int cryptfs_changepw(char *newpw);
|
||||||
|
int cryptfs_setup_volume(const char *label, int major, int minor,
|
||||||
|
char *crypto_dev_path, unsigned int max_pathlen,
|
||||||
|
int *new_major, int *new_minor);
|
||||||
|
int cryptfs_revert_volume(const char *label);
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
918
data.cpp
Normal file
@ -0,0 +1,918 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2007 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/input.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <utility>
|
||||||
|
#include <map>
|
||||||
|
#include <fstream>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
#include "variables.h"
|
||||||
|
#include "data.hpp"
|
||||||
|
#include "partitions.hpp"
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#include "common.h"
|
||||||
|
#include "data.h"
|
||||||
|
#include "tw_reboot.h"
|
||||||
|
#include "roots.h"
|
||||||
|
|
||||||
|
int get_battery_level(void);
|
||||||
|
void get_device_id(void);
|
||||||
|
|
||||||
|
extern char device_id[15];
|
||||||
|
|
||||||
|
void gui_notifyVarChange(const char *name, const char* value);
|
||||||
|
|
||||||
|
int __system(const char *command);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define FILE_VERSION 0x00010001
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
map<string, DataManager::TStrIntPair> DataManager::mValues;
|
||||||
|
map<string, string> DataManager::mConstValues;
|
||||||
|
string DataManager::mBackingFile;
|
||||||
|
int DataManager::mInitialized = 0;
|
||||||
|
|
||||||
|
int DataManager::ResetDefaults()
|
||||||
|
{
|
||||||
|
mValues.clear();
|
||||||
|
mConstValues.clear();
|
||||||
|
SetDefaultValues();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int DataManager::LoadValues(const string filename)
|
||||||
|
{
|
||||||
|
string str;
|
||||||
|
|
||||||
|
if (!mInitialized)
|
||||||
|
SetDefaultValues();
|
||||||
|
|
||||||
|
// Save off the backing file for set operations
|
||||||
|
mBackingFile = filename;
|
||||||
|
|
||||||
|
// Read in the file, if possible
|
||||||
|
FILE* in = fopen(filename.c_str(), "rb");
|
||||||
|
if (!in) return 0;
|
||||||
|
|
||||||
|
int file_version;
|
||||||
|
if (fread(&file_version, 1, sizeof(int), in) != sizeof(int)) goto error;
|
||||||
|
if (file_version != FILE_VERSION) goto error;
|
||||||
|
|
||||||
|
while (!feof(in))
|
||||||
|
{
|
||||||
|
string Name;
|
||||||
|
string Value;
|
||||||
|
unsigned short length;
|
||||||
|
char array[512];
|
||||||
|
|
||||||
|
if (fread(&length, 1, sizeof(unsigned short), in) != sizeof(unsigned short)) goto error;
|
||||||
|
if (length >= 512) goto error;
|
||||||
|
if (fread(array, 1, length, in) != length) goto error;
|
||||||
|
Name = array;
|
||||||
|
|
||||||
|
if (fread(&length, 1, sizeof(unsigned short), in) != sizeof(unsigned short)) goto error;
|
||||||
|
if (length >= 512) goto error;
|
||||||
|
if (fread(array, 1, length, in) != length) goto error;
|
||||||
|
Value = array;
|
||||||
|
|
||||||
|
map<string, TStrIntPair>::iterator pos;
|
||||||
|
|
||||||
|
pos = mValues.find(Name);
|
||||||
|
if (pos != mValues.end())
|
||||||
|
{
|
||||||
|
pos->second.first = Value;
|
||||||
|
pos->second.second = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
mValues.insert(TNameValuePair(Name, TStrIntPair(Value, 1)));
|
||||||
|
}
|
||||||
|
fclose(in);
|
||||||
|
|
||||||
|
str = GetCurrentStoragePath();
|
||||||
|
str += "/TWRP/BACKUPS/";
|
||||||
|
str += device_id;
|
||||||
|
SetValue(TW_BACKUPS_FOLDER_VAR, str, 0);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
error:
|
||||||
|
// File version mismatch. Use defaults.
|
||||||
|
fclose(in);
|
||||||
|
str = GetCurrentStoragePath();
|
||||||
|
str += "/TWRP/BACKUPS/";
|
||||||
|
str += device_id;
|
||||||
|
SetValue(TW_BACKUPS_FOLDER_VAR, str, 0);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int DataManager::Flush()
|
||||||
|
{
|
||||||
|
return SaveValues();
|
||||||
|
}
|
||||||
|
|
||||||
|
int DataManager::SaveValues()
|
||||||
|
{
|
||||||
|
if (mBackingFile.empty()) return -1;
|
||||||
|
|
||||||
|
string mount_path = GetSettingsStoragePath();
|
||||||
|
TWPartitionManager::Mount_By_Path(mount_path.c_str(), 1);
|
||||||
|
|
||||||
|
FILE* out = fopen(mBackingFile.c_str(), "wb");
|
||||||
|
if (!out) return -1;
|
||||||
|
|
||||||
|
int file_version = FILE_VERSION;
|
||||||
|
fwrite(&file_version, 1, sizeof(int), out);
|
||||||
|
|
||||||
|
map<string, TStrIntPair>::iterator iter;
|
||||||
|
for (iter = mValues.begin(); iter != mValues.end(); ++iter)
|
||||||
|
{
|
||||||
|
// Save only the persisted data
|
||||||
|
if (iter->second.second != 0)
|
||||||
|
{
|
||||||
|
unsigned short length = (unsigned short) iter->first.length() + 1;
|
||||||
|
fwrite(&length, 1, sizeof(unsigned short), out);
|
||||||
|
fwrite(iter->first.c_str(), 1, length, out);
|
||||||
|
length = (unsigned short) iter->second.first.length() + 1;
|
||||||
|
fwrite(&length, 1, sizeof(unsigned short), out);
|
||||||
|
fwrite(iter->second.first.c_str(), 1, length, out);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fclose(out);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int DataManager::GetValue(const string varName, string& value)
|
||||||
|
{
|
||||||
|
string localStr = varName;
|
||||||
|
|
||||||
|
if (!mInitialized)
|
||||||
|
SetDefaultValues();
|
||||||
|
|
||||||
|
// Strip off leading and trailing '%' if provided
|
||||||
|
if (localStr.length() > 2 && localStr[0] == '%' && localStr[localStr.length()-1] == '%')
|
||||||
|
{
|
||||||
|
localStr.erase(0, 1);
|
||||||
|
localStr.erase(localStr.length() - 1, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle magic values
|
||||||
|
if (GetMagicValue(localStr, value) == 0) return 0;
|
||||||
|
|
||||||
|
map<string, string>::iterator constPos;
|
||||||
|
constPos = mConstValues.find(localStr);
|
||||||
|
if (constPos != mConstValues.end())
|
||||||
|
{
|
||||||
|
value = constPos->second;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
map<string, TStrIntPair>::iterator pos;
|
||||||
|
pos = mValues.find(localStr);
|
||||||
|
if (pos == mValues.end())
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
value = pos->second.first;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int DataManager::GetValue(const string varName, int& value)
|
||||||
|
{
|
||||||
|
string data;
|
||||||
|
|
||||||
|
if (GetValue(varName,data) != 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
value = atoi(data.c_str());
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is a dangerous function. It will create the value if it doesn't exist so it has a valid c_str
|
||||||
|
string& DataManager::GetValueRef(const string varName)
|
||||||
|
{
|
||||||
|
if (!mInitialized)
|
||||||
|
SetDefaultValues();
|
||||||
|
|
||||||
|
map<string, string>::iterator constPos;
|
||||||
|
constPos = mConstValues.find(varName);
|
||||||
|
if (constPos != mConstValues.end())
|
||||||
|
return constPos->second;
|
||||||
|
|
||||||
|
map<string, TStrIntPair>::iterator pos;
|
||||||
|
pos = mValues.find(varName);
|
||||||
|
if (pos == mValues.end())
|
||||||
|
pos = (mValues.insert(TNameValuePair(varName, TStrIntPair("", 0)))).first;
|
||||||
|
|
||||||
|
return pos->second.first;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This function will return an empty string if the value doesn't exist
|
||||||
|
string DataManager::GetStrValue(const string varName)
|
||||||
|
{
|
||||||
|
string retVal;
|
||||||
|
|
||||||
|
GetValue(varName, retVal);
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This function will return 0 if the value doesn't exist
|
||||||
|
int DataManager::GetIntValue(const string varName)
|
||||||
|
{
|
||||||
|
string retVal;
|
||||||
|
|
||||||
|
GetValue(varName, retVal);
|
||||||
|
return atoi(retVal.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
int DataManager::SetValue(const string varName, string value, int persist /* = 0 */)
|
||||||
|
{
|
||||||
|
if (!mInitialized)
|
||||||
|
SetDefaultValues();
|
||||||
|
|
||||||
|
// Don't allow empty values or numerical starting values
|
||||||
|
if (varName.empty() || (varName[0] >= '0' && varName[0] <= '9'))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
map<string, string>::iterator constChk;
|
||||||
|
constChk = mConstValues.find(varName);
|
||||||
|
if (constChk != mConstValues.end())
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
map<string, TStrIntPair>::iterator pos;
|
||||||
|
pos = mValues.find(varName);
|
||||||
|
if (pos == mValues.end())
|
||||||
|
pos = (mValues.insert(TNameValuePair(varName, TStrIntPair(value, persist)))).first;
|
||||||
|
else
|
||||||
|
pos->second.first = value;
|
||||||
|
|
||||||
|
if (pos->second.second != 0)
|
||||||
|
SaveValues();
|
||||||
|
|
||||||
|
gui_notifyVarChange(varName.c_str(), value.c_str());
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int DataManager::SetValue(const string varName, int value, int persist /* = 0 */)
|
||||||
|
{
|
||||||
|
ostringstream valStr;
|
||||||
|
valStr << value;
|
||||||
|
if (varName == "tw_use_external_storage") {
|
||||||
|
string str;
|
||||||
|
|
||||||
|
if (GetIntValue(TW_HAS_DUAL_STORAGE) == 1) {
|
||||||
|
if (value == 0) {
|
||||||
|
str = GetStrValue(TW_INTERNAL_PATH);
|
||||||
|
if (GetIntValue(TW_HAS_DATA_MEDIA) == 1) {
|
||||||
|
LOGE("TODO: Fix storage size code!\n"); //SetValue(TW_STORAGE_FREE_SIZE, (int)((dat.sze - dat.used) / 1048576LLU));
|
||||||
|
} else {
|
||||||
|
LOGE("TODO: Fix storage size code!\n"); //SetValue(TW_STORAGE_FREE_SIZE, (int)((sdcint.sze - sdcint.used) / 1048576LLU));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
str = GetStrValue(TW_EXTERNAL_PATH);
|
||||||
|
LOGE("TODO: Fix storage size code!\n"); //SetValue(TW_STORAGE_FREE_SIZE, (int)((sdcext.sze - sdcext.used) / 1048576LLU));
|
||||||
|
}
|
||||||
|
} else if (GetIntValue(TW_HAS_INTERNAL) == 1)
|
||||||
|
str = GetStrValue(TW_INTERNAL_PATH);
|
||||||
|
else
|
||||||
|
str = GetStrValue(TW_EXTERNAL_PATH);
|
||||||
|
|
||||||
|
str += "/TWRP/BACKUPS/";
|
||||||
|
str += device_id;
|
||||||
|
|
||||||
|
SetValue(TW_BACKUPS_FOLDER_VAR, str);
|
||||||
|
}
|
||||||
|
return SetValue(varName, valStr.str(), persist);;
|
||||||
|
}
|
||||||
|
|
||||||
|
int DataManager::SetValue(const string varName, float value, int persist /* = 0 */)
|
||||||
|
{
|
||||||
|
ostringstream valStr;
|
||||||
|
valStr << value;
|
||||||
|
return SetValue(varName, valStr.str(), persist);;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DataManager::DumpValues()
|
||||||
|
{
|
||||||
|
map<string, TStrIntPair>::iterator iter;
|
||||||
|
ui_print("Data Manager dump - Values with leading X are persisted.\n");
|
||||||
|
for (iter = mValues.begin(); iter != mValues.end(); ++iter)
|
||||||
|
{
|
||||||
|
ui_print("%c %s=%s\n", iter->second.second ? 'X' : ' ', iter->first.c_str(), iter->second.first.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DataManager::SetDefaultValues()
|
||||||
|
{
|
||||||
|
string str, path;
|
||||||
|
|
||||||
|
get_device_id();
|
||||||
|
|
||||||
|
mInitialized = 1;
|
||||||
|
|
||||||
|
mConstValues.insert(make_pair("true", "1"));
|
||||||
|
mConstValues.insert(make_pair("false", "0"));
|
||||||
|
|
||||||
|
mConstValues.insert(make_pair(TW_VERSION_VAR, TW_VERSION_STR));
|
||||||
|
|
||||||
|
#ifdef BOARD_HAS_NO_REAL_SDCARD
|
||||||
|
mConstValues.insert(make_pair(TW_ALLOW_PARTITION_SDCARD, "0"));
|
||||||
|
#else
|
||||||
|
mConstValues.insert(make_pair(TW_ALLOW_PARTITION_SDCARD, "1"));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef TW_INCLUDE_DUMLOCK
|
||||||
|
mConstValues.insert(make_pair(TW_SHOW_DUMLOCK, "1"));
|
||||||
|
#else
|
||||||
|
mConstValues.insert(make_pair(TW_SHOW_DUMLOCK, "0"));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef TW_INTERNAL_STORAGE_PATH
|
||||||
|
LOGI("Internal path defined: '%s'\n", EXPAND(TW_INTERNAL_STORAGE_PATH));
|
||||||
|
mValues.insert(make_pair(TW_USE_EXTERNAL_STORAGE, make_pair("0", 1)));
|
||||||
|
mConstValues.insert(make_pair(TW_HAS_INTERNAL, "1"));
|
||||||
|
mConstValues.insert(make_pair(TW_INTERNAL_PATH, EXPAND(TW_INTERNAL_STORAGE_PATH)));
|
||||||
|
mConstValues.insert(make_pair(TW_INTERNAL_LABEL, EXPAND(TW_INTERNAL_STORAGE_MOUNT_POINT)));
|
||||||
|
path.clear();
|
||||||
|
path = "/";
|
||||||
|
path += EXPAND(TW_INTERNAL_STORAGE_MOUNT_POINT);
|
||||||
|
mConstValues.insert(make_pair(TW_INTERNAL_MOUNT, path));
|
||||||
|
#ifdef TW_EXTERNAL_STORAGE_PATH
|
||||||
|
LOGI("External path defined: '%s'\n", EXPAND(TW_EXTERNAL_STORAGE_PATH));
|
||||||
|
// Device has dual storage
|
||||||
|
mConstValues.insert(make_pair(TW_HAS_DUAL_STORAGE, "1"));
|
||||||
|
mConstValues.insert(make_pair(TW_HAS_EXTERNAL, "1"));
|
||||||
|
mConstValues.insert(make_pair(TW_EXTERNAL_PATH, EXPAND(TW_EXTERNAL_STORAGE_PATH)));
|
||||||
|
mConstValues.insert(make_pair(TW_EXTERNAL_LABEL, EXPAND(TW_EXTERNAL_STORAGE_MOUNT_POINT)));
|
||||||
|
mValues.insert(make_pair(TW_ZIP_EXTERNAL_VAR, make_pair(EXPAND(TW_EXTERNAL_STORAGE_PATH), 1)));
|
||||||
|
path.clear();
|
||||||
|
path = "/";
|
||||||
|
path += EXPAND(TW_EXTERNAL_STORAGE_MOUNT_POINT);
|
||||||
|
mConstValues.insert(make_pair(TW_EXTERNAL_MOUNT, path));
|
||||||
|
if (strcmp(EXPAND(TW_EXTERNAL_STORAGE_PATH), "/sdcard") == 0) {
|
||||||
|
mValues.insert(make_pair(TW_ZIP_INTERNAL_VAR, make_pair("/emmc", 1)));
|
||||||
|
} else {
|
||||||
|
mValues.insert(make_pair(TW_ZIP_INTERNAL_VAR, make_pair("/sdcard", 1)));
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
LOGI("Just has internal storage.\n");
|
||||||
|
// Just has internal storage
|
||||||
|
mValues.insert(make_pair(TW_ZIP_INTERNAL_VAR, make_pair("/sdcard", 1)));
|
||||||
|
mConstValues.insert(make_pair(TW_HAS_DUAL_STORAGE, "0"));
|
||||||
|
mConstValues.insert(make_pair(TW_HAS_EXTERNAL, "0"));
|
||||||
|
mConstValues.insert(make_pair(TW_EXTERNAL_PATH, "0"));
|
||||||
|
mConstValues.insert(make_pair(TW_EXTERNAL_MOUNT, "0"));
|
||||||
|
mConstValues.insert(make_pair(TW_EXTERNAL_LABEL, "0"));
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#ifdef RECOVERY_SDCARD_ON_DATA
|
||||||
|
#ifdef TW_EXTERNAL_STORAGE_PATH
|
||||||
|
LOGI("Has /data/media + external storage in '%s'\n", EXPAND(TW_EXTERNAL_STORAGE_PATH));
|
||||||
|
// Device has /data/media + external storage
|
||||||
|
mConstValues.insert(make_pair(TW_HAS_DUAL_STORAGE, "1"));
|
||||||
|
#else
|
||||||
|
LOGI("Single storage only -- data/media.\n");
|
||||||
|
// Device just has external storage
|
||||||
|
mConstValues.insert(make_pair(TW_HAS_DUAL_STORAGE, "0"));
|
||||||
|
mConstValues.insert(make_pair(TW_HAS_EXTERNAL, "0"));
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
LOGI("Single storage only.\n");
|
||||||
|
// Device just has external storage
|
||||||
|
mConstValues.insert(make_pair(TW_HAS_DUAL_STORAGE, "0"));
|
||||||
|
#endif
|
||||||
|
#ifdef RECOVERY_SDCARD_ON_DATA
|
||||||
|
LOGI("Device has /data/media defined.\n");
|
||||||
|
// Device has /data/media
|
||||||
|
mConstValues.insert(make_pair(TW_USE_EXTERNAL_STORAGE, "0"));
|
||||||
|
mConstValues.insert(make_pair(TW_HAS_INTERNAL, "1"));
|
||||||
|
mConstValues.insert(make_pair(TW_INTERNAL_PATH, "/data/media"));
|
||||||
|
mConstValues.insert(make_pair(TW_INTERNAL_MOUNT, "/data"));
|
||||||
|
mConstValues.insert(make_pair(TW_INTERNAL_LABEL, "data"));
|
||||||
|
#ifdef TW_EXTERNAL_STORAGE_PATH
|
||||||
|
if (strcmp(EXPAND(TW_EXTERNAL_STORAGE_PATH), "/sdcard") == 0) {
|
||||||
|
mValues.insert(make_pair(TW_ZIP_INTERNAL_VAR, make_pair("/emmc", 1)));
|
||||||
|
} else {
|
||||||
|
mValues.insert(make_pair(TW_ZIP_INTERNAL_VAR, make_pair("/sdcard", 1)));
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
mValues.insert(make_pair(TW_ZIP_INTERNAL_VAR, make_pair("/sdcard", 1)));
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
LOGI("No internal storage defined.\n");
|
||||||
|
// Device has no internal storage
|
||||||
|
mConstValues.insert(make_pair(TW_USE_EXTERNAL_STORAGE, "1"));
|
||||||
|
mConstValues.insert(make_pair(TW_HAS_INTERNAL, "0"));
|
||||||
|
mConstValues.insert(make_pair(TW_INTERNAL_PATH, "0"));
|
||||||
|
mConstValues.insert(make_pair(TW_INTERNAL_MOUNT, "0"));
|
||||||
|
mConstValues.insert(make_pair(TW_INTERNAL_LABEL, "0"));
|
||||||
|
#endif
|
||||||
|
#ifdef TW_EXTERNAL_STORAGE_PATH
|
||||||
|
LOGI("Only external path defined: '%s'\n", EXPAND(TW_EXTERNAL_STORAGE_PATH));
|
||||||
|
// External has custom definition
|
||||||
|
mConstValues.insert(make_pair(TW_HAS_EXTERNAL, "1"));
|
||||||
|
mConstValues.insert(make_pair(TW_EXTERNAL_PATH, EXPAND(TW_EXTERNAL_STORAGE_PATH)));
|
||||||
|
mConstValues.insert(make_pair(TW_EXTERNAL_LABEL, EXPAND(TW_EXTERNAL_STORAGE_MOUNT_POINT)));
|
||||||
|
mValues.insert(make_pair(TW_ZIP_EXTERNAL_VAR, make_pair(EXPAND(TW_EXTERNAL_STORAGE_PATH), 1)));
|
||||||
|
path.clear();
|
||||||
|
path = "/";
|
||||||
|
path += EXPAND(TW_EXTERNAL_STORAGE_MOUNT_POINT);
|
||||||
|
mConstValues.insert(make_pair(TW_EXTERNAL_MOUNT, path));
|
||||||
|
#else
|
||||||
|
#ifndef RECOVERY_SDCARD_ON_DATA
|
||||||
|
LOGI("No storage defined, defaulting to /sdcard.\n");
|
||||||
|
// Standard external definition
|
||||||
|
mConstValues.insert(make_pair(TW_HAS_EXTERNAL, "1"));
|
||||||
|
mConstValues.insert(make_pair(TW_EXTERNAL_PATH, "/sdcard"));
|
||||||
|
mConstValues.insert(make_pair(TW_EXTERNAL_MOUNT, "/sdcard"));
|
||||||
|
mConstValues.insert(make_pair(TW_EXTERNAL_LABEL, "sdcard"));
|
||||||
|
mValues.insert(make_pair(TW_ZIP_EXTERNAL_VAR, make_pair("/sdcard", 1)));
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef TW_DEFAULT_EXTERNAL_STORAGE
|
||||||
|
SetValue(TW_USE_EXTERNAL_STORAGE, 1);
|
||||||
|
LOGI("Defaulting to external storage.\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
str = GetCurrentStoragePath();
|
||||||
|
#ifdef RECOVERY_SDCARD_ON_DATA
|
||||||
|
#ifndef TW_EXTERNAL_STORAGE_PATH
|
||||||
|
SetValue(TW_ZIP_LOCATION_VAR, "/sdcard", 1);
|
||||||
|
#else
|
||||||
|
if (strcmp(EXPAND(TW_EXTERNAL_STORAGE_PATH), "/sdcard") == 0) {
|
||||||
|
SetValue(TW_ZIP_LOCATION_VAR, "/emmc", 1);
|
||||||
|
} else {
|
||||||
|
SetValue(TW_ZIP_LOCATION_VAR, "/sdcard", 1);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
SetValue(TW_ZIP_LOCATION_VAR, str.c_str(), 1);
|
||||||
|
#endif
|
||||||
|
str += "/TWRP/BACKUPS/";
|
||||||
|
str += device_id;
|
||||||
|
SetValue(TW_BACKUPS_FOLDER_VAR, str, 0);
|
||||||
|
|
||||||
|
if (strlen(EXPAND(SP1_DISPLAY_NAME))) mConstValues.insert(make_pair(TW_SP1_PARTITION_NAME_VAR, EXPAND(SP1_DISPLAY_NAME)));
|
||||||
|
if (strlen(EXPAND(SP2_DISPLAY_NAME))) mConstValues.insert(make_pair(TW_SP2_PARTITION_NAME_VAR, EXPAND(SP2_DISPLAY_NAME)));
|
||||||
|
if (strlen(EXPAND(SP3_DISPLAY_NAME))) mConstValues.insert(make_pair(TW_SP3_PARTITION_NAME_VAR, EXPAND(SP3_DISPLAY_NAME)));
|
||||||
|
|
||||||
|
mConstValues.insert(make_pair(TW_REBOOT_SYSTEM, tw_isRebootCommandSupported(rb_system) ? "1" : "0"));
|
||||||
|
#ifdef TW_NO_REBOOT_RECOVERY
|
||||||
|
mConstValues.insert(make_pair(TW_REBOOT_RECOVERY, "0"));
|
||||||
|
#else
|
||||||
|
mConstValues.insert(make_pair(TW_REBOOT_RECOVERY, tw_isRebootCommandSupported(rb_recovery) ? "1" : "0"));
|
||||||
|
#endif
|
||||||
|
mConstValues.insert(make_pair(TW_REBOOT_POWEROFF, tw_isRebootCommandSupported(rb_poweroff) ? "1" : "0"));
|
||||||
|
#ifdef TW_NO_REBOOT_BOOTLOADER
|
||||||
|
mConstValues.insert(make_pair(TW_REBOOT_BOOTLOADER, "0"));
|
||||||
|
#else
|
||||||
|
mConstValues.insert(make_pair(TW_REBOOT_BOOTLOADER, tw_isRebootCommandSupported(rb_bootloader) ? "1" : "0"));
|
||||||
|
#endif
|
||||||
|
#ifdef RECOVERY_SDCARD_ON_DATA
|
||||||
|
mConstValues.insert(make_pair(TW_HAS_DATA_MEDIA, "1"));
|
||||||
|
#else
|
||||||
|
mConstValues.insert(make_pair(TW_HAS_DATA_MEDIA, "0"));
|
||||||
|
#endif
|
||||||
|
#ifdef TW_NO_BATT_PERCENT
|
||||||
|
mConstValues.insert(make_pair(TW_NO_BATTERY_PERCENT, "1"));
|
||||||
|
#else
|
||||||
|
mConstValues.insert(make_pair(TW_NO_BATTERY_PERCENT, "0"));
|
||||||
|
#endif
|
||||||
|
#ifdef TW_CUSTOM_POWER_BUTTON
|
||||||
|
mConstValues.insert(make_pair(TW_POWER_BUTTON, EXPAND(TW_CUSTOM_POWER_BUTTON)));
|
||||||
|
#else
|
||||||
|
mConstValues.insert(make_pair(TW_POWER_BUTTON, "0"));
|
||||||
|
#endif
|
||||||
|
#ifdef TW_ALWAYS_RMRF
|
||||||
|
mConstValues.insert(make_pair(TW_RM_RF_VAR, "1"));
|
||||||
|
#endif
|
||||||
|
#ifdef TW_NEVER_UNMOUNT_SYSTEM
|
||||||
|
mConstValues.insert(make_pair(TW_DONT_UNMOUNT_SYSTEM, "1"));
|
||||||
|
#else
|
||||||
|
mConstValues.insert(make_pair(TW_DONT_UNMOUNT_SYSTEM, "0"));
|
||||||
|
#endif
|
||||||
|
#ifdef TW_NO_USB_STORAGE
|
||||||
|
mConstValues.insert(make_pair(TW_HAS_USB_STORAGE, "0"));
|
||||||
|
#else
|
||||||
|
mConstValues.insert(make_pair(TW_HAS_USB_STORAGE, "1"));
|
||||||
|
#endif
|
||||||
|
#ifdef TW_INCLUDE_INJECTTWRP
|
||||||
|
mConstValues.insert(make_pair(TW_HAS_INJECTTWRP, "1"));
|
||||||
|
mValues.insert(make_pair(TW_INJECT_AFTER_ZIP, make_pair("1", 1)));
|
||||||
|
#else
|
||||||
|
mConstValues.insert(make_pair(TW_HAS_INJECTTWRP, "0"));
|
||||||
|
mValues.insert(make_pair(TW_INJECT_AFTER_ZIP, make_pair("0", 1)));
|
||||||
|
#endif
|
||||||
|
#ifdef TW_FLASH_FROM_STORAGE
|
||||||
|
mConstValues.insert(make_pair(TW_FLASH_ZIP_IN_PLACE, "1"));
|
||||||
|
#endif
|
||||||
|
#ifdef TW_HAS_DOWNLOAD_MODE
|
||||||
|
mConstValues.insert(make_pair(TW_DOWNLOAD_MODE, "1"));
|
||||||
|
#endif
|
||||||
|
#ifdef TW_INCLUDE_CRYPTO
|
||||||
|
mConstValues.insert(make_pair(TW_HAS_CRYPTO, "1"));
|
||||||
|
LOGI("Device has crypto support compiled into recovery.\n");
|
||||||
|
#endif
|
||||||
|
#ifdef TW_SDEXT_NO_EXT4
|
||||||
|
mConstValues.insert(make_pair(TW_SDEXT_DISABLE_EXT4, "1"));
|
||||||
|
#else
|
||||||
|
mConstValues.insert(make_pair(TW_SDEXT_DISABLE_EXT4, "0"));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
mConstValues.insert(make_pair(TW_MIN_SYSTEM_VAR, TW_MIN_SYSTEM_SIZE));
|
||||||
|
mValues.insert(make_pair(TW_BACKUP_NAME, make_pair("(Current Date)", 0)));
|
||||||
|
mValues.insert(make_pair(TW_BACKUP_SYSTEM_VAR, make_pair("1", 1)));
|
||||||
|
mValues.insert(make_pair(TW_BACKUP_DATA_VAR, make_pair("1", 1)));
|
||||||
|
mValues.insert(make_pair(TW_BACKUP_BOOT_VAR, make_pair("1", 1)));
|
||||||
|
mValues.insert(make_pair(TW_BACKUP_RECOVERY_VAR, make_pair("0", 1)));
|
||||||
|
mValues.insert(make_pair(TW_BACKUP_CACHE_VAR, make_pair("0", 1)));
|
||||||
|
mValues.insert(make_pair(TW_BACKUP_SP1_VAR, make_pair("0", 1)));
|
||||||
|
mValues.insert(make_pair(TW_BACKUP_SP2_VAR, make_pair("0", 1)));
|
||||||
|
mValues.insert(make_pair(TW_BACKUP_SP3_VAR, make_pair("0", 1)));
|
||||||
|
mValues.insert(make_pair(TW_BACKUP_ANDSEC_VAR, make_pair("0", 1)));
|
||||||
|
mValues.insert(make_pair(TW_BACKUP_SDEXT_VAR, make_pair("0", 1)));
|
||||||
|
mValues.insert(make_pair(TW_BACKUP_SYSTEM_SIZE, make_pair("0", 0)));
|
||||||
|
mValues.insert(make_pair(TW_BACKUP_DATA_SIZE, make_pair("0", 0)));
|
||||||
|
mValues.insert(make_pair(TW_BACKUP_BOOT_SIZE, make_pair("0", 0)));
|
||||||
|
mValues.insert(make_pair(TW_BACKUP_RECOVERY_SIZE, make_pair("0", 0)));
|
||||||
|
mValues.insert(make_pair(TW_BACKUP_CACHE_SIZE, make_pair("0", 0)));
|
||||||
|
mValues.insert(make_pair(TW_BACKUP_ANDSEC_SIZE, make_pair("0", 0)));
|
||||||
|
mValues.insert(make_pair(TW_BACKUP_SDEXT_SIZE, make_pair("0", 0)));
|
||||||
|
mValues.insert(make_pair(TW_BACKUP_SP1_SIZE, make_pair("0", 0)));
|
||||||
|
mValues.insert(make_pair(TW_BACKUP_SP2_SIZE, make_pair("0", 0)));
|
||||||
|
mValues.insert(make_pair(TW_BACKUP_SP3_SIZE, make_pair("0", 0)));
|
||||||
|
mValues.insert(make_pair(TW_STORAGE_FREE_SIZE, make_pair("0", 0)));
|
||||||
|
|
||||||
|
mValues.insert(make_pair(TW_REBOOT_AFTER_FLASH_VAR, make_pair("0", 1)));
|
||||||
|
mValues.insert(make_pair(TW_SIGNED_ZIP_VERIFY_VAR, make_pair("0", 1)));
|
||||||
|
mValues.insert(make_pair(TW_FORCE_MD5_CHECK_VAR, make_pair("0", 1)));
|
||||||
|
mValues.insert(make_pair(TW_COLOR_THEME_VAR, make_pair("0", 1)));
|
||||||
|
mValues.insert(make_pair(TW_USE_COMPRESSION_VAR, make_pair("0", 1)));
|
||||||
|
mValues.insert(make_pair(TW_IGNORE_IMAGE_SIZE, make_pair("0", 1)));
|
||||||
|
mValues.insert(make_pair(TW_SHOW_SPAM_VAR, make_pair("0", 1)));
|
||||||
|
mValues.insert(make_pair(TW_TIME_ZONE_VAR, make_pair("CST6CDT", 1)));
|
||||||
|
mValues.insert(make_pair(TW_SORT_FILES_BY_DATE_VAR, make_pair("0", 1)));
|
||||||
|
mValues.insert(make_pair(TW_GUI_SORT_ORDER, make_pair("1", 1)));
|
||||||
|
mValues.insert(make_pair(TW_RM_RF_VAR, make_pair("0", 1)));
|
||||||
|
mValues.insert(make_pair(TW_SKIP_MD5_CHECK_VAR, make_pair("0", 1)));
|
||||||
|
mValues.insert(make_pair(TW_SKIP_MD5_GENERATE_VAR, make_pair("0", 1)));
|
||||||
|
mValues.insert(make_pair(TW_SDEXT_SIZE, make_pair("512", 1)));
|
||||||
|
mValues.insert(make_pair(TW_SWAP_SIZE, make_pair("32", 1)));
|
||||||
|
mValues.insert(make_pair(TW_SDPART_FILE_SYSTEM, make_pair("ext3", 1)));
|
||||||
|
mValues.insert(make_pair(TW_TIME_ZONE_GUISEL, make_pair("CST6;CDT", 1)));
|
||||||
|
mValues.insert(make_pair(TW_TIME_ZONE_GUIOFFSET, make_pair("0", 1)));
|
||||||
|
mValues.insert(make_pair(TW_TIME_ZONE_GUIDST, make_pair("1", 1)));
|
||||||
|
mValues.insert(make_pair(TW_ACTION_BUSY, make_pair("0", 0)));
|
||||||
|
mValues.insert(make_pair(TW_BACKUP_AVG_IMG_RATE, make_pair("15000000", 1)));
|
||||||
|
mValues.insert(make_pair(TW_BACKUP_AVG_FILE_RATE, make_pair("3000000", 1)));
|
||||||
|
mValues.insert(make_pair(TW_BACKUP_AVG_FILE_COMP_RATE, make_pair("2000000", 1)));
|
||||||
|
mValues.insert(make_pair(TW_RESTORE_AVG_IMG_RATE, make_pair("15000000", 1)));
|
||||||
|
mValues.insert(make_pair(TW_RESTORE_AVG_FILE_RATE, make_pair("3000000", 1)));
|
||||||
|
mValues.insert(make_pair(TW_RESTORE_AVG_FILE_COMP_RATE, make_pair("2000000", 1)));
|
||||||
|
if (GetIntValue(TW_HAS_INTERNAL) == 1 && GetIntValue(TW_HAS_DATA_MEDIA) == 1 && GetIntValue(TW_HAS_EXTERNAL) == 0)
|
||||||
|
SetValue(TW_HAS_USB_STORAGE, 0, 0);
|
||||||
|
else
|
||||||
|
SetValue(TW_HAS_USB_STORAGE, 1, 0);
|
||||||
|
mValues.insert(make_pair(TW_ZIP_INDEX, make_pair("0", 0)));
|
||||||
|
mValues.insert(make_pair(TW_ZIP_QUEUE_COUNT, make_pair("0", 0)));
|
||||||
|
mValues.insert(make_pair(TW_FILENAME, make_pair("/sdcard", 0)));
|
||||||
|
mValues.insert(make_pair(TW_SIMULATE_ACTIONS, make_pair("0", 1)));
|
||||||
|
mValues.insert(make_pair(TW_SIMULATE_FAIL, make_pair("0", 1)));
|
||||||
|
mValues.insert(make_pair(TW_IS_ENCRYPTED, make_pair("0", 0)));
|
||||||
|
mValues.insert(make_pair(TW_IS_DECRYPTED, make_pair("0", 0)));
|
||||||
|
mValues.insert(make_pair(TW_CRYPTO_PASSWORD, make_pair("0", 0)));
|
||||||
|
mValues.insert(make_pair(TW_DATA_BLK_DEVICE, make_pair("0", 0)));
|
||||||
|
mValues.insert(make_pair("tw_terminal_state", make_pair("0", 0)));
|
||||||
|
mValues.insert(make_pair("tw_background_thread_running", make_pair("0", 0)));
|
||||||
|
mValues.insert(make_pair(TW_RESTORE_FILE_DATE, make_pair("0", 0)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Magic Values
|
||||||
|
int DataManager::GetMagicValue(const string varName, string& value)
|
||||||
|
{
|
||||||
|
// Handle special dynamic cases
|
||||||
|
if (varName == "tw_time")
|
||||||
|
{
|
||||||
|
char tmp[32];
|
||||||
|
|
||||||
|
struct tm *current;
|
||||||
|
time_t now;
|
||||||
|
now = time(0);
|
||||||
|
current = localtime(&now);
|
||||||
|
|
||||||
|
if (current->tm_hour >= 12)
|
||||||
|
sprintf(tmp, "%d:%02d PM", current->tm_hour == 12 ? 12 : current->tm_hour - 12, current->tm_min);
|
||||||
|
else
|
||||||
|
sprintf(tmp, "%d:%02d AM", current->tm_hour == 0 ? 12 : current->tm_hour, current->tm_min);
|
||||||
|
|
||||||
|
value = tmp;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (varName == "tw_battery")
|
||||||
|
{
|
||||||
|
char tmp[16];
|
||||||
|
|
||||||
|
sprintf(tmp, "%i%%", get_battery_level());
|
||||||
|
value = tmp;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DataManager::ReadSettingsFile(void)
|
||||||
|
{
|
||||||
|
// Load up the values for TWRP - Sleep to let the card be ready
|
||||||
|
char mkdir_path[255], settings_file[255];
|
||||||
|
int is_enc, has_dual, use_ext, has_data_media, has_ext;
|
||||||
|
|
||||||
|
GetValue(TW_IS_ENCRYPTED, is_enc);
|
||||||
|
GetValue(TW_HAS_DATA_MEDIA, has_data_media);
|
||||||
|
if (is_enc == 1 && has_data_media == 1) {
|
||||||
|
LOGI("Cannot load settings -- encrypted.\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(mkdir_path, 0, sizeof(mkdir_path));
|
||||||
|
memset(settings_file, 0, sizeof(settings_file));
|
||||||
|
sprintf(mkdir_path, "%s/TWRP", DataManager_GetSettingsStoragePath());
|
||||||
|
sprintf(settings_file, "%s/.twrps", mkdir_path);
|
||||||
|
|
||||||
|
if (TWPartitionManager::Mount_By_Path(DataManager_GetSettingsStorageMount(), 0) < 0)
|
||||||
|
{
|
||||||
|
usleep(500000);
|
||||||
|
if (TWPartitionManager::Mount_By_Path(DataManager_GetSettingsStorageMount(), 0) < 0)
|
||||||
|
LOGE("Unable to mount %s when trying to read settings file.\n", DataManager_GetSettingsStorageMount());
|
||||||
|
}
|
||||||
|
|
||||||
|
mkdir(mkdir_path, 0777);
|
||||||
|
|
||||||
|
LOGI("Attempt to load settings from settings file...\n");
|
||||||
|
LoadValues(settings_file);
|
||||||
|
GetValue(TW_HAS_DUAL_STORAGE, has_dual);
|
||||||
|
GetValue(TW_USE_EXTERNAL_STORAGE, use_ext);
|
||||||
|
GetValue(TW_HAS_EXTERNAL, has_ext);
|
||||||
|
if (has_dual != 0 && use_ext == 1) {
|
||||||
|
// Attempt to sdcard using external storage
|
||||||
|
if (TWPartitionManager::Mount_Current_Storage()) {
|
||||||
|
LOGE("Failed to mount external storage, using internal storage.\n");
|
||||||
|
// Remount failed, default back to internal storage
|
||||||
|
SetValue(TW_USE_EXTERNAL_STORAGE, 0);
|
||||||
|
TWPartitionManager::Mount_Current_Storage();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
TWPartitionManager::Mount_Current_Storage();
|
||||||
|
}
|
||||||
|
if (has_data_media == 1) {
|
||||||
|
if (has_dual == 0) {
|
||||||
|
LOGI("Mounting /data/media to /sdcard\n");
|
||||||
|
system("umount /sdcard");
|
||||||
|
system("mount /data/media /sdcard");
|
||||||
|
} else {
|
||||||
|
string ext_path;
|
||||||
|
|
||||||
|
GetValue(TW_EXTERNAL_PATH, ext_path);
|
||||||
|
if (ext_path == "/sdcard") {
|
||||||
|
LOGI("Mounting /data/media to /emmc\n");
|
||||||
|
system("cd / && mkdir emmc");
|
||||||
|
system("umount /emmc");
|
||||||
|
system("mount /data/media /emmc");
|
||||||
|
} else {
|
||||||
|
LOGI("Mounting /data/media to /sdcard\n");
|
||||||
|
system("umount /sdcard");
|
||||||
|
system("mount /data/media /sdcard");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update storage free space after settings file is loaded
|
||||||
|
if (use_ext == 1)
|
||||||
|
LOGE("TODO: Fix storage size code!\n"); //SetValue(TW_STORAGE_FREE_SIZE, (int)((sdcext.sze - sdcext.used) / 1048576LLU));
|
||||||
|
else if (has_data_media == 1)
|
||||||
|
LOGE("TODO: Fix storage size code!\n"); //SetValue(TW_STORAGE_FREE_SIZE, (int)((dat.sze - dat.used) / 1048576LLU));
|
||||||
|
else
|
||||||
|
LOGE("TODO: Fix storage size code!\n"); //SetValue(TW_STORAGE_FREE_SIZE, (int)((sdcint.sze - sdcint.used) / 1048576LLU));
|
||||||
|
|
||||||
|
if (has_ext) {
|
||||||
|
string ext_path;
|
||||||
|
|
||||||
|
GetValue(TW_EXTERNAL_PATH, ext_path);
|
||||||
|
TWPartitionManager::Mount_By_Path(ext_path, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string DataManager::GetCurrentStoragePath(void)
|
||||||
|
{
|
||||||
|
if (GetIntValue(TW_HAS_DUAL_STORAGE) == 1) {
|
||||||
|
if (GetIntValue(TW_USE_EXTERNAL_STORAGE) == 0)
|
||||||
|
return GetStrValue(TW_INTERNAL_PATH);
|
||||||
|
else
|
||||||
|
return GetStrValue(TW_EXTERNAL_PATH);
|
||||||
|
} else if (GetIntValue(TW_HAS_INTERNAL) == 1)
|
||||||
|
return GetStrValue(TW_INTERNAL_PATH);
|
||||||
|
else
|
||||||
|
return GetStrValue(TW_EXTERNAL_PATH);
|
||||||
|
}
|
||||||
|
|
||||||
|
string& DataManager::CGetCurrentStoragePath()
|
||||||
|
{
|
||||||
|
if (GetIntValue(TW_HAS_DUAL_STORAGE) == 1) {
|
||||||
|
if (GetIntValue(TW_USE_EXTERNAL_STORAGE) == 0)
|
||||||
|
return GetValueRef(TW_INTERNAL_PATH);
|
||||||
|
else
|
||||||
|
return GetValueRef(TW_EXTERNAL_PATH);
|
||||||
|
} else if (GetIntValue(TW_HAS_INTERNAL) == 1)
|
||||||
|
return GetValueRef(TW_INTERNAL_PATH);
|
||||||
|
else
|
||||||
|
return GetValueRef(TW_EXTERNAL_PATH);
|
||||||
|
}
|
||||||
|
|
||||||
|
string DataManager::GetCurrentStorageMount(void)
|
||||||
|
{
|
||||||
|
if (GetIntValue(TW_HAS_DUAL_STORAGE) == 1) {
|
||||||
|
if (GetIntValue(TW_USE_EXTERNAL_STORAGE) == 0)
|
||||||
|
return GetStrValue(TW_INTERNAL_MOUNT);
|
||||||
|
else
|
||||||
|
return GetStrValue(TW_EXTERNAL_MOUNT);
|
||||||
|
} else if (GetIntValue(TW_HAS_INTERNAL) == 1)
|
||||||
|
return GetStrValue(TW_INTERNAL_MOUNT);
|
||||||
|
else
|
||||||
|
return GetStrValue(TW_EXTERNAL_MOUNT);
|
||||||
|
}
|
||||||
|
|
||||||
|
string& DataManager::CGetCurrentStorageMount()
|
||||||
|
{
|
||||||
|
if (GetIntValue(TW_HAS_DUAL_STORAGE) == 1) {
|
||||||
|
if (GetIntValue(TW_USE_EXTERNAL_STORAGE) == 0)
|
||||||
|
return GetValueRef(TW_INTERNAL_MOUNT);
|
||||||
|
else
|
||||||
|
return GetValueRef(TW_EXTERNAL_MOUNT);
|
||||||
|
} else if (GetIntValue(TW_HAS_INTERNAL) == 1)
|
||||||
|
return GetValueRef(TW_INTERNAL_MOUNT);
|
||||||
|
else
|
||||||
|
return GetValueRef(TW_EXTERNAL_MOUNT);
|
||||||
|
}
|
||||||
|
|
||||||
|
string DataManager::GetSettingsStoragePath(void)
|
||||||
|
{
|
||||||
|
if (GetIntValue(TW_HAS_INTERNAL) == 1)
|
||||||
|
return GetStrValue(TW_INTERNAL_PATH);
|
||||||
|
else
|
||||||
|
return GetStrValue(TW_EXTERNAL_PATH);
|
||||||
|
}
|
||||||
|
|
||||||
|
string& DataManager::CGetSettingsStoragePath()
|
||||||
|
{
|
||||||
|
if (GetIntValue(TW_HAS_INTERNAL) == 1)
|
||||||
|
return GetValueRef(TW_INTERNAL_PATH);
|
||||||
|
else
|
||||||
|
return GetValueRef(TW_EXTERNAL_PATH);
|
||||||
|
}
|
||||||
|
|
||||||
|
string DataManager::GetSettingsStorageMount(void)
|
||||||
|
{
|
||||||
|
if (GetIntValue(TW_HAS_INTERNAL) == 1)
|
||||||
|
return GetStrValue(TW_INTERNAL_MOUNT);
|
||||||
|
else
|
||||||
|
return GetStrValue(TW_EXTERNAL_MOUNT);
|
||||||
|
}
|
||||||
|
|
||||||
|
string& DataManager::CGetSettingsStorageMount()
|
||||||
|
{
|
||||||
|
if (GetIntValue(TW_HAS_INTERNAL) == 1)
|
||||||
|
return GetValueRef(TW_INTERNAL_MOUNT);
|
||||||
|
else
|
||||||
|
return GetValueRef(TW_EXTERNAL_MOUNT);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" int DataManager_ResetDefaults()
|
||||||
|
{
|
||||||
|
return DataManager::ResetDefaults();
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void DataManager_LoadDefaults()
|
||||||
|
{
|
||||||
|
return DataManager::SetDefaultValues();
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" int DataManager_LoadValues(const char* filename)
|
||||||
|
{
|
||||||
|
return DataManager::LoadValues(filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" int DataManager_Flush()
|
||||||
|
{
|
||||||
|
return DataManager::Flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" int DataManager_GetValue(const char* varName, char* value)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
string str;
|
||||||
|
|
||||||
|
ret = DataManager::GetValue(varName, str);
|
||||||
|
if (ret == 0)
|
||||||
|
strcpy(value, str.c_str());
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" const char* DataManager_GetStrValue(const char* varName)
|
||||||
|
{
|
||||||
|
string& str = DataManager::GetValueRef(varName);
|
||||||
|
return str.c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" const char* DataManager_GetCurrentStoragePath(void)
|
||||||
|
{
|
||||||
|
string& str = DataManager::CGetCurrentStoragePath();
|
||||||
|
return str.c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" const char* DataManager_GetSettingsStoragePath(void)
|
||||||
|
{
|
||||||
|
string& str = DataManager::CGetSettingsStoragePath();
|
||||||
|
return str.c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" const char* DataManager_GetCurrentStorageMount(void)
|
||||||
|
{
|
||||||
|
string& str = DataManager::CGetCurrentStorageMount();
|
||||||
|
return str.c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" const char* DataManager_GetSettingsStorageMount(void)
|
||||||
|
{
|
||||||
|
string& str = DataManager::CGetSettingsStorageMount();
|
||||||
|
return str.c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" int DataManager_GetIntValue(const char* varName)
|
||||||
|
{
|
||||||
|
return DataManager::GetIntValue(varName);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" int DataManager_SetStrValue(const char* varName, char* value)
|
||||||
|
{
|
||||||
|
return DataManager::SetValue(varName, value, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" int DataManager_SetIntValue(const char* varName, int value)
|
||||||
|
{
|
||||||
|
return DataManager::SetValue(varName, value, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" int DataManager_SetFloatValue(const char* varName, float value)
|
||||||
|
{
|
||||||
|
return DataManager::SetValue(varName, value, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" int DataManager_ToggleIntValue(const char* varName)
|
||||||
|
{
|
||||||
|
if (DataManager::GetIntValue(varName))
|
||||||
|
return DataManager::SetValue(varName, 0);
|
||||||
|
else
|
||||||
|
return DataManager::SetValue(varName, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void DataManager_DumpValues()
|
||||||
|
{
|
||||||
|
return DataManager::DumpValues();
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void DataManager_ReadSettingsFile()
|
||||||
|
{
|
||||||
|
return DataManager::ReadSettingsFile();
|
||||||
|
}
|
41
data.h
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2007 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _DATA_HEADER
|
||||||
|
#define _DATA_HEADER
|
||||||
|
|
||||||
|
int DataManager_ResetDefaults();
|
||||||
|
void DataManager_LoadDefaults();
|
||||||
|
int DataManager_LoadValues(const char* filename);
|
||||||
|
int DataManager_Flush();
|
||||||
|
const char* DataManager_GetStrValue(const char* varName);
|
||||||
|
const char* DataManager_GetCurrentStoragePath();
|
||||||
|
const char* DataManager_GetCurrentStorageMount();
|
||||||
|
const char* DataManager_GetSettingsStoragePath();
|
||||||
|
const char* DataManager_GetSettingsStorageMount();
|
||||||
|
int DataManager_GetIntValue(const char* varName);
|
||||||
|
|
||||||
|
int DataManager_SetStrValue(const char* varName, char* value);
|
||||||
|
int DataManager_SetIntValue(const char* varName, int value);
|
||||||
|
int DataManager_SetFloatValue(const char* varName, float value);
|
||||||
|
|
||||||
|
int DataManager_ToggleIntValue(const char* varName);
|
||||||
|
|
||||||
|
void DataManager_DumpValues();
|
||||||
|
void DataManager_ReadSettingsFile();
|
||||||
|
|
||||||
|
#endif // _DATA_HEADER
|
||||||
|
|
79
data.hpp
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2007 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _DATAMANAGER_HPP_HEADER
|
||||||
|
#define _DATAMANAGER_HPP_HEADER
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <utility>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
class DataManager
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static int ResetDefaults();
|
||||||
|
static int LoadValues(const string filename);
|
||||||
|
static int Flush();
|
||||||
|
|
||||||
|
// Core get routines
|
||||||
|
static int GetValue(const string varName, string& value);
|
||||||
|
static int GetValue(const string varName, int& value);
|
||||||
|
|
||||||
|
// This is a dangerous function. It will create the value if it doesn't exist so it has a valid c_str
|
||||||
|
static string& GetValueRef(const string varName);
|
||||||
|
|
||||||
|
// Helper functions
|
||||||
|
static string GetStrValue(const string varName);
|
||||||
|
static int GetIntValue(const string varName);
|
||||||
|
|
||||||
|
// Core set routines
|
||||||
|
static int SetValue(const string varName, string value, int persist = 0);
|
||||||
|
static int SetValue(const string varName, int value, int persist = 0);
|
||||||
|
static int SetValue(const string varName, float value, int persist = 0);
|
||||||
|
|
||||||
|
static void DumpValues();
|
||||||
|
static void SetDefaultValues();
|
||||||
|
static void ReadSettingsFile(void);
|
||||||
|
|
||||||
|
static string GetCurrentStoragePath(void);
|
||||||
|
static string& CGetCurrentStoragePath();
|
||||||
|
static string GetCurrentStorageMount(void);
|
||||||
|
static string& CGetCurrentStorageMount();
|
||||||
|
static string GetSettingsStoragePath(void);
|
||||||
|
static string& CGetSettingsStoragePath();
|
||||||
|
static string GetSettingsStorageMount(void);
|
||||||
|
static string& CGetSettingsStorageMount();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
typedef pair<string, int> TStrIntPair;
|
||||||
|
typedef pair<string, TStrIntPair> TNameValuePair;
|
||||||
|
static map<string, TStrIntPair> mValues;
|
||||||
|
static string mBackingFile;
|
||||||
|
static int mInitialized;
|
||||||
|
|
||||||
|
static map<string, string> mConstValues;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
static int SaveValues();
|
||||||
|
|
||||||
|
static int GetMagicValue(string varName, string& value);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // _DATAMANAGER_HPP_HEADER
|
||||||
|
|
28
etc/init.rc
@ -3,30 +3,19 @@ on early-init
|
|||||||
|
|
||||||
on init
|
on init
|
||||||
export PATH /sbin
|
export PATH /sbin
|
||||||
|
export LD_LIBRARY_PATH .:/sbin
|
||||||
export ANDROID_ROOT /system
|
export ANDROID_ROOT /system
|
||||||
export ANDROID_DATA /data
|
export ANDROID_DATA /data
|
||||||
export EXTERNAL_STORAGE /sdcard
|
export EXTERNAL_STORAGE /sdcard
|
||||||
|
|
||||||
symlink /system/etc /etc
|
symlink /system/etc /etc
|
||||||
|
|
||||||
mkdir /sdcard
|
mkdir /emmc
|
||||||
mkdir /system
|
mkdir /system
|
||||||
mkdir /data
|
mkdir /data
|
||||||
mkdir /cache
|
mkdir /cache
|
||||||
mount /tmp /tmp tmpfs
|
mount /tmp /tmp tmpfs
|
||||||
|
|
||||||
chown root shell /tmp
|
|
||||||
chmod 0775 /tmp
|
|
||||||
|
|
||||||
write /sys/class/android_usb/android0/enable 0
|
|
||||||
write /sys/class/android_usb/android0/idVendor 18D1
|
|
||||||
write /sys/class/android_usb/android0/idProduct D001
|
|
||||||
write /sys/class/android_usb/android0/functions adb
|
|
||||||
write /sys/class/android_usb/android0/iManufacturer ${ro.product.manufacturer}
|
|
||||||
write /sys/class/android_usb/android0/iProduct ${ro.product.model}
|
|
||||||
write /sys/class/android_usb/android0/iSerial ${ro.serialno}
|
|
||||||
|
|
||||||
|
|
||||||
on boot
|
on boot
|
||||||
|
|
||||||
ifup lo
|
ifup lo
|
||||||
@ -44,9 +33,18 @@ service adbd /sbin/adbd recovery
|
|||||||
disabled
|
disabled
|
||||||
|
|
||||||
# Always start adbd on userdebug and eng builds
|
# Always start adbd on userdebug and eng builds
|
||||||
|
# In recovery, always run adbd as root.
|
||||||
on property:ro.debuggable=1
|
on property:ro.debuggable=1
|
||||||
write /sys/class/android_usb/android0/enable 1
|
write /sys/class/android_usb/android0/enable 0
|
||||||
start adbd
|
write /sys/class/android_usb/android0/idVendor 18D1
|
||||||
|
write /sys/class/android_usb/android0/idProduct D001
|
||||||
|
write /sys/class/android_usb/android0/functions adb
|
||||||
|
#write /sys/class/android_usb/android0/enable 1
|
||||||
|
write /sys/class/android_usb/android0/iManufacturer $ro.product.manufacturer
|
||||||
|
write /sys/class/android_usb/android0/iProduct $ro.product.model
|
||||||
|
write /sys/class/android_usb/android0/iSerial $ro.serialno
|
||||||
|
#start adbd
|
||||||
|
setprop service.adb.root 1
|
||||||
|
|
||||||
# Restart adbd so it can run as root
|
# Restart adbd so it can run as root
|
||||||
on property:service.adb.root=1
|
on property:service.adb.root=1
|
||||||
|
956
extra-functions.c
Normal file
@ -0,0 +1,956 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2011 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <paths.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
|
#include "cutils/misc.h"
|
||||||
|
#include "cutils/properties.h"
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <getopt.h>
|
||||||
|
#include <linux/input.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <sys/limits.h>
|
||||||
|
#include <termios.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <sys/vfs.h>
|
||||||
|
|
||||||
|
#include "tw_reboot.h"
|
||||||
|
#include "bootloader.h"
|
||||||
|
#include "common.h"
|
||||||
|
#include "extra-functions.h"
|
||||||
|
#include "cutils/properties.h"
|
||||||
|
#include "install.h"
|
||||||
|
#include "minuitwrp/minui.h"
|
||||||
|
#include "minzip/DirUtil.h"
|
||||||
|
#include "minzip/Zip.h"
|
||||||
|
#include "recovery_ui.h"
|
||||||
|
#include "roots.h"
|
||||||
|
#include "data.h"
|
||||||
|
#include "variables.h"
|
||||||
|
|
||||||
|
//kang system() from bionic/libc/unistd and rename it __system() so we can be even more hackish :)
|
||||||
|
#undef _PATH_BSHELL
|
||||||
|
#define _PATH_BSHELL "/sbin/sh"
|
||||||
|
|
||||||
|
static const char *SIDELOAD_TEMP_DIR = "/tmp/sideload";
|
||||||
|
extern char **environ;
|
||||||
|
|
||||||
|
int __system(const char *command) {
|
||||||
|
pid_t pid;
|
||||||
|
sig_t intsave, quitsave;
|
||||||
|
sigset_t mask, omask;
|
||||||
|
int pstat;
|
||||||
|
char *argp[] = {"sh", "-c", NULL, NULL};
|
||||||
|
|
||||||
|
if (!command) /* just checking... */
|
||||||
|
return(1);
|
||||||
|
|
||||||
|
argp[2] = (char *)command;
|
||||||
|
|
||||||
|
sigemptyset(&mask);
|
||||||
|
sigaddset(&mask, SIGCHLD);
|
||||||
|
sigprocmask(SIG_BLOCK, &mask, &omask);
|
||||||
|
switch (pid = vfork()) {
|
||||||
|
case -1: /* error */
|
||||||
|
sigprocmask(SIG_SETMASK, &omask, NULL);
|
||||||
|
return(-1);
|
||||||
|
case 0: /* child */
|
||||||
|
sigprocmask(SIG_SETMASK, &omask, NULL);
|
||||||
|
execve(_PATH_BSHELL, argp, environ);
|
||||||
|
_exit(127);
|
||||||
|
}
|
||||||
|
|
||||||
|
intsave = (sig_t) bsd_signal(SIGINT, SIG_IGN);
|
||||||
|
quitsave = (sig_t) bsd_signal(SIGQUIT, SIG_IGN);
|
||||||
|
pid = waitpid(pid, (int *)&pstat, 0);
|
||||||
|
sigprocmask(SIG_SETMASK, &omask, NULL);
|
||||||
|
(void)bsd_signal(SIGINT, intsave);
|
||||||
|
(void)bsd_signal(SIGQUIT, quitsave);
|
||||||
|
return (pid == -1 ? -1 : pstat);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct pid {
|
||||||
|
struct pid *next;
|
||||||
|
FILE *fp;
|
||||||
|
pid_t pid;
|
||||||
|
} *pidlist;
|
||||||
|
|
||||||
|
FILE *__popen(const char *program, const char *type) {
|
||||||
|
struct pid * volatile cur;
|
||||||
|
FILE *iop;
|
||||||
|
int pdes[2];
|
||||||
|
pid_t pid;
|
||||||
|
|
||||||
|
if ((*type != 'r' && *type != 'w') || type[1] != '\0') {
|
||||||
|
errno = EINVAL;
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((cur = malloc(sizeof(struct pid))) == NULL)
|
||||||
|
return (NULL);
|
||||||
|
|
||||||
|
if (pipe(pdes) < 0) {
|
||||||
|
free(cur);
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (pid = vfork()) {
|
||||||
|
case -1: /* Error. */
|
||||||
|
(void)close(pdes[0]);
|
||||||
|
(void)close(pdes[1]);
|
||||||
|
free(cur);
|
||||||
|
return (NULL);
|
||||||
|
/* NOTREACHED */
|
||||||
|
case 0: /* Child. */
|
||||||
|
{
|
||||||
|
struct pid *pcur;
|
||||||
|
/*
|
||||||
|
* because vfork() instead of fork(), must leak FILE *,
|
||||||
|
* but luckily we are terminally headed for an execl()
|
||||||
|
*/
|
||||||
|
for (pcur = pidlist; pcur; pcur = pcur->next)
|
||||||
|
close(fileno(pcur->fp));
|
||||||
|
|
||||||
|
if (*type == 'r') {
|
||||||
|
int tpdes1 = pdes[1];
|
||||||
|
|
||||||
|
(void) close(pdes[0]);
|
||||||
|
/*
|
||||||
|
* We must NOT modify pdes, due to the
|
||||||
|
* semantics of vfork.
|
||||||
|
*/
|
||||||
|
if (tpdes1 != STDOUT_FILENO) {
|
||||||
|
(void)dup2(tpdes1, STDOUT_FILENO);
|
||||||
|
(void)close(tpdes1);
|
||||||
|
tpdes1 = STDOUT_FILENO;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
(void)close(pdes[1]);
|
||||||
|
if (pdes[0] != STDIN_FILENO) {
|
||||||
|
(void)dup2(pdes[0], STDIN_FILENO);
|
||||||
|
(void)close(pdes[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
execl(_PATH_BSHELL, "sh", "-c", program, (char *)NULL);
|
||||||
|
_exit(127);
|
||||||
|
/* NOTREACHED */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Parent; assume fdopen can't fail. */
|
||||||
|
if (*type == 'r') {
|
||||||
|
iop = fdopen(pdes[0], type);
|
||||||
|
(void)close(pdes[1]);
|
||||||
|
} else {
|
||||||
|
iop = fdopen(pdes[1], type);
|
||||||
|
(void)close(pdes[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Link into list of file descriptors. */
|
||||||
|
cur->fp = iop;
|
||||||
|
cur->pid = pid;
|
||||||
|
cur->next = pidlist;
|
||||||
|
pidlist = cur;
|
||||||
|
|
||||||
|
return (iop);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* pclose --
|
||||||
|
* Pclose returns -1 if stream is not associated with a `popened' command,
|
||||||
|
* if already `pclosed', or waitpid returns an error.
|
||||||
|
*/
|
||||||
|
int __pclose(FILE *iop) {
|
||||||
|
struct pid *cur, *last;
|
||||||
|
int pstat;
|
||||||
|
pid_t pid;
|
||||||
|
|
||||||
|
/* Find the appropriate file pointer. */
|
||||||
|
for (last = NULL, cur = pidlist; cur; last = cur, cur = cur->next)
|
||||||
|
if (cur->fp == iop)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (cur == NULL)
|
||||||
|
return (-1);
|
||||||
|
|
||||||
|
(void)fclose(iop);
|
||||||
|
|
||||||
|
do {
|
||||||
|
pid = waitpid(cur->pid, &pstat, 0);
|
||||||
|
} while (pid == -1 && errno == EINTR);
|
||||||
|
|
||||||
|
/* Remove the entry from the linked list. */
|
||||||
|
if (last == NULL)
|
||||||
|
pidlist = cur->next;
|
||||||
|
else
|
||||||
|
last->next = cur->next;
|
||||||
|
free(cur);
|
||||||
|
|
||||||
|
return (pid == -1 ? -1 : pstat);
|
||||||
|
}
|
||||||
|
|
||||||
|
char* sanitize_device_id(char* id) {
|
||||||
|
const char* whitelist ="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890-._";
|
||||||
|
char* c = id;
|
||||||
|
char* str = (int*) calloc(50, sizeof *id);
|
||||||
|
while (*c)
|
||||||
|
{
|
||||||
|
if (strchr(whitelist, *c))
|
||||||
|
{
|
||||||
|
strncat(str, c, 1);
|
||||||
|
}
|
||||||
|
c++;
|
||||||
|
}
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define CMDLINE_SERIALNO "androidboot.serialno="
|
||||||
|
#define CMDLINE_SERIALNO_LEN (strlen(CMDLINE_SERIALNO))
|
||||||
|
#define CPUINFO_SERIALNO "Serial"
|
||||||
|
#define CPUINFO_SERIALNO_LEN (strlen(CPUINFO_SERIALNO))
|
||||||
|
#define CPUINFO_HARDWARE "Hardware"
|
||||||
|
#define CPUINFO_HARDWARE_LEN (strlen(CPUINFO_HARDWARE))
|
||||||
|
|
||||||
|
void get_device_id() {
|
||||||
|
FILE *fp;
|
||||||
|
char line[2048];
|
||||||
|
char hardware_id[32];
|
||||||
|
char* token;
|
||||||
|
char* new_device_id;
|
||||||
|
|
||||||
|
// Assign a blank device_id to start with
|
||||||
|
device_id[0] = 0;
|
||||||
|
|
||||||
|
// First, try the cmdline to see if the serial number was supplied
|
||||||
|
fp = fopen("/proc/cmdline", "rt");
|
||||||
|
if (fp != NULL)
|
||||||
|
{
|
||||||
|
// First step, read the line. For cmdline, it's one long line
|
||||||
|
fgets(line, sizeof(line), fp);
|
||||||
|
fclose(fp);
|
||||||
|
|
||||||
|
// Now, let's tokenize the string
|
||||||
|
token = strtok(line, " ");
|
||||||
|
|
||||||
|
// Let's walk through the line, looking for the CMDLINE_SERIALNO token
|
||||||
|
while (token)
|
||||||
|
{
|
||||||
|
// We don't need to verify the length of token, because if it's too short, it will mismatch CMDLINE_SERIALNO at the NULL
|
||||||
|
if (memcmp(token, CMDLINE_SERIALNO, CMDLINE_SERIALNO_LEN) == 0)
|
||||||
|
{
|
||||||
|
// We found the serial number!
|
||||||
|
strcpy(device_id, token + CMDLINE_SERIALNO_LEN);
|
||||||
|
new_device_id = sanitize_device_id(device_id);
|
||||||
|
strcpy(device_id, new_device_id);
|
||||||
|
free(new_device_id);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
token = strtok(NULL, " ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now we'll try cpuinfo for a serial number
|
||||||
|
fp = fopen("/proc/cpuinfo", "rt");
|
||||||
|
if (fp != NULL)
|
||||||
|
{
|
||||||
|
while (fgets(line, sizeof(line), fp) != NULL) { // First step, read the line.
|
||||||
|
if (memcmp(line, CPUINFO_SERIALNO, CPUINFO_SERIALNO_LEN) == 0) // check the beginning of the line for "Serial"
|
||||||
|
{
|
||||||
|
// We found the serial number!
|
||||||
|
token = line + CPUINFO_SERIALNO_LEN; // skip past "Serial"
|
||||||
|
while ((*token > 0 && *token <= 32 ) || *token == ':') token++; // skip over all spaces and the colon
|
||||||
|
if (*token != 0) {
|
||||||
|
token[30] = 0;
|
||||||
|
if (token[strlen(token)-1] == 10) { // checking for endline chars and dropping them from the end of the string if needed
|
||||||
|
memset(device_id, 0, sizeof(device_id));
|
||||||
|
strncpy(device_id, token, strlen(token) - 1);
|
||||||
|
} else {
|
||||||
|
strcpy(device_id, token);
|
||||||
|
}
|
||||||
|
LOGI("=> serial from cpuinfo: '%s'\n", device_id);
|
||||||
|
fclose(fp);
|
||||||
|
new_device_id = sanitize_device_id(device_id);
|
||||||
|
strcpy(device_id, new_device_id);
|
||||||
|
free(new_device_id);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else if (memcmp(line, CPUINFO_HARDWARE, CPUINFO_HARDWARE_LEN) == 0) {// We're also going to look for the hardware line in cpuinfo and save it for later in case we don't find the device ID
|
||||||
|
// We found the hardware ID
|
||||||
|
token = line + CPUINFO_HARDWARE_LEN; // skip past "Hardware"
|
||||||
|
while ((*token > 0 && *token <= 32 ) || *token == ':') token++; // skip over all spaces and the colon
|
||||||
|
if (*token != 0) {
|
||||||
|
token[30] = 0;
|
||||||
|
if (token[strlen(token)-1] == 10) { // checking for endline chars and dropping them from the end of the string if needed
|
||||||
|
memset(hardware_id, 0, sizeof(hardware_id));
|
||||||
|
strncpy(hardware_id, token, strlen(token) - 1);
|
||||||
|
} else {
|
||||||
|
strcpy(hardware_id, token);
|
||||||
|
}
|
||||||
|
LOGI("=> hardware id from cpuinfo: '%s'\n", hardware_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fclose(fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hardware_id[0] != 0) {
|
||||||
|
LOGW("\nusing hardware id for device id: '%s'\n", hardware_id);
|
||||||
|
strcpy(device_id, hardware_id);
|
||||||
|
new_device_id = sanitize_device_id(device_id);
|
||||||
|
strcpy(device_id, new_device_id);
|
||||||
|
free(new_device_id);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
strcpy(device_id, "serialno");
|
||||||
|
LOGE("=> device id not found, using '%s'.", device_id);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* get_path (char* path) {
|
||||||
|
char *s;
|
||||||
|
|
||||||
|
/* Go to the end of the string. */
|
||||||
|
s = path + strlen(path) - 1;
|
||||||
|
|
||||||
|
/* Strip off trailing /s (unless it is also the leading /). */
|
||||||
|
while (path < s && s[0] == '/')
|
||||||
|
s--;
|
||||||
|
|
||||||
|
/* Strip the last component. */
|
||||||
|
while (path <= s && s[0] != '/')
|
||||||
|
s--;
|
||||||
|
|
||||||
|
while (path < s && s[0] == '/')
|
||||||
|
s--;
|
||||||
|
|
||||||
|
if (s < path)
|
||||||
|
return ".";
|
||||||
|
|
||||||
|
s[1] = '\0';
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* basename(char* name) {
|
||||||
|
const char* base;
|
||||||
|
for (base = name; *name; name++)
|
||||||
|
{
|
||||||
|
if(*name == '/')
|
||||||
|
{
|
||||||
|
base = name + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (char *) base;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Checks md5 for a path
|
||||||
|
Return values:
|
||||||
|
-1 : MD5 does not exist
|
||||||
|
0 : Failed
|
||||||
|
1 : Success
|
||||||
|
*/
|
||||||
|
int check_md5(char* path) {
|
||||||
|
int o;
|
||||||
|
char cmd[PATH_MAX + 30];
|
||||||
|
char md5file[PATH_MAX + 40];
|
||||||
|
strcpy(md5file, path);
|
||||||
|
strcat(md5file, ".md5");
|
||||||
|
char dirpath[PATH_MAX];
|
||||||
|
char* file;
|
||||||
|
if (access(md5file, F_OK ) != -1) {
|
||||||
|
strcpy(dirpath, md5file);
|
||||||
|
get_path(dirpath);
|
||||||
|
chdir(dirpath);
|
||||||
|
file = basename(md5file);
|
||||||
|
sprintf(cmd, "/sbin/busybox md5sum -c '%s'", file);
|
||||||
|
FILE * cs = __popen(cmd, "r");
|
||||||
|
char cs_s[PATH_MAX + 50];
|
||||||
|
fgets(cs_s, PATH_MAX + 50, cs);
|
||||||
|
char* OK = strstr(cs_s, "OK");
|
||||||
|
if (OK != NULL) {
|
||||||
|
printf("MD5 is good. returning 1\n");
|
||||||
|
o = 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
printf("MD5 is bad. return -2\n");
|
||||||
|
o = -2;
|
||||||
|
}
|
||||||
|
|
||||||
|
__pclose(cs);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
//No md5 file
|
||||||
|
printf("setting o to -1\n");
|
||||||
|
o = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_sdcard_update_bootloader_message() {
|
||||||
|
struct bootloader_message boot;
|
||||||
|
memset(&boot, 0, sizeof(boot));
|
||||||
|
strlcpy(boot.command, "boot-recovery", sizeof(boot.command));
|
||||||
|
strlcpy(boot.recovery, "recovery\n", sizeof(boot.recovery));
|
||||||
|
set_bootloader_message(&boot);
|
||||||
|
}
|
||||||
|
|
||||||
|
static char* copy_sideloaded_package(const char* original_path) {
|
||||||
|
if (ensure_path_mounted(original_path) != 0) {
|
||||||
|
LOGE("Can't mount %s\n", original_path);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ensure_path_mounted(SIDELOAD_TEMP_DIR) != 0) {
|
||||||
|
LOGE("Can't mount %s\n", SIDELOAD_TEMP_DIR);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mkdir(SIDELOAD_TEMP_DIR, 0700) != 0) {
|
||||||
|
if (errno != EEXIST) {
|
||||||
|
LOGE("Can't mkdir %s (%s)\n", SIDELOAD_TEMP_DIR, strerror(errno));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// verify that SIDELOAD_TEMP_DIR is exactly what we expect: a
|
||||||
|
// directory, owned by root, readable and writable only by root.
|
||||||
|
struct stat st;
|
||||||
|
if (stat(SIDELOAD_TEMP_DIR, &st) != 0) {
|
||||||
|
LOGE("failed to stat %s (%s)\n", SIDELOAD_TEMP_DIR, strerror(errno));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (!S_ISDIR(st.st_mode)) {
|
||||||
|
LOGE("%s isn't a directory\n", SIDELOAD_TEMP_DIR);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if ((st.st_mode & 0777) != 0700) {
|
||||||
|
LOGE("%s has perms %o\n", SIDELOAD_TEMP_DIR, st.st_mode);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (st.st_uid != 0) {
|
||||||
|
LOGE("%s owned by %lu; not root\n", SIDELOAD_TEMP_DIR, st.st_uid);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
char copy_path[PATH_MAX];
|
||||||
|
strcpy(copy_path, SIDELOAD_TEMP_DIR);
|
||||||
|
strcat(copy_path, "/package.zip");
|
||||||
|
|
||||||
|
char* buffer = malloc(BUFSIZ);
|
||||||
|
if (buffer == NULL) {
|
||||||
|
LOGE("Failed to allocate buffer\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t read;
|
||||||
|
FILE* fin = fopen(original_path, "rb");
|
||||||
|
if (fin == NULL) {
|
||||||
|
LOGE("Failed to open %s (%s)\n", original_path, strerror(errno));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
FILE* fout = fopen(copy_path, "wb");
|
||||||
|
if (fout == NULL) {
|
||||||
|
LOGE("Failed to open %s (%s)\n", copy_path, strerror(errno));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
while ((read = fread(buffer, 1, BUFSIZ, fin)) > 0) {
|
||||||
|
if (fwrite(buffer, 1, read, fout) != read) {
|
||||||
|
LOGE("Short write of %s (%s)\n", copy_path, strerror(errno));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free(buffer);
|
||||||
|
|
||||||
|
if (fclose(fout) != 0) {
|
||||||
|
LOGE("Failed to close %s (%s)\n", copy_path, strerror(errno));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fclose(fin) != 0) {
|
||||||
|
LOGE("Failed to close %s (%s)\n", original_path, strerror(errno));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// "adb push" is happy to overwrite read-only files when it's
|
||||||
|
// running as root, but we'll try anyway.
|
||||||
|
if (chmod(copy_path, 0400) != 0) {
|
||||||
|
LOGE("Failed to chmod %s (%s)\n", copy_path, strerror(errno));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return strdup(copy_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
int install_zip_package(const char* zip_path_filename) {
|
||||||
|
int result = 0;
|
||||||
|
|
||||||
|
//mount_current_storage();
|
||||||
|
int md5_req = DataManager_GetIntValue(TW_FORCE_MD5_CHECK_VAR);
|
||||||
|
if (md5_req == 1) {
|
||||||
|
ui_print("\n-- Verify md5 for %s", zip_path_filename);
|
||||||
|
int md5chk = check_md5((char*) zip_path_filename);
|
||||||
|
if (md5chk == 1) {
|
||||||
|
ui_print("\n-- Md5 verified, continue");
|
||||||
|
result = 0;
|
||||||
|
}
|
||||||
|
else if (md5chk == -1) {
|
||||||
|
if (md5_req == 1) {
|
||||||
|
ui_print("\n-- No md5 file found!");
|
||||||
|
ui_print("\n-- Aborting install");
|
||||||
|
result = INSTALL_ERROR;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ui_print("\n-- No md5 file found, ignoring");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (md5chk == -2) {
|
||||||
|
ui_print("\n-- md5 file doesn't match!");
|
||||||
|
ui_print("\n-- Aborting install");
|
||||||
|
result = INSTALL_ERROR;
|
||||||
|
}
|
||||||
|
printf("%d\n", result);
|
||||||
|
}
|
||||||
|
if (result != INSTALL_ERROR) {
|
||||||
|
ui_print("\n-- Install %s ...\n", zip_path_filename);
|
||||||
|
set_sdcard_update_bootloader_message();
|
||||||
|
char* copy;
|
||||||
|
if (DataManager_GetIntValue(TW_FLASH_ZIP_IN_PLACE) == 1 && strlen(zip_path_filename) > 6 && strncmp(zip_path_filename, "/cache", 6) != 0) {
|
||||||
|
copy = strdup(zip_path_filename);
|
||||||
|
} else {
|
||||||
|
copy = copy_sideloaded_package(zip_path_filename);
|
||||||
|
//unmount_current_storage();
|
||||||
|
}
|
||||||
|
if (copy) {
|
||||||
|
result = really_install_package(copy, 0);
|
||||||
|
free(copy);
|
||||||
|
//update_system_details();
|
||||||
|
} else {
|
||||||
|
result = INSTALL_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//mount_current_storage();
|
||||||
|
//finish_recovery(NULL);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
//partial kangbang from system/vold
|
||||||
|
#ifndef CUSTOM_LUN_FILE
|
||||||
|
#define CUSTOM_LUN_FILE "/sys/devices/platform/usb_mass_storage/lun%d/file"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int usb_storage_enable(void)
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
char lun_file[255];
|
||||||
|
|
||||||
|
if (DataManager_GetIntValue(TW_HAS_DUAL_STORAGE) == 1 && DataManager_GetIntValue(TW_HAS_DATA_MEDIA) == 0) {
|
||||||
|
Volume *vol = volume_for_path(DataManager_GetSettingsStoragePath());
|
||||||
|
if (!vol)
|
||||||
|
{
|
||||||
|
LOGE("Unable to locate volume information.");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
sprintf(lun_file, CUSTOM_LUN_FILE, 0);
|
||||||
|
|
||||||
|
if ((fd = open(lun_file, O_WRONLY)) < 0)
|
||||||
|
{
|
||||||
|
LOGE("Unable to open ums lunfile '%s': (%s)\n", lun_file, strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((write(fd, vol->device, strlen(vol->device)) < 0) &&
|
||||||
|
(!vol->device2 || (write(fd, vol->device, strlen(vol->device2)) < 0))) {
|
||||||
|
LOGE("Unable to write to ums lunfile '%s': (%s)\n", lun_file, strerror(errno));
|
||||||
|
close(fd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
close(fd);
|
||||||
|
|
||||||
|
Volume *vol2 = volume_for_path(DataManager_GetStrValue(TW_EXTERNAL_PATH));
|
||||||
|
if (!vol)
|
||||||
|
{
|
||||||
|
LOGE("Unable to locate volume information.\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
sprintf(lun_file, CUSTOM_LUN_FILE, 1);
|
||||||
|
|
||||||
|
if ((fd = open(lun_file, O_WRONLY)) < 0)
|
||||||
|
{
|
||||||
|
LOGE("Unable to open ums lunfile '%s': (%s)\n", lun_file, strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((write(fd, vol2->device, strlen(vol2->device)) < 0) &&
|
||||||
|
(!vol2->device2 || (write(fd, vol2->device, strlen(vol2->device2)) < 0))) {
|
||||||
|
LOGE("Unable to write to ums lunfile '%s': (%s)\n", lun_file, strerror(errno));
|
||||||
|
close(fd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
close(fd);
|
||||||
|
} else {
|
||||||
|
if (DataManager_GetIntValue(TW_HAS_DATA_MEDIA) == 0)
|
||||||
|
strcpy(lun_file, DataManager_GetCurrentStoragePath());
|
||||||
|
else
|
||||||
|
strcpy(lun_file, DataManager_GetStrValue(TW_EXTERNAL_PATH));
|
||||||
|
|
||||||
|
Volume *vol = volume_for_path(lun_file);
|
||||||
|
if (!vol)
|
||||||
|
{
|
||||||
|
LOGE("Unable to locate volume information.\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
sprintf(lun_file, CUSTOM_LUN_FILE, 0);
|
||||||
|
|
||||||
|
if ((fd = open(lun_file, O_WRONLY)) < 0)
|
||||||
|
{
|
||||||
|
LOGE("Unable to open ums lunfile '%s': (%s)\n", lun_file, strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((write(fd, vol->device, strlen(vol->device)) < 0) &&
|
||||||
|
(!vol->device2 || (write(fd, vol->device, strlen(vol->device2)) < 0))) {
|
||||||
|
LOGE("Unable to write to ums lunfile '%s': (%s)\n", lun_file, strerror(errno));
|
||||||
|
close(fd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int usb_storage_disable(void)
|
||||||
|
{
|
||||||
|
int fd, index;
|
||||||
|
char lun_file[255];
|
||||||
|
|
||||||
|
for (index=0; index<2; index++) {
|
||||||
|
sprintf(lun_file, CUSTOM_LUN_FILE, index);
|
||||||
|
|
||||||
|
if ((fd = open(lun_file, O_WRONLY)) < 0)
|
||||||
|
{
|
||||||
|
if (index == 0)
|
||||||
|
LOGE("Unable to open ums lunfile '%s': (%s)", lun_file, strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
char ch = 0;
|
||||||
|
if (write(fd, &ch, 1) < 0)
|
||||||
|
{
|
||||||
|
if (index == 0)
|
||||||
|
LOGE("Unable to write to ums lunfile '%s': (%s)", lun_file, strerror(errno));
|
||||||
|
close(fd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void wipe_dalvik_cache()
|
||||||
|
{
|
||||||
|
//ui_set_background(BACKGROUND_ICON_WIPE);
|
||||||
|
ensure_path_mounted("/data");
|
||||||
|
ensure_path_mounted("/cache");
|
||||||
|
ui_print("\n-- Wiping Dalvik Cache Directories...\n");
|
||||||
|
__system("rm -rf /data/dalvik-cache");
|
||||||
|
ui_print("Cleaned: /data/dalvik-cache...\n");
|
||||||
|
__system("rm -rf /cache/dalvik-cache");
|
||||||
|
ui_print("Cleaned: /cache/dalvik-cache...\n");
|
||||||
|
__system("rm -rf /cache/dc");
|
||||||
|
ui_print("Cleaned: /cache/dc\n");
|
||||||
|
|
||||||
|
struct stat st;
|
||||||
|
LOGE("TODO: Re-implement wipe dalvik into Partition Manager!\n");
|
||||||
|
if (1) //if (0 != stat(sde.blk, &st))
|
||||||
|
{
|
||||||
|
ui_print("/sd-ext not present, skipping\n");
|
||||||
|
} else {
|
||||||
|
__system("mount /sd-ext");
|
||||||
|
LOGI("Mounting /sd-ext\n");
|
||||||
|
if (stat("/sd-ext/dalvik-cache",&st) == 0)
|
||||||
|
{
|
||||||
|
__system("rm -rf /sd-ext/dalvik-cache");
|
||||||
|
ui_print("Cleaned: /sd-ext/dalvik-cache...\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ensure_path_unmounted("/data");
|
||||||
|
ui_print("-- Dalvik Cache Directories Wipe Complete!\n\n");
|
||||||
|
//ui_set_background(BACKGROUND_ICON_MAIN);
|
||||||
|
//if (!ui_text_visible()) return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// BATTERY STATS
|
||||||
|
void wipe_battery_stats()
|
||||||
|
{
|
||||||
|
ensure_path_mounted("/data");
|
||||||
|
struct stat st;
|
||||||
|
if (0 != stat("/data/system/batterystats.bin", &st))
|
||||||
|
{
|
||||||
|
ui_print("No Battery Stats Found. No Need To Wipe.\n");
|
||||||
|
} else {
|
||||||
|
//ui_set_background(BACKGROUND_ICON_WIPE);
|
||||||
|
remove("/data/system/batterystats.bin");
|
||||||
|
ui_print("Cleared: Battery Stats...\n");
|
||||||
|
ensure_path_unmounted("/data");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ROTATION SETTINGS
|
||||||
|
void wipe_rotate_data()
|
||||||
|
{
|
||||||
|
//ui_set_background(BACKGROUND_ICON_WIPE);
|
||||||
|
ensure_path_mounted("/data");
|
||||||
|
__system("rm -r /data/misc/akmd*");
|
||||||
|
__system("rm -r /data/misc/rild*");
|
||||||
|
ui_print("Cleared: Rotatation Data...\n");
|
||||||
|
ensure_path_unmounted("/data");
|
||||||
|
}
|
||||||
|
|
||||||
|
void fix_perms()
|
||||||
|
{
|
||||||
|
ensure_path_mounted("/data");
|
||||||
|
ensure_path_mounted("/system");
|
||||||
|
//ui_show_progress(1,30);
|
||||||
|
ui_print("\n-- Fixing Permissions\n");
|
||||||
|
ui_print("This may take a few minutes.\n");
|
||||||
|
__system("./sbin/fix_permissions.sh");
|
||||||
|
ui_print("-- Done.\n\n");
|
||||||
|
//ui_reset_progress();
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_battery_level(void)
|
||||||
|
{
|
||||||
|
static int lastVal = -1;
|
||||||
|
static time_t nextSecCheck = 0;
|
||||||
|
|
||||||
|
struct timeval curTime;
|
||||||
|
gettimeofday(&curTime, NULL);
|
||||||
|
if (curTime.tv_sec > nextSecCheck)
|
||||||
|
{
|
||||||
|
char cap_s[4];
|
||||||
|
FILE * cap = fopen("/sys/class/power_supply/battery/capacity","rt");
|
||||||
|
if (cap)
|
||||||
|
{
|
||||||
|
fgets(cap_s, 4, cap);
|
||||||
|
fclose(cap);
|
||||||
|
lastVal = atoi(cap_s);
|
||||||
|
if (lastVal > 100) lastVal = 101;
|
||||||
|
if (lastVal < 0) lastVal = 0;
|
||||||
|
}
|
||||||
|
nextSecCheck = curTime.tv_sec + 60;
|
||||||
|
}
|
||||||
|
return lastVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
char*
|
||||||
|
print_batt_cap() {
|
||||||
|
char* full_cap_s = (char*)malloc(30);
|
||||||
|
char full_cap_a[30];
|
||||||
|
|
||||||
|
int cap_i = get_battery_level();
|
||||||
|
|
||||||
|
//int len = strlen(cap_s);
|
||||||
|
//if (cap_s[len-1] == '\n') {
|
||||||
|
// cap_s[len-1] = 0;
|
||||||
|
//}
|
||||||
|
|
||||||
|
// Get a usable time
|
||||||
|
struct tm *current;
|
||||||
|
time_t now;
|
||||||
|
now = time(0);
|
||||||
|
current = localtime(&now);
|
||||||
|
|
||||||
|
sprintf(full_cap_a, "Battery Level: %i%% @ %02D:%02D", cap_i, current->tm_hour, current->tm_min);
|
||||||
|
strcpy(full_cap_s, full_cap_a);
|
||||||
|
|
||||||
|
return full_cap_s;
|
||||||
|
}
|
||||||
|
|
||||||
|
void update_tz_environment_variables() {
|
||||||
|
setenv("TZ", DataManager_GetStrValue(TW_TIME_ZONE_VAR), 1);
|
||||||
|
tzset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void run_script(const char *str1, const char *str2, const char *str3, const char *str4, const char *str5, const char *str6, const char *str7, int request_confirm)
|
||||||
|
{
|
||||||
|
ui_print("%s", str1);
|
||||||
|
//ui_clear_key_queue();
|
||||||
|
ui_print("\nPress Power to confirm,");
|
||||||
|
ui_print("\nany other key to abort.\n");
|
||||||
|
int confirm;
|
||||||
|
/*if (request_confirm) // this option is used to skip the confirmation when the gui is in use
|
||||||
|
confirm = ui_wait_key();
|
||||||
|
else*/
|
||||||
|
confirm = KEY_POWER;
|
||||||
|
|
||||||
|
if (confirm == BTN_MOUSE || confirm == KEY_POWER || confirm == SELECT_ITEM) {
|
||||||
|
ui_print("%s", str2);
|
||||||
|
pid_t pid = fork();
|
||||||
|
if (pid == 0) {
|
||||||
|
char *args[] = { "/sbin/sh", "-c", (char*)str3, "1>&2", NULL };
|
||||||
|
execv("/sbin/sh", args);
|
||||||
|
fprintf(stderr, str4, strerror(errno));
|
||||||
|
_exit(-1);
|
||||||
|
}
|
||||||
|
int status;
|
||||||
|
while (waitpid(pid, &status, WNOHANG) == 0) {
|
||||||
|
ui_print(".");
|
||||||
|
sleep(1);
|
||||||
|
}
|
||||||
|
ui_print("\n");
|
||||||
|
if (!WIFEXITED(status) || (WEXITSTATUS(status) != 0)) {
|
||||||
|
ui_print("%s", str5);
|
||||||
|
} else {
|
||||||
|
ui_print("%s", str6);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ui_print("%s", str7);
|
||||||
|
}
|
||||||
|
//if (!ui_text_visible()) return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void install_htc_dumlock(void)
|
||||||
|
{
|
||||||
|
struct statfs fs1, fs2;
|
||||||
|
int need_libs = 0;
|
||||||
|
|
||||||
|
ui_print("Installing HTC Dumlock to system...\n");
|
||||||
|
ensure_path_mounted("/system");
|
||||||
|
__system("cp /res/htcd/htcdumlocksys /system/bin/htcdumlock && chmod 755 /system/bin/htcdumlock");
|
||||||
|
if (statfs("/system/bin/flash_image", &fs1) != 0) {
|
||||||
|
ui_print("Installing flash_image...\n");
|
||||||
|
__system("cp /res/htcd/flash_imagesys /system/bin/flash_image && chmod 755 /system/bin/flash_image");
|
||||||
|
need_libs = 1;
|
||||||
|
} else
|
||||||
|
ui_print("flash_image is already installed, skipping...\n");
|
||||||
|
if (statfs("/system/bin/dump_image", &fs2) != 0) {
|
||||||
|
ui_print("Installing dump_image...\n");
|
||||||
|
__system("cp /res/htcd/dump_imagesys /system/bin/dump_image && chmod 755 /system/bin/dump_image");
|
||||||
|
need_libs = 1;
|
||||||
|
} else
|
||||||
|
ui_print("dump_image is already installed, skipping...\n");
|
||||||
|
if (need_libs) {
|
||||||
|
ui_print("Installing libs needed for flash_image and dump_image...\n");
|
||||||
|
__system("cp /res/htcd/libbmlutils.so /system/lib && chmod 755 /system/lib/libbmlutils.so");
|
||||||
|
__system("cp /res/htcd/libflashutils.so /system/lib && chmod 755 /system/lib/libflashutils.so");
|
||||||
|
__system("cp /res/htcd/libmmcutils.so /system/lib && chmod 755 /system/lib/libmmcutils.so");
|
||||||
|
__system("cp /res/htcd/libmtdutils.so /system/lib && chmod 755 /system/lib/libmtdutils.so");
|
||||||
|
}
|
||||||
|
ui_print("Installing HTC Dumlock app...\n");
|
||||||
|
ensure_path_mounted("/data");
|
||||||
|
mkdir("/data/app", 0777);
|
||||||
|
__system("rm /data/app/com.teamwin.htcdumlock*");
|
||||||
|
__system("cp /res/htcd/HTCDumlock.apk /data/app/com.teamwin.htcdumlock.apk");
|
||||||
|
sync();
|
||||||
|
ui_print("HTC Dumlock is installed.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void htc_dumlock_restore_original_boot(void)
|
||||||
|
{
|
||||||
|
ui_print("Restoring original boot...\n");
|
||||||
|
__system("htcdumlock restore");
|
||||||
|
ui_print("Original boot restored.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void htc_dumlock_reflash_recovery_to_boot(void)
|
||||||
|
{
|
||||||
|
ui_print("Reflashing recovery to boot...\n");
|
||||||
|
__system("htcdumlock recovery noreboot");
|
||||||
|
ui_print("Recovery is flashed to boot.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void check_and_run_script(const char* script_file, const char* display_name)
|
||||||
|
{
|
||||||
|
// Check for and run startup script if script exists
|
||||||
|
struct statfs st;
|
||||||
|
if (statfs(script_file, &st) == 0) {
|
||||||
|
ui_print("Running %s script...\n", display_name);
|
||||||
|
char command[255];
|
||||||
|
strcpy(command, "chmod 755 ");
|
||||||
|
strcat(command, script_file);
|
||||||
|
__system(command);
|
||||||
|
__system(script_file);
|
||||||
|
ui_print("\nFinished running %s script.\n", display_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int check_backup_name(int show_error) {
|
||||||
|
// Check the backup name to ensure that it is the correct size and contains only valid characters
|
||||||
|
// and that a backup with that name doesn't already exist
|
||||||
|
char backup_name[MAX_BACKUP_NAME_LEN];
|
||||||
|
char backup_loc[255], tw_image_dir[255];
|
||||||
|
int copy_size = strlen(DataManager_GetStrValue(TW_BACKUP_NAME));
|
||||||
|
int index, cur_char;
|
||||||
|
struct statfs st;
|
||||||
|
|
||||||
|
// Check size
|
||||||
|
if (copy_size > MAX_BACKUP_NAME_LEN) {
|
||||||
|
if (show_error)
|
||||||
|
LOGE("Backup name is too long.\n");
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check characters
|
||||||
|
strncpy(backup_name, DataManager_GetStrValue(TW_BACKUP_NAME), copy_size);
|
||||||
|
if (strcmp(backup_name, "0") == 0)
|
||||||
|
return 0; // A "0" (zero) means to use the current timestamp for the backup name
|
||||||
|
for (index=0; index<copy_size; index++) {
|
||||||
|
cur_char = (int)backup_name[index];
|
||||||
|
if ((cur_char >= 48 && cur_char <= 57) || (cur_char >= 65 && cur_char <= 91) || cur_char == 93 || cur_char == 95 || (cur_char >= 97 && cur_char <= 123) || cur_char == 125 || cur_char == 45 || cur_char == 46) {
|
||||||
|
// These are valid characters
|
||||||
|
// Numbers
|
||||||
|
// Upper case letters
|
||||||
|
// Lower case letters
|
||||||
|
// and -_.{}[]
|
||||||
|
} else {
|
||||||
|
if (show_error)
|
||||||
|
LOGE("Backup name '%s' contains invalid character: '%c'\n", backup_name, (char)cur_char);
|
||||||
|
return -3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check to make sure that a backup with this name doesn't already exist
|
||||||
|
strcpy(backup_loc, DataManager_GetStrValue(TW_BACKUPS_FOLDER_VAR));
|
||||||
|
sprintf(tw_image_dir,"%s/%s/.", backup_loc, backup_name);
|
||||||
|
if (statfs(tw_image_dir, &st) == 0) {
|
||||||
|
if (show_error)
|
||||||
|
LOGE("A backup with this name already exists.\n");
|
||||||
|
return -4;
|
||||||
|
}
|
||||||
|
|
||||||
|
// No problems found, return 0
|
||||||
|
return 0;
|
||||||
|
}
|
36
extra-functions.h
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
#ifndef _EXTRAFUNCTIONS_HEADER
|
||||||
|
#define _EXTRAFUNCTIONS_HEADER
|
||||||
|
|
||||||
|
int __system(const char *command);
|
||||||
|
FILE * __popen(const char *program, const char *type);
|
||||||
|
int __pclose(FILE *iop);
|
||||||
|
|
||||||
|
// Device ID variable / function
|
||||||
|
char device_id[64];
|
||||||
|
void get_device_id();
|
||||||
|
static char* copy_sideloaded_package(const char* original_path);
|
||||||
|
int install_zip_package(const char* zip_path_filename);
|
||||||
|
|
||||||
|
void wipe_dalvik_cache();
|
||||||
|
void wipe_battery_stats();
|
||||||
|
void wipe_rotate_data();
|
||||||
|
|
||||||
|
static long tmplog_offset = 0;
|
||||||
|
|
||||||
|
// Battery level
|
||||||
|
char* print_batt_cap();
|
||||||
|
|
||||||
|
void update_tz_environment_variables();
|
||||||
|
|
||||||
|
void fix_perms();
|
||||||
|
|
||||||
|
void run_script(const char *str1, const char *str2, const char *str3, const char *str4, const char *str5, const char *str6, const char *str7, int request_confirm);
|
||||||
|
|
||||||
|
void install_htc_dumlock(void);
|
||||||
|
void htc_dumlock_restore_original_boot(void);
|
||||||
|
void htc_dumlock_reflash_recovery_to_boot(void);
|
||||||
|
|
||||||
|
void check_and_run_script(const char* script_file, const char* display_name);
|
||||||
|
int check_backup_name(int show_error);
|
||||||
|
|
||||||
|
#endif // _EXTRAFUNCTIONS_HEADER
|
131
firmware.c
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2008 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "bootloader.h"
|
||||||
|
#include "common.h"
|
||||||
|
#include "firmware.h"
|
||||||
|
#include "roots.h"
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/reboot.h>
|
||||||
|
|
||||||
|
static const char *update_type = NULL;
|
||||||
|
static const char *update_data = NULL;
|
||||||
|
static int update_length = 0;
|
||||||
|
|
||||||
|
int remember_firmware_update(const char *type, const char *data, int length) {
|
||||||
|
if (update_type != NULL || update_data != NULL) {
|
||||||
|
LOGE("Multiple firmware images\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
update_type = type;
|
||||||
|
update_data = data;
|
||||||
|
update_length = length;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return true if there is a firmware update pending.
|
||||||
|
int firmware_update_pending() {
|
||||||
|
return update_data != NULL && update_length > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Bootloader / Recovery Flow
|
||||||
|
*
|
||||||
|
* On every boot, the bootloader will read the bootloader_message
|
||||||
|
* from flash and check the command field. The bootloader should
|
||||||
|
* deal with the command field not having a 0 terminator correctly
|
||||||
|
* (so as to not crash if the block is invalid or corrupt).
|
||||||
|
*
|
||||||
|
* The bootloader will have to publish the partition that contains
|
||||||
|
* the bootloader_message to the linux kernel so it can update it.
|
||||||
|
*
|
||||||
|
* if command == "boot-recovery" -> boot recovery.img
|
||||||
|
* else if command == "update-radio" -> update radio image (below)
|
||||||
|
* else if command == "update-hboot" -> update hboot image (below)
|
||||||
|
* else -> boot boot.img (normal boot)
|
||||||
|
*
|
||||||
|
* Radio/Hboot Update Flow
|
||||||
|
* 1. the bootloader will attempt to load and validate the header
|
||||||
|
* 2. if the header is invalid, status="invalid-update", goto #8
|
||||||
|
* 3. display the busy image on-screen
|
||||||
|
* 4. if the update image is invalid, status="invalid-radio-image", goto #8
|
||||||
|
* 5. attempt to update the firmware (depending on the command)
|
||||||
|
* 6. if successful, status="okay", goto #8
|
||||||
|
* 7. if failed, and the old image can still boot, status="failed-update"
|
||||||
|
* 8. write the bootloader_message, leaving the recovery field
|
||||||
|
* unchanged, updating status, and setting command to
|
||||||
|
* "boot-recovery"
|
||||||
|
* 9. reboot
|
||||||
|
*
|
||||||
|
* The bootloader will not modify or erase the cache partition.
|
||||||
|
* It is recovery's responsibility to clean up the mess afterwards.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int maybe_install_firmware_update(const char *send_intent) {
|
||||||
|
if (update_data == NULL || update_length == 0) return 0;
|
||||||
|
|
||||||
|
/* We destroy the cache partition to pass the update image to the
|
||||||
|
* bootloader, so all we can really do afterwards is wipe cache and reboot.
|
||||||
|
* Set up this instruction now, in case we're interrupted while writing.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct bootloader_message boot;
|
||||||
|
memset(&boot, 0, sizeof(boot));
|
||||||
|
strlcpy(boot.command, "boot-recovery", sizeof(boot.command));
|
||||||
|
strlcpy(boot.recovery, "recovery\n--wipe_cache\n", sizeof(boot.command));
|
||||||
|
if (send_intent != NULL) {
|
||||||
|
strlcat(boot.recovery, "--send_intent=", sizeof(boot.recovery));
|
||||||
|
strlcat(boot.recovery, send_intent, sizeof(boot.recovery));
|
||||||
|
strlcat(boot.recovery, "\n", sizeof(boot.recovery));
|
||||||
|
}
|
||||||
|
if (set_bootloader_message(&boot)) return -1;
|
||||||
|
|
||||||
|
int width = 0, height = 0, bpp = 0;
|
||||||
|
char *busy_image = NULL;/*ui_copy_image(
|
||||||
|
BACKGROUND_ICON_FIRMWARE_INSTALLING, &width, &height, &bpp);*/
|
||||||
|
char *fail_image = NULL;/*ui_copy_image(
|
||||||
|
BACKGROUND_ICON_FIRMWARE_ERROR, &width, &height, &bpp);*/
|
||||||
|
|
||||||
|
ui_print("Writing %s image...\n", update_type);
|
||||||
|
if (write_update_for_bootloader(
|
||||||
|
update_data, update_length,
|
||||||
|
width, height, bpp, busy_image, fail_image)) {
|
||||||
|
LOGE("Can't write %s image\n(%s)\n", update_type, strerror(errno));
|
||||||
|
format_volume("/cache"); // Attempt to clean cache up, at least.
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(busy_image);
|
||||||
|
free(fail_image);
|
||||||
|
|
||||||
|
/* The update image is fully written, so now we can instruct the bootloader
|
||||||
|
* to install it. (After doing so, it will come back here, and we will
|
||||||
|
* wipe the cache and reboot into the system.)
|
||||||
|
*/
|
||||||
|
snprintf(boot.command, sizeof(boot.command), "update-%s", update_type);
|
||||||
|
if (set_bootloader_message(&boot)) {
|
||||||
|
format_volume("/cache");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
reboot(RB_AUTOBOOT);
|
||||||
|
|
||||||
|
// Can't reboot? WTF?
|
||||||
|
LOGE("Can't reboot\n");
|
||||||
|
return -1;
|
||||||
|
}
|
35
firmware.h
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2008 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _RECOVERY_FIRMWARE_H
|
||||||
|
#define _RECOVERY_FIRMWARE_H
|
||||||
|
|
||||||
|
/* Save a radio or bootloader update image for later installation.
|
||||||
|
* The type should be one of "hboot" or "radio".
|
||||||
|
* Takes ownership of type and data. Returns nonzero on error.
|
||||||
|
*/
|
||||||
|
int remember_firmware_update(const char *type, const char *data, int length);
|
||||||
|
|
||||||
|
/* Returns true if a firmware update has been saved. */
|
||||||
|
int firmware_update_pending();
|
||||||
|
|
||||||
|
/* If an update was saved, reboot into the bootloader now to install it.
|
||||||
|
* Returns 0 if no radio image was defined, nonzero on error,
|
||||||
|
* doesn't return at all on success...
|
||||||
|
*/
|
||||||
|
int maybe_install_firmware_update(const char *send_intent);
|
||||||
|
|
||||||
|
#endif
|
157
flashutils/Android.mk
Normal file
@ -0,0 +1,157 @@
|
|||||||
|
LOCAL_PATH := $(call my-dir)
|
||||||
|
|
||||||
|
ifneq ($(TARGET_SIMULATOR),true)
|
||||||
|
ifeq ($(TARGET_ARCH),arm)
|
||||||
|
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
LOCAL_SRC_FILES := flashutils.c
|
||||||
|
LOCAL_MODULE := libflashutils
|
||||||
|
LOCAL_MODULE_TAGS := optional
|
||||||
|
LOCAL_C_INCLUDES += bootable/recovery
|
||||||
|
LOCAL_STATIC_LIBRARIES := libmmcutils libmtdutils libbmlutils libcrecovery
|
||||||
|
|
||||||
|
BOARD_RECOVERY_DEFINES := BOARD_BML_BOOT BOARD_BML_RECOVERY
|
||||||
|
|
||||||
|
$(foreach board_define,$(BOARD_RECOVERY_DEFINES), \
|
||||||
|
$(if $($(board_define)), \
|
||||||
|
$(eval LOCAL_CFLAGS += -D$(board_define)=\"$($(board_define))\") \
|
||||||
|
) \
|
||||||
|
)
|
||||||
|
|
||||||
|
include $(BUILD_STATIC_LIBRARY)
|
||||||
|
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
LOCAL_SRC_FILES := flash_image.c
|
||||||
|
LOCAL_MODULE := flash_image
|
||||||
|
LOCAL_MODULE_TAGS := optional
|
||||||
|
LOCAL_STATIC_LIBRARIES := libflashutils libmtdutils libmmcutils libbmlutils libcrecovery
|
||||||
|
LOCAL_SHARED_LIBRARIES := libcutils libc
|
||||||
|
include $(BUILD_EXECUTABLE)
|
||||||
|
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
LOCAL_SRC_FILES := dump_image.c
|
||||||
|
LOCAL_MODULE := dump_image
|
||||||
|
LOCAL_MODULE_TAGS := optional
|
||||||
|
LOCAL_STATIC_LIBRARIES := libflashutils libmtdutils libmmcutils libbmlutils libcrecovery
|
||||||
|
LOCAL_SHARED_LIBRARIES := libcutils libc
|
||||||
|
include $(BUILD_EXECUTABLE)
|
||||||
|
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
LOCAL_SRC_FILES := erase_image.c
|
||||||
|
LOCAL_MODULE := erase_image
|
||||||
|
LOCAL_MODULE_TAGS := optional
|
||||||
|
LOCAL_STATIC_LIBRARIES := libflashutils libmtdutils libmmcutils libbmlutils libcrecovery
|
||||||
|
LOCAL_SHARED_LIBRARIES := libcutils libc
|
||||||
|
include $(BUILD_EXECUTABLE)
|
||||||
|
|
||||||
|
ALL_DEFAULT_INSTALLED_MODULES += $(addprefix $(TARGET_OUT)/bin/, flash_image dump_image erase_image)
|
||||||
|
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
LOCAL_SRC_FILES := flash_image.c
|
||||||
|
LOCAL_MODULE := libflash_image
|
||||||
|
LOCAL_MODULE_TAGS := optional
|
||||||
|
LOCAL_CFLAGS += -Dmain=flash_image_main
|
||||||
|
include $(BUILD_STATIC_LIBRARY)
|
||||||
|
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
LOCAL_SRC_FILES := dump_image.c
|
||||||
|
LOCAL_MODULE := libdump_image
|
||||||
|
LOCAL_MODULE_TAGS := optional
|
||||||
|
LOCAL_CFLAGS += -Dmain=dump_image_main
|
||||||
|
include $(BUILD_STATIC_LIBRARY)
|
||||||
|
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
LOCAL_SRC_FILES := erase_image.c
|
||||||
|
LOCAL_MODULE := liberase_image
|
||||||
|
LOCAL_MODULE_TAGS := optional
|
||||||
|
LOCAL_CFLAGS += -Dmain=erase_image_main
|
||||||
|
include $(BUILD_STATIC_LIBRARY)
|
||||||
|
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
LOCAL_SRC_FILES := dump_image.c
|
||||||
|
LOCAL_MODULE := utility_dump_image
|
||||||
|
LOCAL_MODULE_TAGS := optional
|
||||||
|
LOCAL_MODULE_CLASS := UTILITY_EXECUTABLES
|
||||||
|
LOCAL_MODULE_PATH := $(PRODUCT_OUT)/utilities
|
||||||
|
LOCAL_UNSTRIPPED_PATH := $(PRODUCT_OUT)/symbols/utilities
|
||||||
|
LOCAL_MODULE_STEM := dump_image
|
||||||
|
LOCAL_STATIC_LIBRARIES := libflashutils libmtdutils libmmcutils libbmlutils libcutils libc
|
||||||
|
LOCAL_FORCE_STATIC_EXECUTABLE := true
|
||||||
|
include $(BUILD_EXECUTABLE)
|
||||||
|
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
LOCAL_SRC_FILES := flash_image.c
|
||||||
|
LOCAL_MODULE := utility_flash_image
|
||||||
|
LOCAL_MODULE_TAGS := optional
|
||||||
|
LOCAL_MODULE_CLASS := UTILITY_EXECUTABLES
|
||||||
|
LOCAL_MODULE_PATH := $(PRODUCT_OUT)/utilities
|
||||||
|
LOCAL_UNSTRIPPED_PATH := $(PRODUCT_OUT)/symbols/utilities
|
||||||
|
LOCAL_MODULE_STEM := flash_image
|
||||||
|
LOCAL_STATIC_LIBRARIES := libflashutils libmtdutils libmmcutils libbmlutils libcutils libc
|
||||||
|
LOCAL_FORCE_STATIC_EXECUTABLE := true
|
||||||
|
include $(BUILD_EXECUTABLE)
|
||||||
|
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
LOCAL_SRC_FILES := erase_image.c
|
||||||
|
LOCAL_MODULE := utility_erase_image
|
||||||
|
LOCAL_MODULE_TAGS := optional
|
||||||
|
LOCAL_MODULE_CLASS := UTILITY_EXECUTABLES
|
||||||
|
LOCAL_MODULE_PATH := $(PRODUCT_OUT)/utilities
|
||||||
|
LOCAL_UNSTRIPPED_PATH := $(PRODUCT_OUT)/symbols/utilities
|
||||||
|
LOCAL_MODULE_STEM := erase_image
|
||||||
|
LOCAL_STATIC_LIBRARIES := libflashutils libmtdutils libmmcutils libbmlutils libcutils libc
|
||||||
|
LOCAL_FORCE_STATIC_EXECUTABLE := true
|
||||||
|
include $(BUILD_EXECUTABLE)
|
||||||
|
|
||||||
|
#Added for dynamic building for TWRP:
|
||||||
|
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
LOCAL_SRC_FILES := flashutils.c
|
||||||
|
LOCAL_MODULE := libflashutils
|
||||||
|
LOCAL_MODULE_TAGS := eng
|
||||||
|
LOCAL_C_INCLUDES += bootable/recovery
|
||||||
|
LOCAL_SHARED_LIBRARIES := libc libmmcutils libbmlutils
|
||||||
|
LOCAL_STATIC_LIBRARIES := libmtdutils
|
||||||
|
|
||||||
|
BOARD_RECOVERY_DEFINES := BOARD_BML_BOOT BOARD_BML_RECOVERY
|
||||||
|
|
||||||
|
$(foreach board_define,$(BOARD_RECOVERY_DEFINES), \
|
||||||
|
$(if $($(board_define)), \
|
||||||
|
$(eval LOCAL_CFLAGS += -D$(board_define)=\"$($(board_define))\") \
|
||||||
|
) \
|
||||||
|
)
|
||||||
|
|
||||||
|
include $(BUILD_SHARED_LIBRARY)
|
||||||
|
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
LOCAL_MODULE := flash_image
|
||||||
|
LOCAL_MODULE_TAGS := eng
|
||||||
|
LOCAL_MODULE_CLASS := RECOVERY_EXECUTABLES
|
||||||
|
LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/sbin
|
||||||
|
LOCAL_SRC_FILES := flash_image.c
|
||||||
|
LOCAL_SHARED_LIBRARIES := libflashutils libmmcutils libbmlutils libcutils libc
|
||||||
|
LOCAL_STATIC_LIBRARIES := libmtdutils
|
||||||
|
include $(BUILD_EXECUTABLE)
|
||||||
|
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
LOCAL_MODULE := dump_image
|
||||||
|
LOCAL_MODULE_TAGS := eng
|
||||||
|
LOCAL_MODULE_CLASS := RECOVERY_EXECUTABLES
|
||||||
|
LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/sbin
|
||||||
|
LOCAL_SRC_FILES := dump_image.c
|
||||||
|
LOCAL_SHARED_LIBRARIES := libflashutils libmmcutils libbmlutils libcutils libc
|
||||||
|
LOCAL_STATIC_LIBRARIES := libmtdutils
|
||||||
|
include $(BUILD_EXECUTABLE)
|
||||||
|
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
LOCAL_MODULE := erase_image
|
||||||
|
LOCAL_MODULE_TAGS := eng
|
||||||
|
LOCAL_MODULE_CLASS := RECOVERY_EXECUTABLES
|
||||||
|
LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/sbin
|
||||||
|
LOCAL_SRC_FILES := erase_image.c
|
||||||
|
LOCAL_SHARED_LIBRARIES := libflashutils libmmcutils libbmlutils libcutils libc
|
||||||
|
LOCAL_STATIC_LIBRARIES := libmtdutils
|
||||||
|
include $(BUILD_EXECUTABLE)
|
||||||
|
|
||||||
|
endif # TARGET_ARCH == arm
|
||||||
|
endif # !TARGET_SIMULATOR
|
150
flashutils/dump_image.c
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2008 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
|
||||||
|
#include "cutils/log.h"
|
||||||
|
#include "flashutils.h"
|
||||||
|
|
||||||
|
#ifdef LOG_TAG
|
||||||
|
#undef LOG_TAG
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
|
||||||
|
#define LOG_TAG "dump_image"
|
||||||
|
|
||||||
|
#define BLOCK_SIZE 2048
|
||||||
|
#define SPARE_SIZE (BLOCK_SIZE >> 5)
|
||||||
|
|
||||||
|
static int die(const char *msg, ...) {
|
||||||
|
int err = errno;
|
||||||
|
va_list args;
|
||||||
|
va_start(args, msg);
|
||||||
|
char buf[1024];
|
||||||
|
vsnprintf(buf, sizeof(buf), msg, args);
|
||||||
|
va_end(args);
|
||||||
|
|
||||||
|
if (err != 0) {
|
||||||
|
strlcat(buf, ": ", sizeof(buf));
|
||||||
|
strlcat(buf, strerror(err), sizeof(buf));
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stderr, "%s\n", buf);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read a flash partition and write it to an image file. */
|
||||||
|
|
||||||
|
int dump_image(char* partition_name, char* filename, dump_image_callback callback) {
|
||||||
|
MtdReadContext *in;
|
||||||
|
const MtdPartition *partition;
|
||||||
|
char buf[BLOCK_SIZE + SPARE_SIZE];
|
||||||
|
size_t partition_size;
|
||||||
|
size_t read_size;
|
||||||
|
size_t total;
|
||||||
|
int fd;
|
||||||
|
int wrote;
|
||||||
|
int len;
|
||||||
|
|
||||||
|
if (mtd_scan_partitions() <= 0)
|
||||||
|
return die("error scanning partitions");
|
||||||
|
|
||||||
|
partition = mtd_find_partition_by_name(partition_name);
|
||||||
|
if (partition == NULL)
|
||||||
|
return die("can't find %s partition", partition_name);
|
||||||
|
|
||||||
|
if (mtd_partition_info(partition, &partition_size, NULL, NULL)) {
|
||||||
|
return die("can't get info of partition %s", partition_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strcmp(filename, "-")) {
|
||||||
|
fd = fileno(stdout);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
fd = open(filename, O_WRONLY|O_CREAT|O_TRUNC, 0666);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fd < 0)
|
||||||
|
return die("error opening %s", filename);
|
||||||
|
|
||||||
|
in = mtd_read_partition(partition);
|
||||||
|
if (in == NULL) {
|
||||||
|
close(fd);
|
||||||
|
unlink(filename);
|
||||||
|
return die("error opening %s: %s\n", partition_name, strerror(errno));
|
||||||
|
}
|
||||||
|
|
||||||
|
total = 0;
|
||||||
|
while ((len = mtd_read_data(in, buf, BLOCK_SIZE)) > 0) {
|
||||||
|
wrote = write(fd, buf, len);
|
||||||
|
if (wrote != len) {
|
||||||
|
close(fd);
|
||||||
|
unlink(filename);
|
||||||
|
return die("error writing %s", filename);
|
||||||
|
}
|
||||||
|
total += BLOCK_SIZE;
|
||||||
|
if (callback != NULL)
|
||||||
|
callback(total, partition_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
mtd_read_close(in);
|
||||||
|
|
||||||
|
if (close(fd)) {
|
||||||
|
unlink(filename);
|
||||||
|
return die("error closing %s", filename);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
ssize_t (*read_func) (MtdReadContext *, char *, size_t);
|
||||||
|
MtdReadContext *in;
|
||||||
|
const MtdPartition *partition;
|
||||||
|
char buf[BLOCK_SIZE + SPARE_SIZE];
|
||||||
|
size_t partition_size;
|
||||||
|
size_t read_size;
|
||||||
|
size_t total;
|
||||||
|
int fd;
|
||||||
|
int wrote;
|
||||||
|
int len;
|
||||||
|
|
||||||
|
if (argc != 3) {
|
||||||
|
fprintf(stderr, "usage: %s partition file.img\n", argv[0]);
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
return dump_image(argv[1], argv[2], NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
if (argc != 3) {
|
||||||
|
fprintf(stderr, "usage: %s partition file.img\n", argv[0]);
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
return backup_raw_partition(NULL, argv[1], argv[2]);
|
||||||
|
}
|
103
flashutils/erase_image.c
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2008 The Android Open Source Project
|
||||||
|
* Portions Copyright (C) 2010 Magnus Eriksson <packetlss@gmail.com>
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
#include "cutils/log.h"
|
||||||
|
#include "flashutils.h"
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
|
||||||
|
#ifdef LOG_TAG
|
||||||
|
#undef LOG_TAG
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#define LOG_TAG "erase_image"
|
||||||
|
|
||||||
|
static int die(const char *msg, ...) {
|
||||||
|
int err = errno;
|
||||||
|
va_list args;
|
||||||
|
va_start(args, msg);
|
||||||
|
char buf[1024];
|
||||||
|
vsnprintf(buf, sizeof(buf), msg, args);
|
||||||
|
va_end(args);
|
||||||
|
|
||||||
|
if (err != 0) {
|
||||||
|
strlcat(buf, ": ", sizeof(buf));
|
||||||
|
strlcat(buf, strerror(err), sizeof(buf));
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stderr, "%s\n", buf);
|
||||||
|
LOGE("%s\n", buf);
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int erase_image(char* partition_name) {
|
||||||
|
MtdWriteContext *out;
|
||||||
|
size_t erased;
|
||||||
|
size_t total_size;
|
||||||
|
size_t erase_size;
|
||||||
|
|
||||||
|
if (mtd_scan_partitions() <= 0) die("error scanning partitions");
|
||||||
|
const MtdPartition *partition = mtd_find_partition_by_name(partition_name);
|
||||||
|
if (partition == NULL) return die("can't find %s partition", partition_name);
|
||||||
|
|
||||||
|
out = mtd_write_partition(partition);
|
||||||
|
if (out == NULL) return die("could not estabilish write context for %s", partition_name);
|
||||||
|
|
||||||
|
// do the actual erase, -1 = full partition erase
|
||||||
|
erased = mtd_erase_blocks(out, -1);
|
||||||
|
|
||||||
|
// erased = bytes erased, if zero, something borked
|
||||||
|
if (!erased) return die("error erasing %s", partition_name);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Erase a mtd partition */
|
||||||
|
|
||||||
|
int main(int argc, char **argv) {
|
||||||
|
if (argc != 2) {
|
||||||
|
fprintf(stderr, "usage: %s <partition>\n", argv[0]);
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
return erase_image(argv[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
if (argc != 2) {
|
||||||
|
fprintf(stderr, "usage: %s partition\n", argv[0]);
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
return erase_raw_partition(NULL, argv[1]);
|
||||||
|
}
|
155
flashutils/flash_image.c
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2008 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "cutils/log.h"
|
||||||
|
#include "flashutils.h"
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
#define LOG_TAG "flash_image"
|
||||||
|
|
||||||
|
#define HEADER_SIZE 2048 // size of header to compare for equality
|
||||||
|
|
||||||
|
void die(const char *msg, ...) {
|
||||||
|
int err = errno;
|
||||||
|
va_list args;
|
||||||
|
va_start(args, msg);
|
||||||
|
char buf[1024];
|
||||||
|
vsnprintf(buf, sizeof(buf), msg, args);
|
||||||
|
va_end(args);
|
||||||
|
|
||||||
|
if (err != 0) {
|
||||||
|
strlcat(buf, ": ", sizeof(buf));
|
||||||
|
strlcat(buf, strerror(err), sizeof(buf));
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stderr, "%s\n", buf);
|
||||||
|
LOGE("%s\n", buf);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read an image file and write it to a flash partition. */
|
||||||
|
|
||||||
|
int main(int argc, char **argv) {
|
||||||
|
const MtdPartition *ptn;
|
||||||
|
MtdWriteContext *write;
|
||||||
|
void *data;
|
||||||
|
unsigned sz;
|
||||||
|
|
||||||
|
if (argc != 3) {
|
||||||
|
fprintf(stderr, "usage: %s partition file.img\n", argv[0]);
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mtd_scan_partitions() <= 0) die("error scanning partitions");
|
||||||
|
const MtdPartition *partition = mtd_find_partition_by_name(argv[1]);
|
||||||
|
if (partition == NULL) die("can't find %s partition", argv[1]);
|
||||||
|
|
||||||
|
// If the first part of the file matches the partition, skip writing
|
||||||
|
|
||||||
|
int fd = open(argv[2], O_RDONLY);
|
||||||
|
if (fd < 0) die("error opening %s", argv[2]);
|
||||||
|
|
||||||
|
char header[HEADER_SIZE];
|
||||||
|
int headerlen = read(fd, header, sizeof(header));
|
||||||
|
if (headerlen <= 0) die("error reading %s header", argv[2]);
|
||||||
|
|
||||||
|
MtdReadContext *in = mtd_read_partition(partition);
|
||||||
|
if (in == NULL) {
|
||||||
|
LOGW("error opening %s: %s\n", argv[1], strerror(errno));
|
||||||
|
// just assume it needs re-writing
|
||||||
|
} else {
|
||||||
|
char check[HEADER_SIZE];
|
||||||
|
int checklen = mtd_read_data(in, check, sizeof(check));
|
||||||
|
if (checklen <= 0) {
|
||||||
|
LOGW("error reading %s: %s\n", argv[1], strerror(errno));
|
||||||
|
// just assume it needs re-writing
|
||||||
|
} else if (checklen == headerlen && !memcmp(header, check, headerlen)) {
|
||||||
|
LOGI("header is the same, not flashing %s\n", argv[1]);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
mtd_read_close(in);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip the header (we'll come back to it), write everything else
|
||||||
|
LOGI("flashing %s from %s\n", argv[1], argv[2]);
|
||||||
|
|
||||||
|
MtdWriteContext *out = mtd_write_partition(partition);
|
||||||
|
if (out == NULL) die("error writing %s", argv[1]);
|
||||||
|
|
||||||
|
char buf[HEADER_SIZE];
|
||||||
|
memset(buf, 0, headerlen);
|
||||||
|
int wrote = mtd_write_data(out, buf, headerlen);
|
||||||
|
if (wrote != headerlen) die("error writing %s", argv[1]);
|
||||||
|
|
||||||
|
int len;
|
||||||
|
while ((len = read(fd, buf, sizeof(buf))) > 0) {
|
||||||
|
wrote = mtd_write_data(out, buf, len);
|
||||||
|
if (wrote != len) die("error writing %s", argv[1]);
|
||||||
|
}
|
||||||
|
if (len < 0) die("error reading %s", argv[2]);
|
||||||
|
|
||||||
|
if (mtd_write_close(out)) die("error closing %s", argv[1]);
|
||||||
|
|
||||||
|
// Now come back and write the header last
|
||||||
|
|
||||||
|
out = mtd_write_partition(partition);
|
||||||
|
if (out == NULL) die("error re-opening %s", argv[1]);
|
||||||
|
|
||||||
|
wrote = mtd_write_data(out, header, headerlen);
|
||||||
|
if (wrote != headerlen) die("error re-writing %s", argv[1]);
|
||||||
|
|
||||||
|
// Need to write a complete block, so write the rest of the first block
|
||||||
|
size_t block_size;
|
||||||
|
if (mtd_partition_info(partition, NULL, &block_size, NULL))
|
||||||
|
die("error getting %s block size", argv[1]);
|
||||||
|
|
||||||
|
if (lseek(fd, headerlen, SEEK_SET) != headerlen)
|
||||||
|
die("error rewinding %s", argv[2]);
|
||||||
|
|
||||||
|
int left = block_size - headerlen;
|
||||||
|
while (left < 0) left += block_size;
|
||||||
|
while (left > 0) {
|
||||||
|
len = read(fd, buf, left > (int)sizeof(buf) ? (int)sizeof(buf) : left);
|
||||||
|
if (len <= 0) die("error reading %s", argv[2]);
|
||||||
|
if (mtd_write_data(out, buf, len) != len)
|
||||||
|
die("error writing %s", argv[1]);
|
||||||
|
left -= len;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mtd_write_close(out)) die("error closing %s", argv[1]);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
if (argc != 3) {
|
||||||
|
fprintf(stderr, "usage: %s partition file.img\n", argv[0]);
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ret = restore_raw_partition(NULL, argv[1], argv[2]);
|
||||||
|
if (ret != 0)
|
||||||
|
fprintf(stderr, "failed with error: %d\n", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
156
flashutils/flashutils.c
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
#include <signal.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "flashutils/flashutils.h"
|
||||||
|
|
||||||
|
#ifndef BOARD_BML_BOOT
|
||||||
|
#define BOARD_BML_BOOT "/dev/block/bml7"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef BOARD_BML_RECOVERY
|
||||||
|
#define BOARD_BML_RECOVERY "/dev/block/bml8"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int the_flash_type = UNKNOWN;
|
||||||
|
|
||||||
|
int device_flash_type()
|
||||||
|
{
|
||||||
|
if (the_flash_type == UNKNOWN) {
|
||||||
|
if (access(BOARD_BML_BOOT, F_OK) == 0) {
|
||||||
|
the_flash_type = BML;
|
||||||
|
} else if (access("/proc/emmc", F_OK) == 0) {
|
||||||
|
the_flash_type = MMC;
|
||||||
|
} else if (access("/proc/mtd", F_OK) == 0) {
|
||||||
|
the_flash_type = MTD;
|
||||||
|
} else {
|
||||||
|
the_flash_type = UNSUPPORTED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return the_flash_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* get_default_filesystem()
|
||||||
|
{
|
||||||
|
return device_flash_type() == MMC ? "ext3" : "yaffs2";
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_flash_type(const char* partitionType) {
|
||||||
|
int type = UNSUPPORTED;
|
||||||
|
if (strcmp(partitionType, "mtd") == 0)
|
||||||
|
type = MTD;
|
||||||
|
else if (strcmp(partitionType, "emmc") == 0)
|
||||||
|
type = MMC;
|
||||||
|
else if (strcmp(partitionType, "bml") == 0)
|
||||||
|
type = BML;
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int detect_partition(const char *partitionType, const char *partition)
|
||||||
|
{
|
||||||
|
int type = device_flash_type();
|
||||||
|
if (strstr(partition, "/dev/block/mtd") != NULL)
|
||||||
|
type = MTD;
|
||||||
|
else if (strstr(partition, "/dev/block/mmc") != NULL)
|
||||||
|
type = MMC;
|
||||||
|
else if (strstr(partition, "/dev/block/bml") != NULL)
|
||||||
|
type = BML;
|
||||||
|
|
||||||
|
if (partitionType != NULL) {
|
||||||
|
type = get_flash_type(partitionType);
|
||||||
|
}
|
||||||
|
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
int restore_raw_partition(const char* partitionType, const char *partition, const char *filename)
|
||||||
|
{
|
||||||
|
int type = detect_partition(partitionType, partition);
|
||||||
|
switch (type) {
|
||||||
|
case MTD:
|
||||||
|
return cmd_mtd_restore_raw_partition(partition, filename);
|
||||||
|
case MMC:
|
||||||
|
return cmd_mmc_restore_raw_partition(partition, filename);
|
||||||
|
case BML:
|
||||||
|
return cmd_bml_restore_raw_partition(partition, filename);
|
||||||
|
default:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int backup_raw_partition(const char* partitionType, const char *partition, const char *filename)
|
||||||
|
{
|
||||||
|
int type = detect_partition(partitionType, partition);
|
||||||
|
switch (type) {
|
||||||
|
case MTD:
|
||||||
|
return cmd_mtd_backup_raw_partition(partition, filename);
|
||||||
|
case MMC:
|
||||||
|
return cmd_mmc_backup_raw_partition(partition, filename);
|
||||||
|
case BML:
|
||||||
|
return cmd_bml_backup_raw_partition(partition, filename);
|
||||||
|
default:
|
||||||
|
printf("unable to detect device type");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int erase_raw_partition(const char* partitionType, const char *partition)
|
||||||
|
{
|
||||||
|
int type = detect_partition(partitionType, partition);
|
||||||
|
switch (type) {
|
||||||
|
case MTD:
|
||||||
|
return cmd_mtd_erase_raw_partition(partition);
|
||||||
|
case MMC:
|
||||||
|
return cmd_mmc_erase_raw_partition(partition);
|
||||||
|
case BML:
|
||||||
|
return cmd_bml_erase_raw_partition(partition);
|
||||||
|
default:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int erase_partition(const char *partition, const char *filesystem)
|
||||||
|
{
|
||||||
|
int type = detect_partition(NULL, partition);
|
||||||
|
switch (type) {
|
||||||
|
case MTD:
|
||||||
|
return cmd_mtd_erase_partition(partition, filesystem);
|
||||||
|
case MMC:
|
||||||
|
return cmd_mmc_erase_partition(partition, filesystem);
|
||||||
|
case BML:
|
||||||
|
return cmd_bml_erase_partition(partition, filesystem);
|
||||||
|
default:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int mount_partition(const char *partition, const char *mount_point, const char *filesystem, int read_only)
|
||||||
|
{
|
||||||
|
int type = detect_partition(NULL, partition);
|
||||||
|
switch (type) {
|
||||||
|
case MTD:
|
||||||
|
return cmd_mtd_mount_partition(partition, mount_point, filesystem, read_only);
|
||||||
|
case MMC:
|
||||||
|
return cmd_mmc_mount_partition(partition, mount_point, filesystem, read_only);
|
||||||
|
case BML:
|
||||||
|
return cmd_bml_mount_partition(partition, mount_point, filesystem, read_only);
|
||||||
|
default:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_partition_device(const char *partition, char *device)
|
||||||
|
{
|
||||||
|
int type = device_flash_type();
|
||||||
|
switch (type) {
|
||||||
|
case MTD:
|
||||||
|
return cmd_mtd_get_partition_device(partition, device);
|
||||||
|
case MMC:
|
||||||
|
return cmd_mmc_get_partition_device(partition, device);
|
||||||
|
case BML:
|
||||||
|
return cmd_bml_get_partition_device(partition, device);
|
||||||
|
default:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
50
flashutils/flashutils.h
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
#ifndef FLASHUTILS_H
|
||||||
|
#define FLASHUTILS_H
|
||||||
|
|
||||||
|
int restore_raw_partition(const char* partitionType, const char *partition, const char *filename);
|
||||||
|
int backup_raw_partition(const char* partitionType, const char *partition, const char *filename);
|
||||||
|
int erase_raw_partition(const char* partitionType, const char *partition);
|
||||||
|
int erase_partition(const char *partition, const char *filesystem);
|
||||||
|
int mount_partition(const char *partition, const char *mount_point, const char *filesystem, int read_only);
|
||||||
|
int get_partition_device(const char *partition, char *device);
|
||||||
|
|
||||||
|
#define FLASH_MTD 0
|
||||||
|
#define FLASH_MMC 1
|
||||||
|
#define FLASH_BML 2
|
||||||
|
|
||||||
|
int is_mtd_device();
|
||||||
|
char* get_default_filesystem();
|
||||||
|
|
||||||
|
extern int cmd_mtd_restore_raw_partition(const char *partition, const char *filename);
|
||||||
|
extern int cmd_mtd_backup_raw_partition(const char *partition, const char *filename);
|
||||||
|
extern int cmd_mtd_erase_raw_partition(const char *partition);
|
||||||
|
extern int cmd_mtd_erase_partition(const char *partition, const char *filesystem);
|
||||||
|
extern int cmd_mtd_mount_partition(const char *partition, const char *mount_point, const char *filesystem, int read_only);
|
||||||
|
extern int cmd_mtd_get_partition_device(const char *partition, char *device);
|
||||||
|
|
||||||
|
extern int cmd_mmc_restore_raw_partition(const char *partition, const char *filename);
|
||||||
|
extern int cmd_mmc_backup_raw_partition(const char *partition, const char *filename);
|
||||||
|
extern int cmd_mmc_erase_raw_partition(const char *partition);
|
||||||
|
extern int cmd_mmc_erase_partition(const char *partition, const char *filesystem);
|
||||||
|
extern int cmd_mmc_mount_partition(const char *partition, const char *mount_point, const char *filesystem, int read_only);
|
||||||
|
extern int cmd_mmc_get_partition_device(const char *partition, char *device);
|
||||||
|
|
||||||
|
extern int cmd_bml_restore_raw_partition(const char *partition, const char *filename);
|
||||||
|
extern int cmd_bml_backup_raw_partition(const char *partition, const char *filename);
|
||||||
|
extern int cmd_bml_erase_raw_partition(const char *partition);
|
||||||
|
extern int cmd_bml_erase_partition(const char *partition, const char *filesystem);
|
||||||
|
extern int cmd_bml_mount_partition(const char *partition, const char *mount_point, const char *filesystem, int read_only);
|
||||||
|
extern int cmd_bml_get_partition_device(const char *partition, char *device);
|
||||||
|
|
||||||
|
extern int device_flash_type();
|
||||||
|
extern int get_flash_type(const char* fs_type);
|
||||||
|
|
||||||
|
enum flash_type {
|
||||||
|
UNSUPPORTED = -1,
|
||||||
|
UNKNOWN = 0,
|
||||||
|
MTD = 1,
|
||||||
|
MMC = 2,
|
||||||
|
BML = 3
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
70
gui/Android.mk
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
LOCAL_PATH := $(call my-dir)
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
|
||||||
|
LOCAL_SRC_FILES := \
|
||||||
|
gui.cpp \
|
||||||
|
resources.cpp \
|
||||||
|
pages.cpp \
|
||||||
|
text.cpp \
|
||||||
|
image.cpp \
|
||||||
|
action.cpp \
|
||||||
|
console.cpp \
|
||||||
|
fill.cpp \
|
||||||
|
button.cpp \
|
||||||
|
checkbox.cpp \
|
||||||
|
fileselector.cpp \
|
||||||
|
progressbar.cpp \
|
||||||
|
animation.cpp \
|
||||||
|
conditional.cpp \
|
||||||
|
slider.cpp \
|
||||||
|
listbox.cpp \
|
||||||
|
keyboard.cpp \
|
||||||
|
input.cpp \
|
||||||
|
|
||||||
|
ifneq ($(TWRP_CUSTOM_KEYBOARD),)
|
||||||
|
LOCAL_SRC_FILES += $(TWRP_CUSTOM_KEYBOARD)
|
||||||
|
else
|
||||||
|
LOCAL_SRC_FILES += hardwarekeyboard.cpp
|
||||||
|
endif
|
||||||
|
|
||||||
|
LOCAL_MODULE := libgui
|
||||||
|
|
||||||
|
# Use this flag to create a build that simulates threaded actions like installing zips, backups, restores, and wipes for theme testing
|
||||||
|
#TWRP_SIMULATE_ACTIONS := true
|
||||||
|
ifeq ($(TWRP_SIMULATE_ACTIONS), true)
|
||||||
|
LOCAL_CFLAGS += -D_SIMULATE_ACTIONS
|
||||||
|
endif
|
||||||
|
|
||||||
|
#TWRP_EVENT_LOGGING := true
|
||||||
|
ifeq ($(TWRP_EVENT_LOGGING), true)
|
||||||
|
LOCAL_CFLAGS += -D_EVENT_LOGGING
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifneq ($(RECOVERY_SDCARD_ON_DATA),)
|
||||||
|
LOCAL_CFLAGS += -DRECOVERY_SDCARD_ON_DATA
|
||||||
|
endif
|
||||||
|
|
||||||
|
LOCAL_C_INCLUDES += bionic external/stlport/stlport $(commands_recovery_local_path)/gui/devices/$(DEVICE_RESOLUTION)
|
||||||
|
|
||||||
|
include $(BUILD_STATIC_LIBRARY)
|
||||||
|
|
||||||
|
# Transfer in the resources for the device
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
LOCAL_MODULE := twrp
|
||||||
|
LOCAL_MODULE_TAGS := eng
|
||||||
|
LOCAL_MODULE_CLASS := RECOVERY_EXECUTABLES
|
||||||
|
LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/res
|
||||||
|
|
||||||
|
TWRP_RES_LOC := $(commands_recovery_local_path)/gui/devices
|
||||||
|
TWRP_RES_GEN := $(intermediates)/twrp
|
||||||
|
|
||||||
|
$(TWRP_RES_GEN):
|
||||||
|
mkdir -p $(TARGET_RECOVERY_ROOT_OUT)/res/
|
||||||
|
cp -fr $(TWRP_RES_LOC)/common/res/* $(TARGET_RECOVERY_ROOT_OUT)/res/
|
||||||
|
cp -fr $(TWRP_RES_LOC)/$(DEVICE_RESOLUTION)/res/* $(TARGET_RECOVERY_ROOT_OUT)/res/
|
||||||
|
mkdir -p $(TARGET_RECOVERY_ROOT_OUT)/sbin/
|
||||||
|
ln -sf /sbin/busybox $(TARGET_RECOVERY_ROOT_OUT)/sbin/sh
|
||||||
|
|
||||||
|
LOCAL_GENERATED_SOURCES := $(TWRP_RES_GEN)
|
||||||
|
LOCAL_SRC_FILES := twrp $(TWRP_RES_GEN)
|
||||||
|
include $(BUILD_PREBUILT)
|
1134
gui/action.cpp
Normal file
137
gui/animation.cpp
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
// animation.cpp - GUIAnimation object
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <sys/reboot.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include "../common.h"
|
||||||
|
#include "../minuitwrp/minui.h"
|
||||||
|
#include "../recovery_ui.h"
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "rapidxml.hpp"
|
||||||
|
#include "objects.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
GUIAnimation::GUIAnimation(xml_node<>* node)
|
||||||
|
{
|
||||||
|
xml_node<>* child;
|
||||||
|
xml_attribute<>* attr;
|
||||||
|
|
||||||
|
mAnimation = NULL;
|
||||||
|
mFrame = 1;
|
||||||
|
mFPS = 1;
|
||||||
|
mLoop = -1;
|
||||||
|
mRender = 1;
|
||||||
|
mUpdateCount = 0;
|
||||||
|
|
||||||
|
if (!node) return;
|
||||||
|
|
||||||
|
child = node->first_node("resource");
|
||||||
|
if (child)
|
||||||
|
{
|
||||||
|
attr = child->first_attribute("name");
|
||||||
|
if (attr)
|
||||||
|
mAnimation = (AnimationResource*) PageManager::FindResource(attr->value());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load the placement
|
||||||
|
LoadPlacement(node->first_node("placement"), &mRenderX, &mRenderY, NULL, NULL, &mPlacement);
|
||||||
|
|
||||||
|
child = node->first_node("speed");
|
||||||
|
if (child)
|
||||||
|
{
|
||||||
|
attr = child->first_attribute("fps");
|
||||||
|
if (attr)
|
||||||
|
mFPS = atoi(attr->value());
|
||||||
|
attr = child->first_attribute("render");
|
||||||
|
if (attr)
|
||||||
|
mRender = atoi(attr->value());
|
||||||
|
}
|
||||||
|
if (mFPS > 30) mFPS = 30;
|
||||||
|
|
||||||
|
child = node->first_node("loop");
|
||||||
|
if (child)
|
||||||
|
{
|
||||||
|
attr = child->first_attribute("frame");
|
||||||
|
if (attr)
|
||||||
|
mLoop = atoi(attr->value()) - 1;
|
||||||
|
attr = child->first_attribute("start");
|
||||||
|
if (attr)
|
||||||
|
mFrame = atoi(attr->value());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch the render sizes
|
||||||
|
if (mAnimation && mAnimation->GetResource())
|
||||||
|
{
|
||||||
|
mRenderW = gr_get_width(mAnimation->GetResource());
|
||||||
|
mRenderH = gr_get_height(mAnimation->GetResource());
|
||||||
|
|
||||||
|
// Adjust for placement
|
||||||
|
if (mPlacement != TOP_LEFT && mPlacement != BOTTOM_LEFT)
|
||||||
|
{
|
||||||
|
if (mPlacement == CENTER)
|
||||||
|
mRenderX -= (mRenderW / 2);
|
||||||
|
else
|
||||||
|
mRenderX -= mRenderW;
|
||||||
|
}
|
||||||
|
if (mPlacement != TOP_LEFT && mPlacement != TOP_RIGHT)
|
||||||
|
{
|
||||||
|
if (mPlacement == CENTER)
|
||||||
|
mRenderY -= (mRenderH / 2);
|
||||||
|
else
|
||||||
|
mRenderY -= mRenderH;
|
||||||
|
}
|
||||||
|
SetPlacement(TOP_LEFT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int GUIAnimation::Render(void)
|
||||||
|
{
|
||||||
|
if (!mAnimation || !mAnimation->GetResource(mFrame)) return -1;
|
||||||
|
|
||||||
|
gr_blit(mAnimation->GetResource(mFrame), 0, 0, mRenderW, mRenderH, mRenderX, mRenderY);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int GUIAnimation::Update(void)
|
||||||
|
{
|
||||||
|
if (!mAnimation) return -1;
|
||||||
|
|
||||||
|
// Handle the "end-of-animation" state
|
||||||
|
if (mLoop == -2) return 0;
|
||||||
|
|
||||||
|
// Determine if we need the next frame yet...
|
||||||
|
if (++mUpdateCount > 30 / mFPS)
|
||||||
|
{
|
||||||
|
mUpdateCount = 0;
|
||||||
|
if (++mFrame >= mAnimation->GetResourceCount())
|
||||||
|
{
|
||||||
|
if (mLoop < 0)
|
||||||
|
{
|
||||||
|
mFrame = mAnimation->GetResourceCount() - 1;
|
||||||
|
mLoop = -2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
mFrame = mLoop;
|
||||||
|
}
|
||||||
|
if (mRender == 2) return 2;
|
||||||
|
return (Render() == 0 ? 1 : -1);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
6
gui/basicTheme/mkTheme.sh
Executable file
@ -0,0 +1,6 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
cd res
|
||||||
|
zip -r ../ui.zip *
|
||||||
|
cd ..
|
||||||
|
|
BIN
gui/basicTheme/res/fonts/bluehighway-25.dat
Executable file
BIN
gui/basicTheme/res/fonts/bluehighway-40.dat
Executable file
BIN
gui/basicTheme/res/images/android.png
Normal file
After Width: | Height: | Size: 2.0 KiB |
BIN
gui/basicTheme/res/images/checkbox_checked.png
Normal file
After Width: | Height: | Size: 858 B |
BIN
gui/basicTheme/res/images/checkbox_empty.png
Normal file
After Width: | Height: | Size: 311 B |
BIN
gui/basicTheme/res/images/file.png
Normal file
After Width: | Height: | Size: 533 B |
BIN
gui/basicTheme/res/images/folder.png
Normal file
After Width: | Height: | Size: 591 B |
BIN
gui/basicTheme/res/images/indeterminate001.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
gui/basicTheme/res/images/indeterminate002.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
gui/basicTheme/res/images/indeterminate003.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
gui/basicTheme/res/images/indeterminate004.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
gui/basicTheme/res/images/indeterminate005.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
gui/basicTheme/res/images/indeterminate006.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
gui/basicTheme/res/images/qhd-medium-button.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
BIN
gui/basicTheme/res/images/qhd-menu-button.png
Normal file
After Width: | Height: | Size: 3.8 KiB |
BIN
gui/basicTheme/res/images/qhd-minus-button.png
Normal file
After Width: | Height: | Size: 819 B |
BIN
gui/basicTheme/res/images/qhd-plus-button.png
Normal file
After Width: | Height: | Size: 845 B |
BIN
gui/basicTheme/res/images/qhd-small-button.png
Normal file
After Width: | Height: | Size: 807 B |
BIN
gui/basicTheme/res/images/qhd-sort-button.png
Normal file
After Width: | Height: | Size: 854 B |
BIN
gui/basicTheme/res/images/slideout.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
1949
gui/basicTheme/res/ui.xml
Normal file
BIN
gui/basicTheme/ui.zip
Normal file
194
gui/button.cpp
Normal file
@ -0,0 +1,194 @@
|
|||||||
|
// button.cpp - GUIButton object
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <sys/reboot.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include "../common.h"
|
||||||
|
#include "../minuitwrp/minui.h"
|
||||||
|
#include "../recovery_ui.h"
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "rapidxml.hpp"
|
||||||
|
#include "objects.hpp"
|
||||||
|
|
||||||
|
GUIButton::GUIButton(xml_node<>* node)
|
||||||
|
: Conditional(node)
|
||||||
|
{
|
||||||
|
xml_attribute<>* attr;
|
||||||
|
xml_node<>* child;
|
||||||
|
|
||||||
|
mButtonImg = NULL;
|
||||||
|
mButtonIcon = NULL;
|
||||||
|
mButtonLabel = NULL;
|
||||||
|
mAction = NULL;
|
||||||
|
mRendered = false;
|
||||||
|
|
||||||
|
if (!node) return;
|
||||||
|
|
||||||
|
// Three of the four can be loaded directly from the node
|
||||||
|
mButtonImg = new GUIImage(node);
|
||||||
|
mButtonLabel = new GUIText(node);
|
||||||
|
mAction = new GUIAction(node);
|
||||||
|
|
||||||
|
if (mButtonImg->Render() < 0)
|
||||||
|
{
|
||||||
|
LOGE("Unable to locate button image\n");
|
||||||
|
delete mButtonImg;
|
||||||
|
mButtonImg = NULL;
|
||||||
|
}
|
||||||
|
if (mButtonLabel->Render() < 0)
|
||||||
|
{
|
||||||
|
delete mButtonLabel;
|
||||||
|
mButtonLabel = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The icon is a special case
|
||||||
|
child = node->first_node("icon");
|
||||||
|
if (child)
|
||||||
|
{
|
||||||
|
attr = child->first_attribute("resource");
|
||||||
|
if (attr)
|
||||||
|
mButtonIcon = PageManager::FindResource(attr->value());
|
||||||
|
}
|
||||||
|
|
||||||
|
int x, y, w, h;
|
||||||
|
if (mButtonImg) mButtonImg->GetRenderPos(x, y, w, h);
|
||||||
|
SetRenderPos(x, y, w, h);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
GUIButton::~GUIButton()
|
||||||
|
{
|
||||||
|
if (mButtonImg) delete mButtonImg;
|
||||||
|
if (mButtonLabel) delete mButtonLabel;
|
||||||
|
if (mAction) delete mAction;
|
||||||
|
if (mButtonIcon) delete mButtonIcon;
|
||||||
|
}
|
||||||
|
|
||||||
|
int GUIButton::Render(void)
|
||||||
|
{
|
||||||
|
if (!isConditionTrue())
|
||||||
|
{
|
||||||
|
mRendered = false;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
if (mButtonImg) ret = mButtonImg->Render();
|
||||||
|
if (ret < 0) return ret;
|
||||||
|
if (mButtonIcon && mButtonIcon->GetResource())
|
||||||
|
gr_blit(mButtonIcon->GetResource(), 0, 0, mIconW, mIconH, mIconX, mIconY);
|
||||||
|
if (mButtonLabel) ret = mButtonLabel->Render();
|
||||||
|
if (ret < 0) return ret;
|
||||||
|
mRendered = true;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int GUIButton::Update(void)
|
||||||
|
{
|
||||||
|
if (!isConditionTrue()) return (mRendered ? 2 : 0);
|
||||||
|
if (!mRendered) return 2;
|
||||||
|
|
||||||
|
int ret = 0, ret2 = 0;
|
||||||
|
|
||||||
|
if (mButtonImg) ret = mButtonImg->Update();
|
||||||
|
if (ret < 0) return ret;
|
||||||
|
|
||||||
|
if (ret == 0)
|
||||||
|
{
|
||||||
|
if (mButtonLabel) ret2 = mButtonLabel->Update();
|
||||||
|
if (ret2 < 0) return ret2;
|
||||||
|
if (ret2 > ret) ret = ret2;
|
||||||
|
}
|
||||||
|
else if (ret == 1)
|
||||||
|
{
|
||||||
|
// The button re-rendered, so everyone else is a render
|
||||||
|
if (mButtonIcon && mButtonIcon->GetResource())
|
||||||
|
gr_blit(mButtonIcon->GetResource(), 0, 0, mIconW, mIconH, mIconX, mIconY);
|
||||||
|
if (mButtonLabel) ret = mButtonLabel->Render();
|
||||||
|
if (ret < 0) return ret;
|
||||||
|
ret = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Aparently, the button needs a background update
|
||||||
|
ret = 2;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int GUIButton::SetRenderPos(int x, int y, int w, int h)
|
||||||
|
{
|
||||||
|
mRenderX = x;
|
||||||
|
mRenderY = y;
|
||||||
|
if (w || h)
|
||||||
|
{
|
||||||
|
mRenderW = w;
|
||||||
|
mRenderH = h;
|
||||||
|
}
|
||||||
|
|
||||||
|
mIconW = 0; mIconH = 0;
|
||||||
|
if (mButtonIcon && mButtonIcon->GetResource())
|
||||||
|
{
|
||||||
|
mIconW = gr_get_width(mButtonIcon->GetResource());
|
||||||
|
mIconH = gr_get_height(mButtonIcon->GetResource());
|
||||||
|
}
|
||||||
|
|
||||||
|
mTextH = 0;
|
||||||
|
mTextW = 0;
|
||||||
|
mIconX = mRenderX + ((mRenderW - mIconW) / 2);
|
||||||
|
if (mButtonLabel) mButtonLabel->GetCurrentBounds(mTextW, mTextH);
|
||||||
|
if (mTextW)
|
||||||
|
{
|
||||||
|
// As a special case, we'll allow large text which automatically moves it to the right.
|
||||||
|
if (mTextW > mRenderW)
|
||||||
|
{
|
||||||
|
mTextX = mRenderW + mRenderX + 5;
|
||||||
|
mRenderW += mTextW + 5;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mTextX = mRenderX + ((mRenderW - mTextW) / 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mIconH == 0 || mTextH == 0 || mIconH + mTextH > mRenderH)
|
||||||
|
{
|
||||||
|
mIconY = mRenderY + (mRenderH / 2) - (mIconH / 2);
|
||||||
|
mTextY = mRenderY + (mRenderH / 2) - (mTextH / 2);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int divisor = mRenderH - (mIconH + mTextH);
|
||||||
|
mIconY = mRenderY + (divisor / 3);
|
||||||
|
mTextY = mRenderY + (divisor * 2 / 3) + mIconH;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mButtonLabel) mButtonLabel->SetRenderPos(mTextX, mTextY);
|
||||||
|
if (mAction) mAction->SetActionPos(mRenderX, mRenderY, mRenderW, mRenderH);
|
||||||
|
SetActionPos(mRenderX, mRenderY, mRenderW, mRenderH);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int GUIButton::NotifyTouch(TOUCH_STATE state, int x, int y)
|
||||||
|
{
|
||||||
|
if (!isConditionTrue()) return -1;
|
||||||
|
return (mAction ? mAction->NotifyTouch(state, x, y) : 1);
|
||||||
|
}
|
||||||
|
|
169
gui/checkbox.cpp
Normal file
@ -0,0 +1,169 @@
|
|||||||
|
// checkbox.cpp - GUICheckbox object
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <sys/reboot.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include "../common.h"
|
||||||
|
#include "../minuitwrp/minui.h"
|
||||||
|
#include "../recovery_ui.h"
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "rapidxml.hpp"
|
||||||
|
#include "objects.hpp"
|
||||||
|
|
||||||
|
GUICheckbox::GUICheckbox(xml_node<>* node)
|
||||||
|
: Conditional(node)
|
||||||
|
{
|
||||||
|
xml_attribute<>* attr;
|
||||||
|
xml_node<>* child;
|
||||||
|
|
||||||
|
mChecked = NULL;
|
||||||
|
mUnchecked = NULL;
|
||||||
|
mLabel = NULL;
|
||||||
|
mRendered = false;
|
||||||
|
|
||||||
|
mLastState = 0;
|
||||||
|
|
||||||
|
if (!node) return;
|
||||||
|
|
||||||
|
// The label can be loaded directly
|
||||||
|
mLabel = new GUIText(node);
|
||||||
|
|
||||||
|
// Read the check states
|
||||||
|
child = node->first_node("image");
|
||||||
|
if (child)
|
||||||
|
{
|
||||||
|
attr = child->first_attribute("checked");
|
||||||
|
if (attr)
|
||||||
|
mChecked = PageManager::FindResource(attr->value());
|
||||||
|
attr = child->first_attribute("unchecked");
|
||||||
|
if (attr)
|
||||||
|
mUnchecked = PageManager::FindResource(attr->value());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the variable data
|
||||||
|
child = node->first_node("data");
|
||||||
|
if (child)
|
||||||
|
{
|
||||||
|
attr = child->first_attribute("variable");
|
||||||
|
if (attr)
|
||||||
|
mVarName = attr->value();
|
||||||
|
attr = child->first_attribute("default");
|
||||||
|
if (attr)
|
||||||
|
DataManager::SetValue(mVarName, attr->value());
|
||||||
|
}
|
||||||
|
|
||||||
|
mCheckW = 0; mCheckH = 0;
|
||||||
|
if (mChecked && mChecked->GetResource())
|
||||||
|
{
|
||||||
|
mCheckW = gr_get_width(mChecked->GetResource());
|
||||||
|
mCheckH = gr_get_height(mChecked->GetResource());
|
||||||
|
}
|
||||||
|
else if (mUnchecked && mUnchecked->GetResource())
|
||||||
|
{
|
||||||
|
mCheckW = gr_get_width(mUnchecked->GetResource());
|
||||||
|
mCheckH = gr_get_height(mUnchecked->GetResource());
|
||||||
|
}
|
||||||
|
|
||||||
|
int x, y, w, h;
|
||||||
|
mLabel->GetRenderPos(x, y, w, h);
|
||||||
|
SetRenderPos(x, y, 0, 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
GUICheckbox::~GUICheckbox()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int GUICheckbox::Render(void)
|
||||||
|
{
|
||||||
|
if (!isConditionTrue())
|
||||||
|
{
|
||||||
|
mRendered = false;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ret = 0;
|
||||||
|
int lastState = 0;
|
||||||
|
DataManager::GetValue(mVarName, lastState);
|
||||||
|
|
||||||
|
if (lastState)
|
||||||
|
{
|
||||||
|
if (mChecked && mChecked->GetResource())
|
||||||
|
gr_blit(mChecked->GetResource(), 0, 0, mCheckW, mCheckH, mRenderX, mRenderY);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (mUnchecked && mUnchecked->GetResource())
|
||||||
|
gr_blit(mUnchecked->GetResource(), 0, 0, mCheckW, mCheckH, mRenderX, mRenderY);
|
||||||
|
}
|
||||||
|
if (mLabel) ret = mLabel->Render();
|
||||||
|
mLastState = lastState;
|
||||||
|
mRendered = true;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int GUICheckbox::Update(void)
|
||||||
|
{
|
||||||
|
if (!isConditionTrue()) return (mRendered ? 2 : 0);
|
||||||
|
if (!mRendered) return 2;
|
||||||
|
|
||||||
|
int lastState = 0;
|
||||||
|
DataManager::GetValue(mVarName, lastState);
|
||||||
|
|
||||||
|
if (lastState != mLastState)
|
||||||
|
return 2;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int GUICheckbox::SetRenderPos(int x, int y, int w, int h)
|
||||||
|
{
|
||||||
|
mRenderX = x;
|
||||||
|
mRenderY = y;
|
||||||
|
|
||||||
|
if (w || h) return -1;
|
||||||
|
|
||||||
|
int textW, textH;
|
||||||
|
mLabel->GetCurrentBounds(textW, textH);
|
||||||
|
|
||||||
|
w = textW + mCheckW + 5;
|
||||||
|
mRenderW = w;
|
||||||
|
mRenderH = mCheckH;
|
||||||
|
|
||||||
|
mTextX = mRenderX + mCheckW + 5;
|
||||||
|
mTextY = mRenderY + ((mCheckH / 2) - (textH / 2));
|
||||||
|
|
||||||
|
mLabel->SetRenderPos(mTextX, mTextY, 0, 0);
|
||||||
|
SetActionPos(mRenderX, mRenderY, mRenderW, mRenderH);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int GUICheckbox::NotifyTouch(TOUCH_STATE state, int x, int y)
|
||||||
|
{
|
||||||
|
if (!isConditionTrue()) return -1;
|
||||||
|
|
||||||
|
if (state == TOUCH_RELEASE)
|
||||||
|
{
|
||||||
|
int lastState;
|
||||||
|
DataManager::GetValue(mVarName, lastState);
|
||||||
|
lastState = (lastState == 0) ? 1 : 0;
|
||||||
|
DataManager::SetValue(mVarName, lastState);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
203
gui/conditional.cpp
Normal file
@ -0,0 +1,203 @@
|
|||||||
|
// checkbox.cpp - GUICheckbox object
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <sys/reboot.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include "../common.h"
|
||||||
|
#include "../minuitwrp/minui.h"
|
||||||
|
#include "../recovery_ui.h"
|
||||||
|
#include "../variables.h"
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "rapidxml.hpp"
|
||||||
|
#include "objects.hpp"
|
||||||
|
#include "../data.hpp"
|
||||||
|
|
||||||
|
Conditional::Conditional(xml_node<>* node)
|
||||||
|
{
|
||||||
|
// Break out early, it's too hard to check if valid every step
|
||||||
|
if (!node) return;
|
||||||
|
|
||||||
|
// First, get the action
|
||||||
|
xml_node<>* condition = node->first_node("conditions");
|
||||||
|
if (condition) condition = condition->first_node("condition");
|
||||||
|
else condition = node->first_node("condition");
|
||||||
|
|
||||||
|
if (!condition) return;
|
||||||
|
|
||||||
|
while (condition)
|
||||||
|
{
|
||||||
|
Condition cond;
|
||||||
|
|
||||||
|
cond.mCompareOp = "=";
|
||||||
|
|
||||||
|
xml_attribute<>* attr;
|
||||||
|
attr = condition->first_attribute("var1");
|
||||||
|
if (attr) cond.mVar1 = attr->value();
|
||||||
|
|
||||||
|
attr = condition->first_attribute("op");
|
||||||
|
if (attr) cond.mCompareOp = attr->value();
|
||||||
|
|
||||||
|
attr = condition->first_attribute("var2");
|
||||||
|
if (attr) cond.mVar2 = attr->value();
|
||||||
|
|
||||||
|
mConditions.push_back(cond);
|
||||||
|
|
||||||
|
condition = condition->next_sibling("condition");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Conditional::IsConditionVariable(std::string var)
|
||||||
|
{
|
||||||
|
std::vector<Condition>::iterator iter;
|
||||||
|
for (iter = mConditions.begin(); iter != mConditions.end(); iter++)
|
||||||
|
{
|
||||||
|
if (iter->mVar1 == var) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Conditional::isConditionTrue()
|
||||||
|
{
|
||||||
|
std::vector<Condition>::iterator iter;
|
||||||
|
for (iter = mConditions.begin(); iter != mConditions.end(); iter++)
|
||||||
|
{
|
||||||
|
if (!isConditionTrue(&(*iter))) return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Conditional::isConditionTrue(Condition* condition)
|
||||||
|
{
|
||||||
|
// This is used to hold the proper value of "true" based on the '!' NOT flag
|
||||||
|
bool bTrue = true;
|
||||||
|
|
||||||
|
if (condition->mVar1.empty()) return bTrue;
|
||||||
|
|
||||||
|
if (!condition->mCompareOp.empty() && condition->mCompareOp[0] == '!')
|
||||||
|
bTrue = false;
|
||||||
|
|
||||||
|
if (condition->mVar2.empty() && condition->mCompareOp != "modified")
|
||||||
|
{
|
||||||
|
if (!DataManager::GetStrValue(condition->mVar1).empty())
|
||||||
|
return bTrue;
|
||||||
|
|
||||||
|
return !bTrue;
|
||||||
|
}
|
||||||
|
|
||||||
|
string var1, var2;
|
||||||
|
if (DataManager::GetValue(condition->mVar1, var1))
|
||||||
|
var1 = condition->mVar1;
|
||||||
|
if (DataManager::GetValue(condition->mVar2, var2))
|
||||||
|
var2 = condition->mVar2;
|
||||||
|
|
||||||
|
// This is a special case, we stat the file and that determines our result
|
||||||
|
if (var1 == "fileexists")
|
||||||
|
{
|
||||||
|
struct stat st;
|
||||||
|
if (stat(var2.c_str(), &st) == 0)
|
||||||
|
var2 = var1;
|
||||||
|
else
|
||||||
|
var2 = "FAILED";
|
||||||
|
}
|
||||||
|
if (var1 == "mounted")
|
||||||
|
{
|
||||||
|
if (isMounted(condition->mVar2))
|
||||||
|
var2 = var1;
|
||||||
|
else
|
||||||
|
var2 = "FAILED";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (condition->mCompareOp.find('=') != string::npos && var1 == var2)
|
||||||
|
return bTrue;
|
||||||
|
|
||||||
|
if (condition->mCompareOp.find('>') != string::npos && (atof(var1.c_str()) > atof(var2.c_str())))
|
||||||
|
return bTrue;
|
||||||
|
|
||||||
|
if (condition->mCompareOp.find('<') != string::npos && (atof(var1.c_str()) < atof(var2.c_str())))
|
||||||
|
return bTrue;
|
||||||
|
|
||||||
|
if (condition->mCompareOp == "modified")
|
||||||
|
{
|
||||||
|
// This is a hack to allow areas to reset the default value
|
||||||
|
if (var1.empty())
|
||||||
|
{
|
||||||
|
condition->mLastVal = var1;
|
||||||
|
return !bTrue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (var1 != condition->mLastVal)
|
||||||
|
return bTrue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return !bTrue;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Conditional::isConditionValid()
|
||||||
|
{
|
||||||
|
return !mConditions.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Conditional::NotifyPageSet()
|
||||||
|
{
|
||||||
|
std::vector<Condition>::iterator iter;
|
||||||
|
for (iter = mConditions.begin(); iter != mConditions.end(); iter++)
|
||||||
|
{
|
||||||
|
if (iter->mCompareOp == "modified")
|
||||||
|
{
|
||||||
|
string val;
|
||||||
|
|
||||||
|
// If this fails, val will not be set, which is perfect
|
||||||
|
if (DataManager::GetValue(iter->mVar1, val))
|
||||||
|
{
|
||||||
|
DataManager::SetValue(iter->mVar1, "");
|
||||||
|
DataManager::GetValue(iter->mVar1, val);
|
||||||
|
}
|
||||||
|
iter->mLastVal = val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Conditional::isMounted(string vol)
|
||||||
|
{
|
||||||
|
FILE *fp;
|
||||||
|
char tmpOutput[255];
|
||||||
|
|
||||||
|
if (strcmp(vol.c_str(), "EXTERNAL") == 0)
|
||||||
|
DataManager::GetValue(TW_EXTERNAL_MOUNT, vol);
|
||||||
|
else if (strcmp(vol.c_str(), "INTERNAL") == 0)
|
||||||
|
DataManager::GetValue(TW_INTERNAL_MOUNT, vol);
|
||||||
|
fp = fopen("/proc/mounts", "rt");
|
||||||
|
while (fgets(tmpOutput,255,fp) != NULL)
|
||||||
|
{
|
||||||
|
char* mnt = tmpOutput;
|
||||||
|
while (*mnt > 32) mnt++;
|
||||||
|
while (*mnt > 0 && *mnt <= 32) mnt++;
|
||||||
|
char* pos = mnt;
|
||||||
|
while (*pos > 32) pos++;
|
||||||
|
*pos = 0;
|
||||||
|
if (vol == mnt)
|
||||||
|
{
|
||||||
|
fclose(fp);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fclose(fp);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
398
gui/console.cpp
Normal file
@ -0,0 +1,398 @@
|
|||||||
|
// console.cpp - GUIConsole object
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <sys/reboot.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include "../common.h"
|
||||||
|
#include "../minuitwrp/minui.h"
|
||||||
|
#include "../recovery_ui.h"
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "rapidxml.hpp"
|
||||||
|
#include "objects.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
static std::vector<std::string> gConsole;
|
||||||
|
|
||||||
|
extern "C" void gui_print(const char *fmt, ...)
|
||||||
|
{
|
||||||
|
char buf[512]; // We're going to limit a single request to 512 bytes
|
||||||
|
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, fmt);
|
||||||
|
vsnprintf(buf, 512, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
char *start, *next;
|
||||||
|
|
||||||
|
if (buf[0] == '\n' && strlen(buf) < 2) {
|
||||||
|
// This prevents the double lines bug seen in the console during zip installs
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (start = next = buf; *next != '\0'; next++)
|
||||||
|
{
|
||||||
|
if (*next == '\n')
|
||||||
|
{
|
||||||
|
*next = '\0';
|
||||||
|
next++;
|
||||||
|
|
||||||
|
std::string line = start;
|
||||||
|
gConsole.push_back(line);
|
||||||
|
start = next;
|
||||||
|
|
||||||
|
// Handle the normal \n\0 case
|
||||||
|
if (*next == '\0')
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::string line = start;
|
||||||
|
gConsole.push_back(line);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void gui_print_overwrite(const char *fmt, ...)
|
||||||
|
{
|
||||||
|
char buf[512]; // We're going to limit a single request to 512 bytes
|
||||||
|
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, fmt);
|
||||||
|
vsnprintf(buf, 512, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
// Pop the last line, and we can continue
|
||||||
|
if (!gConsole.empty()) gConsole.pop_back();
|
||||||
|
|
||||||
|
char *start, *next;
|
||||||
|
for (start = next = buf; *next != '\0'; next++)
|
||||||
|
{
|
||||||
|
if (*next == '\n')
|
||||||
|
{
|
||||||
|
*next = '\0';
|
||||||
|
next++;
|
||||||
|
|
||||||
|
std::string line = start;
|
||||||
|
gConsole.push_back(line);
|
||||||
|
start = next;
|
||||||
|
|
||||||
|
// Handle the normal \n\0 case
|
||||||
|
if (*next == '\0')
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::string line = start;
|
||||||
|
gConsole.push_back(line);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
GUIConsole::GUIConsole(xml_node<>* node)
|
||||||
|
{
|
||||||
|
xml_attribute<>* attr;
|
||||||
|
xml_node<>* child;
|
||||||
|
|
||||||
|
mFont = NULL;
|
||||||
|
mCurrentLine = -1;
|
||||||
|
memset(&mForegroundColor, 255, sizeof(COLOR));
|
||||||
|
memset(&mBackgroundColor, 0, sizeof(COLOR));
|
||||||
|
mBackgroundColor.alpha = 255;
|
||||||
|
memset(&mScrollColor, 0x08, sizeof(COLOR));
|
||||||
|
mScrollColor.alpha = 255;
|
||||||
|
mLastCount = 0;
|
||||||
|
mSlideout = 0;
|
||||||
|
mSlideoutState = hidden;
|
||||||
|
|
||||||
|
mRenderX = 0; mRenderY = 0; mRenderW = gr_fb_width(); mRenderH = gr_fb_height();
|
||||||
|
|
||||||
|
if (!node)
|
||||||
|
{
|
||||||
|
mSlideoutX = 0; mSlideoutY = 0; mSlideoutW = 0; mSlideoutH = 0;
|
||||||
|
mConsoleX = 0; mConsoleY = 0; mConsoleW = gr_fb_width(); mConsoleH = gr_fb_height();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
child = node->first_node("font");
|
||||||
|
if (child)
|
||||||
|
{
|
||||||
|
attr = child->first_attribute("resource");
|
||||||
|
if (attr)
|
||||||
|
mFont = PageManager::FindResource(attr->value());
|
||||||
|
}
|
||||||
|
|
||||||
|
child = node->first_node("color");
|
||||||
|
if (child)
|
||||||
|
{
|
||||||
|
attr = child->first_attribute("foreground");
|
||||||
|
if (attr)
|
||||||
|
{
|
||||||
|
std::string color = attr->value();
|
||||||
|
ConvertStrToColor(color, &mForegroundColor);
|
||||||
|
}
|
||||||
|
attr = child->first_attribute("background");
|
||||||
|
if (attr)
|
||||||
|
{
|
||||||
|
std::string color = attr->value();
|
||||||
|
ConvertStrToColor(color, &mBackgroundColor);
|
||||||
|
}
|
||||||
|
attr = child->first_attribute("scroll");
|
||||||
|
if (attr)
|
||||||
|
{
|
||||||
|
std::string color = attr->value();
|
||||||
|
ConvertStrToColor(color, &mScrollColor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load the placement
|
||||||
|
LoadPlacement(node->first_node("placement"), &mConsoleX, &mConsoleY, &mConsoleW, &mConsoleH);
|
||||||
|
|
||||||
|
child = node->first_node("slideout");
|
||||||
|
if (child)
|
||||||
|
{
|
||||||
|
mSlideout = 1;
|
||||||
|
LoadPlacement(child, &mSlideoutX, &mSlideoutY);
|
||||||
|
|
||||||
|
attr = child->first_attribute("resource");
|
||||||
|
if (attr) mSlideoutImage = PageManager::FindResource(attr->value());
|
||||||
|
|
||||||
|
if (mSlideoutImage && mSlideoutImage->GetResource())
|
||||||
|
{
|
||||||
|
mSlideoutW = gr_get_width(mSlideoutImage->GetResource());
|
||||||
|
mSlideoutH = gr_get_height(mSlideoutImage->GetResource());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gr_getFontDetails(mFont, &mFontHeight, NULL);
|
||||||
|
SetActionPos(mRenderX, mRenderY, mRenderW, mRenderH);
|
||||||
|
SetRenderPos(mConsoleX, mConsoleY);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int GUIConsole::RenderSlideout(void)
|
||||||
|
{
|
||||||
|
if (!mSlideoutImage || !mSlideoutImage->GetResource()) return -1;
|
||||||
|
|
||||||
|
gr_blit(mSlideoutImage->GetResource(), 0, 0, mSlideoutW, mSlideoutH, mSlideoutX, mSlideoutY);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int GUIConsole::RenderConsole(void)
|
||||||
|
{
|
||||||
|
void* fontResource = NULL;
|
||||||
|
if (mFont) fontResource = mFont->GetResource();
|
||||||
|
|
||||||
|
// We fill the background
|
||||||
|
gr_color(mBackgroundColor.red, mBackgroundColor.green, mBackgroundColor.blue, 255);
|
||||||
|
gr_fill(mConsoleX, mConsoleY, mConsoleW, mConsoleH);
|
||||||
|
|
||||||
|
gr_color(mScrollColor.red, mScrollColor.green, mScrollColor.blue, mScrollColor.alpha);
|
||||||
|
gr_fill(mConsoleX + (mConsoleW * 9 / 10), mConsoleY, (mConsoleW / 10), mConsoleH);
|
||||||
|
|
||||||
|
// Render the lines
|
||||||
|
gr_color(mForegroundColor.red, mForegroundColor.green, mForegroundColor.blue, mForegroundColor.alpha);
|
||||||
|
|
||||||
|
// Don't try to continue to render without data
|
||||||
|
mLastCount = gConsole.size();
|
||||||
|
if (mLastCount == 0) return (mSlideout ? RenderSlideout() : 0);
|
||||||
|
|
||||||
|
// Find the start point
|
||||||
|
int start;
|
||||||
|
int curLine = mCurrentLine; // Thread-safing (Another thread updates this value)
|
||||||
|
if (curLine == -1)
|
||||||
|
{
|
||||||
|
start = mLastCount - mMaxRows;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (curLine > (int) mLastCount) curLine = (int) mLastCount;
|
||||||
|
if ((int) mMaxRows > curLine) curLine = (int) mMaxRows;
|
||||||
|
start = curLine - mMaxRows;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int line;
|
||||||
|
for (line = 0; line < mMaxRows; line++)
|
||||||
|
{
|
||||||
|
if ((start + (int) line) >= 0 && (start + (int) line) < (int) mLastCount)
|
||||||
|
{
|
||||||
|
gr_textExW(mConsoleX, mStartY + (line * mFontHeight), gConsole[start + line].c_str(), fontResource, mConsoleW + mConsoleX);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (mSlideout ? RenderSlideout() : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int GUIConsole::Render(void)
|
||||||
|
{
|
||||||
|
if (mSlideout && mSlideoutState == hidden)
|
||||||
|
{
|
||||||
|
return RenderSlideout();
|
||||||
|
}
|
||||||
|
return RenderConsole();
|
||||||
|
}
|
||||||
|
|
||||||
|
int GUIConsole::Update(void)
|
||||||
|
{
|
||||||
|
if (mSlideout && mSlideoutState != visible)
|
||||||
|
{
|
||||||
|
if (mSlideoutState == hidden)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (mSlideoutState == request_hide)
|
||||||
|
mSlideoutState = hidden;
|
||||||
|
|
||||||
|
if (mSlideoutState == request_show)
|
||||||
|
mSlideoutState = visible;
|
||||||
|
|
||||||
|
// Any time we activate the slider, we reset the position
|
||||||
|
mCurrentLine = -1;
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mCurrentLine == -1 && mLastCount != gConsole.size())
|
||||||
|
{
|
||||||
|
// We can use Render, and return for just a flip
|
||||||
|
Render();
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
else if (mLastTouchY >= 0)
|
||||||
|
{
|
||||||
|
// They're still touching, so re-render
|
||||||
|
Render();
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int GUIConsole::SetRenderPos(int x, int y, int w, int h)
|
||||||
|
{
|
||||||
|
// Adjust the stub position accordingly
|
||||||
|
mSlideoutX += (x - mConsoleX);
|
||||||
|
mSlideoutY += (y - mConsoleY);
|
||||||
|
|
||||||
|
mConsoleX = x;
|
||||||
|
mConsoleY = y;
|
||||||
|
if (w || h)
|
||||||
|
{
|
||||||
|
mConsoleW = w;
|
||||||
|
mConsoleH = h;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate the max rows
|
||||||
|
mMaxRows = mConsoleH / mFontHeight;
|
||||||
|
|
||||||
|
// Adjust so we always fit to bottom
|
||||||
|
mStartY = mConsoleY + (mConsoleH % mFontHeight);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsInRegion - Checks if the request is handled by this object
|
||||||
|
// Return 0 if this object handles the request, 1 if not
|
||||||
|
int GUIConsole::IsInRegion(int x, int y)
|
||||||
|
{
|
||||||
|
if (mSlideout)
|
||||||
|
{
|
||||||
|
// Check if they tapped the slideout button
|
||||||
|
if (x >= mSlideoutX && x <= mSlideoutX + mSlideoutW && y >= mSlideoutY && y < mSlideoutY + mSlideoutH)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
// If we're only rendering the slideout, bail now
|
||||||
|
if (mSlideoutState == hidden)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (x < mConsoleX || x > mConsoleX + mConsoleW || y < mConsoleY || y > mConsoleY + mConsoleH) ? 0 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// NotifyTouch - Notify of a touch event
|
||||||
|
// Return 0 on success, >0 to ignore remainder of touch, and <0 on error
|
||||||
|
int GUIConsole::NotifyTouch(TOUCH_STATE state, int x, int y)
|
||||||
|
{
|
||||||
|
if (mSlideout && mSlideoutState == hidden)
|
||||||
|
{
|
||||||
|
if (state == TOUCH_START)
|
||||||
|
{
|
||||||
|
mSlideoutState = request_show;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (mSlideout && mSlideoutState == visible)
|
||||||
|
{
|
||||||
|
// Are we sliding it back in?
|
||||||
|
if (state == TOUCH_START && x > mSlideoutX && x < (mSlideoutX + mSlideoutW) && y > mSlideoutY && y < (mSlideoutY + mSlideoutH))
|
||||||
|
{
|
||||||
|
mSlideoutState = request_hide;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we don't have enough lines to scroll, throw this away.
|
||||||
|
if (mLastCount < mMaxRows) return 1;
|
||||||
|
|
||||||
|
// We are scrolling!!!
|
||||||
|
switch (state)
|
||||||
|
{
|
||||||
|
case TOUCH_START:
|
||||||
|
mLastTouchX = x;
|
||||||
|
mLastTouchY = y;
|
||||||
|
if ((x - mConsoleX) > ((9 * mConsoleW) / 10))
|
||||||
|
mSlideMultiplier = 10;
|
||||||
|
else
|
||||||
|
mSlideMultiplier = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TOUCH_DRAG:
|
||||||
|
// This handles tapping
|
||||||
|
if (x == mLastTouchX && y == mLastTouchY) break;
|
||||||
|
mLastTouchX = -1;
|
||||||
|
|
||||||
|
if (y > mLastTouchY + 5)
|
||||||
|
{
|
||||||
|
mLastTouchY = y;
|
||||||
|
if (mCurrentLine == -1)
|
||||||
|
mCurrentLine = mLastCount - mMaxRows;
|
||||||
|
else if (mCurrentLine > mSlideMultiplier)
|
||||||
|
mCurrentLine -= mSlideMultiplier;
|
||||||
|
else
|
||||||
|
mCurrentLine = mMaxRows;
|
||||||
|
|
||||||
|
if (mCurrentLine < (int) mMaxRows)
|
||||||
|
mCurrentLine = mMaxRows;
|
||||||
|
}
|
||||||
|
else if (y < mLastTouchY - 5)
|
||||||
|
{
|
||||||
|
mLastTouchY = y;
|
||||||
|
if (mCurrentLine >= 0)
|
||||||
|
{
|
||||||
|
mCurrentLine += mSlideMultiplier;
|
||||||
|
if (mCurrentLine >= (int) mLastCount)
|
||||||
|
mCurrentLine = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TOUCH_RELEASE:
|
||||||
|
// On a tap, we jump to the tail
|
||||||
|
if (mLastTouchX >= 0)
|
||||||
|
mCurrentLine = -1;
|
||||||
|
|
||||||
|
mLastTouchY = -1;
|
||||||
|
case TOUCH_REPEAT:
|
||||||
|
case TOUCH_HOLD:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
3164
gui/devices/1024x600/curtain.h
Normal file
BIN
gui/devices/1024x600/curtain.jpg
Normal file
After Width: | Height: | Size: 49 KiB |
BIN
gui/devices/1024x600/res/fonts/Roboto-Regular-20.dat
Executable file
BIN
gui/devices/1024x600/res/images/back-icon.png
Normal file
After Width: | Height: | Size: 508 B |
BIN
gui/devices/1024x600/res/images/background.jpg
Normal file
After Width: | Height: | Size: 35 KiB |
BIN
gui/devices/1024x600/res/images/backgroundbottom.jpg
Normal file
After Width: | Height: | Size: 20 KiB |
BIN
gui/devices/1024x600/res/images/backgroundside.jpg
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
gui/devices/1024x600/res/images/button.png
Normal file
After Width: | Height: | Size: 866 B |
BIN
gui/devices/1024x600/res/images/checkbox_checked.png
Normal file
After Width: | Height: | Size: 446 B |
BIN
gui/devices/1024x600/res/images/checkbox_empty.png
Normal file
After Width: | Height: | Size: 216 B |
BIN
gui/devices/1024x600/res/images/console-icon.png
Normal file
After Width: | Height: | Size: 653 B |
BIN
gui/devices/1024x600/res/images/console-toggle.png
Normal file
After Width: | Height: | Size: 649 B |
BIN
gui/devices/1024x600/res/images/file.png
Normal file
After Width: | Height: | Size: 287 B |
BIN
gui/devices/1024x600/res/images/folder.png
Normal file
After Width: | Height: | Size: 322 B |
BIN
gui/devices/1024x600/res/images/home-icon.png
Normal file
After Width: | Height: | Size: 426 B |
BIN
gui/devices/1024x600/res/images/indeterminate001.png
Executable file
After Width: | Height: | Size: 1.7 KiB |
BIN
gui/devices/1024x600/res/images/indeterminate002.png
Executable file
After Width: | Height: | Size: 1.7 KiB |
BIN
gui/devices/1024x600/res/images/indeterminate003.png
Executable file
After Width: | Height: | Size: 1.7 KiB |
BIN
gui/devices/1024x600/res/images/indeterminate004.png
Executable file
After Width: | Height: | Size: 1.7 KiB |
BIN
gui/devices/1024x600/res/images/indeterminate005.png
Executable file
After Width: | Height: | Size: 1.7 KiB |
BIN
gui/devices/1024x600/res/images/indeterminate006.png
Executable file
After Width: | Height: | Size: 1.7 KiB |
BIN
gui/devices/1024x600/res/images/keyboard1.png
Normal file
After Width: | Height: | Size: 21 KiB |
BIN
gui/devices/1024x600/res/images/keyboard2.png
Normal file
After Width: | Height: | Size: 21 KiB |
BIN
gui/devices/1024x600/res/images/keyboard3.png
Normal file
After Width: | Height: | Size: 21 KiB |
BIN
gui/devices/1024x600/res/images/keyboard4.png
Normal file
After Width: | Height: | Size: 19 KiB |
BIN
gui/devices/1024x600/res/images/large_black.png
Normal file
After Width: | Height: | Size: 4.3 KiB |
BIN
gui/devices/1024x600/res/images/medium-button.png
Normal file
After Width: | Height: | Size: 366 B |
BIN
gui/devices/1024x600/res/images/mediumwide-button.png
Normal file
After Width: | Height: | Size: 390 B |
BIN
gui/devices/1024x600/res/images/minus-button.png
Normal file
After Width: | Height: | Size: 275 B |
BIN
gui/devices/1024x600/res/images/plus-button.png
Normal file
After Width: | Height: | Size: 342 B |
BIN
gui/devices/1024x600/res/images/progress_empty.png
Normal file
After Width: | Height: | Size: 1004 B |
BIN
gui/devices/1024x600/res/images/progress_fill.png
Normal file
After Width: | Height: | Size: 238 B |
BIN
gui/devices/1024x600/res/images/radio_empty.png
Normal file
After Width: | Height: | Size: 983 B |
BIN
gui/devices/1024x600/res/images/radio_selected.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
gui/devices/1024x600/res/images/slider-touch.png
Normal file
After Width: | Height: | Size: 6.2 KiB |
BIN
gui/devices/1024x600/res/images/slider-used.png
Normal file
After Width: | Height: | Size: 2.0 KiB |
BIN
gui/devices/1024x600/res/images/slider.png
Normal file
After Width: | Height: | Size: 3.6 KiB |
BIN
gui/devices/1024x600/res/images/sort-button.png
Normal file
After Width: | Height: | Size: 406 B |