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
This commit is contained in:
Dees_Troy 2012-09-05 15:24:24 -04:00
parent 240e4a7247
commit 51a0e82eb2
757 changed files with 165707 additions and 109 deletions

View File

@ -14,6 +14,7 @@
LOCAL_PATH := $(call my-dir)
TARGET_RECOVERY_GUI := true
include $(CLEAR_VARS)
@ -27,32 +28,50 @@ LOCAL_SRC_FILES := \
verifier.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_FORCE_STATIC_EXECUTABLE := true
#LOCAL_FORCE_STATIC_EXECUTABLE := true
RECOVERY_API_VERSION := 3
LOCAL_CFLAGS += -DRECOVERY_API_VERSION=$(RECOVERY_API_VERSION)
LOCAL_STATIC_LIBRARIES := \
libext4_utils_static \
libsparse_static \
libminzip \
libz \
libmtdutils \
libmincrypt \
libminadbd \
libminui \
libpixelflinger_static \
libpng \
libcutils \
libstdc++ \
libc
#LOCAL_STATIC_LIBRARIES := \
# libext4_utils \
# libminzip \
# libmtdutils \
# libmincrypt \
# libminadbd \
# libpixelflinger_static
LOCAL_C_INCLUDES += bionic external/stlport/stlport
LOCAL_STATIC_LIBRARIES :=
LOCAL_SHARED_LIBRARIES :=
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)
LOCAL_CFLAGS += -DUSE_EXT4
LOCAL_C_INCLUDES += system/extras/ext4_utils
LOCAL_STATIC_LIBRARIES += libext4_utils_static libz
LOCAL_STATIC_LIBRARIES += libext4_utils
endif
ifeq ($(HAVE_SELINUX), true)
@ -73,14 +92,118 @@ else
LOCAL_STATIC_LIBRARIES += $(TARGET_RECOVERY_UI_LIB)
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
#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)
@ -101,13 +224,34 @@ LOCAL_STATIC_LIBRARIES := \
libc
include $(BUILD_EXECUTABLE)
commands_recovery_local_path := $(LOCAL_PATH)
include $(LOCAL_PATH)/minui/Android.mk \
$(LOCAL_PATH)/minelf/Android.mk \
$(LOCAL_PATH)/minzip/Android.mk \
$(LOCAL_PATH)/minadbd/Android.mk \
$(LOCAL_PATH)/mtdutils/Android.mk \
$(LOCAL_PATH)/tools/Android.mk \
$(LOCAL_PATH)/edify/Android.mk \
$(LOCAL_PATH)/updater/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 :=

View File

@ -52,5 +52,6 @@ LOCAL_MODULE := imgdiff
LOCAL_FORCE_STATIC_EXECUTABLE := true
LOCAL_C_INCLUDES += external/zlib external/bzip2
LOCAL_STATIC_LIBRARIES += libz libbz
LOCAL_MODULE_TAGS := eng
include $(BUILD_HOST_EXECUTABLE)

35
bmlutils/Android.mk Normal file
View 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
View 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
View File

@ -0,0 +1,6 @@
#ifndef BMLUTILS_H_
#define BMLUTILS_H_
int format_rfs_device (const char *device, const char *path);
#endif // BMLUTILS_H_

View File

@ -16,7 +16,9 @@
#include "bootloader.h"
#include "common.h"
extern "C" {
#include "mtdutils/mtdutils.h"
}
#include "roots.h"
#include <errno.h>

View File

@ -23,6 +23,9 @@
extern "C" {
#endif
#define ui_print(...) fprintf(stdout, __VA_ARGS__)
#define ui_print_overwrite(...) fprintf(stdout, __VA_ARGS__)
// TODO: restore ui_print for LOGE
#define LOGE(...) fprintf(stdout, "E:" __VA_ARGS__)
#define LOGW(...) fprintf(stdout, "W:" __VA_ARGS__)

View 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)

View 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
View 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
View 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
View 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);
}

View 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 */

View 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

File diff suppressed because it is too large Load Diff

89
crypto/ics/cryptfs.h Normal file
View 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

File diff suppressed because it is too large Load Diff

89
crypto/jb/cryptfs.h Normal file
View 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
View 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
View 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
View 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

View File

@ -3,30 +3,19 @@ on early-init
on init
export PATH /sbin
export LD_LIBRARY_PATH .:/sbin
export ANDROID_ROOT /system
export ANDROID_DATA /data
export EXTERNAL_STORAGE /sdcard
symlink /system/etc /etc
mkdir /sdcard
mkdir /emmc
mkdir /system
mkdir /data
mkdir /cache
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
ifup lo
@ -44,9 +33,18 @@ service adbd /sbin/adbd recovery
disabled
# Always start adbd on userdebug and eng builds
# In recovery, always run adbd as root.
on property:ro.debuggable=1
write /sys/class/android_usb/android0/enable 1
start adbd
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/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
on property:service.adb.root=1

956
extra-functions.c Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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

File diff suppressed because it is too large Load Diff

137
gui/animation.cpp Normal file
View 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
View File

@ -0,0 +1,6 @@
#!/bin/sh
cd res
zip -r ../ui.zip *
cd ..

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 858 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 311 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 533 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 591 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 819 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 845 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 807 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 854 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

1949
gui/basicTheme/res/ui.xml Normal file

File diff suppressed because it is too large Load Diff

BIN
gui/basicTheme/ui.zip Normal file

Binary file not shown.

194
gui/button.cpp Normal file
View 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
View 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
View 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
View 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;
}

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 508 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 866 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 446 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 216 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 653 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 649 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 287 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 322 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 426 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 366 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 390 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 275 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 342 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1004 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 238 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 983 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 406 B

Some files were not shown because too many files have changed in this diff Show More