Compare commits

..

1 Commits

Author SHA1 Message Date
7a1c31d8ab fix yes/no issue where the index is 0 and not 7 2012-01-13 14:17:40 +00:00
68 changed files with 1685 additions and 2301 deletions

View File

@ -1,3 +1,6 @@
ifneq ($(TARGET_SIMULATOR),true)
ifeq ($(TARGET_ARCH),arm)
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
@ -10,15 +13,15 @@ LOCAL_SRC_FILES := \
install.c \
roots.c \
ui.c \
verifier.c \
encryptedfs_provisioning.c \
mounts.c \
extendedcommands.c \
nandroid.c \
../../system/core/toolbox/reboot.c \
firmware.c \
edifyscripting.c \
setprop.c \
default_recovery_ui.c \
verifier.c
setprop.c
ADDITIONAL_RECOVERY_FILES := $(shell echo $$ADDITIONAL_RECOVERY_FILES)
LOCAL_SRC_FILES += $(ADDITIONAL_RECOVERY_FILES)
@ -34,22 +37,13 @@ else
RECOVERY_NAME := CWM-based Recovery
endif
RECOVERY_VERSION := $(RECOVERY_NAME) v5.5.0.4
RECOVERY_VERSION := $(RECOVERY_NAME) v5.0.2.7
LOCAL_CFLAGS += -DRECOVERY_VERSION="$(RECOVERY_VERSION)"
RECOVERY_API_VERSION := 2
LOCAL_CFLAGS += -DRECOVERY_API_VERSION=$(RECOVERY_API_VERSION)
ifneq ($(BOARD_USE_CUSTOM_RECOVERY_FONT),)
BOARD_RECOVERY_CHAR_WIDTH := $(shell echo $(BOARD_USE_CUSTOM_RECOVERY_FONT) | cut -d _ -f 2 | cut -d . -f 1 | cut -d x -f 1)
BOARD_RECOVERY_CHAR_HEIGHT := $(shell echo $(BOARD_USE_CUSTOM_RECOVERY_FONT) | cut -d _ -f 2 | cut -d . -f 1 | cut -d x -f 2)
else
BOARD_RECOVERY_CHAR_WIDTH := 10
BOARD_RECOVERY_CHAR_HEIGHT := 18
endif
LOCAL_CFLAGS += -DBOARD_RECOVERY_CHAR_WIDTH=$(BOARD_RECOVERY_CHAR_WIDTH) -DBOARD_RECOVERY_CHAR_HEIGHT=$(BOARD_RECOVERY_CHAR_HEIGHT)
BOARD_RECOVERY_DEFINES := BOARD_HAS_NO_SELECT_BUTTON BOARD_UMS_LUNFILE BOARD_RECOVERY_ALWAYS_WIPES BOARD_RECOVERY_HANDLES_MOUNT BOARD_TOUCH_RECOVERY
BOARD_RECOVERY_DEFINES := BOARD_HAS_NO_SELECT_BUTTON BOARD_HAS_SMALL_RECOVERY BOARD_LDPI_RECOVERY BOARD_UMS_LUNFILE BOARD_RECOVERY_ALWAYS_WIPES BOARD_RECOVERY_HANDLES_MOUNT
$(foreach board_define,$(BOARD_RECOVERY_DEFINES), \
$(if $($(board_define)), \
@ -57,12 +51,6 @@ $(foreach board_define,$(BOARD_RECOVERY_DEFINES), \
) \
)
LOCAL_STATIC_LIBRARIES :=
LOCAL_CFLAGS += -DUSE_EXT4
LOCAL_C_INCLUDES += system/extras/ext4_utils
LOCAL_STATIC_LIBRARIES += libext4_utils libz
# This binary is in the recovery ramdisk, which is otherwise a copy of root.
# It gets copied there in config/Makefile. LOCAL_MODULE_TAGS suppresses
# a (redundant) copy of the binary in /system/bin for user builds.
@ -70,16 +58,18 @@ LOCAL_STATIC_LIBRARIES += libext4_utils libz
LOCAL_MODULE_TAGS := eng
LOCAL_STATIC_LIBRARIES :=
ifeq ($(BOARD_CUSTOM_RECOVERY_KEYMAPPING),)
LOCAL_SRC_FILES += default_recovery_keys.c
LOCAL_SRC_FILES += default_recovery_ui.c
else
LOCAL_SRC_FILES += $(BOARD_CUSTOM_RECOVERY_KEYMAPPING)
endif
LOCAL_STATIC_LIBRARIES += librebootrecovery
LOCAL_STATIC_LIBRARIES += libext4_utils libz
LOCAL_STATIC_LIBRARIES += libminzip libunz libmincrypt
LOCAL_STATIC_LIBRARIES += libedify libbusybox libmkyaffs2image libunyaffs liberase_image libdump_image libflash_image
LOCAL_STATIC_LIBRARIES += libedify libbusybox libclearsilverregex libmkyaffs2image libunyaffs liberase_image libdump_image libflash_image
LOCAL_STATIC_LIBRARIES += libcrecovery libflashutils libmtdutils libmmcutils libbmlutils
@ -109,7 +99,12 @@ ALL_DEFAULT_INSTALLED_MODULES += $(RECOVERY_SYMLINKS)
# Now let's do recovery symlinks
BUSYBOX_LINKS := $(shell cat external/busybox/busybox-minimal.links)
exclude := tune2fs mke2fs
ifndef BOARD_HAS_SMALL_RECOVERY
exclude := tune2fs
ifeq ($(BOARD_HAS_LARGE_FILESYSTEM),true)
exclude += mke2fs
endif
endif
RECOVERY_BUSYBOX_SYMLINKS := $(addprefix $(TARGET_RECOVERY_ROOT_OUT)/sbin/,$(filter-out $(exclude),$(notdir $(BUSYBOX_LINKS))))
$(RECOVERY_BUSYBOX_SYMLINKS): BUSYBOX_BINARY := busybox
$(RECOVERY_BUSYBOX_SYMLINKS): $(LOCAL_INSTALLED_MODULE)
@ -118,11 +113,11 @@ $(RECOVERY_BUSYBOX_SYMLINKS): $(LOCAL_INSTALLED_MODULE)
@rm -rf $@
$(hide) ln -sf $(BUSYBOX_BINARY) $@
ALL_DEFAULT_INSTALLED_MODULES += $(RECOVERY_BUSYBOX_SYMLINKS)
ALL_DEFAULT_INSTALLED_MODULES += $(RECOVERY_BUSYBOX_SYMLINKS)
include $(CLEAR_VARS)
LOCAL_MODULE := nandroid-md5.sh
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_TAGS := eng
LOCAL_MODULE_CLASS := RECOVERY_EXECUTABLES
LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/sbin
LOCAL_SRC_FILES := nandroid-md5.sh
@ -130,7 +125,7 @@ include $(BUILD_PREBUILT)
include $(CLEAR_VARS)
LOCAL_MODULE := killrecovery.sh
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_TAGS := eng
LOCAL_MODULE_CLASS := RECOVERY_EXECUTABLES
LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/sbin
LOCAL_SRC_FILES := killrecovery.sh
@ -150,11 +145,12 @@ LOCAL_STATIC_LIBRARIES := libmincrypt libcutils libstdc++ libc
include $(BUILD_EXECUTABLE)
include $(commands_recovery_local_path)/dedupe/Android.mk
include $(commands_recovery_local_path)/bmlutils/Android.mk
include $(commands_recovery_local_path)/flashutils/Android.mk
include $(commands_recovery_local_path)/libcrecovery/Android.mk
include $(commands_recovery_local_path)/minui/Android.mk
include $(commands_recovery_local_path)/minelf/Android.mk
include $(commands_recovery_local_path)/minzip/Android.mk
include $(commands_recovery_local_path)/mtdutils/Android.mk
include $(commands_recovery_local_path)/mmcutils/Android.mk
@ -164,3 +160,7 @@ include $(commands_recovery_local_path)/updater/Android.mk
include $(commands_recovery_local_path)/applypatch/Android.mk
include $(commands_recovery_local_path)/utilities/Android.mk
commands_recovery_local_path :=
endif # TARGET_ARCH == arm
endif # !TARGET_SIMULATOR

View File

@ -12,6 +12,9 @@
# See the License for the specific language governing permissions and
# limitations under the License.
ifneq ($(TARGET_SIMULATOR),true)
ifeq ($(TARGET_ARCH),arm)
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
@ -28,7 +31,7 @@ include $(CLEAR_VARS)
LOCAL_SRC_FILES := main.c
LOCAL_MODULE := applypatch
LOCAL_C_INCLUDES += bootable/recovery
LOCAL_STATIC_LIBRARIES += libapplypatch libmtdutils libmincrypt libbz libminelf
LOCAL_STATIC_LIBRARIES += libapplypatch libmtdutils libmincrypt libbz
LOCAL_SHARED_LIBRARIES += libz libcutils libstdc++ libc
include $(BUILD_EXECUTABLE)
@ -40,7 +43,7 @@ LOCAL_MODULE := applypatch_static
LOCAL_FORCE_STATIC_EXECUTABLE := true
LOCAL_MODULE_TAGS := eng
LOCAL_C_INCLUDES += bootable/recovery
LOCAL_STATIC_LIBRARIES += libapplypatch libmtdutils libmincrypt libbz libminelf
LOCAL_STATIC_LIBRARIES += libapplypatch libmtdutils libmincrypt libbz
LOCAL_STATIC_LIBRARIES += libz libcutils libstdc++ libc
include $(BUILD_EXECUTABLE)
@ -55,3 +58,6 @@ LOCAL_C_INCLUDES += external/zlib external/bzip2
LOCAL_STATIC_LIBRARIES += libz libbz
include $(BUILD_HOST_EXECUTABLE)
endif # TARGET_ARCH == arm
endif # !TARGET_SIMULATOR

View File

@ -30,21 +30,16 @@
#include "mtdutils/mtdutils.h"
#include "edify/expr.h"
int SaveFileContents(const char* filename, FileContents file);
static int SaveFileContents(const char* filename, FileContents file);
static int LoadPartitionContents(const char* filename, FileContents* file);
int ParseSha1(const char* str, uint8_t* digest);
static ssize_t FileSink(unsigned char* data, ssize_t len, void* token);
static int mtd_partitions_scanned = 0;
// Read a file into memory; optionally (retouch_flag == RETOUCH_DO_MASK) mask
// the retouched entries back to their original value (such that SHA-1 checks
// don't fail due to randomization); store the file contents and associated
// metadata in *file.
//
// Return 0 on success.
int LoadFileContents(const char* filename, FileContents* file,
int retouch_flag) {
// Read a file into memory; store it and its associated metadata in
// *file. Return 0 on success.
int LoadFileContents(const char* filename, FileContents* file) {
file->data = NULL;
// A special 'filename' beginning with "MTD:" or "EMMC:" means to
@ -80,20 +75,6 @@ int LoadFileContents(const char* filename, FileContents* file,
}
fclose(f);
// apply_patch[_check] functions are blind to randomization. Randomization
// is taken care of in [Undo]RetouchBinariesFn. If there is a mismatch
// within a file, this means the file is assumed "corrupt" for simplicity.
if (retouch_flag) {
int32_t desired_offset = 0;
if (retouch_mask_data(file->data, file->size,
&desired_offset, NULL) != RETOUCH_DATA_MATCHED) {
printf("error trying to mask retouch entries\n");
free(file->data);
file->data = NULL;
return -1;
}
}
SHA(file->data, file->size, file->sha1);
return 0;
}
@ -322,7 +303,7 @@ static int LoadPartitionContents(const char* filename, FileContents* file) {
// Save the contents of the given FileContents object under the given
// filename. Return 0 on success.
int SaveFileContents(const char* filename, FileContents file) {
static int SaveFileContents(const char* filename, FileContents file) {
int fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC);
if (fd < 0) {
printf("failed to open \"%s\" for write: %s\n",
@ -496,7 +477,7 @@ int applypatch_check(const char* filename,
// LoadFileContents is successful. (Useful for reading
// partitions, where the filename encodes the sha1s; no need to
// check them twice.)
if (LoadFileContents(filename, &file, RETOUCH_DO_MASK) != 0 ||
if (LoadFileContents(filename, &file) != 0 ||
(num_patches > 0 &&
FindMatchingPatch(file.sha1, patch_sha1_str, num_patches) < 0)) {
printf("file \"%s\" doesn't have any of expected "
@ -510,7 +491,7 @@ int applypatch_check(const char* filename,
// exists and matches the sha1 we're looking for, the check still
// passes.
if (LoadFileContents(CACHE_TEMP_SOURCE, &file, RETOUCH_DO_MASK) != 0) {
if (LoadFileContents(CACHE_TEMP_SOURCE, &file) != 0) {
printf("failed to load cache file\n");
return 1;
}
@ -636,8 +617,7 @@ int applypatch(const char* source_filename,
int made_copy = 0;
// We try to load the target file into the source_file object.
if (LoadFileContents(target_filename, &source_file,
RETOUCH_DO_MASK) == 0) {
if (LoadFileContents(target_filename, &source_file) == 0) {
if (memcmp(source_file.sha1, target_sha1, SHA_DIGEST_SIZE) == 0) {
// The early-exit case: the patch was already applied, this file
// has the desired hash, nothing for us to do.
@ -653,8 +633,7 @@ int applypatch(const char* source_filename,
// Need to load the source file: either we failed to load the
// target file, or we did but it's different from the source file.
free(source_file.data);
LoadFileContents(source_filename, &source_file,
RETOUCH_DO_MASK);
LoadFileContents(source_filename, &source_file);
}
if (source_file.data != NULL) {
@ -669,8 +648,7 @@ int applypatch(const char* source_filename,
free(source_file.data);
printf("source file is bad; trying copy\n");
if (LoadFileContents(CACHE_TEMP_SOURCE, &copy_file,
RETOUCH_DO_MASK) < 0) {
if (LoadFileContents(CACHE_TEMP_SOURCE, &copy_file) < 0) {
// fail.
printf("failed to read copy file\n");
return 1;

View File

@ -19,7 +19,6 @@
#include <sys/stat.h>
#include "mincrypt/sha.h"
#include "minelf/Retouch.h"
#include "edify/expr.h"
typedef struct _Patch {
@ -60,12 +59,10 @@ int applypatch_check(const char* filename,
int num_patches,
char** const patch_sha1_str);
int LoadFileContents(const char* filename, FileContents* file,
int retouch_flag);
int SaveFileContents(const char* filename, FileContents file);
// Read a file into memory; store it and its associated metadata in
// *file. Return 0 on success.
int LoadFileContents(const char* filename, FileContents* file);
void FreeFileContents(FileContents* file);
int FindMatchingPatch(uint8_t* sha1, char** const patch_sha1_str,
int num_patches);
// bsdiff.c
void ShowBSDiffLicense();

View File

@ -74,7 +74,7 @@ static int ParsePatchArgs(int argc, char** argv,
(*patches)[i] = NULL;
} else {
FileContents fc;
if (LoadFileContents(colon, &fc, RETOUCH_DONT_MASK) != 0) {
if (LoadFileContents(colon, &fc) != 0) {
goto abort;
}
(*patches)[i] = malloc(sizeof(Value));

View File

@ -10,9 +10,6 @@ $(foreach board_define,$(BOARD_RECOVERY_DEFINES), \
) \
)
LOCAL_STATIC_LIBRARIES := libcrecovery
LOCAL_C_INCLUDES := bootable/recovery/libcrecovery
LOCAL_SRC_FILES := bmlutils.c
LOCAL_MODULE := libbmlutils
LOCAL_MODULE_TAGS := eng

View File

@ -20,8 +20,7 @@
#include <signal.h>
#include <sys/wait.h>
#include <common.h>
extern int __system(const char *command);
#define BML_UNLOCK_ALL 0x8A29 ///< unlock all partition RO -> RW
#ifndef BOARD_BML_BOOT

View File

@ -22,8 +22,6 @@
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
static int get_bootloader_message_mtd(struct bootloader_message *out, const Volume* v);
static int set_bootloader_message_mtd(const struct bootloader_message *in, const Volume* v);
@ -142,26 +140,8 @@ static int set_bootloader_message_mtd(const struct bootloader_message *in,
// for misc partitions on block devices
// ------------------------------------
static void wait_for_device(const char* fn) {
int tries = 0;
int ret;
struct stat buf;
do {
++tries;
ret = stat(fn, &buf);
if (ret) {
printf("stat %s try %d: %s\n", fn, tries, strerror(errno));
sleep(1);
}
} while (ret && tries < 10);
if (ret) {
printf("failed to stat %s\n", fn);
}
}
static int get_bootloader_message_block(struct bootloader_message *out,
const Volume* v) {
wait_for_device(v->device);
FILE* f = fopen(v->device, "rb");
if (f == NULL) {
LOGE("Can't open %s\n(%s)\n", v->device, strerror(errno));
@ -183,7 +163,6 @@ static int get_bootloader_message_block(struct bootloader_message *out,
static int set_bootloader_message_block(const struct bootloader_message *in,
const Volume* v) {
wait_for_device(v->device);
FILE* f = fopen(v->device, "wb");
if (f == NULL) {
LOGE("Can't open %s\n(%s)\n", v->device, strerror(errno));
@ -349,4 +328,4 @@ int write_update_for_bootloader(
}
return 0;
}
}

View File

@ -26,7 +26,6 @@ void ui_init();
int ui_wait_key(); // waits for a key/button press, returns the code
int ui_key_pressed(int key); // returns >0 if the code is currently pressed
int ui_text_visible(); // returns >0 if text log is currently visible
int ui_text_ever_visible(); // returns >0 if text log was ever visible
void ui_show_text(int visible);
void ui_clear_key_queue();
@ -114,13 +113,6 @@ typedef struct {
const char* device2; // alternative device to try if fs_type
// == "ext4" or "vfat" and mounting
// 'device' fails
long long length; // (ext4 partition only) when
// formatting, size to use for the
// partition. 0 or negative number
// means to format all but the last
// (that much).
const char* fs_type2;
const char* fs_options;
@ -128,26 +120,4 @@ typedef struct {
const char* fs_options2;
} Volume;
typedef struct {
// number of frames in indeterminate progress bar animation
int indeterminate_frames;
// number of frames per second to try to maintain when animating
int update_fps;
// number of frames in installing animation. may be zero for a
// static installation icon.
int installing_frames;
// the install icon is animated by drawing images containing the
// changing part over the base icon. These specify the
// coordinates of the upper-left corner.
int install_overlay_offset_x;
int install_overlay_offset_y;
} UIParameters;
// fopen a file, mounting volumes and making parent dirs as necessary.
FILE* fopen_path(const char *path, const char *mode);
#endif // RECOVERY_COMMON_H

24
dedupe/Android.mk Normal file
View File

@ -0,0 +1,24 @@
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := dedupe.c
LOCAL_FORCE_STATIC_EXECUTABLE := true
LOCAL_MODULE_TAGS := eng
LOCAL_MODULE := dedupe
LOCAL_STATIC_LIBRARIES := libcrypto_static
LOCAL_C_INCLUDES += $(LOCAL_PATH)/../../../external/openssl/include
include $(BUILD_HOST_EXECUTABLE)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := dedupe.c
LOCAL_STATIC_LIBRARIES := libcrypto libcutils libc
LOCAL_MODULE := utility_dedupe
LOCAL_MODULE_TAGS := eng
LOCAL_MODULE_STEM := dedupe
LOCAL_MODULE_CLASS := UTILITY_EXECUTABLES
LOCAL_C_INCLUDES := external/openssl/include
LOCAL_UNSTRIPPED_PATH := $(PRODUCT_OUT)/symbols/utilities
LOCAL_MODULE_PATH := $(PRODUCT_OUT)/utilities
LOCAL_FORCE_STATIC_EXECUTABLE := true
include $(BUILD_EXECUTABLE)

330
dedupe/dedupe.c Normal file
View File

@ -0,0 +1,330 @@
#include <stdio.h>
#include <sys/stat.h>
#include <openssl/md5.h>
#include <openssl/sha.h>
#include <openssl/ripemd.h>
#include <errno.h>
#include <dirent.h>
#include <limits.h>
#include <stdlib.h>
#include <fcntl.h>
#include <limits.h>
typedef struct DEDUPE_STORE_CONTEXT {
char blob_dir[PATH_MAX];
FILE *output_manifest;
};
static void usage(char** argv) {
fprintf(stderr, "usage: %s c input_directory blob_dir output_manifest\n", argv[0]);
fprintf(stderr, "usage: %s x input_manifest blob_dir output_directory\n", argv[0]);
}
static int copy_file(const char *dst, const char *src) {
char buf[4096];
int dstfd, srcfd, bytes_read, bytes_written, total_read = 0;
if (src == NULL)
return 1;
if (dst == NULL)
return 2;
srcfd = open(src, O_RDONLY);
if (srcfd < 0)
return 3;
dstfd = open(dst, O_RDWR | O_CREAT | O_TRUNC, 0600);
if (dstfd < 0) {
close(srcfd);
return 4;
}
while (bytes_read = read(srcfd, buf, 4096)) {
total_read += bytes_read;
if (write(dstfd, buf, bytes_read) != bytes_read)
return 5;
}
close(dstfd);
close(srcfd);
return 0;
}
static void do_sha256sum(FILE *mfile, unsigned char *rptr) {
char rdata[BUFSIZ];
int rsize;
SHA256_CTX c;
SHA256_Init(&c);
while(!feof(mfile)) {
rsize = fread(rdata, sizeof(char), BUFSIZ, mfile);
if(rsize > 0) {
SHA256_Update(&c, rdata, rsize);
}
}
SHA256_Final(rptr, &c);
}
static int do_sha256sum_file(const char* filename, unsigned char *rptr) {
FILE *f = fopen(filename, "rb");
if (f == NULL) {
fprintf(stderr, "Unable to open file: %s\n", filename);
return 1;
}
do_sha256sum(f, rptr);
fclose(f);
return 0;
}
static int store_st(struct DEDUPE_STORE_CONTEXT *context, struct stat st, const char* s);
void print_stat(struct DEDUPE_STORE_CONTEXT *context, char type, struct stat st, const char *f) {
fprintf(context->output_manifest, "%c\t%o\t%d\t%d\t%s\t", type, st.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO | S_ISUID | S_ISGID), st.st_uid, st.st_gid, f);
}
static int store_file(struct DEDUPE_STORE_CONTEXT *context, struct stat st, const char* f) {
printf("%s\n", f);
unsigned char sumdata[SHA256_DIGEST_LENGTH];
int ret;
if (ret = do_sha256sum_file(f, sumdata)) {
fprintf(stderr, "Error calculating sha256sum of %s\n", f);
return ret;
}
char psum[128];
int j;
for (j = 0; j < SHA256_DIGEST_LENGTH; j++)
sprintf(&psum[(j*2)], "%02x", (int)sumdata[j]);
psum[(SHA256_DIGEST_LENGTH * 2)] = '\0';
char out_blob[PATH_MAX];
sprintf(out_blob, "%s/%s", context->blob_dir, psum);
if (ret = copy_file(out_blob, f)) {
fprintf(stderr, "Error copying blob %s\n", f);
return ret;
}
fprintf(context->output_manifest, "%s\t%d\t\n", psum, st.st_size);
return 0;
}
static int store_dir(struct DEDUPE_STORE_CONTEXT *context, struct stat st, const char* d) {
printf("%s\n", d);
DIR *dp = opendir(d);
if (d == NULL) {
fprintf(stderr, "Error opening directory: %s\n", d);
return 1;
}
struct dirent *ep;
char full_path[PATH_MAX];
while (ep = readdir(dp)) {
if (strcmp(ep->d_name, ".") == 0)
continue;
if (strcmp(ep->d_name, "..") == 0)
continue;
struct stat cst;
int ret;
sprintf(full_path, "%s/%s", d, ep->d_name);
if (0 != (ret = lstat(full_path, &cst))) {
fprintf(stderr, "Error opening: %s\n", ep->d_name);
closedir(dp);
return ret;
}
if (ret = store_st(context, cst, full_path))
return ret;
}
closedir(dp);
return 0;
}
static int store_link(struct DEDUPE_STORE_CONTEXT *context, struct stat st, const char* l) {
printf("%s\n", l);
char link[PATH_MAX];
int ret = readlink(l, link, PATH_MAX);
if (ret < 0) {
fprintf(stderr, "Error reading symlink\n");
return errno;
}
link[ret] = '\0';
fprintf(context->output_manifest, "%s\t\n", link);
return 0;
}
static int store_st(struct DEDUPE_STORE_CONTEXT *context, struct stat st, const char* s) {
if (S_ISREG(st.st_mode)) {
print_stat(context, 'f', st, s);
return store_file(context, st, s);
}
else if (S_ISDIR(st.st_mode)) {
print_stat(context, 'd', st, s);
fprintf(context->output_manifest, "\n");
return store_dir(context, st, s);
}
else if (S_ISLNK(st.st_mode)) {
print_stat(context, 'l', st, s);
return store_link(context, st, s);
}
else {
fprintf(stderr, "Skipping special: %s\n", s);
return 0;
}
}
void get_full_path(char *out_path, char *rel_path) {
char tmp[PATH_MAX];
getcwd(tmp, PATH_MAX);
chdir(rel_path);
getcwd(out_path, PATH_MAX);
chdir(tmp);
}
static char* tokenize(char *out, const char* line, const char sep) {
while (*line != sep) {
if (*line == '\0') {
return NULL;
}
*out = *line;
out++;
line++;
}
*out = '\0';
// resume at the next char
return ++line;
}
static int dec_to_oct(int dec) {
int ret = 0;
int mult = 1;
while (dec != 0) {
int rem = dec % 10;
ret += (rem * mult);
dec /= 10;
mult *= 8;
}
return ret;
}
int main(int argc, char** argv) {
if (argc != 5) {
usage(argv);
return 1;
}
if (strcmp(argv[1], "c") == 0) {
struct stat st;
int ret;
if (0 != (ret = lstat(argv[2], &st))) {
fprintf(stderr, "Error opening input_file/input_directory.\n");
return ret;
}
if (!S_ISDIR(st.st_mode)) {
fprintf(stderr, "%s must be a directory.\n", argv[2]);
return 1;
}
char blob_dir[PATH_MAX];
struct DEDUPE_STORE_CONTEXT context;
context.output_manifest = fopen(argv[4], "wb");
if (context.output_manifest == NULL) {
fprintf(stderr, "Unable to open output file %s\n", argv[4]);
return 1;
}
get_full_path(context.blob_dir, argv[3]);
chdir(argv[2]);
return store_dir(&context, st, ".");
}
else if (strcmp(argv[1], "x") == 0) {
FILE *input_manifest = fopen(argv[2], "rb");
if (input_manifest == NULL) {
fprintf(stderr, "Unable to open input manifest %s\n", argv[2]);
return 1;
}
char blob_dir[PATH_MAX];
char *output_dir = argv[4];
get_full_path(blob_dir, argv[3]);
printf("%s\n" , output_dir);
chdir(output_dir);
char line[PATH_MAX];
while (fgets(line, PATH_MAX, input_manifest)) {
//printf("%s", line);
char type[4];
char mode[8];
char uid[32];
char gid[32];
char filename[PATH_MAX];
char *token = line;
token = tokenize(type, token, '\t');
token = tokenize(mode, token, '\t');
token = tokenize(uid, token, '\t');
token = tokenize(gid, token, '\t');
token = tokenize(filename, token, '\t');
int mode_oct = dec_to_oct(atoi(mode));
int uid_int = atoi(uid);
int gid_int = atoi(gid);
int ret;
printf("%s\t%s\t%s\t%s\t%s\t", type, mode, uid, gid, filename);
if (strcmp(type, "f") == 0) {
char sha256[128];
token = tokenize(sha256, token, '\t');
char sizeStr[32];
token = tokenize(sizeStr, token, '\t');
int size = atoi(sizeStr);
printf("%s\t%d\n", sha256, size);
char blob_file[PATH_MAX];
sprintf(blob_file, "%s/%s", blob_dir, sha256);
if (ret = copy_file(filename, blob_file)) {
fprintf(stderr, "Unable to copy file %s\n", filename);
fclose(input_manifest);
return ret;
}
chmod(filename, mode_oct);
chown(filename, uid_int, gid_int);
}
else if (strcmp(type, "l") == 0) {
char link[41];
token = tokenize(link, token, '\t');
printf("%s\n", link);
symlink(link, filename);
// Android has no lchmod, and chmod follows symlinks
//chmod(filename, mode_oct);
lchown(filename, uid_int, gid_int);
}
else if (strcmp(type, "d") == 0) {
printf("\n");
mkdir(filename, mode_oct);
chmod(filename, mode_oct);
chown(filename, uid_int, gid_int);
}
else {
fprintf(stderr, "Unknown type %s\n", type);
fclose(input_manifest);
return 1;
}
}
fclose(input_manifest);
return 0;
}
else {
usage(argv);
return 1;
}
}

View File

@ -1,68 +0,0 @@
#include <linux/input.h>
#include "recovery_ui.h"
#include "common.h"
#include "extendedcommands.h"
int device_toggle_display(volatile char* key_pressed, int key_code) {
int alt = key_pressed[KEY_LEFTALT] || key_pressed[KEY_RIGHTALT];
if (alt && key_code == KEY_L)
return 1;
// allow toggling of the display if the correct key is pressed, and the display toggle is allowed or the display is currently off
if (ui_get_showing_back_button()) {
return 0;
//return get_allow_toggle_display() && (key_code == KEY_HOME || key_code == KEY_MENU || key_code == KEY_END);
}
return get_allow_toggle_display() && (key_code == KEY_HOME || key_code == KEY_MENU || key_code == KEY_POWER || key_code == KEY_END);
}
int device_handle_key(int key_code, int visible) {
if (visible) {
switch (key_code) {
case KEY_CAPSLOCK:
case KEY_DOWN:
case KEY_VOLUMEDOWN:
case KEY_MENU:
return HIGHLIGHT_DOWN;
case KEY_LEFTSHIFT:
case KEY_UP:
case KEY_VOLUMEUP:
case KEY_HOME:
return HIGHLIGHT_UP;
case KEY_POWER:
if (ui_get_showing_back_button()) {
return SELECT_ITEM;
}
if (!get_allow_toggle_display() && ui_menu_level > 0) {
return GO_BACK;
}
break;
case KEY_LEFTBRACE:
case KEY_ENTER:
case BTN_MOUSE:
case KEY_CAMERA:
case KEY_F21:
case KEY_SEND:
return SELECT_ITEM;
case KEY_END:
case KEY_BACKSPACE:
case KEY_SEARCH:
if (ui_get_showing_back_button()) {
return SELECT_ITEM;
}
if (!get_allow_toggle_display() && ui_menu_level > 0) {
return GO_BACK;
}
case KEY_BACK:
if (ui_menu_level > 0) {
return GO_BACK;
}
}
}
return NO_ACTION;
}

View File

@ -23,25 +23,83 @@
char* MENU_HEADERS[] = { NULL };
char* MENU_ITEMS[] = { "reboot system now",
"install zip from sdcard",
"apply update from sdcard",
"wipe data/factory reset",
"wipe cache partition",
"install zip from sdcard",
"backup and restore",
"mounts and storage",
"advanced",
"power off",
NULL };
void device_ui_init(UIParameters* ui_parameters) {
}
int device_recovery_start() {
return 0;
}
int device_toggle_display(volatile char* key_pressed, int key_code) {
int alt = key_pressed[KEY_LEFTALT] || key_pressed[KEY_RIGHTALT];
if (alt && key_code == KEY_L)
return 1;
// allow toggling of the display if the correct key is pressed, and the display toggle is allowed or the display is currently off
if (ui_get_showing_back_button()) {
return 0;
//return get_allow_toggle_display() && (key_code == KEY_HOME || key_code == KEY_MENU || key_code == KEY_END);
}
return get_allow_toggle_display() && (key_code == KEY_HOME || key_code == KEY_MENU || key_code == KEY_POWER || key_code == KEY_END);
}
int device_reboot_now(volatile char* key_pressed, int key_code) {
return 0;
}
int device_handle_key(int key_code, int visible) {
if (visible) {
switch (key_code) {
case KEY_CAPSLOCK:
case KEY_DOWN:
case KEY_VOLUMEDOWN:
case KEY_MENU:
return HIGHLIGHT_DOWN;
case KEY_LEFTSHIFT:
case KEY_UP:
case KEY_VOLUMEUP:
case KEY_HOME:
return HIGHLIGHT_UP;
case KEY_POWER:
if (ui_get_showing_back_button()) {
return SELECT_ITEM;
}
if (!get_allow_toggle_display())
return GO_BACK;
break;
case KEY_LEFTBRACE:
case KEY_ENTER:
case BTN_MOUSE:
case KEY_CENTER:
case KEY_CAMERA:
case KEY_F21:
case KEY_SEND:
return SELECT_ITEM;
case KEY_END:
case KEY_BACKSPACE:
case KEY_SEARCH:
if (ui_get_showing_back_button()) {
return SELECT_ITEM;
}
if (!get_allow_toggle_display())
return GO_BACK;
case KEY_BACK:
return GO_BACK;
}
}
return NO_ACTION;
}
int device_perform_action(int which) {
return which;
}

View File

@ -1,18 +1,6 @@
/*
* 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.
*/
// Copyright ClockworkMod, LLC. Reference and porting purposes only. Usage of the extendedcommand API
// is restricted to those granted explicit permission, or by use of the ROM Manager Recovery API.
// https://github.com/koush/TestRomManager
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>

283
encryptedfs_provisioning.c Normal file
View File

@ -0,0 +1,283 @@
/*
* Copyright (C) 2009 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 <stdlib.h>
#include <string.h>
#include <sys/mount.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include "encryptedfs_provisioning.h"
#include "cutils/misc.h"
#include "cutils/properties.h"
#include "common.h"
#include "mtdutils/mtdutils.h"
#include "mounts.h"
#include "roots.h"
const char* encrypted_fs_enabled_property = "persist.security.secfs.enabled";
const char* encrypted_fs_property_dir = "/data/property/";
const char* encrypted_fs_system_dir = "/data/system/";
const char* encrypted_fs_key_file_name = "/data/fs_key.dat";
const char* encrypted_fs_salt_file_name = "/data/hash_salt.dat";
const char* encrypted_fs_hash_file_src_name = "/data/system/password.key";
const char* encrypted_fs_hash_file_dst_name = "/data/hash.dat";
const char* encrypted_fs_entropy_file_src_name = "/data/system/entropy.dat";
const char* encrypted_fs_entropy_file_dst_name = "/data/ported_entropy.dat";
void get_property_file_name(char *buffer, const char *property_name) {
sprintf(buffer, "%s%s", encrypted_fs_property_dir, property_name);
}
int get_binary_file_contents(char *buffer, int buf_size, const char *file_name, int *out_size) {
FILE *in_file;
int read_bytes;
in_file = fopen(file_name, "r");
if (in_file == NULL) {
LOGE("Secure FS: error accessing key file.");
return ENCRYPTED_FS_ERROR;
}
read_bytes = fread(buffer, 1, buf_size, in_file);
if (out_size == NULL) {
if (read_bytes != buf_size) {
// Error or unexpected data
fclose(in_file);
LOGE("Secure FS: error reading conmplete key.");
return ENCRYPTED_FS_ERROR;
}
} else {
*out_size = read_bytes;
}
fclose(in_file);
return ENCRYPTED_FS_OK;
}
int set_binary_file_contents(char *buffer, int buf_size, const char *file_name) {
FILE *out_file;
int write_bytes;
out_file = fopen(file_name, "w");
if (out_file == NULL) {
LOGE("Secure FS: error setting up key file.");
return ENCRYPTED_FS_ERROR;
}
write_bytes = fwrite(buffer, 1, buf_size, out_file);
if (write_bytes != buf_size) {
// Error or unexpected data
fclose(out_file);
LOGE("Secure FS: error reading conmplete key.");
return ENCRYPTED_FS_ERROR;
}
fclose(out_file);
return ENCRYPTED_FS_OK;
}
int get_text_file_contents(char *buffer, int buf_size, char *file_name) {
FILE *in_file;
char *read_data;
in_file = fopen(file_name, "r");
if (in_file == NULL) {
LOGE("Secure FS: error accessing properties.");
return ENCRYPTED_FS_ERROR;
}
read_data = fgets(buffer, buf_size, in_file);
if (read_data == NULL) {
// Error or unexpected data
fclose(in_file);
LOGE("Secure FS: error accessing properties.");
return ENCRYPTED_FS_ERROR;
}
fclose(in_file);
return ENCRYPTED_FS_OK;
}
int set_text_file_contents(char *buffer, char *file_name) {
FILE *out_file;
int result;
out_file = fopen(file_name, "w");
if (out_file == NULL) {
LOGE("Secure FS: error setting up properties.");
return ENCRYPTED_FS_ERROR;
}
result = fputs(buffer, out_file);
if (result != 0) {
// Error or unexpected data
fclose(out_file);
LOGE("Secure FS: error setting up properties.");
return ENCRYPTED_FS_ERROR;
}
fflush(out_file);
fclose(out_file);
return ENCRYPTED_FS_OK;
}
int read_encrypted_fs_boolean_property(const char *prop_name, int *value) {
char prop_file_name[PROPERTY_KEY_MAX + 32];
char prop_value[PROPERTY_VALUE_MAX];
int result;
get_property_file_name(prop_file_name, prop_name);
result = get_text_file_contents(prop_value, PROPERTY_VALUE_MAX, prop_file_name);
if (result < 0) {
return result;
}
if (strncmp(prop_value, "1", 1) == 0) {
*value = 1;
} else if (strncmp(prop_value, "0", 1) == 0) {
*value = 0;
} else {
LOGE("Secure FS: error accessing properties.");
return ENCRYPTED_FS_ERROR;
}
return ENCRYPTED_FS_OK;
}
int write_encrypted_fs_boolean_property(const char *prop_name, int value) {
char prop_file_name[PROPERTY_KEY_MAX + 32];
char prop_value[PROPERTY_VALUE_MAX];
int result;
get_property_file_name(prop_file_name, prop_name);
// Create the directory if needed
mkdir(encrypted_fs_property_dir, 0755);
if (value == 1) {
result = set_text_file_contents("1", prop_file_name);
} else if (value == 0) {
result = set_text_file_contents("0", prop_file_name);
} else {
return ENCRYPTED_FS_ERROR;
}
if (result < 0) {
return result;
}
return ENCRYPTED_FS_OK;
}
int read_encrypted_fs_info(encrypted_fs_info *encrypted_fs_data) {
int result;
int value;
result = ensure_path_mounted("/data");
if (result != 0) {
LOGE("Secure FS: error mounting userdata partition.");
return ENCRYPTED_FS_ERROR;
}
// Read the pre-generated encrypted FS key, password hash and salt.
result = get_binary_file_contents(encrypted_fs_data->key, ENCRYPTED_FS_KEY_SIZE,
encrypted_fs_key_file_name, NULL);
if (result != 0) {
LOGE("Secure FS: error reading generated file system key.");
return ENCRYPTED_FS_ERROR;
}
result = get_binary_file_contents(encrypted_fs_data->salt, ENCRYPTED_FS_SALT_SIZE,
encrypted_fs_salt_file_name, &(encrypted_fs_data->salt_length));
if (result != 0) {
LOGE("Secure FS: error reading file system salt.");
return ENCRYPTED_FS_ERROR;
}
result = get_binary_file_contents(encrypted_fs_data->hash, ENCRYPTED_FS_MAX_HASH_SIZE,
encrypted_fs_hash_file_src_name, &(encrypted_fs_data->hash_length));
if (result != 0) {
LOGE("Secure FS: error reading password hash.");
return ENCRYPTED_FS_ERROR;
}
result = get_binary_file_contents(encrypted_fs_data->entropy, ENTROPY_MAX_SIZE,
encrypted_fs_entropy_file_src_name, &(encrypted_fs_data->entropy_length));
if (result != 0) {
LOGE("Secure FS: error reading ported entropy.");
return ENCRYPTED_FS_ERROR;
}
result = ensure_path_unmounted("/data");
if (result != 0) {
LOGE("Secure FS: error unmounting data partition.");
return ENCRYPTED_FS_ERROR;
}
return ENCRYPTED_FS_OK;
}
int restore_encrypted_fs_info(encrypted_fs_info *encrypted_fs_data) {
int result;
result = ensure_path_mounted("/data");
if (result != 0) {
LOGE("Secure FS: error mounting userdata partition.");
return ENCRYPTED_FS_ERROR;
}
// Write the pre-generated secure FS key, password hash and salt.
result = set_binary_file_contents(encrypted_fs_data->key, ENCRYPTED_FS_KEY_SIZE,
encrypted_fs_key_file_name);
if (result != 0) {
LOGE("Secure FS: error writing generated file system key.");
return ENCRYPTED_FS_ERROR;
}
result = set_binary_file_contents(encrypted_fs_data->salt, encrypted_fs_data->salt_length,
encrypted_fs_salt_file_name);
if (result != 0) {
LOGE("Secure FS: error writing file system salt.");
return ENCRYPTED_FS_ERROR;
}
result = set_binary_file_contents(encrypted_fs_data->hash, encrypted_fs_data->hash_length,
encrypted_fs_hash_file_dst_name);
if (result != 0) {
LOGE("Secure FS: error writing password hash.");
return ENCRYPTED_FS_ERROR;
}
result = set_binary_file_contents(encrypted_fs_data->entropy, encrypted_fs_data->entropy_length,
encrypted_fs_entropy_file_dst_name);
if (result != 0) {
LOGE("Secure FS: error writing ported entropy.");
return ENCRYPTED_FS_ERROR;
}
// Set the secure FS properties to their respective values
result = write_encrypted_fs_boolean_property(encrypted_fs_enabled_property, encrypted_fs_data->mode);
if (result != 0) {
return result;
}
result = ensure_path_unmounted("/data");
if (result != 0) {
LOGE("Secure FS: error unmounting data partition.");
return ENCRYPTED_FS_ERROR;
}
return ENCRYPTED_FS_OK;
}

View File

@ -0,0 +1,51 @@
/*
* Copyright (C) 2009 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>
#ifndef __ENCRYPTEDFS_PROVISIONING_H__
#define __ENCRYPTEDFS_PROVISIONING_H__
#define MODE_ENCRYPTED_FS_DISABLED 0
#define MODE_ENCRYPTED_FS_ENABLED 1
#define ENCRYPTED_FS_OK 0
#define ENCRYPTED_FS_ERROR (-1)
#define ENCRYPTED_FS_KEY_SIZE 16
#define ENCRYPTED_FS_SALT_SIZE 16
#define ENCRYPTED_FS_MAX_HASH_SIZE 128
#define ENTROPY_MAX_SIZE 4096
struct encrypted_fs_info {
int mode;
char key[ENCRYPTED_FS_KEY_SIZE];
char salt[ENCRYPTED_FS_SALT_SIZE];
int salt_length;
char hash[ENCRYPTED_FS_MAX_HASH_SIZE];
int hash_length;
char entropy[ENTROPY_MAX_SIZE];
int entropy_length;
};
typedef struct encrypted_fs_info encrypted_fs_info;
int read_encrypted_fs_info(encrypted_fs_info *secure_fs_data);
int restore_encrypted_fs_info(encrypted_fs_info *secure_data);
#endif /* __ENCRYPTEDFS_PROVISIONING_H__ */

View File

@ -35,22 +35,8 @@ service recovery /sbin/recovery
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 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
on property:persist.service.adb.enable=1
start adbd
# Restart adbd so it can run as root
on property:service.adb.root=1
write /sys/class/android_usb/android0/enable 0
restart adbd
write /sys/class/android_usb/android0/enable 1
on property:persist.service.adb.enable=0
stop adbd

View File

@ -8,6 +8,7 @@
#include <stdlib.h>
#include <string.h>
#include <sys/reboot.h>
#include <reboot/reboot.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>
@ -25,7 +26,6 @@
#include "cutils/properties.h"
#include "firmware.h"
#include "install.h"
#include "make_ext4fs.h"
#include "minui/minui.h"
#include "minzip/DirUtil.h"
#include "roots.h"
@ -42,7 +42,6 @@
#include <libgen.h>
#include "mtdutils/mtdutils.h"
#include "bmlutils/bmlutils.h"
#include "cutils/android_reboot.h"
int signature_check_enabled = 1;
@ -445,9 +444,6 @@ int format_device(const char *device, const char *path, const char *fs_type) {
LOGE("unknown volume \"%s\"\n", path);
return -1;
}
if (strstr(path, "/data") == path && volume_for_path("/sdcard") == NULL && is_data_media()) {
return format_unknown_device(NULL, path, NULL);
}
if (strcmp(fs_type, "ramdisk") == 0) {
// you can't format the ramdisk.
LOGE("can't format_volume \"%s\"", path);
@ -499,13 +495,8 @@ int format_device(const char *device, const char *path, const char *fs_type) {
}
if (strcmp(fs_type, "ext4") == 0) {
int length = 0;
if (strcmp(v->fs_type, "ext4") == 0) {
// Our desired filesystem matches the one in fstab, respect v->length
length = v->length;
}
reset_ext4fs_info();
int result = make_ext4fs(device, length);
int result = make_ext4fs(device, NULL, NULL, 0, 0, 0);
if (result != 0) {
LOGE("format_volume: make_extf4fs failed on %s\n", device);
return -1;
@ -632,7 +623,7 @@ void show_partition_menu()
string options[255];
if(!device_volumes)
return;
return;
mountable_volumes = 0;
formatable_volumes = 0;
@ -641,24 +632,25 @@ void show_partition_menu()
format_menue = malloc(num_volumes * sizeof(FormatMenuEntry));
for (i = 0; i < num_volumes; ++i) {
Volume* v = &device_volumes[i];
if(strcmp("ramdisk", v->fs_type) != 0 && strcmp("mtd", v->fs_type) != 0 && strcmp("emmc", v->fs_type) != 0 && strcmp("bml", v->fs_type) != 0) {
sprintf(&mount_menue[mountable_volumes].mount, "mount %s", v->mount_point);
sprintf(&mount_menue[mountable_volumes].unmount, "unmount %s", v->mount_point);
mount_menue[mountable_volumes].v = &device_volumes[i];
++mountable_volumes;
if (is_safe_to_format(v->mount_point)) {
sprintf(&format_menue[formatable_volumes].txt, "format %s", v->mount_point);
format_menue[formatable_volumes].v = &device_volumes[i];
++formatable_volumes;
}
}
else if (strcmp("ramdisk", v->fs_type) != 0 && strcmp("mtd", v->fs_type) == 0 && is_safe_to_format(v->mount_point))
{
sprintf(&format_menue[formatable_volumes].txt, "format %s", v->mount_point);
format_menue[formatable_volumes].v = &device_volumes[i];
++formatable_volumes;
}
Volume* v = &device_volumes[i];
if(strcmp("ramdisk", v->fs_type) != 0 && strcmp("mtd", v->fs_type) != 0 && strcmp("emmc", v->fs_type) != 0 && strcmp("bml", v->fs_type) != 0)
{
sprintf(&mount_menue[mountable_volumes].mount, "mount %s", v->mount_point);
sprintf(&mount_menue[mountable_volumes].unmount, "unmount %s", v->mount_point);
mount_menue[mountable_volumes].v = &device_volumes[i];
++mountable_volumes;
if (is_safe_to_format(v->mount_point)) {
sprintf(&format_menue[formatable_volumes].txt, "format %s", v->mount_point);
format_menue[formatable_volumes].v = &device_volumes[i];
++formatable_volumes;
}
}
else if (strcmp("ramdisk", v->fs_type) != 0 && strcmp("mtd", v->fs_type) == 0 && is_safe_to_format(v->mount_point))
{
sprintf(&format_menue[formatable_volumes].txt, "format %s", v->mount_point);
format_menue[formatable_volumes].v = &device_volumes[i];
++formatable_volumes;
}
}
@ -668,39 +660,37 @@ void show_partition_menu()
for (;;)
{
for (i = 0; i < mountable_volumes; i++)
{
MountMenuEntry* e = &mount_menue[i];
Volume* v = e->v;
if(is_path_mounted(v->mount_point))
options[i] = e->unmount;
else
options[i] = e->mount;
}
for (i = 0; i < formatable_volumes; i++)
{
FormatMenuEntry* e = &format_menue[i];
for (i = 0; i < mountable_volumes; i++)
{
MountMenuEntry* e = &mount_menue[i];
Volume* v = e->v;
if(is_path_mounted(v->mount_point))
options[i] = e->unmount;
else
options[i] = e->mount;
}
options[mountable_volumes+i] = e->txt;
}
for (i = 0; i < formatable_volumes; i++)
{
FormatMenuEntry* e = &format_menue[i];
if (!is_data_media()) {
options[mountable_volumes + formatable_volumes] = "mount USB storage";
options[mountable_volumes + formatable_volumes + 1] = NULL;
}
else {
options[mountable_volumes + formatable_volumes] = NULL;
}
options[mountable_volumes+i] = e->txt;
}
options[mountable_volumes+formatable_volumes] = "mount USB storage";
options[mountable_volumes+formatable_volumes + 1] = NULL;
int chosen_item = get_menu_selection(headers, &options, 0, 0);
if (chosen_item == GO_BACK)
break;
if (chosen_item == (mountable_volumes+formatable_volumes)) {
if (chosen_item == (mountable_volumes+formatable_volumes))
{
show_mount_usb_storage_menu();
}
else if (chosen_item < mountable_volumes) {
MountMenuEntry* e = &mount_menue[chosen_item];
else if (chosen_item < mountable_volumes)
{
MountMenuEntry* e = &mount_menue[chosen_item];
Volume* v = e->v;
if (is_path_mounted(v->mount_point))
@ -734,6 +724,7 @@ void show_partition_menu()
free(mount_menue);
free(format_menue);
}
void show_nandroid_advanced_restore_menu(const char* path)
@ -825,7 +816,7 @@ void show_nandroid_menu()
NULL
};
if (volume_for_path("/emmc") == NULL || volume_for_path("/sdcard") == NULL && is_data_media())
if (volume_for_path("/emmc") == NULL)
list[3] = NULL;
int chosen_item = get_menu_selection(headers, list, 0, 0);
@ -903,10 +894,12 @@ void show_advanced_menu()
"Report Error",
"Key Test",
"Show log",
#ifndef BOARD_HAS_SMALL_RECOVERY
"Partition SD Card",
"Fix Permissions",
#ifdef BOARD_HAS_SDCARD_INTERNAL
"Partition Internal SD Card",
#endif
#endif
NULL
};
@ -920,7 +913,7 @@ void show_advanced_menu()
{
case 0:
{
android_reboot(ANDROID_RB_RESTART2, 0, "recovery");
reboot_wrapper("recovery");
break;
}
case 1:

View File

@ -6,7 +6,7 @@ ifeq ($(TARGET_ARCH),arm)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := flashutils.c
LOCAL_MODULE := libflashutils
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_TAGS := eng
LOCAL_C_INCLUDES += bootable/recovery
LOCAL_STATIC_LIBRARIES := libmmcutils libmtdutils libbmlutils libcrecovery
@ -23,54 +23,53 @@ 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_MODULE_TAGS := eng
#LOCAL_STATIC_LIBRARIES += $(BOARD_FLASH_LIBRARY)
LOCAL_STATIC_LIBRARIES := libflashutils libmtdutils libmmcutils libbmlutils
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_MODULE_TAGS := eng
LOCAL_STATIC_LIBRARIES := libflashutils libmtdutils libmmcutils libbmlutils
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_MODULE_TAGS := eng
LOCAL_STATIC_LIBRARIES := libflashutils libmtdutils libmmcutils libbmlutils
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_MODULE_TAGS := eng
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_MODULE_TAGS := eng
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_MODULE_TAGS := eng
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_TAGS := eng
LOCAL_MODULE_CLASS := UTILITY_EXECUTABLES
LOCAL_MODULE_PATH := $(PRODUCT_OUT)/utilities
LOCAL_UNSTRIPPED_PATH := $(PRODUCT_OUT)/symbols/utilities
@ -82,7 +81,7 @@ include $(BUILD_EXECUTABLE)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := flash_image.c
LOCAL_MODULE := utility_flash_image
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_TAGS := eng
LOCAL_MODULE_CLASS := UTILITY_EXECUTABLES
LOCAL_MODULE_PATH := $(PRODUCT_OUT)/utilities
LOCAL_UNSTRIPPED_PATH := $(PRODUCT_OUT)/symbols/utilities
@ -94,7 +93,7 @@ include $(BUILD_EXECUTABLE)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := erase_image.c
LOCAL_MODULE := utility_erase_image
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_TAGS := eng
LOCAL_MODULE_CLASS := UTILITY_EXECUTABLES
LOCAL_MODULE_PATH := $(PRODUCT_OUT)/utilities
LOCAL_UNSTRIPPED_PATH := $(PRODUCT_OUT)/symbols/utilities

View File

@ -103,8 +103,6 @@ handle_firmware_update(char* type, char* filename, ZipArchive* zip) {
return INSTALL_SUCCESS;
}
static const char *LAST_INSTALL_FILE = "/cache/recovery/last_install";
// If the package contains an update binary, extract it and run it.
static int
try_update_binary(const char *path, ZipArchive *zip) {
@ -334,8 +332,8 @@ exit:
return NULL;
}
static int
really_install_package(const char *path)
int
install_package(const char *path)
{
ui_set_background(BACKGROUND_ICON_INSTALLING);
ui_print("Finding update package...\n");
@ -389,23 +387,3 @@ really_install_package(const char *path)
ui_print("Installing update...\n");
return try_update_binary(path, &zip);
}
int
install_package(const char* path)
{
FILE* install_log = fopen_path(LAST_INSTALL_FILE, "w");
if (install_log) {
fputs(path, install_log);
fputc('\n', install_log);
} else {
LOGE("failed to open last_install: %s\n", strerror(errno));
}
int result = really_install_package(path);
if (install_log) {
fputc(result == INSTALL_SUCCESS ? '1' : '0', install_log);
fputc('\n', install_log);
fclose(install_log);
chmod(LAST_INSTALL_FILE, 0644);
}
return result;
}

View File

@ -1,102 +0,0 @@
# 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.
"""Script to take a set of frames (PNG files) for a recovery
"installing" icon animation and turn it into a base image plus a set
of overlays, as needed by the recovery UI code. Run with the names of
all the input frames on the command line, in order."""
import sys
try:
import Image
except ImportError:
print "This script requires the Python Imaging Library to be installed."
sys.exit(1)
# Find the smallest box that contains all the pixels which change
# between images.
print "reading", sys.argv[1]
base = Image.open(sys.argv[1])
minmini = base.size[0]-1
maxmaxi = 0
minminj = base.size[1]-1
maxmaxj = 0
for top_name in sys.argv[2:]:
print "reading", top_name
top = Image.open(top_name)
assert base.size == top.size
mini = base.size[0]-1
maxi = 0
minj = base.size[1]-1
maxj = 0
h, w = base.size
for j in range(w):
for i in range(h):
b = base.getpixel((i,j))
t = top.getpixel((i,j))
if b != t:
if i < mini: mini = i
if i > maxi: maxi = i
if j < minj: minj = j
if j > maxj: maxj = j
minmini = min(minmini, mini)
maxmaxi = max(maxmaxi, maxi)
minminj = min(minminj, minj)
maxmaxj = max(maxmaxj, maxj)
w = maxmaxi - minmini + 1
h = maxmaxj - minminj + 1
# Now write out an image containing just that box, for each frame.
for num, top_name in enumerate(sys.argv[1:]):
top = Image.open(top_name)
out = Image.new("RGB", (w, h))
for i in range(w):
for j in range(h):
t = top.getpixel((i+minmini, j+minminj))
out.putpixel((i, j), t)
fn = "icon_installing_overlay%02d.png" % (num+1,)
out.save(fn)
print "saved", fn
# Write out the base icon, which is the first frame with that box
# blacked out (just to make the file smaller, since it's always
# displayed with one of the overlays on top of it).
for i in range(w):
for j in range(h):
base.putpixel((i+minmini, j+minminj), (0, 0, 0))
fn = "icon_installing.png"
base.save(fn)
print "saved", fn
# The device_ui_init() function needs to tell the recovery UI the
# position of the overlay box.
print
print "add this to your device_ui_init() function:"
print "-" * 40
print " ui_parameters->install_overlay_offset_x = %d;" % (minmini,)
print " ui_parameters->install_overlay_offset_y = %d;" % (minminj,)
print "-" * 40

View File

@ -1,27 +0,0 @@
# Copyright (C) 2009 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.
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := \
Retouch.c
LOCAL_C_INCLUDES += bootable/recovery
LOCAL_MODULE := libminelf
LOCAL_CFLAGS += -Wall
include $(BUILD_STATIC_LIBRARY)

View File

@ -1,406 +0,0 @@
/*
* Copyright (C) 2009 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 <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <strings.h>
#include "Retouch.h"
#include "applypatch/applypatch.h"
typedef struct {
int32_t mmap_addr;
char tag[4]; /* 'P', 'R', 'E', ' ' */
} prelink_info_t __attribute__((packed));
#define false 0
#define true 1
static int32_t offs_prev;
static uint32_t cont_prev;
static void init_compression_state(void) {
offs_prev = 0;
cont_prev = 0;
}
// For details on the encoding used for relocation lists, please
// refer to build/tools/retouch/retouch-prepare.c. The intent is to
// save space by removing most of the inherent redundancy.
static void decode_bytes(uint8_t *encoded_bytes, int encoded_size,
int32_t *dst_offset, uint32_t *dst_contents) {
if (encoded_size == 2) {
*dst_offset = offs_prev + (((encoded_bytes[0]&0x60)>>5)+1)*4;
// if the original was negative, we need to 1-pad before applying delta
int32_t tmp = (((encoded_bytes[0] & 0x0000001f) << 8) |
encoded_bytes[1]);
if (tmp & 0x1000) tmp = 0xffffe000 | tmp;
*dst_contents = cont_prev + tmp;
} else if (encoded_size == 3) {
*dst_offset = offs_prev + (((encoded_bytes[0]&0x30)>>4)+1)*4;
// if the original was negative, we need to 1-pad before applying delta
int32_t tmp = (((encoded_bytes[0] & 0x0000000f) << 16) |
(encoded_bytes[1] << 8) |
encoded_bytes[2]);
if (tmp & 0x80000) tmp = 0xfff00000 | tmp;
*dst_contents = cont_prev + tmp;
} else {
*dst_offset =
(encoded_bytes[0]<<24) |
(encoded_bytes[1]<<16) |
(encoded_bytes[2]<<8) |
encoded_bytes[3];
if (*dst_offset == 0x3fffffff) *dst_offset = -1;
*dst_contents =
(encoded_bytes[4]<<24) |
(encoded_bytes[5]<<16) |
(encoded_bytes[6]<<8) |
encoded_bytes[7];
}
}
static uint8_t *decode_in_memory(uint8_t *encoded_bytes,
int32_t *offset, uint32_t *contents) {
int input_size, charIx;
uint8_t input[8];
input[0] = *(encoded_bytes++);
if (input[0] & 0x80)
input_size = 2;
else if (input[0] & 0x40)
input_size = 3;
else
input_size = 8;
// we already read one byte..
charIx = 1;
while (charIx < input_size) {
input[charIx++] = *(encoded_bytes++);
}
// depends on the decoder state!
decode_bytes(input, input_size, offset, contents);
offs_prev = *offset;
cont_prev = *contents;
return encoded_bytes;
}
int retouch_mask_data(uint8_t *binary_object,
int32_t binary_size,
int32_t *desired_offset,
int32_t *retouch_offset) {
retouch_info_t *r_info;
prelink_info_t *p_info;
int32_t target_offset = 0;
if (desired_offset) target_offset = *desired_offset;
int32_t p_offs = binary_size-sizeof(prelink_info_t); // prelink_info_t
int32_t r_offs = p_offs-sizeof(retouch_info_t); // retouch_info_t
int32_t b_offs; // retouch data blob
// If not retouched, we say it was a match. This might get invoked on
// non-retouched binaries, so that's why we need to do this.
if (retouch_offset != NULL) *retouch_offset = target_offset;
if (r_offs < 0) return (desired_offset == NULL) ?
RETOUCH_DATA_NOTAPPLICABLE : RETOUCH_DATA_MATCHED;
p_info = (prelink_info_t *)(binary_object+p_offs);
r_info = (retouch_info_t *)(binary_object+r_offs);
if (strncmp(p_info->tag, "PRE ", 4) ||
strncmp(r_info->tag, "RETOUCH ", 8))
return (desired_offset == NULL) ?
RETOUCH_DATA_NOTAPPLICABLE : RETOUCH_DATA_MATCHED;
b_offs = r_offs-r_info->blob_size;
if (b_offs < 0) {
printf("negative binary offset: %d = %d - %d\n",
b_offs, r_offs, r_info->blob_size);
return RETOUCH_DATA_ERROR;
}
uint8_t *b_ptr = binary_object+b_offs;
// Retouched: let's go through the work then.
int32_t offset_candidate = target_offset;
bool offset_set = false, offset_mismatch = false;
init_compression_state();
while (b_ptr < (uint8_t *)r_info) {
int32_t retouch_entry_offset;
uint32_t *retouch_entry;
uint32_t retouch_original_value;
b_ptr = decode_in_memory(b_ptr,
&retouch_entry_offset,
&retouch_original_value);
if (retouch_entry_offset < (-1) ||
retouch_entry_offset >= b_offs) {
printf("bad retouch_entry_offset: %d", retouch_entry_offset);
return RETOUCH_DATA_ERROR;
}
// "-1" means this is the value in prelink_info_t, which also gets
// randomized.
if (retouch_entry_offset == -1)
retouch_entry = (uint32_t *)&(p_info->mmap_addr);
else
retouch_entry = (uint32_t *)(binary_object+retouch_entry_offset);
if (desired_offset)
*retouch_entry = retouch_original_value + target_offset;
// Infer the randomization shift, compare to previously inferred.
int32_t offset_of_this_entry = (int32_t)(*retouch_entry-
retouch_original_value);
if (!offset_set) {
offset_candidate = offset_of_this_entry;
offset_set = true;
} else {
if (offset_candidate != offset_of_this_entry) {
offset_mismatch = true;
printf("offset is mismatched: %d, this entry is %d,"
" original 0x%x @ 0x%x",
offset_candidate, offset_of_this_entry,
retouch_original_value, retouch_entry_offset);
}
}
}
if (b_ptr > (uint8_t *)r_info) {
printf("b_ptr went too far: %p, while r_info is %p",
b_ptr, r_info);
return RETOUCH_DATA_ERROR;
}
if (offset_mismatch) return RETOUCH_DATA_MISMATCHED;
if (retouch_offset != NULL) *retouch_offset = offset_candidate;
return RETOUCH_DATA_MATCHED;
}
// On success, _override is set to the offset that was actually applied.
// This implies that once we randomize to an offset we stick with it.
// This in turn is necessary in order to guarantee recovery after crash.
bool retouch_one_library(const char *binary_name,
const char *binary_sha1,
int32_t retouch_offset,
int32_t *retouch_offset_override) {
bool success = true;
int result;
FileContents file;
file.data = NULL;
char binary_name_atomic[strlen(binary_name)+10];
strcpy(binary_name_atomic, binary_name);
strcat(binary_name_atomic, ".atomic");
// We need a path that exists for calling statfs() later.
//
// Assume that binary_name (eg "/system/app/Foo.apk") is located
// on the same filesystem as its top-level directory ("/system").
char target_fs[strlen(binary_name)+1];
char* slash = strchr(binary_name+1, '/');
if (slash != NULL) {
int count = slash - binary_name;
strncpy(target_fs, binary_name, count);
target_fs[count] = '\0';
} else {
strcpy(target_fs, binary_name);
}
result = LoadFileContents(binary_name, &file, RETOUCH_DONT_MASK);
if (result == 0) {
// Figure out the *apparent* offset to which this file has been
// retouched. If it looks good, we will skip processing (we might
// have crashed and during this recovery pass we don't want to
// overwrite a valuable saved file in /cache---which would happen
// if we blindly retouch everything again). NOTE: This implies
// that we might have to override the supplied retouch offset. We
// can do the override only once though: everything should match
// afterward.
int32_t inferred_offset;
int retouch_probe_result = retouch_mask_data(file.data,
file.size,
NULL,
&inferred_offset);
if (retouch_probe_result == RETOUCH_DATA_MATCHED) {
if ((retouch_offset == inferred_offset) ||
((retouch_offset != 0 && inferred_offset != 0) &&
(retouch_offset_override != NULL))) {
// This file is OK already and we are allowed to override.
// Let's just return the offset override value. It is critical
// to skip regardless of override: a broken file might need
// recovery down the list and we should not mess up the saved
// copy by doing unnecessary retouching.
//
// NOTE: If retouching was already started with a different
// value, we will not be allowed to override. This happens
// if on the retouch list there is a patched binary (which is
// masked in apply_patch()) before there is a non-patched
// binary.
if (retouch_offset_override != NULL)
*retouch_offset_override = inferred_offset;
success = true;
goto out;
} else {
// Retouch to zero (mask the retouching), to make sure that
// the SHA-1 check will pass below.
int32_t zero = 0;
retouch_mask_data(file.data, file.size, &zero, NULL);
SHA(file.data, file.size, file.sha1);
}
}
if (retouch_probe_result == RETOUCH_DATA_NOTAPPLICABLE) {
// In the case of not retouchable, fake it. We do not want
// to do the normal processing and overwrite the backup file:
// we might be recovering!
//
// We return a zero override, which tells the caller that we
// simply skipped the file.
if (retouch_offset_override != NULL)
*retouch_offset_override = 0;
success = true;
goto out;
}
// If we get here, either there was a mismatch in the offset, or
// the file has not been processed yet. Continue with normal
// processing.
}
if (result != 0 || FindMatchingPatch(file.sha1, &binary_sha1, 1) < 0) {
free(file.data);
printf("Attempting to recover source from '%s' ...\n",
CACHE_TEMP_SOURCE);
result = LoadFileContents(CACHE_TEMP_SOURCE, &file, RETOUCH_DO_MASK);
if (result != 0 || FindMatchingPatch(file.sha1, &binary_sha1, 1) < 0) {
printf(" failed.\n");
success = false;
goto out;
}
printf(" succeeded.\n");
}
// Retouch in-memory before worrying about backing up the original.
//
// Recovery steps will be oblivious to the actual retouch offset used,
// so might as well write out the already-retouched copy. Then, in the
// usual case, we will just swap the file locally, with no more writes
// needed. In the no-free-space case, we will then write the same to the
// original location.
result = retouch_mask_data(file.data, file.size, &retouch_offset, NULL);
if (result != RETOUCH_DATA_MATCHED) {
success = false;
goto out;
}
if (retouch_offset_override != NULL)
*retouch_offset_override = retouch_offset;
// How much free space do we need?
bool enough_space = false;
size_t free_space = FreeSpaceForFile(target_fs);
// 50% margin when estimating the space needed.
enough_space = (free_space > (file.size * 3 / 2));
// The experts say we have to allow for a retry of the
// whole process to avoid filesystem weirdness.
int retry = 1;
bool made_copy = false;
do {
// First figure out where to store a copy of the original.
// Ideally leave the original itself intact until the
// atomic swap. If no room on the same partition, fall back
// to the cache partition and remove the original.
if (!enough_space) {
printf("Target is %ldB; free space is %ldB: not enough.\n",
(long)file.size, (long)free_space);
retry = 0;
if (MakeFreeSpaceOnCache(file.size) < 0) {
printf("Not enough free space on '/cache'.\n");
success = false;
goto out;
}
if (SaveFileContents(CACHE_TEMP_SOURCE, file) < 0) {
printf("Failed to back up source file.\n");
success = false;
goto out;
}
made_copy = true;
unlink(binary_name);
size_t free_space = FreeSpaceForFile(target_fs);
printf("(now %ld bytes free for target)\n", (long)free_space);
}
result = SaveFileContents(binary_name_atomic, file);
if (result != 0) {
// Maybe the filesystem was optimistic: retry.
enough_space = false;
unlink(binary_name_atomic);
printf("Saving the retouched contents failed; retrying.\n");
continue;
}
// Succeeded; no need to retry.
break;
} while (retry-- > 0);
// Give the .atomic file the same owner, group, and mode of the
// original source file.
if (chmod(binary_name_atomic, file.st.st_mode) != 0) {
printf("chmod of \"%s\" failed: %s\n",
binary_name_atomic, strerror(errno));
success = false;
goto out;
}
if (chown(binary_name_atomic, file.st.st_uid, file.st.st_gid) != 0) {
printf("chown of \"%s\" failed: %s\n",
binary_name_atomic,
strerror(errno));
success = false;
goto out;
}
// Finally, rename the .atomic file to replace the target file.
if (rename(binary_name_atomic, binary_name) != 0) {
printf("rename of .atomic to \"%s\" failed: %s\n",
binary_name, strerror(errno));
success = false;
goto out;
}
// If this run created a copy, and we're here, we can delete it.
if (made_copy) unlink(CACHE_TEMP_SOURCE);
out:
// clean up
free(file.data);
unlink(binary_name_atomic);
return success;
}

View File

@ -1,51 +0,0 @@
/*
* Copyright (C) 2009 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 _MINELF_RETOUCH
#define _MINELF_RETOUCH
#include <stdbool.h>
#include <sys/types.h>
typedef struct {
char tag[8]; /* "RETOUCH ", not zero-terminated */
uint32_t blob_size; /* in bytes, located right before this struct */
} retouch_info_t __attribute__((packed));
// Retouch a file. Use CACHED_SOURCE_TEMP to store a copy.
bool retouch_one_library(const char *binary_name,
const char *binary_sha1,
int32_t retouch_offset,
int32_t *retouch_offset_override);
#define RETOUCH_DONT_MASK 0
#define RETOUCH_DO_MASK 1
#define RETOUCH_DATA_ERROR 0 // This is bad. Should not happen.
#define RETOUCH_DATA_MATCHED 1 // Up to an uniform random offset.
#define RETOUCH_DATA_MISMATCHED 2 // Partially randomized, or total mess.
#define RETOUCH_DATA_NOTAPPLICABLE 3 // Not retouched. Only when inferring.
// Mask retouching in-memory. Used before apply_patch[_check].
// Also used to determine status of retouching after a crash.
//
// If desired_offset is not NULL, then apply retouching instead,
// and return that in retouch_offset.
int retouch_mask_data(uint8_t *binary_object,
int32_t binary_size,
int32_t *desired_offset,
int32_t *retouch_offset);
#endif

View File

@ -12,17 +12,18 @@ LOCAL_C_INCLUDES +=\
external/libpng\
external/zlib
ifneq ($(BOARD_LDPI_RECOVERY),)
LOCAL_CFLAGS += -DBOARD_LDPI_RECOVERY='"$(BOARD_LDPI_RECOVERY)"'
endif
ifneq ($(BOARD_HAS_JANKY_BACKBUFFER),)
LOCAL_CFLAGS += -DBOARD_HAS_JANKY_BACKBUFFER
endif
ifeq ($(BOARD_HAS_FLIPPED_SCREEN), true)
LOCAL_CFLAGS += -DBOARD_HAS_FLIPPED_SCREEN
endif
LOCAL_MODULE := libminui
ifeq ($(TARGET_RECOVERY_PIXEL_FORMAT),"RGBX_8888")
LOCAL_CFLAGS += -DRECOVERY_RGBX
endif
ifeq ($(TARGET_RECOVERY_PIXEL_FORMAT),"BGRA_8888")
LOCAL_CFLAGS += -DRECOVERY_BGRA
endif
ifneq ($(BOARD_USE_CUSTOM_RECOVERY_FONT),)
LOCAL_CFLAGS += -DBOARD_USE_CUSTOM_RECOVERY_FONT=$(BOARD_USE_CUSTOM_RECOVERY_FONT)
endif
include $(BUILD_STATIC_LIBRARY)

View File

@ -19,33 +19,167 @@
#include <fcntl.h>
#include <dirent.h>
#include <sys/poll.h>
#include <limits.h>
#include <linux/input.h>
#include "../common.h"
#include "minui.h"
#define MAX_DEVICES 16
#define MAX_MISC_FDS 16
#define BITS_PER_LONG (sizeof(unsigned long) * 8)
#define BITS_TO_LONGS(x) (((x) + BITS_PER_LONG - 1) / BITS_PER_LONG)
#define VIBRATOR_TIMEOUT_FILE "/sys/class/timed_output/vibrator/enable"
#define VIBRATOR_TIME_MS 50
#define test_bit(bit, array) \
((array)[(bit)/BITS_PER_LONG] & (1 << ((bit) % BITS_PER_LONG)))
#define PRESS_THRESHHOLD 10
struct fd_info {
ev_callback cb;
void *data;
#define ABS_MT_POSITION_X 0x35
#define ABS_MT_POSITION_Y 0x36
#define ABS_MT_TOUCH_MAJOR 0x30
#define SYN_MT_REPORT 2
struct virtualkey {
int scancode;
int centerx, centery;
int width, height;
};
static struct pollfd ev_fds[MAX_DEVICES + MAX_MISC_FDS];
static struct fd_info ev_fdinfo[MAX_DEVICES + MAX_MISC_FDS];
struct position {
int x, y;
int pressed;
struct input_absinfo xi, yi;
};
struct ev {
struct pollfd *fd;
struct virtualkey *vks;
int vk_count;
struct position p, mt_p;
int sent, mt_idx;
};
static struct pollfd ev_fds[MAX_DEVICES];
static struct ev evs[MAX_DEVICES];
static unsigned ev_count = 0;
static unsigned ev_dev_count = 0;
static unsigned ev_misc_count = 0;
int ev_init(ev_callback input_cb, void *data)
static inline int ABS(int x) {
return x<0?-x:x;
}
int vibrate(int timeout_ms)
{
char str[20];
int fd;
int ret;
fd = open(VIBRATOR_TIMEOUT_FILE, O_WRONLY);
if (fd < 0)
return -1;
ret = snprintf(str, sizeof(str), "%d", timeout_ms);
ret = write(fd, str, ret);
close(fd);
if (ret < 0)
return -1;
return 0;
}
/* Returns empty tokens */
static char *vk_strtok_r(char *str, const char *delim, char **save_str)
{
if(!str) {
if(!*save_str) return NULL;
str = (*save_str) + 1;
}
*save_str = strpbrk(str, delim);
if(*save_str) **save_str = '\0';
return str;
}
static int vk_init(struct ev *e)
{
char vk_path[PATH_MAX] = "/sys/board_properties/virtualkeys.";
char vks[2048], *ts;
ssize_t len;
int vk_fd;
int i;
e->vk_count = 0;
len = strlen(vk_path);
len = ioctl(e->fd->fd, EVIOCGNAME(sizeof(vk_path) - len), vk_path + len);
if (len <= 0)
return -1;
vk_fd = open(vk_path, O_RDONLY);
if (vk_fd < 0)
return -1;
len = read(vk_fd, vks, sizeof(vks)-1);
close(vk_fd);
if (len <= 0)
return -1;
vks[len] = '\0';
/* Parse a line like:
keytype:keycode:centerx:centery:width:height:keytype2:keycode2:centerx2:...
*/
for (ts = vks, e->vk_count = 1; *ts; ++ts) {
if (*ts == ':')
++e->vk_count;
}
if (e->vk_count % 6) {
LOGW("minui: %s is %d %% 6\n", vk_path, e->vk_count % 6);
}
e->vk_count /= 6;
if (e->vk_count <= 0)
return -1;
e->sent = 0;
e->mt_idx = 0;
ioctl(e->fd->fd, EVIOCGABS(ABS_X), &e->p.xi);
ioctl(e->fd->fd, EVIOCGABS(ABS_Y), &e->p.yi);
e->p.pressed = 0;
ioctl(e->fd->fd, EVIOCGABS(ABS_MT_POSITION_X), &e->mt_p.xi);
ioctl(e->fd->fd, EVIOCGABS(ABS_MT_POSITION_Y), &e->mt_p.yi);
e->mt_p.pressed = 0;
e->vks = malloc(sizeof(*e->vks) * e->vk_count);
for (i = 0; i < e->vk_count; ++i) {
char *token[6];
int j;
for (j = 0; j < 6; ++j) {
token[j] = vk_strtok_r((i||j)?NULL:vks, ":", &ts);
}
if (strcmp(token[0], "0x01") != 0) {
/* Java does string compare, so we do too. */
LOGW("minui: %s: ignoring unknown virtual key type %s\n", vk_path, token[0]);
continue;
}
e->vks[i].scancode = strtol(token[1], NULL, 0);
e->vks[i].centerx = strtol(token[2], NULL, 0);
e->vks[i].centery = strtol(token[3], NULL, 0);
e->vks[i].width = strtol(token[4], NULL, 0);
e->vks[i].height = strtol(token[5], NULL, 0);
}
return 0;
}
int ev_init(void)
{
DIR *dir;
struct dirent *de;
@ -54,122 +188,177 @@ int ev_init(ev_callback input_cb, void *data)
dir = opendir("/dev/input");
if(dir != 0) {
while((de = readdir(dir))) {
unsigned long ev_bits[BITS_TO_LONGS(EV_MAX)];
// fprintf(stderr,"/dev/input/%s\n", de->d_name);
if(strncmp(de->d_name,"event",5)) continue;
fd = openat(dirfd(dir), de->d_name, O_RDONLY);
if(fd < 0) continue;
/* read the evbits of the input device */
if (ioctl(fd, EVIOCGBIT(0, sizeof(ev_bits)), ev_bits) < 0) {
close(fd);
continue;
}
/* TODO: add ability to specify event masks. For now, just assume
* that only EV_KEY and EV_REL event types are ever needed. */
if (!test_bit(EV_KEY, ev_bits) && !test_bit(EV_REL, ev_bits)) {
close(fd);
continue;
}
ev_fds[ev_count].fd = fd;
ev_fds[ev_count].events = POLLIN;
ev_fdinfo[ev_count].cb = input_cb;
ev_fdinfo[ev_count].data = data;
evs[ev_count].fd = &ev_fds[ev_count];
/* Load virtualkeys if there are any */
vk_init(&evs[ev_count]);
ev_count++;
ev_dev_count++;
if(ev_dev_count == MAX_DEVICES) break;
if(ev_count == MAX_DEVICES) break;
}
}
return 0;
}
int ev_add_fd(int fd, ev_callback cb, void *data)
{
if (ev_misc_count == MAX_MISC_FDS || cb == NULL)
return -1;
ev_fds[ev_count].fd = fd;
ev_fds[ev_count].events = POLLIN;
ev_fdinfo[ev_count].cb = cb;
ev_fdinfo[ev_count].data = data;
ev_count++;
ev_misc_count++;
return 0;
}
void ev_exit(void)
{
while (ev_count > 0) {
close(ev_fds[--ev_count].fd);
}
ev_misc_count = 0;
ev_dev_count = 0;
}
int ev_wait(int timeout)
{
int r;
r = poll(ev_fds, ev_count, timeout);
if (r <= 0)
return -1;
return 0;
}
void ev_dispatch(void)
{
unsigned n;
int ret;
for (n = 0; n < ev_count; n++) {
ev_callback cb = ev_fdinfo[n].cb;
if (cb && (ev_fds[n].revents & ev_fds[n].events))
cb(ev_fds[n].fd, ev_fds[n].revents, ev_fdinfo[n].data);
while (ev_count-- > 0) {
if (evs[ev_count].vk_count) {
free(evs[ev_count].vks);
evs[ev_count].vk_count = 0;
}
close(ev_fds[ev_count].fd);
}
}
int ev_get_input(int fd, short revents, struct input_event *ev)
static int vk_inside_display(__s32 value, struct input_absinfo *info, int screen_size)
{
int r;
int screen_pos;
if (revents & POLLIN) {
r = read(fd, ev, sizeof(*ev));
if (r == sizeof(*ev))
if (info->minimum == info->maximum)
return 0;
screen_pos = (value - info->minimum) * (screen_size - 1) / (info->maximum - info->minimum);
return (screen_pos >= 0 && screen_pos < screen_size);
}
static int vk_tp_to_screen(struct position *p, int *x, int *y)
{
if (p->xi.minimum == p->xi.maximum || p->yi.minimum == p->yi.maximum)
return 0;
*x = (p->x - p->xi.minimum) * (gr_fb_width() - 1) / (p->xi.maximum - p->xi.minimum);
*y = (p->y - p->yi.minimum) * (gr_fb_height() - 1) / (p->yi.maximum - p->yi.minimum);
if (*x >= 0 && *x < gr_fb_width() &&
*y >= 0 && *y < gr_fb_height()) {
return 0;
}
return 1;
}
/* Translate a virtual key in to a real key event, if needed */
/* Returns non-zero when the event should be consumed */
static int vk_modify(struct ev *e, struct input_event *ev)
{
int i;
int x, y;
if (ev->type == EV_KEY) {
if (ev->code == BTN_TOUCH)
e->p.pressed = ev->value;
return 0;
}
if (ev->type == EV_ABS) {
switch (ev->code) {
case ABS_X:
e->p.x = ev->value;
return !vk_inside_display(e->p.x, &e->p.xi, gr_fb_width());
case ABS_Y:
e->p.y = ev->value;
return !vk_inside_display(e->p.y, &e->p.yi, gr_fb_height());
case ABS_MT_POSITION_X:
if (e->mt_idx) return 1;
e->mt_p.x = ev->value;
return !vk_inside_display(e->mt_p.x, &e->mt_p.xi, gr_fb_width());
case ABS_MT_POSITION_Y:
if (e->mt_idx) return 1;
e->mt_p.y = ev->value;
return !vk_inside_display(e->mt_p.y, &e->mt_p.yi, gr_fb_height());
case ABS_MT_TOUCH_MAJOR:
if (e->mt_idx) return 1;
if (e->sent)
e->mt_p.pressed = (ev->value > 0);
else
e->mt_p.pressed = (ev->value > PRESS_THRESHHOLD);
return 0;
}
return 0;
}
return -1;
}
int ev_sync_key_state(ev_set_key_callback set_key_cb, void *data)
{
unsigned long key_bits[BITS_TO_LONGS(KEY_MAX)];
unsigned long ev_bits[BITS_TO_LONGS(EV_MAX)];
unsigned i;
int ret;
if (ev->type != EV_SYN)
return 0;
for (i = 0; i < ev_dev_count; i++) {
int code;
if (ev->code == SYN_MT_REPORT) {
/* Ignore the rest of the points */
++e->mt_idx;
return 1;
}
if (ev->code != SYN_REPORT)
return 0;
memset(key_bits, 0, sizeof(key_bits));
memset(ev_bits, 0, sizeof(ev_bits));
/* Report complete */
ret = ioctl(ev_fds[i].fd, EVIOCGBIT(0, sizeof(ev_bits)), ev_bits);
if (ret < 0 || !test_bit(EV_KEY, ev_bits))
continue;
e->mt_idx = 0;
ret = ioctl(ev_fds[i].fd, EVIOCGKEY(sizeof(key_bits)), key_bits);
if (ret < 0)
continue;
if (!e->p.pressed && !e->mt_p.pressed) {
/* No touch */
e->sent = 0;
return 0;
}
for (code = 0; code <= KEY_MAX; code++) {
if (test_bit(code, key_bits))
set_key_cb(code, 1, data);
if (!(e->p.pressed && vk_tp_to_screen(&e->p, &x, &y)) &&
!(e->mt_p.pressed && vk_tp_to_screen(&e->mt_p, &x, &y))) {
/* No touch inside vk area */
return 0;
}
if (e->sent) {
/* We've already sent a fake key for this touch */
return 1;
}
/* The screen is being touched on the vk area */
e->sent = 1;
for (i = 0; i < e->vk_count; ++i) {
int xd = ABS(e->vks[i].centerx - x);
int yd = ABS(e->vks[i].centery - y);
if (xd < e->vks[i].width/2 && yd < e->vks[i].height/2) {
/* Fake a key event */
ev->type = EV_KEY;
ev->code = e->vks[i].scancode;
ev->value = 1;
vibrate(VIBRATOR_TIME_MS);
return 0;
}
}
return 0;
return 1;
}
int ev_get(struct input_event *ev, unsigned dont_wait)
{
int r;
unsigned n;
do {
r = poll(ev_fds, ev_count, dont_wait ? 0 : -1);
if(r > 0) {
for(n = 0; n < ev_count; n++) {
if(ev_fds[n].revents & POLLIN) {
r = read(ev_fds[n].fd, ev, sizeof(*ev));
if(r == sizeof(*ev)) {
if (!vk_modify(&evs[n], ev))
return 0;
}
}
}
}
} while(dont_wait == 0);
return -1;
}

View File

@ -14,7 +14,6 @@
* limitations under the License.
*/
#include <stdbool.h>
#include <stdlib.h>
#include <unistd.h>
@ -30,25 +29,14 @@
#include <pixelflinger/pixelflinger.h>
#ifdef BOARD_USE_CUSTOM_RECOVERY_FONT
#include BOARD_USE_CUSTOM_RECOVERY_FONT
#ifndef BOARD_LDPI_RECOVERY
#include "font_10x18.h"
#else
#include "font_10x18.h"
#include "font_7x16.h"
#endif
#include "minui.h"
#if defined(RECOVERY_BGRA)
#define PIXEL_FORMAT GGL_PIXEL_FORMAT_BGRA_8888
#define PIXEL_SIZE 4
#elif defined(RECOVERY_RGBX)
#define PIXEL_FORMAT GGL_PIXEL_FORMAT_RGBX_8888
#define PIXEL_SIZE 4
#else
#define PIXEL_FORMAT GGL_PIXEL_FORMAT_RGB_565
#define PIXEL_SIZE 2
#endif
typedef struct {
GGLSurface texture;
unsigned cwidth;
@ -67,11 +55,11 @@ static int gr_fb_fd = -1;
static int gr_vt_fd = -1;
static struct fb_var_screeninfo vi;
static struct fb_fix_screeninfo fi;
static int get_framebuffer(GGLSurface *fb)
{
int fd;
struct fb_fix_screeninfo fi;
void *bits;
fd = open("/dev/graphics/fb0", O_RDWR);
@ -80,48 +68,13 @@ static int get_framebuffer(GGLSurface *fb)
return -1;
}
if (ioctl(fd, FBIOGET_VSCREENINFO, &vi) < 0) {
if (ioctl(fd, FBIOGET_FSCREENINFO, &fi) < 0) {
perror("failed to get fb0 info");
close(fd);
return -1;
}
vi.bits_per_pixel = PIXEL_SIZE * 8;
if (PIXEL_FORMAT == GGL_PIXEL_FORMAT_BGRA_8888) {
vi.red.offset = 8;
vi.red.length = 8;
vi.green.offset = 16;
vi.green.length = 8;
vi.blue.offset = 24;
vi.blue.length = 8;
vi.transp.offset = 0;
vi.transp.length = 8;
} else if (PIXEL_FORMAT == GGL_PIXEL_FORMAT_RGBX_8888) {
vi.red.offset = 24;
vi.red.length = 8;
vi.green.offset = 16;
vi.green.length = 8;
vi.blue.offset = 8;
vi.blue.length = 8;
vi.transp.offset = 0;
vi.transp.length = 8;
} else { /* RGB565*/
vi.red.offset = 11;
vi.red.length = 5;
vi.green.offset = 5;
vi.green.length = 6;
vi.blue.offset = 0;
vi.blue.length = 5;
vi.transp.offset = 0;
vi.transp.length = 0;
}
if (ioctl(fd, FBIOPUT_VSCREENINFO, &vi) < 0) {
perror("failed to put fb0 info");
close(fd);
return -1;
}
if (ioctl(fd, FBIOGET_FSCREENINFO, &fi) < 0) {
if (ioctl(fd, FBIOGET_VSCREENINFO, &vi) < 0) {
perror("failed to get fb0 info");
close(fd);
return -1;
@ -137,20 +90,29 @@ static int get_framebuffer(GGLSurface *fb)
fb->version = sizeof(*fb);
fb->width = vi.xres;
fb->height = vi.yres;
fb->stride = fi.line_length/PIXEL_SIZE;
#ifdef BOARD_HAS_JANKY_BACKBUFFER
fb->stride = fi.line_length/2;
#else
fb->stride = vi.xres;
#endif
fb->data = bits;
fb->format = PIXEL_FORMAT;
memset(fb->data, 0, vi.yres * fi.line_length);
fb->format = GGL_PIXEL_FORMAT_RGB_565;
memset(fb->data, 0, vi.yres * vi.xres * 2);
fb++;
fb->version = sizeof(*fb);
fb->width = vi.xres;
fb->height = vi.yres;
fb->stride = fi.line_length/PIXEL_SIZE;
#ifdef BOARD_HAS_JANKY_BACKBUFFER
fb->stride = fi.line_length/2;
fb->data = (void*) (((unsigned) bits) + vi.yres * fi.line_length);
fb->format = PIXEL_FORMAT;
memset(fb->data, 0, vi.yres * fi.line_length);
#else
fb->stride = vi.xres;
fb->data = (void*) (((unsigned) bits) + vi.yres * vi.xres * 2);
#endif
fb->format = GGL_PIXEL_FORMAT_RGB_565;
memset(fb->data, 0, vi.yres * vi.xres * 2);
return fd;
}
@ -159,17 +121,17 @@ static void get_memory_surface(GGLSurface* ms) {
ms->version = sizeof(*ms);
ms->width = vi.xres;
ms->height = vi.yres;
ms->stride = fi.line_length/PIXEL_SIZE;
ms->data = malloc(fi.line_length * vi.yres);
ms->format = PIXEL_FORMAT;
ms->stride = vi.xres;
ms->data = malloc(vi.xres * vi.yres * 2);
ms->format = GGL_PIXEL_FORMAT_RGB_565;
}
static void set_active_framebuffer(unsigned n)
{
if (n > 1) return;
vi.yres_virtual = vi.yres * PIXEL_SIZE;
vi.yres_virtual = vi.yres * 2;
vi.yoffset = n * vi.yres;
vi.bits_per_pixel = PIXEL_SIZE * 8;
vi.bits_per_pixel = 16;
if (ioctl(gr_fb_fd, FBIOPUT_VSCREENINFO, &vi) < 0) {
perror("active fb swap failed");
}
@ -182,10 +144,20 @@ void gr_flip(void)
/* swap front and back buffers */
gr_active_fb = (gr_active_fb + 1) & 1;
#ifdef BOARD_HAS_FLIPPED_SCREEN
/* flip buffer 180 degrees for devices with physicaly inverted screens */
unsigned int i;
for (i = 1; i < (vi.xres * vi.yres); i++) {
unsigned short tmp = gr_mem_surface.data[i];
gr_mem_surface.data[i] = gr_mem_surface.data[(vi.xres * vi.yres * 2) - i];
gr_mem_surface.data[(vi.xres * vi.yres * 2) - i] = tmp;
}
#endif
/* copy data from the in-memory surface to the buffer we're about
* to make active. */
memcpy(gr_framebuffer[gr_active_fb].data, gr_mem_surface.data,
fi.line_length * vi.yres);
vi.xres * vi.yres * 2);
/* inform the display driver */
set_active_framebuffer(gr_active_fb);
@ -207,12 +179,6 @@ int gr_measure(const char *s)
return gr_font->cwidth * strlen(s);
}
void gr_font_size(int *x, int *y)
{
*x = gr_font->cwidth;
*y = gr_font->cheight;
}
int gr_text(int x, int y, const char *s)
{
GGLContext *gl = gr_context;
@ -341,9 +307,6 @@ int gr_init(void)
gl->enable(gl, GGL_BLEND);
gl->blendFunc(gl, GGL_SRC_ALPHA, GGL_ONE_MINUS_SRC_ALPHA);
gr_fb_blank(true);
gr_fb_blank(false);
return 0;
}
@ -374,11 +337,3 @@ gr_pixel *gr_fb_data(void)
return (unsigned short *) gr_mem_surface.data;
}
void gr_fb_blank(bool blank)
{
int ret;
ret = ioctl(gr_fb_fd, FBIOBLANK, blank ? FB_BLANK_POWERDOWN : FB_BLANK_UNBLANK);
if (ret < 0)
perror("ioctl(): blank");
}

View File

@ -17,8 +17,6 @@
#ifndef _MINUI_H_
#define _MINUI_H_
#include <stdbool.h>
typedef void* gr_surface;
typedef unsigned short gr_pixel;
@ -29,13 +27,11 @@ int gr_fb_width(void);
int gr_fb_height(void);
gr_pixel *gr_fb_data(void);
void gr_flip(void);
void gr_fb_blank(bool blank);
void gr_color(unsigned char r, unsigned char g, unsigned char b, unsigned char a);
void gr_fill(int x, int y, int w, int h);
int gr_text(int x, int y, const char *s);
int gr_measure(const char *s);
void gr_font_size(int *x, int *y);
void gr_blit(gr_surface source, int sx, int sy, int w, int h, int dx, int dy);
unsigned int gr_get_width(gr_surface surface);
@ -45,23 +41,9 @@ unsigned int gr_get_height(gr_surface surface);
// see http://www.mjmwired.net/kernel/Documentation/input/ for info.
struct input_event;
typedef int (*ev_callback)(int fd, short revents, void *data);
typedef int (*ev_set_key_callback)(int code, int value, void *data);
int ev_init(ev_callback input_cb, void *data);
int ev_init(void);
void ev_exit(void);
int ev_add_fd(int fd, ev_callback cb, void *data);
int ev_sync_key_state(ev_set_key_callback set_key_cb, void *data);
/* timeout has the same semantics as for poll
* 0 : don't block
* < 0 : block forever
* > 0 : block for 'timeout' milliseconds
*/
int ev_wait(int timeout);
int ev_get_input(int fd, short revents, struct input_event *ev);
void ev_dispatch(void);
int ev_get(struct input_event *ev, unsigned dont_wait);
// Resources

View File

@ -49,8 +49,6 @@ int res_create_surface(const char* name, gr_surface* pSurface) {
png_structp png_ptr = NULL;
png_infop info_ptr = NULL;
*pSurface = NULL;
snprintf(resPath, sizeof(resPath)-1, "/res/images/%s.png", name);
resPath[sizeof(resPath)-1] = '\0';
FILE* fp = fopen(resPath, "rb");
@ -121,18 +119,13 @@ int res_create_surface(const char* name, gr_surface* pSurface) {
surface->format = (channels == 3) ?
GGL_PIXEL_FORMAT_RGBX_8888 : GGL_PIXEL_FORMAT_RGBA_8888;
int alpha = 0;
if (color_type == PNG_COLOR_TYPE_PALETTE) {
png_set_palette_to_rgb(png_ptr);
}
if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
png_set_tRNS_to_alpha(png_ptr);
alpha = 1;
png_set_palette_to_rgb(png_ptr);
}
int y;
if (channels == 3 || (channels == 1 && !alpha)) {
for (y = 0; y < height; ++y) {
if (channels == 3) {
for (y = 0; y < (int)height; ++y) {
unsigned char* pRow = pData + y * stride;
png_read_row(png_ptr, pRow, NULL);
@ -151,7 +144,7 @@ int res_create_surface(const char* name, gr_surface* pSurface) {
}
}
} else {
for (y = 0; y < height; ++y) {
for (y = 0; y < (int)height; ++y) {
unsigned char* pRow = pData + y * stride;
png_read_row(png_ptr, pRow, NULL);
}

View File

@ -1,197 +0,0 @@
struct {
unsigned width;
unsigned height;
unsigned cwidth;
unsigned cheight;
unsigned char rundata[];
} font = {
.width = 960,
.height = 18,
.cwidth = 10,
.cheight = 18,
.rundata = {
0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,
0x3b,0x81,0x29,0x81,0x06,0x81,0x3f,0x81,0x7f,0x7f,0x7f,0x37,0x83,0x05,0x81,
0x0a,0x83,0x7f,0x7f,0x2f,0x81,0x0e,0x81,0x29,0x82,0x07,0x81,0x01,0x82,0x07,
0x81,0x02,0x81,0x05,0x83,0x05,0x82,0x0a,0x82,0x09,0x82,0x09,0x81,0x08,0x81,
0x3e,0x81,0x05,0x84,0x06,0x84,0x06,0x83,0x06,0x84,0x09,0x82,0x05,0x85,0x06,
0x84,0x04,0x87,0x04,0x84,0x07,0x84,0x39,0x83,0x06,0x84,0x07,0x81,0x06,0x86,
0x06,0x84,0x04,0x86,0x04,0x87,0x04,0x87,0x04,0x84,0x04,0x82,0x04,0x82,0x03,
0x86,0x08,0x82,0x03,0x82,0x04,0x82,0x02,0x82,0x07,0x82,0x05,0x82,0x02,0x82,
0x05,0x81,0x04,0x84,0x04,0x86,0x06,0x84,0x04,0x86,0x06,0x84,0x04,0x88,0x02,
0x82,0x05,0x81,0x01,0x82,0x06,0x81,0x01,0x81,0x07,0x81,0x02,0x81,0x05,0x82,
0x02,0x82,0x04,0x82,0x02,0x87,0x06,0x81,0x07,0x82,0x0b,0x81,0x08,0x81,0x12,
0x82,0x10,0x82,0x18,0x82,0x10,0x83,0x0d,0x82,0x0b,0x82,0x08,0x82,0x06,0x82,
0x09,0x83,0x4c,0x82,0x48,0x81,0x07,0x82,0x07,0x81,0x28,0x82,0x07,0x81,0x01,
0x82,0x07,0x81,0x02,0x81,0x04,0x82,0x01,0x82,0x03,0x81,0x02,0x81,0x08,0x81,
0x02,0x81,0x08,0x82,0x08,0x82,0x08,0x82,0x3c,0x82,0x04,0x82,0x02,0x82,0x04,
0x85,0x05,0x82,0x01,0x82,0x04,0x82,0x02,0x82,0x07,0x83,0x05,0x85,0x05,0x82,
0x02,0x81,0x09,0x82,0x03,0x82,0x02,0x82,0x05,0x82,0x02,0x82,0x37,0x82,0x01,
0x82,0x04,0x81,0x03,0x82,0x06,0x82,0x05,0x82,0x03,0x82,0x04,0x83,0x01,0x82,
0x03,0x82,0x03,0x82,0x03,0x82,0x09,0x82,0x08,0x82,0x02,0x82,0x03,0x82,0x04,
0x82,0x05,0x82,0x0a,0x82,0x03,0x82,0x03,0x82,0x03,0x82,0x07,0x82,0x05,0x82,
0x02,0x82,0x05,0x81,0x03,0x82,0x02,0x82,0x03,0x82,0x03,0x82,0x04,0x82,0x02,
0x82,0x03,0x82,0x03,0x82,0x04,0x82,0x02,0x82,0x06,0x82,0x05,0x82,0x05,0x81,
0x02,0x81,0x05,0x82,0x01,0x81,0x07,0x81,0x02,0x82,0x04,0x81,0x03,0x82,0x04,
0x82,0x07,0x82,0x06,0x81,0x08,0x81,0x0b,0x81,0x07,0x82,0x13,0x81,0x10,0x82,
0x18,0x82,0x0f,0x84,0x0d,0x82,0x1d,0x82,0x0a,0x82,0x4c,0x82,0x47,0x82,0x07,
0x82,0x07,0x82,0x27,0x82,0x07,0x81,0x01,0x82,0x06,0x81,0x02,0x81,0x04,0x82,
0x03,0x82,0x02,0x81,0x02,0x81,0x02,0x81,0x04,0x82,0x02,0x82,0x08,0x81,0x08,
0x81,0x0a,0x81,0x12,0x82,0x28,0x81,0x05,0x81,0x04,0x81,0x07,0x82,0x04,0x82,
0x03,0x82,0x03,0x81,0x04,0x81,0x07,0x83,0x05,0x81,0x08,0x82,0x0c,0x82,0x04,
0x81,0x04,0x82,0x04,0x81,0x04,0x81,0x36,0x82,0x03,0x81,0x03,0x81,0x05,0x82,
0x04,0x83,0x05,0x82,0x04,0x81,0x03,0x83,0x03,0x82,0x02,0x82,0x04,0x82,0x02,
0x82,0x09,0x82,0x07,0x82,0x04,0x82,0x02,0x82,0x04,0x82,0x05,0x82,0x0a,0x82,
0x03,0x82,0x02,0x82,0x04,0x82,0x07,0x83,0x03,0x83,0x02,0x83,0x04,0x81,0x02,
0x82,0x04,0x82,0x02,0x82,0x04,0x82,0x02,0x82,0x04,0x82,0x02,0x82,0x04,0x81,
0x03,0x82,0x04,0x81,0x06,0x82,0x05,0x82,0x05,0x81,0x02,0x81,0x05,0x82,0x01,
0x82,0x02,0x81,0x02,0x82,0x03,0x82,0x02,0x82,0x04,0x81,0x03,0x82,0x08,0x81,
0x07,0x81,0x08,0x81,0x0b,0x81,0x07,0x83,0x13,0x81,0x0f,0x82,0x18,0x82,0x0e,
0x82,0x10,0x82,0x1d,0x82,0x0a,0x82,0x4c,0x82,0x47,0x81,0x08,0x82,0x08,0x81,
0x27,0x82,0x07,0x81,0x01,0x81,0x05,0x88,0x02,0x82,0x07,0x81,0x02,0x81,0x01,
0x82,0x05,0x81,0x02,0x81,0x08,0x81,0x08,0x82,0x0a,0x82,0x07,0x81,0x09,0x82,
0x27,0x82,0x04,0x82,0x04,0x82,0x06,0x82,0x0a,0x81,0x08,0x81,0x06,0x81,0x01,
0x82,0x05,0x81,0x08,0x82,0x0c,0x81,0x05,0x81,0x04,0x82,0x04,0x81,0x04,0x81,
0x05,0x82,0x08,0x82,0x2a,0x81,0x03,0x81,0x02,0x81,0x03,0x81,0x04,0x81,0x01,
0x82,0x04,0x82,0x04,0x81,0x03,0x82,0x04,0x82,0x02,0x82,0x05,0x81,0x02,0x82,
0x09,0x82,0x07,0x82,0x04,0x82,0x02,0x82,0x04,0x82,0x05,0x82,0x0a,0x82,0x03,
0x82,0x02,0x81,0x05,0x82,0x07,0x83,0x03,0x83,0x02,0x84,0x03,0x81,0x02,0x82,
0x05,0x81,0x02,0x82,0x04,0x82,0x02,0x82,0x04,0x82,0x02,0x82,0x04,0x82,0x02,
0x82,0x0b,0x82,0x05,0x82,0x05,0x81,0x02,0x82,0x04,0x81,0x03,0x81,0x02,0x82,
0x01,0x82,0x04,0x81,0x01,0x82,0x05,0x82,0x01,0x82,0x08,0x82,0x07,0x81,0x08,
0x82,0x0a,0x81,0x06,0x82,0x01,0x81,0x1a,0x85,0x04,0x82,0x01,0x83,0x06,0x84,
0x06,0x83,0x01,0x82,0x04,0x84,0x06,0x82,0x07,0x85,0x04,0x82,0x01,0x83,0x06,
0x83,0x08,0x82,0x06,0x82,0x02,0x82,0x06,0x82,0x05,0x81,0x01,0x82,0x01,0x82,
0x03,0x82,0x01,0x84,0x05,0x84,0x04,0x82,0x01,0x83,0x06,0x83,0x01,0x82,0x03,
0x82,0x01,0x84,0x04,0x84,0x04,0x86,0x04,0x82,0x04,0x82,0x02,0x82,0x04,0x81,
0x02,0x82,0x06,0x81,0x02,0x82,0x03,0x82,0x03,0x82,0x04,0x82,0x03,0x86,0x07,
0x81,0x08,0x82,0x08,0x81,0x27,0x82,0x11,0x81,0x02,0x81,0x05,0x82,0x06,0x84,
0x01,0x81,0x06,0x83,0x12,0x82,0x0a,0x82,0x05,0x81,0x01,0x81,0x01,0x81,0x07,
0x82,0x27,0x81,0x05,0x82,0x04,0x82,0x06,0x82,0x09,0x82,0x07,0x82,0x05,0x82,
0x01,0x82,0x04,0x85,0x05,0x81,0x01,0x83,0x08,0x82,0x06,0x81,0x02,0x82,0x05,
0x81,0x04,0x81,0x05,0x82,0x08,0x82,0x0a,0x83,0x04,0x86,0x04,0x82,0x0c,0x82,
0x02,0x81,0x02,0x81,0x01,0x81,0x02,0x81,0x04,0x81,0x01,0x82,0x04,0x82,0x03,
0x82,0x03,0x82,0x08,0x82,0x05,0x81,0x02,0x82,0x09,0x82,0x07,0x81,0x09,0x82,
0x04,0x82,0x05,0x82,0x0a,0x82,0x03,0x82,0x01,0x82,0x05,0x82,0x07,0x84,0x02,
0x83,0x02,0x82,0x01,0x81,0x03,0x81,0x02,0x82,0x05,0x81,0x02,0x82,0x04,0x82,
0x02,0x81,0x06,0x81,0x02,0x82,0x03,0x82,0x04,0x82,0x0a,0x82,0x05,0x82,0x05,
0x81,0x03,0x81,0x03,0x82,0x03,0x81,0x01,0x81,0x01,0x81,0x01,0x81,0x05,0x83,
0x07,0x84,0x07,0x82,0x08,0x81,0x09,0x81,0x0a,0x81,0x06,0x81,0x02,0x81,0x19,
0x82,0x02,0x83,0x03,0x83,0x02,0x82,0x04,0x82,0x02,0x82,0x04,0x82,0x02,0x83,
0x03,0x82,0x02,0x82,0x04,0x85,0x04,0x83,0x01,0x83,0x03,0x83,0x02,0x82,0x06,
0x82,0x08,0x82,0x06,0x82,0x02,0x81,0x07,0x82,0x05,0x82,0x01,0x82,0x01,0x82,
0x02,0x83,0x03,0x82,0x03,0x82,0x02,0x82,0x03,0x83,0x02,0x82,0x04,0x82,0x02,
0x83,0x03,0x83,0x03,0x81,0x03,0x82,0x02,0x82,0x04,0x82,0x07,0x82,0x04,0x82,
0x03,0x81,0x03,0x82,0x02,0x82,0x02,0x82,0x02,0x81,0x03,0x82,0x02,0x81,0x05,
0x81,0x04,0x82,0x07,0x81,0x08,0x81,0x08,0x82,0x08,0x81,0x27,0x82,0x11,0x81,
0x02,0x81,0x06,0x83,0x08,0x81,0x07,0x82,0x13,0x82,0x0a,0x82,0x05,0x85,0x04,
0x88,0x23,0x82,0x05,0x82,0x04,0x82,0x06,0x82,0x08,0x82,0x06,0x83,0x06,0x81,
0x02,0x82,0x04,0x82,0x02,0x82,0x04,0x82,0x02,0x82,0x07,0x81,0x08,0x83,0x06,
0x82,0x02,0x82,0x19,0x83,0x11,0x83,0x09,0x82,0x03,0x81,0x01,0x81,0x02,0x81,
0x02,0x81,0x03,0x82,0x02,0x81,0x04,0x86,0x04,0x82,0x08,0x82,0x05,0x81,0x02,
0x86,0x05,0x86,0x03,0x81,0x09,0x88,0x05,0x82,0x0a,0x82,0x03,0x84,0x06,0x82,
0x07,0x82,0x01,0x81,0x01,0x81,0x01,0x82,0x02,0x82,0x01,0x82,0x02,0x81,0x02,
0x82,0x05,0x81,0x02,0x82,0x03,0x82,0x03,0x81,0x06,0x81,0x02,0x86,0x06,0x83,
0x08,0x82,0x05,0x82,0x05,0x81,0x03,0x82,0x02,0x81,0x04,0x81,0x01,0x81,0x01,
0x81,0x01,0x81,0x06,0x82,0x08,0x82,0x08,0x81,0x09,0x81,0x09,0x82,0x09,0x81,
0x06,0x81,0x02,0x82,0x1d,0x82,0x03,0x82,0x04,0x82,0x02,0x82,0x04,0x81,0x03,
0x82,0x04,0x82,0x02,0x82,0x04,0x82,0x04,0x82,0x06,0x82,0x03,0x82,0x03,0x82,
0x04,0x82,0x05,0x82,0x08,0x82,0x06,0x82,0x01,0x81,0x08,0x82,0x05,0x82,0x01,
0x82,0x01,0x82,0x02,0x82,0x04,0x82,0x02,0x82,0x04,0x82,0x02,0x82,0x04,0x82,
0x02,0x82,0x04,0x82,0x03,0x82,0x08,0x81,0x09,0x82,0x07,0x82,0x04,0x82,0x03,
0x82,0x02,0x81,0x04,0x81,0x02,0x82,0x02,0x81,0x04,0x81,0x01,0x82,0x05,0x82,
0x02,0x82,0x07,0x82,0x08,0x81,0x08,0x82,0x08,0x81,0x07,0x83,0x03,0x81,0x19,
0x82,0x11,0x81,0x02,0x81,0x08,0x82,0x07,0x81,0x01,0x82,0x03,0x82,0x01,0x81,
0x02,0x82,0x0e,0x81,0x0c,0x81,0x06,0x82,0x06,0x88,0x0d,0x86,0x10,0x81,0x06,
0x82,0x04,0x82,0x06,0x82,0x07,0x82,0x09,0x82,0x04,0x82,0x02,0x82,0x09,0x82,
0x03,0x81,0x04,0x82,0x05,0x82,0x06,0x82,0x03,0x81,0x06,0x85,0x18,0x82,0x15,
0x83,0x06,0x82,0x04,0x81,0x01,0x81,0x02,0x81,0x02,0x81,0x03,0x81,0x03,0x82,
0x03,0x82,0x04,0x82,0x02,0x82,0x08,0x82,0x05,0x81,0x02,0x82,0x09,0x82,0x07,
0x81,0x03,0x84,0x02,0x82,0x04,0x82,0x05,0x82,0x0a,0x82,0x03,0x82,0x01,0x82,
0x05,0x82,0x07,0x82,0x01,0x81,0x01,0x81,0x01,0x82,0x02,0x82,0x02,0x82,0x01,
0x81,0x02,0x82,0x05,0x81,0x02,0x86,0x04,0x81,0x06,0x81,0x02,0x82,0x03,0x82,
0x07,0x82,0x07,0x82,0x05,0x82,0x05,0x81,0x03,0x82,0x02,0x81,0x04,0x83,0x01,
0x83,0x05,0x83,0x08,0x82,0x07,0x82,0x09,0x81,0x0a,0x81,0x09,0x81,0x25,0x85,
0x03,0x82,0x04,0x82,0x02,0x82,0x08,0x82,0x04,0x82,0x02,0x88,0x04,0x82,0x06,
0x82,0x03,0x82,0x03,0x82,0x04,0x82,0x05,0x82,0x08,0x82,0x06,0x84,0x08,0x82,
0x05,0x82,0x01,0x82,0x01,0x82,0x02,0x82,0x04,0x82,0x02,0x82,0x04,0x82,0x02,
0x82,0x04,0x82,0x02,0x82,0x04,0x82,0x03,0x82,0x08,0x83,0x07,0x82,0x07,0x82,
0x04,0x82,0x04,0x81,0x02,0x81,0x04,0x81,0x02,0x82,0x02,0x81,0x05,0x82,0x06,
0x82,0x02,0x82,0x06,0x82,0x07,0x82,0x09,0x82,0x09,0x82,0x04,0x82,0x01,0x82,
0x01,0x82,0x2a,0x87,0x08,0x82,0x05,0x81,0x01,0x81,0x02,0x81,0x02,0x81,0x02,
0x82,0x01,0x82,0x0e,0x81,0x0c,0x81,0x05,0x82,0x01,0x82,0x07,0x82,0x26,0x81,
0x06,0x82,0x04,0x82,0x06,0x82,0x06,0x82,0x0b,0x82,0x03,0x87,0x08,0x82,0x03,
0x81,0x04,0x82,0x05,0x82,0x06,0x81,0x04,0x82,0x09,0x81,0x18,0x82,0x08,0x86,
0x08,0x82,0x06,0x82,0x04,0x81,0x01,0x81,0x02,0x81,0x02,0x81,0x03,0x86,0x03,
0x82,0x04,0x82,0x02,0x82,0x08,0x82,0x05,0x81,0x02,0x82,0x09,0x82,0x07,0x82,
0x04,0x82,0x02,0x82,0x04,0x82,0x05,0x82,0x0a,0x82,0x03,0x82,0x02,0x82,0x04,
0x82,0x07,0x82,0x01,0x83,0x01,0x82,0x02,0x82,0x03,0x81,0x01,0x81,0x02,0x82,
0x05,0x81,0x02,0x82,0x08,0x82,0x04,0x82,0x02,0x82,0x04,0x81,0x08,0x82,0x06,
0x82,0x05,0x82,0x05,0x81,0x04,0x81,0x01,0x82,0x05,0x82,0x02,0x82,0x05,0x81,
0x01,0x82,0x07,0x82,0x06,0x82,0x0a,0x81,0x0a,0x81,0x09,0x81,0x24,0x82,0x02,
0x82,0x03,0x82,0x04,0x82,0x02,0x82,0x08,0x82,0x04,0x82,0x02,0x82,0x0a,0x82,
0x06,0x82,0x03,0x82,0x03,0x82,0x04,0x82,0x05,0x82,0x08,0x82,0x06,0x84,0x08,
0x82,0x05,0x82,0x01,0x82,0x01,0x82,0x02,0x82,0x04,0x82,0x02,0x82,0x04,0x82,
0x02,0x82,0x04,0x82,0x02,0x82,0x04,0x82,0x03,0x82,0x0b,0x83,0x04,0x82,0x07,
0x82,0x04,0x82,0x04,0x81,0x01,0x82,0x04,0x81,0x01,0x81,0x01,0x81,0x01,0x82,
0x05,0x82,0x07,0x81,0x02,0x82,0x06,0x81,0x0a,0x81,0x08,0x82,0x08,0x81,0x06,
0x81,0x03,0x83,0x2c,0x81,0x02,0x81,0x05,0x81,0x04,0x82,0x04,0x81,0x02,0x81,
0x02,0x81,0x01,0x82,0x03,0x83,0x0f,0x82,0x0a,0x82,0x11,0x82,0x25,0x82,0x07,
0x81,0x04,0x81,0x07,0x82,0x05,0x82,0x07,0x81,0x04,0x82,0x03,0x87,0x03,0x81,
0x04,0x82,0x03,0x81,0x04,0x82,0x05,0x81,0x07,0x81,0x04,0x82,0x08,0x82,0x19,
0x84,0x10,0x83,0x0e,0x81,0x01,0x81,0x02,0x81,0x01,0x82,0x02,0x82,0x04,0x81,
0x03,0x82,0x04,0x82,0x02,0x83,0x03,0x82,0x02,0x82,0x04,0x82,0x02,0x82,0x09,
0x82,0x07,0x82,0x04,0x82,0x02,0x82,0x04,0x82,0x05,0x82,0x05,0x81,0x04,0x82,
0x03,0x82,0x03,0x81,0x04,0x82,0x07,0x82,0x02,0x81,0x02,0x82,0x02,0x82,0x03,
0x83,0x02,0x82,0x04,0x82,0x02,0x82,0x08,0x82,0x04,0x82,0x02,0x82,0x04,0x82,
0x02,0x81,0x05,0x81,0x06,0x82,0x05,0x83,0x03,0x82,0x04,0x83,0x06,0x82,0x02,
0x82,0x04,0x82,0x02,0x81,0x07,0x82,0x06,0x81,0x0b,0x81,0x0a,0x82,0x08,0x81,
0x23,0x82,0x03,0x82,0x03,0x82,0x04,0x82,0x02,0x82,0x04,0x81,0x03,0x82,0x04,
0x82,0x02,0x82,0x0a,0x82,0x06,0x82,0x03,0x82,0x03,0x82,0x04,0x82,0x05,0x82,
0x08,0x82,0x06,0x82,0x01,0x82,0x07,0x82,0x05,0x82,0x01,0x82,0x01,0x82,0x02,
0x82,0x04,0x82,0x02,0x82,0x04,0x82,0x02,0x82,0x04,0x82,0x02,0x82,0x04,0x82,
0x03,0x82,0x0d,0x81,0x04,0x82,0x07,0x82,0x03,0x83,0x04,0x83,0x06,0x82,0x02,
0x82,0x05,0x81,0x01,0x82,0x06,0x84,0x06,0x81,0x0b,0x81,0x08,0x82,0x08,0x81,
0x27,0x82,0x10,0x81,0x02,0x81,0x05,0x82,0x02,0x83,0x04,0x81,0x02,0x81,0x02,
0x81,0x02,0x81,0x04,0x82,0x0f,0x82,0x0a,0x82,0x11,0x82,0x07,0x82,0x12,0x82,
0x08,0x81,0x08,0x82,0x02,0x82,0x07,0x82,0x05,0x81,0x08,0x82,0x03,0x81,0x08,
0x82,0x04,0x82,0x02,0x82,0x04,0x82,0x02,0x82,0x06,0x81,0x07,0x82,0x02,0x82,
0x08,0x82,0x06,0x82,0x08,0x82,0x0b,0x82,0x0e,0x82,0x0a,0x82,0x04,0x81,0x01,
0x83,0x01,0x82,0x03,0x81,0x05,0x82,0x02,0x82,0x04,0x82,0x03,0x83,0x01,0x82,
0x03,0x82,0x03,0x82,0x03,0x82,0x09,0x82,0x08,0x82,0x03,0x82,0x02,0x82,0x04,
0x82,0x05,0x82,0x05,0x82,0x02,0x82,0x04,0x82,0x03,0x82,0x03,0x82,0x07,0x82,
0x05,0x82,0x02,0x82,0x04,0x82,0x03,0x82,0x02,0x82,0x03,0x82,0x09,0x82,0x02,
0x82,0x03,0x82,0x04,0x82,0x02,0x82,0x03,0x82,0x06,0x82,0x06,0x82,0x03,0x82,
0x05,0x82,0x06,0x82,0x02,0x81,0x04,0x82,0x03,0x82,0x06,0x82,0x05,0x82,0x0b,
0x81,0x0b,0x81,0x08,0x81,0x23,0x82,0x02,0x83,0x03,0x83,0x02,0x82,0x04,0x82,
0x02,0x82,0x04,0x82,0x02,0x83,0x03,0x82,0x03,0x82,0x04,0x82,0x06,0x83,0x01,
0x83,0x03,0x82,0x04,0x82,0x05,0x82,0x08,0x82,0x06,0x82,0x02,0x82,0x06,0x82,
0x05,0x82,0x01,0x82,0x01,0x82,0x02,0x82,0x04,0x82,0x03,0x82,0x02,0x82,0x03,
0x83,0x02,0x82,0x04,0x82,0x02,0x83,0x03,0x82,0x08,0x82,0x02,0x82,0x04,0x82,
0x03,0x81,0x03,0x83,0x01,0x84,0x05,0x82,0x06,0x82,0x02,0x82,0x04,0x82,0x02,
0x81,0x07,0x83,0x05,0x82,0x0b,0x81,0x08,0x82,0x08,0x81,0x27,0x82,0x10,0x81,
0x02,0x81,0x06,0x85,0x09,0x82,0x04,0x84,0x01,0x82,0x0f,0x81,0x0a,0x81,0x1b,
0x82,0x12,0x82,0x08,0x81,0x09,0x84,0x08,0x82,0x04,0x87,0x04,0x84,0x09,0x82,
0x05,0x84,0x06,0x84,0x07,0x81,0x08,0x84,0x06,0x84,0x07,0x82,0x08,0x82,0x27,
0x82,0x04,0x82,0x09,0x81,0x06,0x81,0x02,0x87,0x05,0x84,0x04,0x86,0x04,0x87,
0x04,0x82,0x09,0x85,0x03,0x82,0x04,0x82,0x03,0x86,0x04,0x84,0x05,0x82,0x04,
0x82,0x02,0x87,0x02,0x82,0x05,0x82,0x02,0x82,0x05,0x81,0x04,0x84,0x04,0x82,
0x0a,0x86,0x02,0x82,0x04,0x82,0x03,0x85,0x07,0x82,0x07,0x85,0x06,0x82,0x06,
0x82,0x02,0x81,0x04,0x82,0x04,0x82,0x05,0x82,0x05,0x87,0x06,0x81,0x0b,0x82,
0x07,0x81,0x23,0x84,0x01,0x82,0x03,0x82,0x01,0x83,0x06,0x84,0x06,0x83,0x01,
0x82,0x04,0x85,0x05,0x82,0x07,0x83,0x01,0x82,0x03,0x82,0x04,0x82,0x03,0x86,
0x06,0x82,0x06,0x82,0x03,0x81,0x04,0x86,0x03,0x82,0x01,0x82,0x01,0x82,0x02,
0x82,0x04,0x82,0x04,0x84,0x04,0x82,0x01,0x83,0x06,0x83,0x01,0x82,0x03,0x82,
0x09,0x84,0x06,0x84,0x05,0x84,0x01,0x82,0x05,0x82,0x06,0x81,0x03,0x82,0x03,
0x82,0x03,0x82,0x07,0x82,0x05,0x86,0x07,0x81,0x08,0x82,0x08,0x81,0x45,0x81,
0x27,0x81,0x0a,0x81,0x1c,0x81,0x1b,0x82,0x78,0x81,0x2e,0x82,0x7f,0x30,0x82,
0x5e,0x81,0x0c,0x81,0x07,0x81,0x0f,0x88,0x4d,0x82,0x1a,0x82,0x37,0x82,0x0e,
0x82,0x4b,0x82,0x13,0x82,0x07,0x82,0x07,0x82,0x45,0x81,0x28,0x81,0x08,0x81,
0x1c,0x81,0x1c,0x81,0x78,0x81,0x30,0x84,0x7f,0x7f,0x0e,0x83,0x0a,0x81,0x05,
0x83,0x64,0x82,0x1a,0x82,0x37,0x82,0x0e,0x82,0x4b,0x82,0x14,0x81,0x07,0x82,
0x07,0x81,0x70,0x81,0x06,0x81,0x7f,0x7f,0x7f,0x7f,0x6e,0x85,0x1a,0x82,0x38,
0x82,0x0e,0x82,0x4a,0x82,0x16,0x81,0x0e,0x81,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,
0x7f,0x62,
0x00,
}
};

View File

@ -1,281 +0,0 @@
struct {
unsigned width;
unsigned height;
unsigned cwidth;
unsigned cheight;
unsigned char rundata[];
} font = {
.width = 1440,
.height = 24,
.cwidth = 15,
.cheight = 24,
.rundata = {
0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x6e,0x81,0x3e,0x81,
0x07,0x81,0x7f,0x7f,0x7f,0x7f,0x7f,0x76,0x84,0x17,0x84,0x7f,0x7f,0x7f,0x7f,
0x4c,0x81,0x3d,0x82,0x07,0x82,0x5f,0x81,0x7f,0x7f,0x7f,0x7f,0x7f,0x15,0x84,
0x07,0x82,0x0e,0x84,0x45,0x82,0x24,0x82,0x1a,0x83,0x16,0x82,0x10,0x82,0x0e,
0x82,0x0a,0x82,0x0d,0x84,0x7f,0x62,0x82,0x0b,0x82,0x0b,0x82,0x3b,0x82,0x0c,
0x82,0x02,0x82,0x0a,0x82,0x03,0x81,0x0a,0x84,0x08,0x83,0x0e,0x84,0x0b,0x82,
0x10,0x82,0x09,0x82,0x5e,0x81,0x09,0x84,0x0b,0x84,0x0b,0x84,0x0b,0x84,0x0e,
0x83,0x08,0x88,0x09,0x84,0x07,0x8a,0x08,0x84,0x0b,0x84,0x56,0x84,0x1c,0x82,
0x08,0x87,0x0b,0x85,0x07,0x87,0x09,0x89,0x06,0x8a,0x07,0x85,0x06,0x82,0x08,
0x82,0x06,0x86,0x0f,0x82,0x06,0x82,0x07,0x82,0x04,0x82,0x0a,0x83,0x09,0x82,
0x03,0x82,0x08,0x82,0x06,0x85,0x07,0x87,0x0b,0x85,0x07,0x87,0x0c,0x84,0x06,
0x8d,0x03,0x82,0x07,0x82,0x02,0x83,0x08,0x83,0x01,0x82,0x0a,0x82,0x02,0x82,
0x08,0x82,0x03,0x82,0x08,0x82,0x04,0x8b,0x09,0x82,0x09,0x82,0x10,0x82,0x0d,
0x81,0x1d,0x82,0x18,0x82,0x24,0x82,0x19,0x84,0x16,0x82,0x10,0x82,0x0e,0x82,
0x0a,0x82,0x0d,0x84,0x7f,0x61,0x82,0x0c,0x82,0x0c,0x82,0x3a,0x82,0x0c,0x82,
0x02,0x82,0x0a,0x82,0x03,0x81,0x08,0x87,0x06,0x82,0x01,0x82,0x0c,0x86,0x0a,
0x82,0x0f,0x82,0x0b,0x82,0x5c,0x82,0x08,0x87,0x07,0x86,0x0a,0x87,0x08,0x87,
0x0c,0x83,0x08,0x88,0x07,0x87,0x06,0x8a,0x07,0x87,0x07,0x87,0x54,0x87,0x08,
0x86,0x0c,0x82,0x08,0x89,0x07,0x88,0x06,0x89,0x07,0x89,0x06,0x8a,0x05,0x88,
0x05,0x82,0x08,0x82,0x06,0x86,0x0f,0x82,0x06,0x82,0x06,0x82,0x05,0x82,0x0a,
0x83,0x08,0x83,0x03,0x83,0x07,0x82,0x04,0x88,0x06,0x89,0x07,0x88,0x06,0x89,
0x08,0x88,0x04,0x8d,0x03,0x82,0x07,0x82,0x03,0x82,0x08,0x82,0x02,0x82,0x04,
0x81,0x05,0x82,0x03,0x82,0x06,0x82,0x04,0x82,0x07,0x83,0x04,0x8b,0x09,0x82,
0x0a,0x82,0x0f,0x82,0x0c,0x83,0x1d,0x82,0x17,0x82,0x24,0x82,0x18,0x83,0x18,
0x82,0x2c,0x82,0x0f,0x82,0x7f,0x60,0x83,0x0c,0x82,0x0d,0x82,0x39,0x82,0x0c,
0x82,0x02,0x82,0x0a,0x82,0x02,0x82,0x07,0x83,0x03,0x83,0x04,0x82,0x03,0x81,
0x04,0x81,0x06,0x83,0x03,0x82,0x09,0x82,0x0f,0x82,0x0b,0x82,0x5c,0x82,0x07,
0x82,0x04,0x82,0x0a,0x83,0x09,0x82,0x04,0x83,0x06,0x82,0x04,0x83,0x0a,0x84,
0x08,0x82,0x0d,0x82,0x13,0x82,0x06,0x82,0x04,0x83,0x06,0x82,0x04,0x82,0x52,
0x82,0x04,0x82,0x07,0x82,0x05,0x82,0x09,0x84,0x07,0x82,0x05,0x83,0x06,0x82,
0x05,0x82,0x05,0x82,0x05,0x83,0x06,0x82,0x0d,0x82,0x0d,0x82,0x05,0x82,0x04,
0x82,0x08,0x82,0x08,0x82,0x11,0x82,0x06,0x82,0x05,0x82,0x06,0x82,0x0a,0x83,
0x08,0x83,0x03,0x83,0x07,0x82,0x04,0x82,0x05,0x82,0x05,0x82,0x06,0x82,0x06,
0x82,0x05,0x82,0x05,0x82,0x05,0x83,0x06,0x83,0x04,0x83,0x08,0x83,0x08,0x82,
0x07,0x82,0x03,0x82,0x08,0x82,0x02,0x82,0x03,0x83,0x04,0x82,0x03,0x83,0x04,
0x83,0x05,0x82,0x06,0x82,0x0d,0x82,0x0a,0x82,0x0a,0x82,0x0f,0x82,0x0c,0x83,
0x1e,0x81,0x17,0x82,0x24,0x82,0x18,0x82,0x19,0x82,0x2c,0x82,0x0f,0x82,0x74,
0x82,0x69,0x82,0x0d,0x82,0x0d,0x82,0x39,0x82,0x0c,0x82,0x02,0x82,0x0a,0x82,
0x02,0x82,0x07,0x82,0x05,0x82,0x04,0x82,0x03,0x82,0x02,0x82,0x06,0x82,0x04,
0x82,0x09,0x82,0x0e,0x82,0x0d,0x82,0x1c,0x82,0x3c,0x82,0x08,0x82,0x05,0x82,
0x09,0x83,0x09,0x82,0x05,0x82,0x05,0x83,0x05,0x82,0x09,0x85,0x07,0x82,0x0d,
0x82,0x13,0x82,0x07,0x82,0x05,0x82,0x05,0x82,0x05,0x83,0x51,0x82,0x04,0x82,
0x06,0x82,0x07,0x82,0x08,0x84,0x07,0x82,0x06,0x82,0x05,0x82,0x07,0x82,0x04,
0x82,0x06,0x83,0x05,0x82,0x0d,0x82,0x0c,0x82,0x07,0x82,0x03,0x82,0x08,0x82,
0x08,0x82,0x11,0x82,0x06,0x82,0x04,0x83,0x06,0x82,0x0a,0x84,0x06,0x84,0x03,
0x84,0x06,0x82,0x03,0x82,0x07,0x82,0x04,0x82,0x07,0x82,0x04,0x82,0x07,0x82,
0x04,0x82,0x06,0x82,0x06,0x82,0x06,0x82,0x08,0x83,0x08,0x82,0x07,0x82,0x03,
0x83,0x06,0x83,0x02,0x82,0x03,0x83,0x03,0x82,0x05,0x82,0x04,0x82,0x06,0x82,
0x05,0x83,0x0c,0x83,0x0a,0x82,0x0b,0x82,0x0e,0x82,0x0c,0x81,0x01,0x82,0x35,
0x82,0x24,0x82,0x18,0x82,0x19,0x82,0x2c,0x82,0x0f,0x82,0x74,0x82,0x69,0x82,
0x0d,0x82,0x0d,0x83,0x38,0x82,0x0c,0x82,0x02,0x81,0x0b,0x81,0x03,0x82,0x07,
0x82,0x05,0x82,0x04,0x82,0x03,0x82,0x02,0x81,0x07,0x82,0x04,0x82,0x09,0x82,
0x0e,0x82,0x0d,0x82,0x0d,0x82,0x0d,0x82,0x3c,0x82,0x07,0x82,0x06,0x82,0x09,
0x83,0x08,0x83,0x05,0x82,0x0d,0x82,0x09,0x85,0x07,0x82,0x0d,0x82,0x12,0x83,
0x07,0x82,0x05,0x82,0x05,0x82,0x06,0x82,0x57,0x83,0x04,0x82,0x09,0x81,0x08,
0x84,0x07,0x82,0x06,0x82,0x05,0x82,0x07,0x82,0x04,0x82,0x07,0x82,0x05,0x82,
0x0d,0x82,0x0c,0x82,0x07,0x82,0x03,0x82,0x08,0x82,0x08,0x82,0x11,0x82,0x06,
0x82,0x03,0x83,0x07,0x82,0x0a,0x84,0x06,0x84,0x03,0x85,0x05,0x82,0x03,0x82,
0x07,0x82,0x04,0x82,0x07,0x82,0x04,0x82,0x07,0x82,0x04,0x82,0x06,0x83,0x05,
0x82,0x06,0x82,0x08,0x83,0x08,0x82,0x07,0x82,0x04,0x82,0x06,0x82,0x03,0x82,
0x03,0x83,0x03,0x82,0x05,0x83,0x02,0x83,0x07,0x82,0x04,0x82,0x0d,0x82,0x0b,
0x82,0x0b,0x82,0x0e,0x82,0x0b,0x82,0x01,0x82,0x29,0x84,0x08,0x82,0x01,0x84,
0x0a,0x86,0x0a,0x83,0x02,0x82,0x08,0x84,0x0a,0x86,0x0a,0x83,0x02,0x82,0x06,
0x82,0x01,0x84,0x09,0x84,0x0e,0x82,0x0a,0x82,0x04,0x83,0x08,0x82,0x07,0x81,
0x02,0x83,0x03,0x83,0x05,0x81,0x02,0x84,0x0b,0x84,0x09,0x81,0x02,0x84,0x0a,
0x83,0x02,0x82,0x08,0x81,0x02,0x84,0x08,0x84,0x08,0x88,0x07,0x82,0x06,0x82,
0x05,0x82,0x06,0x82,0x03,0x82,0x03,0x82,0x05,0x82,0x04,0x82,0x05,0x82,0x04,
0x83,0x05,0x83,0x06,0x89,0x09,0x82,0x0d,0x82,0x0d,0x83,0x38,0x82,0x0c,0x82,
0x02,0x81,0x08,0x8b,0x05,0x82,0x0b,0x82,0x03,0x81,0x02,0x82,0x07,0x83,0x02,
0x82,0x0a,0x81,0x0f,0x82,0x0d,0x82,0x0d,0x82,0x0d,0x82,0x3c,0x82,0x07,0x82,
0x06,0x82,0x09,0x83,0x10,0x82,0x0d,0x82,0x08,0x82,0x01,0x83,0x07,0x82,0x0d,
0x82,0x12,0x82,0x08,0x82,0x05,0x82,0x05,0x82,0x06,0x82,0x08,0x82,0x0d,0x82,
0x13,0x81,0x06,0x89,0x06,0x81,0x14,0x82,0x05,0x81,0x04,0x84,0x02,0x82,0x06,
0x82,0x02,0x82,0x06,0x82,0x06,0x82,0x04,0x82,0x0e,0x82,0x07,0x82,0x05,0x82,
0x0d,0x82,0x0b,0x82,0x0d,0x82,0x08,0x82,0x08,0x82,0x11,0x82,0x06,0x82,0x03,
0x82,0x08,0x82,0x0a,0x82,0x01,0x82,0x05,0x84,0x03,0x82,0x01,0x82,0x05,0x82,
0x02,0x82,0x09,0x82,0x03,0x82,0x07,0x82,0x03,0x82,0x09,0x82,0x03,0x82,0x06,
0x83,0x05,0x82,0x10,0x83,0x08,0x82,0x07,0x82,0x04,0x82,0x06,0x82,0x03,0x82,
0x03,0x81,0x01,0x82,0x02,0x82,0x06,0x82,0x02,0x82,0x08,0x82,0x03,0x83,0x0c,
0x82,0x0c,0x82,0x0b,0x82,0x0e,0x82,0x0b,0x82,0x02,0x81,0x28,0x87,0x06,0x88,
0x08,0x88,0x08,0x88,0x07,0x86,0x09,0x86,0x09,0x88,0x06,0x88,0x08,0x84,0x0e,
0x82,0x0a,0x82,0x03,0x83,0x09,0x82,0x07,0x87,0x01,0x85,0x04,0x88,0x09,0x87,
0x07,0x81,0x01,0x86,0x08,0x88,0x08,0x87,0x06,0x87,0x07,0x88,0x07,0x82,0x06,
0x82,0x05,0x82,0x05,0x82,0x04,0x82,0x03,0x82,0x05,0x82,0x04,0x83,0x03,0x83,
0x05,0x82,0x05,0x82,0x07,0x89,0x09,0x82,0x0d,0x82,0x0d,0x83,0x38,0x82,0x1b,
0x82,0x03,0x81,0x08,0x83,0x0b,0x85,0x01,0x82,0x09,0x85,0x1a,0x83,0x0d,0x83,
0x09,0x81,0x02,0x82,0x01,0x81,0x0b,0x82,0x3b,0x82,0x08,0x82,0x06,0x82,0x09,
0x83,0x0f,0x82,0x0d,0x82,0x09,0x82,0x01,0x83,0x07,0x87,0x07,0x83,0x01,0x84,
0x0c,0x82,0x09,0x83,0x03,0x82,0x06,0x82,0x06,0x82,0x08,0x82,0x0d,0x82,0x11,
0x83,0x06,0x89,0x06,0x83,0x12,0x82,0x05,0x81,0x03,0x82,0x02,0x82,0x02,0x81,
0x06,0x82,0x02,0x82,0x06,0x82,0x05,0x82,0x05,0x82,0x0e,0x82,0x07,0x83,0x04,
0x82,0x0d,0x82,0x0b,0x82,0x0d,0x82,0x08,0x82,0x08,0x82,0x11,0x82,0x06,0x82,
0x02,0x82,0x09,0x82,0x0a,0x82,0x01,0x82,0x04,0x82,0x01,0x82,0x03,0x82,0x02,
0x82,0x04,0x82,0x02,0x82,0x09,0x82,0x03,0x82,0x07,0x82,0x03,0x82,0x09,0x82,
0x03,0x82,0x06,0x82,0x06,0x83,0x0f,0x83,0x08,0x82,0x07,0x82,0x05,0x82,0x04,
0x82,0x05,0x81,0x02,0x82,0x01,0x82,0x02,0x82,0x07,0x84,0x0a,0x82,0x02,0x82,
0x0c,0x83,0x0c,0x82,0x0c,0x82,0x0d,0x82,0x0a,0x82,0x03,0x82,0x26,0x82,0x04,
0x82,0x06,0x83,0x03,0x83,0x07,0x82,0x05,0x82,0x06,0x82,0x04,0x83,0x06,0x82,
0x04,0x82,0x0a,0x82,0x0a,0x83,0x03,0x83,0x06,0x82,0x04,0x83,0x09,0x82,0x0e,
0x82,0x0a,0x82,0x03,0x82,0x0a,0x82,0x07,0x82,0x03,0x84,0x02,0x82,0x04,0x82,
0x04,0x83,0x07,0x82,0x04,0x83,0x06,0x82,0x04,0x83,0x06,0x82,0x04,0x83,0x08,
0x83,0x0a,0x82,0x04,0x82,0x08,0x82,0x0b,0x82,0x06,0x82,0x05,0x82,0x05,0x82,
0x04,0x82,0x03,0x83,0x03,0x82,0x06,0x82,0x03,0x82,0x06,0x82,0x05,0x82,0x0d,
0x82,0x0a,0x82,0x0d,0x82,0x0d,0x83,0x38,0x82,0x1b,0x82,0x02,0x82,0x09,0x85,
0x0e,0x81,0x0b,0x83,0x1b,0x82,0x0f,0x82,0x09,0x87,0x0b,0x82,0x3b,0x82,0x08,
0x82,0x06,0x82,0x09,0x83,0x0e,0x83,0x09,0x85,0x09,0x82,0x02,0x83,0x07,0x88,
0x06,0x89,0x0b,0x82,0x0a,0x86,0x07,0x82,0x06,0x82,0x27,0x85,0x17,0x84,0x0f,
0x82,0x05,0x82,0x03,0x81,0x03,0x82,0x02,0x81,0x06,0x82,0x02,0x82,0x06,0x88,
0x06,0x82,0x0e,0x82,0x07,0x83,0x04,0x88,0x07,0x88,0x05,0x82,0x0d,0x8c,0x08,
0x82,0x11,0x82,0x06,0x85,0x0a,0x82,0x0a,0x82,0x01,0x82,0x04,0x82,0x01,0x82,
0x03,0x82,0x02,0x82,0x04,0x82,0x02,0x82,0x09,0x82,0x03,0x82,0x06,0x82,0x04,
0x82,0x09,0x82,0x03,0x82,0x04,0x83,0x08,0x85,0x0c,0x83,0x08,0x82,0x07,0x82,
0x05,0x82,0x04,0x82,0x05,0x82,0x01,0x82,0x01,0x82,0x02,0x81,0x08,0x84,0x0a,
0x86,0x0c,0x82,0x0d,0x82,0x0c,0x82,0x0d,0x82,0x0a,0x82,0x03,0x82,0x26,0x82,
0x04,0x83,0x05,0x82,0x05,0x82,0x06,0x83,0x05,0x82,0x05,0x83,0x05,0x82,0x05,
0x83,0x04,0x82,0x0a,0x82,0x0a,0x82,0x05,0x82,0x06,0x82,0x05,0x82,0x09,0x82,
0x0e,0x82,0x0a,0x82,0x02,0x82,0x0b,0x82,0x07,0x82,0x03,0x83,0x03,0x83,0x03,
0x82,0x05,0x82,0x06,0x83,0x05,0x82,0x06,0x82,0x05,0x82,0x05,0x83,0x05,0x82,
0x08,0x82,0x0b,0x82,0x04,0x82,0x08,0x82,0x0b,0x82,0x06,0x82,0x06,0x82,0x04,
0x82,0x04,0x82,0x02,0x84,0x03,0x82,0x07,0x82,0x01,0x82,0x07,0x83,0x03,0x83,
0x0c,0x83,0x0a,0x82,0x0d,0x82,0x0e,0x82,0x0a,0x82,0x2c,0x82,0x1b,0x82,0x02,
0x82,0x0b,0x85,0x0b,0x82,0x09,0x85,0x1b,0x82,0x0f,0x82,0x0b,0x83,0x09,0x8b,
0x36,0x81,0x09,0x82,0x06,0x82,0x09,0x83,0x0e,0x82,0x0a,0x86,0x07,0x82,0x03,
0x83,0x07,0x82,0x04,0x83,0x05,0x84,0x03,0x83,0x09,0x82,0x0b,0x87,0x07,0x82,
0x04,0x83,0x25,0x85,0x1b,0x85,0x0b,0x82,0x06,0x82,0x02,0x82,0x03,0x82,0x02,
0x81,0x05,0x82,0x04,0x82,0x05,0x8a,0x04,0x82,0x0e,0x82,0x07,0x83,0x04,0x88,
0x07,0x88,0x05,0x82,0x04,0x86,0x03,0x8c,0x08,0x82,0x11,0x82,0x06,0x86,0x09,
0x82,0x0a,0x82,0x02,0x82,0x02,0x82,0x02,0x82,0x03,0x82,0x03,0x82,0x03,0x82,
0x02,0x82,0x09,0x82,0x03,0x8a,0x04,0x82,0x09,0x82,0x03,0x89,0x0a,0x85,0x0a,
0x83,0x08,0x82,0x07,0x82,0x05,0x82,0x04,0x82,0x05,0x82,0x01,0x82,0x02,0x81,
0x01,0x82,0x09,0x82,0x0c,0x84,0x0c,0x82,0x0e,0x82,0x0d,0x82,0x0c,0x82,0x3d,
0x83,0x05,0x82,0x05,0x82,0x06,0x82,0x0d,0x82,0x06,0x82,0x05,0x82,0x06,0x82,
0x09,0x82,0x09,0x82,0x06,0x82,0x06,0x82,0x05,0x82,0x09,0x82,0x0e,0x82,0x0a,
0x82,0x01,0x83,0x0b,0x82,0x07,0x82,0x04,0x82,0x04,0x82,0x03,0x82,0x05,0x82,
0x06,0x82,0x06,0x82,0x06,0x82,0x05,0x82,0x05,0x82,0x06,0x82,0x08,0x82,0x0b,
0x82,0x0e,0x82,0x0b,0x82,0x06,0x82,0x06,0x82,0x03,0x82,0x06,0x82,0x01,0x82,
0x01,0x81,0x03,0x82,0x07,0x82,0x01,0x82,0x08,0x82,0x03,0x82,0x0c,0x83,0x09,
0x83,0x0e,0x82,0x0e,0x83,0x07,0x86,0x04,0x82,0x24,0x82,0x1b,0x81,0x03,0x82,
0x0d,0x84,0x0a,0x81,0x02,0x84,0x03,0x83,0x01,0x83,0x03,0x82,0x15,0x82,0x0f,
0x82,0x0b,0x84,0x08,0x8b,0x15,0x86,0x1a,0x82,0x09,0x82,0x06,0x82,0x09,0x83,
0x0d,0x82,0x0f,0x83,0x06,0x82,0x03,0x83,0x0e,0x82,0x05,0x83,0x05,0x82,0x09,
0x82,0x0a,0x82,0x04,0x83,0x06,0x89,0x24,0x83,0x21,0x84,0x08,0x82,0x07,0x81,
0x03,0x82,0x03,0x81,0x03,0x81,0x05,0x82,0x04,0x82,0x05,0x82,0x06,0x83,0x03,
0x82,0x0e,0x82,0x07,0x83,0x04,0x82,0x0d,0x82,0x0b,0x82,0x04,0x86,0x03,0x82,
0x08,0x82,0x08,0x82,0x11,0x82,0x06,0x82,0x02,0x82,0x09,0x82,0x0a,0x82,0x02,
0x82,0x02,0x82,0x02,0x82,0x03,0x82,0x03,0x83,0x02,0x82,0x02,0x82,0x09,0x82,
0x03,0x88,0x06,0x82,0x09,0x82,0x03,0x82,0x05,0x83,0x0c,0x84,0x08,0x83,0x08,
0x82,0x07,0x82,0x06,0x82,0x02,0x82,0x06,0x82,0x01,0x81,0x03,0x84,0x08,0x84,
0x0b,0x83,0x0c,0x83,0x0e,0x82,0x0d,0x82,0x0c,0x82,0x39,0x87,0x05,0x82,0x05,
0x82,0x06,0x82,0x0d,0x82,0x06,0x82,0x05,0x8a,0x09,0x82,0x09,0x82,0x06,0x82,
0x06,0x82,0x05,0x82,0x09,0x82,0x0e,0x82,0x0a,0x85,0x0c,0x82,0x07,0x82,0x04,
0x82,0x04,0x82,0x03,0x82,0x05,0x82,0x06,0x82,0x06,0x82,0x06,0x82,0x05,0x82,
0x05,0x82,0x06,0x82,0x08,0x82,0x0b,0x85,0x0b,0x82,0x0b,0x82,0x06,0x82,0x06,
0x82,0x03,0x82,0x06,0x82,0x01,0x82,0x01,0x82,0x02,0x82,0x08,0x83,0x09,0x82,
0x03,0x82,0x0c,0x82,0x0a,0x82,0x0f,0x82,0x0f,0x83,0x06,0x82,0x02,0x83,0x02,
0x82,0x25,0x82,0x18,0x8b,0x0d,0x82,0x09,0x82,0x01,0x82,0x02,0x82,0x02,0x82,
0x03,0x83,0x02,0x82,0x15,0x82,0x0f,0x82,0x0a,0x82,0x01,0x82,0x0c,0x82,0x3a,
0x82,0x09,0x82,0x06,0x82,0x09,0x83,0x0c,0x82,0x11,0x82,0x05,0x82,0x04,0x83,
0x0e,0x82,0x05,0x83,0x05,0x82,0x09,0x82,0x09,0x82,0x06,0x82,0x08,0x83,0x02,
0x82,0x24,0x83,0x0c,0x89,0x0d,0x83,0x08,0x82,0x07,0x81,0x03,0x82,0x03,0x81,
0x03,0x81,0x04,0x89,0x05,0x82,0x07,0x82,0x03,0x82,0x0e,0x82,0x07,0x82,0x05,
0x82,0x0d,0x82,0x0b,0x82,0x08,0x82,0x03,0x82,0x08,0x82,0x08,0x82,0x11,0x82,
0x06,0x82,0x03,0x82,0x08,0x82,0x0a,0x82,0x03,0x81,0x02,0x81,0x03,0x82,0x03,
0x82,0x04,0x82,0x02,0x82,0x02,0x82,0x09,0x82,0x03,0x82,0x0c,0x82,0x09,0x82,
0x03,0x82,0x06,0x82,0x0e,0x82,0x08,0x83,0x08,0x82,0x07,0x82,0x06,0x82,0x02,
0x82,0x06,0x84,0x03,0x84,0x07,0x86,0x0b,0x82,0x0c,0x82,0x0f,0x82,0x0d,0x82,
0x0c,0x82,0x37,0x89,0x05,0x82,0x05,0x82,0x06,0x82,0x0d,0x82,0x06,0x82,0x05,
0x8a,0x09,0x82,0x09,0x82,0x06,0x82,0x06,0x82,0x05,0x82,0x09,0x82,0x0e,0x82,
0x0a,0x85,0x0c,0x82,0x07,0x82,0x04,0x82,0x04,0x82,0x03,0x82,0x05,0x82,0x06,
0x82,0x06,0x82,0x06,0x82,0x05,0x82,0x05,0x82,0x06,0x82,0x08,0x82,0x0d,0x85,
0x09,0x82,0x0b,0x82,0x06,0x82,0x07,0x82,0x02,0x81,0x07,0x82,0x01,0x81,0x02,
0x82,0x01,0x82,0x09,0x83,0x0a,0x82,0x01,0x83,0x0b,0x82,0x0c,0x82,0x0e,0x82,
0x0e,0x82,0x07,0x82,0x04,0x86,0x3f,0x8b,0x05,0x82,0x06,0x82,0x08,0x82,0x02,
0x81,0x04,0x81,0x02,0x82,0x04,0x85,0x16,0x82,0x0f,0x82,0x0e,0x81,0x0c,0x82,
0x39,0x82,0x0a,0x82,0x06,0x82,0x09,0x83,0x0b,0x83,0x11,0x82,0x05,0x8b,0x0c,
0x82,0x06,0x82,0x05,0x82,0x08,0x83,0x09,0x82,0x06,0x82,0x0d,0x82,0x25,0x85,
0x09,0x89,0x0a,0x85,0x09,0x82,0x07,0x81,0x03,0x82,0x03,0x81,0x02,0x82,0x04,
0x8a,0x04,0x82,0x07,0x82,0x03,0x83,0x07,0x82,0x04,0x82,0x07,0x82,0x05,0x82,
0x0d,0x82,0x0b,0x83,0x07,0x82,0x03,0x82,0x08,0x82,0x08,0x82,0x11,0x82,0x06,
0x82,0x03,0x83,0x07,0x82,0x0a,0x82,0x03,0x84,0x03,0x82,0x03,0x82,0x05,0x82,
0x01,0x82,0x02,0x83,0x07,0x83,0x03,0x82,0x0c,0x83,0x07,0x83,0x03,0x82,0x06,
0x83,0x04,0x82,0x07,0x82,0x08,0x83,0x08,0x82,0x07,0x82,0x06,0x82,0x01,0x83,
0x07,0x83,0x03,0x84,0x07,0x82,0x02,0x82,0x0b,0x82,0x0b,0x82,0x10,0x82,0x0e,
0x82,0x0b,0x82,0x36,0x83,0x04,0x83,0x05,0x82,0x05,0x82,0x06,0x82,0x0d,0x82,
0x06,0x82,0x05,0x82,0x11,0x82,0x09,0x82,0x06,0x82,0x06,0x82,0x05,0x82,0x09,
0x82,0x0e,0x82,0x0a,0x82,0x02,0x82,0x0b,0x82,0x07,0x82,0x04,0x82,0x04,0x82,
0x03,0x82,0x05,0x82,0x06,0x82,0x06,0x82,0x06,0x82,0x05,0x82,0x05,0x82,0x06,
0x82,0x08,0x82,0x10,0x83,0x08,0x82,0x0b,0x82,0x06,0x82,0x07,0x82,0x01,0x82,
0x08,0x83,0x03,0x81,0x01,0x82,0x08,0x85,0x09,0x82,0x01,0x82,0x0b,0x83,0x0d,
0x82,0x0d,0x82,0x0e,0x82,0x0f,0x82,0x43,0x82,0x02,0x82,0x08,0x83,0x05,0x82,
0x08,0x81,0x03,0x81,0x04,0x81,0x02,0x82,0x05,0x84,0x16,0x82,0x0f,0x82,0x1b,
0x82,0x39,0x82,0x0a,0x83,0x05,0x82,0x09,0x83,0x0a,0x83,0x0a,0x82,0x06,0x82,
0x0b,0x83,0x07,0x82,0x05,0x82,0x06,0x82,0x05,0x82,0x08,0x82,0x0a,0x82,0x06,
0x82,0x0c,0x83,0x27,0x85,0x18,0x84,0x15,0x82,0x02,0x82,0x02,0x82,0x02,0x81,
0x05,0x82,0x06,0x82,0x04,0x82,0x07,0x82,0x04,0x82,0x07,0x82,0x04,0x82,0x06,
0x83,0x05,0x82,0x0d,0x82,0x0c,0x82,0x07,0x82,0x03,0x82,0x08,0x82,0x08,0x82,
0x0a,0x82,0x05,0x82,0x06,0x82,0x04,0x83,0x06,0x82,0x0a,0x82,0x03,0x84,0x03,
0x82,0x03,0x82,0x05,0x85,0x03,0x82,0x07,0x82,0x04,0x82,0x0d,0x82,0x05,0x81,
0x01,0x82,0x04,0x82,0x06,0x83,0x04,0x83,0x06,0x82,0x08,0x83,0x08,0x82,0x07,
0x82,0x07,0x84,0x08,0x83,0x04,0x82,0x07,0x82,0x04,0x82,0x0a,0x82,0x0a,0x83,
0x10,0x82,0x0e,0x82,0x0b,0x82,0x36,0x82,0x05,0x83,0x05,0x82,0x05,0x82,0x06,
0x83,0x05,0x82,0x05,0x82,0x06,0x82,0x05,0x83,0x10,0x82,0x09,0x83,0x05,0x82,
0x06,0x82,0x05,0x82,0x09,0x82,0x0e,0x82,0x0a,0x82,0x02,0x83,0x0a,0x82,0x07,
0x82,0x04,0x82,0x04,0x82,0x03,0x82,0x05,0x82,0x06,0x83,0x05,0x82,0x06,0x82,
0x05,0x82,0x05,0x82,0x06,0x82,0x08,0x82,0x0a,0x82,0x05,0x82,0x08,0x82,0x0b,
0x82,0x06,0x82,0x08,0x81,0x01,0x82,0x08,0x83,0x03,0x84,0x08,0x82,0x01,0x82,
0x09,0x82,0x01,0x82,0x0b,0x82,0x0e,0x82,0x0d,0x82,0x0d,0x83,0x54,0x82,0x02,
0x82,0x09,0x82,0x04,0x83,0x07,0x82,0x03,0x81,0x04,0x81,0x02,0x82,0x06,0x82,
0x18,0x82,0x0d,0x82,0x1c,0x82,0x39,0x81,0x0c,0x82,0x04,0x83,0x09,0x83,0x09,
0x83,0x0c,0x82,0x05,0x82,0x0b,0x83,0x07,0x82,0x04,0x83,0x06,0x83,0x04,0x82,
0x08,0x82,0x0a,0x83,0x05,0x82,0x0c,0x82,0x2b,0x83,0x15,0x84,0x18,0x81,0x03,
0x83,0x01,0x83,0x05,0x82,0x07,0x83,0x03,0x82,0x06,0x83,0x04,0x83,0x05,0x82,
0x05,0x82,0x06,0x82,0x06,0x82,0x0d,0x82,0x0c,0x83,0x06,0x82,0x03,0x82,0x08,
0x82,0x08,0x82,0x0a,0x82,0x05,0x82,0x06,0x82,0x05,0x83,0x05,0x82,0x0a,0x82,
0x04,0x82,0x04,0x82,0x03,0x82,0x06,0x84,0x03,0x83,0x05,0x83,0x04,0x82,0x0d,
0x83,0x05,0x83,0x04,0x82,0x06,0x83,0x05,0x82,0x06,0x82,0x08,0x83,0x08,0x83,
0x05,0x83,0x07,0x84,0x08,0x82,0x05,0x82,0x06,0x83,0x04,0x83,0x09,0x82,0x0a,
0x82,0x11,0x82,0x0e,0x82,0x0b,0x82,0x36,0x82,0x05,0x83,0x05,0x83,0x04,0x82,
0x07,0x82,0x05,0x82,0x06,0x82,0x04,0x83,0x06,0x82,0x10,0x82,0x0a,0x82,0x04,
0x83,0x06,0x82,0x05,0x82,0x09,0x82,0x0e,0x82,0x0a,0x82,0x03,0x82,0x0a,0x82,
0x07,0x82,0x04,0x82,0x04,0x82,0x03,0x82,0x05,0x82,0x07,0x82,0x04,0x83,0x06,
0x82,0x05,0x82,0x06,0x82,0x04,0x83,0x08,0x82,0x0a,0x83,0x04,0x82,0x08,0x82,
0x03,0x82,0x06,0x83,0x04,0x83,0x08,0x83,0x09,0x82,0x04,0x83,0x08,0x82,0x03,
0x82,0x09,0x83,0x0b,0x82,0x0f,0x82,0x0d,0x82,0x0d,0x83,0x38,0x82,0x1a,0x81,
0x03,0x82,0x09,0x88,0x08,0x81,0x04,0x82,0x02,0x82,0x03,0x83,0x02,0x85,0x17,
0x82,0x0d,0x82,0x29,0x82,0x1d,0x82,0x0c,0x82,0x0c,0x83,0x02,0x83,0x0a,0x83,
0x09,0x89,0x06,0x84,0x01,0x83,0x0c,0x83,0x07,0x84,0x01,0x83,0x08,0x83,0x01,
0x83,0x09,0x82,0x0b,0x84,0x01,0x83,0x07,0x82,0x02,0x84,0x09,0x82,0x0d,0x82,
0x13,0x81,0x15,0x82,0x10,0x82,0x08,0x81,0x0f,0x82,0x08,0x82,0x03,0x8a,0x06,
0x83,0x02,0x84,0x05,0x89,0x07,0x89,0x06,0x82,0x0d,0x84,0x02,0x84,0x03,0x82,
0x08,0x82,0x06,0x86,0x09,0x83,0x01,0x83,0x07,0x82,0x06,0x83,0x04,0x8a,0x02,
0x82,0x04,0x82,0x04,0x82,0x03,0x82,0x07,0x83,0x04,0x89,0x05,0x82,0x0e,0x8a,
0x04,0x82,0x07,0x82,0x05,0x84,0x02,0x83,0x09,0x83,0x09,0x84,0x01,0x84,0x08,
0x83,0x09,0x82,0x05,0x82,0x06,0x82,0x06,0x82,0x09,0x82,0x09,0x8b,0x09,0x82,
0x0f,0x82,0x0a,0x82,0x37,0x89,0x05,0x88,0x08,0x88,0x07,0x89,0x06,0x84,0x02,
0x82,0x0a,0x82,0x0a,0x89,0x06,0x82,0x05,0x82,0x06,0x88,0x0b,0x82,0x0a,0x82,
0x04,0x82,0x06,0x88,0x04,0x82,0x04,0x82,0x04,0x82,0x03,0x82,0x05,0x82,0x07,
0x84,0x01,0x83,0x07,0x84,0x01,0x83,0x07,0x83,0x02,0x84,0x08,0x82,0x0b,0x83,
0x02,0x83,0x08,0x87,0x06,0x8a,0x08,0x83,0x09,0x82,0x05,0x82,0x07,0x83,0x03,
0x83,0x08,0x83,0x0a,0x89,0x09,0x82,0x0d,0x82,0x0d,0x83,0x38,0x82,0x1a,0x81,
0x03,0x82,0x0a,0x86,0x0f,0x84,0x05,0x86,0x01,0x83,0x16,0x82,0x0d,0x82,0x29,
0x82,0x1d,0x82,0x0c,0x82,0x0d,0x86,0x0b,0x83,0x09,0x89,0x07,0x86,0x0d,0x83,
0x08,0x86,0x0a,0x85,0x0a,0x82,0x0c,0x86,0x08,0x86,0x0b,0x82,0x0d,0x82,0x3b,
0x82,0x09,0x81,0x0e,0x82,0x08,0x82,0x03,0x89,0x08,0x86,0x07,0x88,0x08,0x89,
0x06,0x82,0x0e,0x87,0x05,0x82,0x08,0x82,0x06,0x86,0x0a,0x85,0x08,0x82,0x07,
0x82,0x04,0x8a,0x02,0x82,0x0a,0x82,0x03,0x82,0x07,0x83,0x05,0x86,0x07,0x82,
0x0f,0x86,0x01,0x83,0x03,0x82,0x07,0x82,0x07,0x86,0x0a,0x83,0x0a,0x87,0x0a,
0x82,0x09,0x82,0x06,0x81,0x05,0x83,0x06,0x83,0x08,0x82,0x09,0x8b,0x09,0x82,
0x0f,0x82,0x0a,0x82,0x37,0x85,0x02,0x82,0x05,0x81,0x01,0x85,0x0b,0x85,0x09,
0x85,0x01,0x82,0x08,0x86,0x0a,0x82,0x0b,0x85,0x01,0x82,0x06,0x82,0x05,0x82,
0x06,0x88,0x0b,0x82,0x0a,0x82,0x04,0x83,0x05,0x88,0x04,0x82,0x04,0x82,0x04,
0x82,0x03,0x82,0x05,0x82,0x09,0x85,0x08,0x87,0x09,0x85,0x01,0x82,0x08,0x82,
0x0c,0x86,0x0a,0x84,0x09,0x86,0x01,0x82,0x09,0x82,0x0a,0x81,0x05,0x82,0x07,
0x82,0x05,0x82,0x08,0x83,0x0a,0x89,0x09,0x82,0x0d,0x82,0x0d,0x82,0x68,0x81,
0x3b,0x82,0x0b,0x82,0x2a,0x82,0x2a,0x82,0x7f,0x35,0x82,0x46,0x83,0x7f,0x7f,
0x08,0x82,0x7f,0x10,0x82,0x10,0x82,0x09,0x82,0x18,0x8a,0x76,0x82,0x28,0x82,
0x54,0x82,0x14,0x82,0x71,0x82,0x1d,0x82,0x0d,0x82,0x0d,0x82,0x68,0x81,0x3b,
0x82,0x0b,0x82,0x2a,0x82,0x2a,0x82,0x7f,0x35,0x82,0x48,0x86,0x7f,0x7f,0x7f,
0x15,0x84,0x0e,0x82,0x07,0x84,0x18,0x8a,0x76,0x82,0x28,0x82,0x54,0x82,0x14,
0x82,0x71,0x82,0x1d,0x83,0x0c,0x82,0x0d,0x82,0x7f,0x26,0x82,0x09,0x82,0x2b,
0x81,0x7f,0x62,0x81,0x7f,0x7f,0x7f,0x64,0x84,0x17,0x84,0x7f,0x12,0x82,0x04,
0x82,0x28,0x83,0x54,0x82,0x14,0x82,0x70,0x83,0x1e,0x83,0x0b,0x82,0x0c,0x82,
0x7f,0x28,0x82,0x07,0x82,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x27,0x88,0x26,
0x84,0x55,0x82,0x14,0x82,0x6e,0x84,0x21,0x81,0x0b,0x82,0x0c,0x81,0x7f,0x2a,
0x81,0x07,0x81,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x2a,0x84,0x28,0x83,0x7f,
0x5d,0x83,0x64,
0x00,
}
};

View File

@ -4,6 +4,10 @@ ifeq ($(TARGET_ARCH),arm)
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
ifeq ($(BOARD_HAS_LARGE_FILESYSTEM),true)
LOCAL_CFLAGS += -DBOARD_HAS_LARGE_FILESYSTEM
endif
LOCAL_SRC_FILES := \
mmcutils.c

View File

@ -340,8 +340,13 @@ run_exec_process ( char **argv) {
int
format_ext3_device (const char *device) {
#ifdef BOARD_HAS_LARGE_FILESYSTEM
char *const mke2fs[] = {MKE2FS_BIN, "-j", "-q", device, NULL};
char *const tune2fs[] = {TUNE2FS_BIN, "-C", "1", device, NULL};
#else
char *const mke2fs[] = {MKE2FS_BIN, "-j", device, NULL};
char *const tune2fs[] = {TUNE2FS_BIN, "-j", "-C", "1", device, NULL};
#endif
// Run mke2fs
if(run_exec_process(mke2fs)) {
printf("failure while running mke2fs\n");

View File

@ -1,3 +1,6 @@
ifneq ($(TARGET_SIMULATOR),true)
ifeq ($(TARGET_ARCH),arm)
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
@ -27,3 +30,6 @@ LOCAL_STATIC_LIBRARIES := libmtdutils libcutils libc
LOCAL_FORCE_STATIC_EXECUTABLE := true
include $(BUILD_EXECUTABLE)
endif
endif # TARGET_ARCH == arm
endif # !TARGET_SIMULATOR

View File

@ -262,8 +262,8 @@ MtdReadContext *mtd_read_partition(const MtdPartition *partition)
sprintf(mtddevname, "/dev/mtd/mtd%d", partition->device_index);
ctx->fd = open(mtddevname, O_RDONLY);
if (ctx->fd < 0) {
free(ctx->buffer);
free(ctx);
free(ctx->buffer);
return NULL;
}
@ -572,22 +572,17 @@ int cmd_mtd_restore_raw_partition(const char *partition_name, const char *filena
const MtdPartition *ptn;
MtdWriteContext *write;
void *data;
FILE* f = fopen(filename, "rb");
if (f == NULL) {
fprintf(stderr, "error opening %s", filename);
return -1;
}
unsigned sz;
if (mtd_scan_partitions() <= 0)
{
fprintf(stderr, "error scanning partitions");
printf("error scanning partitions");
return -1;
}
const MtdPartition *mtd = mtd_find_partition_by_name(partition_name);
if (mtd == NULL)
const MtdPartition *partition = mtd_find_partition_by_name(partition_name);
if (partition == NULL)
{
fprintf(stderr, "can't find %s partition", partition_name);
printf("can't find %s partition", partition_name);
return -1;
}
@ -597,35 +592,107 @@ int cmd_mtd_restore_raw_partition(const char *partition_name, const char *filena
printf("error opening %s", filename);
return -1;
}
MtdWriteContext* ctx = mtd_write_partition(mtd);
if (ctx == NULL) {
char header[HEADER_SIZE];
int headerlen = read(fd, header, sizeof(header));
if (headerlen <= 0)
{
printf("error reading %s header", filename);
return -1;
}
// Skip the header (we'll come back to it), write everything else
printf("flashing %s from %s\n", partition_name, filename);
MtdWriteContext *out = mtd_write_partition(partition);
if (out == NULL)
{
printf("error writing %s", partition_name);
return -1;
}
char buf[HEADER_SIZE];
memset(buf, 0, headerlen);
int wrote = mtd_write_data(out, buf, headerlen);
if (wrote != headerlen)
{
printf("error writing %s", partition_name);
return -1;
}
int success = 1;
char* buffer = malloc(BUFSIZ);
int read;
while (success && (read = fread(buffer, 1, BUFSIZ, f)) > 0) {
int wrote = mtd_write_data(ctx, buffer, read);
success = success && (wrote == read);
int len;
while ((len = read(fd, buf, sizeof(buf))) > 0) {
wrote = mtd_write_data(out, buf, len);
if (wrote != len)
{
printf("error writing %s", partition_name);
return -1;
}
}
if (len < 0)
{
printf("error reading %s", filename);
return -1;
}
free(buffer);
fclose(f);
if (!success) {
fprintf(stderr, "error writing %s", partition_name);
if (mtd_write_close(out))
{
printf("error closing %s", partition_name);
return -1;
}
if (mtd_erase_blocks(ctx, -1) == -1) {
fprintf(stderr, "error erasing blocks of %s\n", partition_name);
// Now come back and write the header last
out = mtd_write_partition(partition);
if (out == NULL)
{
printf("error re-opening %s", partition_name);
return -1;
}
if (mtd_write_close(ctx) != 0) {
fprintf(stderr, "error closing write of %s\n", partition_name);
wrote = mtd_write_data(out, header, headerlen);
if (wrote != headerlen)
{
printf("error re-writing %s", partition_name);
return -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))
{
printf("error getting %s block size", partition_name);
return -1;
}
if (lseek(fd, headerlen, SEEK_SET) != headerlen)
{
printf("error rewinding %s", filename);
return -1;
}
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){
printf("error reading %s", filename);
return -1;
}
if (mtd_write_data(out, buf, len) != len)
{
printf("error writing %s", partition_name);
return -1;
}
left -= len;
}
if (mtd_write_close(out))
{
printf("error closing %s", partition_name);
return -1;
}
printf("%s %s partition\n", success ? "wrote" : "failed to write", partition_name);
return 0;
}

View File

@ -233,25 +233,20 @@ int nandroid_backup(const char* backup_path)
}
Volume* volume = volume_for_path(backup_path);
if (NULL == volume) {
if (strstr(backup_path, "/sdcard") == backup_path && is_data_media())
volume = volume_for_path("/data");
else
return print_and_error("Unable to find volume for backup path.\n");
}
if (NULL == volume)
return print_and_error("Unable to find volume for backup path.\n");
int ret;
struct statfs s;
if (NULL != volume) {
if (0 != (ret = statfs(volume->mount_point, &s)))
return print_and_error("Unable to stat backup path.\n");
uint64_t bavail = s.f_bavail;
uint64_t bsize = s.f_bsize;
uint64_t sdcard_free = bavail * bsize;
uint64_t sdcard_free_mb = sdcard_free / (uint64_t)(1024 * 1024);
ui_print("SD Card space free: %lluMB\n", sdcard_free_mb);
if (sdcard_free_mb < 150)
ui_print("There may not be enough free space to complete backup... continuing...\n");
}
if (0 != (ret = statfs(volume->mount_point, &s)))
return print_and_error("Unable to stat backup path.\n");
uint64_t bavail = s.f_bavail;
uint64_t bsize = s.f_bsize;
uint64_t sdcard_free = bavail * bsize;
uint64_t sdcard_free_mb = sdcard_free / (uint64_t)(1024 * 1024);
ui_print("SD Card space free: %lluMB\n", sdcard_free_mb);
if (sdcard_free_mb < 150)
ui_print("There may not be enough free space to complete backup... continuing...\n");
char tmp[PATH_MAX];
sprintf(tmp, "mkdir -p %s", backup_path);
__system(tmp);
@ -436,23 +431,16 @@ int nandroid_restore_partition_extended(const char* backup_path, const char* mou
printf("Found new backup image: %s\n", tmp);
}
// If the fs_type of this volume is "auto" or mount_point is /data
// and is_data_media (redundantly, and vol for /sdcard is NULL), let's revert
// to using a rm -rf, rather than trying to do a
// ext3/ext4/whatever format.
// If the fs_type of this volume is "auto", let's revert to using a
// rm -rf, rather than trying to do a ext3/ext4/whatever format.
// This is because some phones (like DroidX) will freak out if you
// reformat the /system or /data partitions, and not boot due to
// a locked bootloader.
// Other devices, like the Galaxy Nexus, XOOM, and Galaxy Tab 10.1
// have a /sdcard symlinked to /data/media. /data is set to "auto"
// so that when the format occurs, /data/media is not erased.
// The "auto" fs type preserves the file system, and does not
// trigger that lock.
// Or of volume does not exist (.android_secure), just rm -rf.
if (vol == NULL || 0 == strcmp(vol->fs_type, "auto"))
backup_filesystem = NULL;
else if (0 == strcmp(vol->mount_point, "/data") && volume_for_path("/sdcard") == NULL && is_data_media())
backup_filesystem = NULL;
}
ensure_directory(mount_point);

View File

@ -24,6 +24,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/reboot.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <time.h>
@ -34,12 +35,12 @@
#include "bootloader.h"
#include "common.h"
#include "cutils/properties.h"
#include "cutils/android_reboot.h"
#include "install.h"
#include "minui/minui.h"
#include "minzip/DirUtil.h"
#include "roots.h"
#include "recovery_ui.h"
#include "encryptedfs_provisioning.h"
#include "extendedcommands.h"
#include "flashutils/flashutils.h"
@ -49,6 +50,7 @@ static const struct option OPTIONS[] = {
{ "update_package", required_argument, NULL, 'u' },
{ "wipe_data", no_argument, NULL, 'w' },
{ "wipe_cache", no_argument, NULL, 'c' },
{ "set_encrypted_filesystems", required_argument, NULL, 'e' },
{ "show_text", no_argument, NULL, 't' },
{ NULL, 0, NULL, 0 },
};
@ -57,7 +59,6 @@ static const char *COMMAND_FILE = "/cache/recovery/command";
static const char *INTENT_FILE = "/cache/recovery/intent";
static const char *LOG_FILE = "/cache/recovery/log";
static const char *LAST_LOG_FILE = "/cache/recovery/last_log";
static const char *CACHE_ROOT = "/cache";
static const char *SDCARD_ROOT = "/sdcard";
static int allow_display_toggle = 1;
static int poweroff = 0;
@ -65,8 +66,6 @@ static const char *SDCARD_PACKAGE_FILE = "/sdcard/update.zip";
static const char *TEMPORARY_LOG_FILE = "/tmp/recovery.log";
static const char *SIDELOAD_TEMP_DIR = "/tmp/sideload";
extern UIParameters ui_parameters; // from ui.c
/*
* The recovery tool communicates with the main system through /cache files.
* /cache/recovery/command - INPUT - command line for tool, one arg per line
@ -123,13 +122,33 @@ extern UIParameters ui_parameters; // from ui.c
* 8g. finish_recovery() erases BCB
* -- after this, rebooting will (try to) restart the main system --
* 9. main() calls reboot() to boot main system
*
* SECURE FILE SYSTEMS ENABLE/DISABLE
* 1. user selects "enable encrypted file systems"
* 2. main system writes "--set_encrypted_filesystems=on|off" to
* /cache/recovery/command
* 3. main system reboots into recovery
* 4. get_args() writes BCB with "boot-recovery" and
* "--set_encrypted_filesystems=on|off"
* -- after this, rebooting will restart the transition --
* 5. read_encrypted_fs_info() retrieves encrypted file systems settings from /data
* Settings include: property to specify the Encrypted FS istatus and
* FS encryption key if enabled (not yet implemented)
* 6. erase_volume() reformats /data
* 7. erase_volume() reformats /cache
* 8. restore_encrypted_fs_info() writes required encrypted file systems settings to /data
* Settings include: property to specify the Encrypted FS status and
* FS encryption key if enabled (not yet implemented)
* 9. finish_recovery() erases BCB
* -- after this, rebooting will restart the main system --
* 10. main() calls reboot() to boot main system
*/
static const int MAX_ARG_LENGTH = 4096;
static const int MAX_ARGS = 100;
// open a given path, mounting partitions as necessary
FILE*
static FILE*
fopen_path(const char *path, const char *mode) {
if (ensure_path_mounted(path) != 0) {
LOGE("Can't mount %s\n", path);
@ -161,7 +180,7 @@ static void
get_args(int *argc, char ***argv) {
struct bootloader_message boot;
memset(&boot, 0, sizeof(boot));
if (device_flash_type() == MTD || device_flash_type() == MMC) {
if (device_flash_type() == MTD) {
get_bootloader_message(&boot); // this may fail, leaving a zeroed structure
}
@ -220,7 +239,9 @@ get_args(int *argc, char ***argv) {
strlcat(boot.recovery, (*argv)[i], sizeof(boot.recovery));
strlcat(boot.recovery, "\n", sizeof(boot.recovery));
}
set_bootloader_message(&boot);
if (device_flash_type() == MTD) {
set_bootloader_message(&boot);
}
}
void
@ -282,10 +303,12 @@ finish_recovery(const char *send_intent) {
copy_log_file(LAST_LOG_FILE, false);
chmod(LAST_LOG_FILE, 0640);
// Reset to normal system boot so recovery won't cycle indefinitely.
struct bootloader_message boot;
memset(&boot, 0, sizeof(boot));
set_bootloader_message(&boot);
if (device_flash_type() == MTD) {
// Reset to mormal system boot so recovery won't cycle indefinitely.
struct bootloader_message boot;
memset(&boot, 0, sizeof(boot));
set_bootloader_message(&boot);
}
// Remove the command file, so recovery won't repeat indefinitely.
if (ensure_path_mounted(COMMAND_FILE) != 0 ||
@ -430,8 +453,7 @@ get_menu_selection(char** headers, char** items, int menu_only,
// throw away keys pressed previously, so user doesn't
// accidentally trigger menu items.
ui_clear_key_queue();
++ui_menu_level;
int item_count = ui_start_menu(headers, items, initial_selection);
int selected = initial_selection;
int chosen_item = -1;
@ -445,16 +467,6 @@ get_menu_selection(char** headers, char** items, int menu_only,
int key = ui_wait_key();
int visible = ui_text_visible();
if (key == -1) { // ui_wait_key() timed out
if (ui_text_ever_visible()) {
continue;
} else {
LOGI("timed out waiting for key input; rebooting.\n");
ui_end_menu();
return ITEM_REBOOT;
}
}
int action = device_handle_key(key, visible);
int old_selected = selected;
@ -472,8 +484,7 @@ get_menu_selection(char** headers, char** items, int menu_only,
case SELECT_ITEM:
chosen_item = selected;
if (ui_get_showing_back_button()) {
if (chosen_item == item_count-1) {
--ui_menu_level;
if (chosen_item == item_count) {
chosen_item = GO_BACK;
}
}
@ -481,7 +492,6 @@ get_menu_selection(char** headers, char** items, int menu_only,
case NO_ACTION:
break;
case GO_BACK:
--ui_menu_level;
chosen_item = GO_BACK;
break;
}
@ -515,8 +525,8 @@ static int compare_string(const void* a, const void* b) {
}
static int
update_directory(const char* path, const char* unmount_when_done) {
ensure_path_mounted(path);
sdcard_directory(const char* path) {
ensure_path_mounted(SDCARD_ROOT);
const char* MENU_HEADERS[] = { "Choose a package to install:",
path,
@ -527,9 +537,7 @@ update_directory(const char* path, const char* unmount_when_done) {
d = opendir(path);
if (d == NULL) {
LOGE("error opening %s: %s\n", path, strerror(errno));
if (unmount_when_done != NULL) {
ensure_path_unmounted(unmount_when_done);
}
ensure_path_unmounted(SDCARD_ROOT);
return 0;
}
@ -594,7 +602,7 @@ update_directory(const char* path, const char* unmount_when_done) {
char* item = zips[chosen_item];
int item_len = strlen(item);
if (chosen_item == 0) { // item 0 is always "../"
// go up but continue browsing (if the caller is update_directory)
// go up but continue browsing (if the caller is sdcard_directory)
result = -1;
break;
} else if (item[item_len-1] == '/') {
@ -604,7 +612,7 @@ update_directory(const char* path, const char* unmount_when_done) {
strlcat(new_path, "/", PATH_MAX);
strlcat(new_path, item, PATH_MAX);
new_path[strlen(new_path)-1] = '\0'; // truncate the trailing '/'
result = update_directory(new_path, unmount_when_done);
result = sdcard_directory(new_path);
if (result >= 0) break;
} else {
// selected a zip file: attempt to install it, and return
@ -617,9 +625,7 @@ update_directory(const char* path, const char* unmount_when_done) {
ui_print("\n-- Install %s ...\n", path);
set_sdcard_update_bootloader_message();
char* copy = copy_sideloaded_package(new_path);
if (unmount_when_done != NULL) {
ensure_path_unmounted(unmount_when_done);
}
ensure_path_unmounted(SDCARD_ROOT);
if (copy) {
result = install_package(copy);
free(copy);
@ -635,9 +641,7 @@ update_directory(const char* path, const char* unmount_when_done) {
free(zips);
free(headers);
if (unmount_when_done != NULL) {
ensure_path_unmounted(unmount_when_done);
}
ensure_path_unmounted(SDCARD_ROOT);
return result;
}
@ -683,8 +687,7 @@ prompt_and_wait() {
for (;;) {
finish_recovery(NULL);
ui_reset_progress();
ui_menu_level = -1;
allow_display_toggle = 1;
int chosen_item = get_menu_selection(headers, MENU_ITEMS, 0, 0);
allow_display_toggle = 0;
@ -694,7 +697,6 @@ prompt_and_wait() {
// statement below.
chosen_item = device_perform_action(chosen_item);
int status;
switch (chosen_item) {
case ITEM_REBOOT:
poweroff=0;
@ -716,23 +718,34 @@ prompt_and_wait() {
break;
case ITEM_APPLY_SDCARD:
if (confirm_selection("Confirm install?", "Yes - Install /sdcard/update.zip"))
{
ui_print("\n-- Install from sdcard...\n");
int status = install_package(SDCARD_PACKAGE_FILE);
if (status != INSTALL_SUCCESS) {
ui_set_background(BACKGROUND_ICON_ERROR);
ui_print("Installation aborted.\n");
} else if (!ui_text_visible()) {
return; // reboot if logs aren't visible
} else {
ui_print("\nInstall from sdcard complete.\n");
}
}
break;
case ITEM_INSTALL_ZIP:
show_install_update_menu();
break;
case ITEM_NANDROID:
show_nandroid_menu();
break;
case ITEM_PARTITION:
show_partition_menu();
break;
case ITEM_ADVANCED:
show_advanced_menu();
break;
case ITEM_POWEROFF:
poweroff = 1;
poweroff=1;
return;
}
}
@ -789,7 +802,6 @@ main(int argc, char **argv) {
freopen(TEMPORARY_LOG_FILE, "a", stderr); setbuf(stderr, NULL);
printf("Starting recovery on %s", ctime(&start));
device_ui_init(&ui_parameters);
ui_init();
ui_print(EXPAND(RECOVERY_VERSION)"\n");
load_volume_table();
@ -800,7 +812,10 @@ main(int argc, char **argv) {
int previous_runs = 0;
const char *send_intent = NULL;
const char *update_package = NULL;
const char *encrypted_fs_mode = NULL;
int wipe_data = 0, wipe_cache = 0;
int toggle_secure_fs = 0;
encrypted_fs_info encrypted_fs_data;
LOGI("Checking arguments.\n");
int arg;
@ -815,6 +830,7 @@ main(int argc, char **argv) {
#endif
break;
case 'c': wipe_cache = 1; break;
case 'e': encrypted_fs_mode = optarg; toggle_secure_fs = 1; break;
case 't': ui_show_text(1); break;
case '?':
LOGE("Invalid command argument\n");
@ -851,14 +867,49 @@ main(int argc, char **argv) {
printf("\n");
int status = INSTALL_SUCCESS;
if (toggle_secure_fs) {
if (strcmp(encrypted_fs_mode,"on") == 0) {
encrypted_fs_data.mode = MODE_ENCRYPTED_FS_ENABLED;
ui_print("Enabling Encrypted FS.\n");
} else if (strcmp(encrypted_fs_mode,"off") == 0) {
encrypted_fs_data.mode = MODE_ENCRYPTED_FS_DISABLED;
ui_print("Disabling Encrypted FS.\n");
} else {
ui_print("Error: invalid Encrypted FS setting.\n");
status = INSTALL_ERROR;
}
if (update_package != NULL) {
// Recovery strategy: if the data partition is damaged, disable encrypted file systems.
// This preventsthe device recycling endlessly in recovery mode.
if ((encrypted_fs_data.mode == MODE_ENCRYPTED_FS_ENABLED) &&
(read_encrypted_fs_info(&encrypted_fs_data))) {
ui_print("Encrypted FS change aborted, resetting to disabled state.\n");
encrypted_fs_data.mode = MODE_ENCRYPTED_FS_DISABLED;
}
if (status != INSTALL_ERROR) {
if (erase_volume("/data")) {
ui_print("Data wipe failed.\n");
status = INSTALL_ERROR;
} else if (erase_volume("/cache")) {
ui_print("Cache wipe failed.\n");
status = INSTALL_ERROR;
} else if ((encrypted_fs_data.mode == MODE_ENCRYPTED_FS_ENABLED) &&
(restore_encrypted_fs_info(&encrypted_fs_data))) {
ui_print("Encrypted FS change aborted.\n");
status = INSTALL_ERROR;
} else {
ui_print("Successfully updated Encrypted FS.\n");
status = INSTALL_SUCCESS;
}
}
} else if (update_package != NULL) {
status = install_package(update_package);
if (status != INSTALL_SUCCESS) ui_print("Installation aborted.\n");
} else if (wipe_data) {
if (device_wipe_data()) status = INSTALL_ERROR;
if (erase_volume("/data")) status = INSTALL_ERROR;
if (has_datadata() && erase_volume("/datadata")) status = INSTALL_ERROR;
if (wipe_cache && erase_volume("/cache")) status = INSTALL_ERROR;
if (status != INSTALL_SUCCESS) ui_print("Data wipe failed.\n");
} else if (wipe_cache) {
@ -890,10 +941,7 @@ main(int argc, char **argv) {
}
}
if (status != INSTALL_SUCCESS && !is_user_initiated_recovery) {
ui_set_show_text(1);
ui_set_background(BACKGROUND_ICON_ERROR);
}
if (status != INSTALL_SUCCESS && !is_user_initiated_recovery) ui_set_background(BACKGROUND_ICON_ERROR);
if (status != INSTALL_SUCCESS || ui_text_visible()) {
prompt_and_wait();
}
@ -903,16 +951,12 @@ main(int argc, char **argv) {
// Otherwise, get ready to boot the main system...
finish_recovery(send_intent);
sync();
if(!poweroff) {
if(!poweroff)
ui_print("Rebooting...\n");
android_reboot(ANDROID_RB_RESTART, 0, 0);
}
else {
else
ui_print("Shutting down...\n");
android_reboot(ANDROID_RB_POWEROFF, 0, 0);
}
sync();
reboot((!poweroff) ? RB_AUTOBOOT : RB_POWER_OFF);
return EXIT_SUCCESS;
}

View File

@ -17,12 +17,6 @@
#ifndef _RECOVERY_UI_H
#define _RECOVERY_UI_H
#include "common.h"
// Called before UI library is initialized. Can change things like
// how many frames are included in various animations, etc.
extern void device_ui_init(UIParameters* ui_parameters);
// Called when recovery starts up. Returns 0.
extern int device_recovery_start();
@ -73,16 +67,14 @@ int device_wipe_data();
#define GO_BACK -5
#define ITEM_REBOOT 0
#define ITEM_APPLY_EXT 1
#define ITEM_APPLY_SDCARD 1 // historical synonym for ITEM_APPLY_EXT
#define ITEM_APPLY_SDCARD 1
#define ITEM_WIPE_DATA 2
#define ITEM_WIPE_CACHE 3
// unused in cwr
#define ITEM_APPLY_CACHE 4
#define ITEM_NANDROID 4
#define ITEM_PARTITION 5
#define ITEM_ADVANCED 6
#define ITEM_POWEROFF 7
#define ITEM_INSTALL_ZIP 4
#define ITEM_NANDROID 5
#define ITEM_PARTITION 6
#define ITEM_ADVANCED 7
#define ITEM_POWEROFF 8
// Header text to display above the main menu.
extern char* MENU_HEADERS[];
@ -90,9 +82,6 @@ extern char* MENU_HEADERS[];
// Text of menu items.
extern char* MENU_ITEMS[];
// Loosely track the depth of the current menu
int ui_menu_level;
int
get_menu_selection(char** headers, char** items, int menu_only, int initial_selection);

BIN
res/images/icon_error.png Normal file → Executable file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 10 KiB

BIN
res/images/icon_installing.png Normal file → Executable file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 673 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 687 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 661 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 665 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 683 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 676 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 118 B

After

Width:  |  Height:  |  Size: 361 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 404 B

After

Width:  |  Height:  |  Size: 286 B

75
roots.c
View File

@ -56,28 +56,6 @@ static char* dupe_string(const char* sz) {
return strdup(sz);
}
static int parse_options(char* options, Volume* volume) {
char* option;
while (option = strtok(options, ",")) {
options = NULL;
if (strncmp(option, "length=", 7) == 0) {
volume->length = strtoll(option+7, NULL, 10);
} else if (strncmp(option, "fstype2=", 8) == 0) {
volume->fs_type2 = volume->fs_type;
volume->fs_type = strdup(option + 8);
} else if (strncmp(option, "fs_options=", 11) == 0) {
volume->fs_options = strdup(option + 11);
} else if (strncmp(option, "fs_options2=", 12) == 0) {
volume->fs_options2 = strdup(option + 12);
} else {
LOGE("bad option \"%s\"\n", option);
return -1;
}
}
return 0;
}
void load_volume_table() {
int alloc = 2;
device_volumes = malloc(alloc * sizeof(Volume));
@ -87,10 +65,8 @@ void load_volume_table() {
device_volumes[0].fs_type = "ramdisk";
device_volumes[0].device = NULL;
device_volumes[0].device2 = NULL;
device_volumes[0].fs_type2 = NULL;
device_volumes[0].fs_options = NULL;
device_volumes[0].fs_options2 = NULL;
device_volumes[0].length = 0;
num_volumes = 1;
FILE* fstab = fopen("/etc/recovery.fstab", "r");
@ -112,16 +88,10 @@ void load_volume_table() {
char* device = strtok(NULL, " \t\n");
// lines may optionally have a second device, to use if
// mounting the first one fails.
char* options = NULL;
char* device2 = strtok(NULL, " \t\n");
if (device2) {
if (device2[0] == '/') {
options = strtok(NULL, " \t\n");
} else {
options = device2;
device2 = NULL;
}
}
char* fs_type2 = strtok(NULL, " \t\n");
char* fs_options = strtok(NULL, " \t\n");
char* fs_options2 = strtok(NULL, " \t\n");
if (mount_point && fs_type && device) {
while (num_volumes >= alloc) {
@ -129,22 +99,21 @@ void load_volume_table() {
device_volumes = realloc(device_volumes, alloc*sizeof(Volume));
}
device_volumes[num_volumes].mount_point = strdup(mount_point);
device_volumes[num_volumes].fs_type = strdup(fs_type);
device_volumes[num_volumes].fs_type = !is_null(fs_type2) ? strdup(fs_type2) : strdup(fs_type);
device_volumes[num_volumes].device = strdup(device);
device_volumes[num_volumes].device2 =
device2 ? strdup(device2) : NULL;
!is_null(device2) ? strdup(device2) : NULL;
device_volumes[num_volumes].fs_type2 = !is_null(fs_type2) ? strdup(fs_type) : NULL;
device_volumes[num_volumes].length = 0;
device_volumes[num_volumes].fs_type2 = NULL;
device_volumes[num_volumes].fs_options = NULL;
device_volumes[num_volumes].fs_options2 = NULL;
if (parse_options(options, device_volumes + num_volumes) != 0) {
LOGE("skipping malformed recovery.fstab line: %s\n", original);
} else {
++num_volumes;
if (!is_null(fs_type2)) {
device_volumes[num_volumes].fs_options2 = dupe_string(fs_options);
device_volumes[num_volumes].fs_options = dupe_string(fs_options2);
}
else {
device_volumes[num_volumes].fs_options2 = NULL;
device_volumes[num_volumes].fs_options = dupe_string(fs_options);
}
++num_volumes;
} else {
LOGE("skipping malformed recovery.fstab line: %s\n", original);
}
@ -157,8 +126,8 @@ void load_volume_table() {
printf("=========================\n");
for (i = 0; i < num_volumes; ++i) {
Volume* v = &device_volumes[i];
printf(" %d %s %s %s %s %lld\n", i, v->mount_point, v->fs_type,
v->device, v->device2, v->length);
printf(" %d %s %s %s %s\n", i, v->mount_point, v->fs_type,
v->device, v->device2);
}
printf("\n");
}
@ -197,7 +166,7 @@ int try_mount(const char* device, const char* mount_point, const char* fs_type,
int is_data_media() {
Volume *data = volume_for_path("/data");
return data != NULL && strcmp(data->fs_type, "auto") == 0 || volume_for_path("/sdcard") == NULL;
return data != NULL && strcmp(data->fs_type, "auto") == 0 && volume_for_path("/sdcard") == NULL;
}
void setup_data_media() {
@ -215,7 +184,7 @@ int ensure_path_mounted_at_mount_point(const char* path, const char* mount_point
if (v == NULL) {
// no /sdcard? let's assume /data/media
if (strstr(path, "/sdcard") == path && is_data_media()) {
LOGI("using /data/media, no /sdcard found.\n");
LOGW("using /data/media, no /sdcard found.\n");
int ret;
if (0 != (ret = ensure_path_mounted("/data")))
return ret;
@ -334,11 +303,6 @@ int format_volume(const char* volume) {
LOGE("unknown volume \"%s\"\n", volume);
return -1;
}
// check to see if /data is being formatted, and if it is /data/media
// Note: the /sdcard check is redundant probably, just being safe.
if (strstr(volume, "/data") == volume && volume_for_path("/sdcard") == NULL && is_data_media()) {
return format_unknown_device(NULL, volume, NULL);
}
if (strcmp(v->fs_type, "ramdisk") == 0) {
// you can't format the ramdisk.
LOGE("can't format_volume \"%s\"", volume);
@ -381,7 +345,8 @@ int format_volume(const char* volume) {
}
if (strcmp(v->fs_type, "ext4") == 0) {
int result = make_ext4fs(v->device, v->length);
reset_ext4fs_info();
int result = make_ext4fs(v->device, NULL, NULL, 0, 0, 0);
if (result != 0) {
LOGE("format_volume: make_extf4fs failed on %s\n", v->device);
return -1;

View File

@ -14,6 +14,8 @@
LOCAL_PATH := $(call my-dir)
ifneq ($(TARGET_SIMULATOR),true)
include $(CLEAR_VARS)
LOCAL_FORCE_STATIC_EXECUTABLE := true
LOCAL_MODULE := add-property-tag
@ -31,3 +33,5 @@ LOCAL_MODULE_TAGS := debug
LOCAL_SRC_FILES := check-lost+found.c
LOCAL_STATIC_LIBRARIES := libcutils libc
include $(BUILD_EXECUTABLE)
endif # !TARGET_SIMULATOR

454
ui.c
View File

@ -14,22 +14,18 @@
* limitations under the License.
*/
#include <errno.h>
#include <fcntl.h>
#include <linux/input.h>
#include <pthread.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/reboot.h>
#include <sys/time.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>
#include "common.h"
#include <cutils/android_reboot.h>
#include "minui/minui.h"
#include "recovery_ui.h"
@ -47,24 +43,20 @@ static int gShowBackButton = 0;
#define MENU_MAX_COLS 64
#define MENU_MAX_ROWS 250
#define MIN_LOG_ROWS 3
#ifndef BOARD_LDPI_RECOVERY
#define CHAR_WIDTH 10
#define CHAR_HEIGHT 18
#else
#define CHAR_WIDTH 7
#define CHAR_HEIGHT 16
#endif
#define CHAR_WIDTH BOARD_RECOVERY_CHAR_WIDTH
#define CHAR_HEIGHT BOARD_RECOVERY_CHAR_HEIGHT
#define UI_WAIT_KEY_TIMEOUT_SEC 3600
UIParameters ui_parameters = {
6, // indeterminate progress bar frames
20, // fps
7, // installation icon frames (0 == static image)
13, 190, // installation icon overlay offset
};
#define PROGRESSBAR_INDETERMINATE_STATES 6
#define PROGRESSBAR_INDETERMINATE_FPS 15
static pthread_mutex_t gUpdateMutex = PTHREAD_MUTEX_INITIALIZER;
static gr_surface gBackgroundIcon[NUM_BACKGROUND_ICONS];
static gr_surface *gInstallationOverlay;
static gr_surface *gProgressBarIndeterminate;
static gr_surface gProgressBarIndeterminate[PROGRESSBAR_INDETERMINATE_STATES];
static gr_surface gProgressBarEmpty;
static gr_surface gProgressBarFill;
static int ui_has_initialized = 0;
@ -76,13 +68,18 @@ static const struct { gr_surface* surface; const char *name; } BITMAPS[] = {
{ &gBackgroundIcon[BACKGROUND_ICON_CLOCKWORK], "icon_clockwork" },
{ &gBackgroundIcon[BACKGROUND_ICON_FIRMWARE_INSTALLING], "icon_firmware_install" },
{ &gBackgroundIcon[BACKGROUND_ICON_FIRMWARE_ERROR], "icon_firmware_error" },
{ &gProgressBarIndeterminate[0], "indeterminate1" },
{ &gProgressBarIndeterminate[1], "indeterminate2" },
{ &gProgressBarIndeterminate[2], "indeterminate3" },
{ &gProgressBarIndeterminate[3], "indeterminate4" },
{ &gProgressBarIndeterminate[4], "indeterminate5" },
{ &gProgressBarIndeterminate[5], "indeterminate6" },
{ &gProgressBarEmpty, "progress_empty" },
{ &gProgressBarFill, "progress_fill" },
{ NULL, NULL },
};
static int gCurrentIcon = 0;
static int gInstallingFrame = 0;
static gr_surface gCurrentIcon = NULL;
static enum ProgressBarType {
PROGRESSBAR_TYPE_NONE,
@ -92,7 +89,7 @@ static enum ProgressBarType {
// Progress bar scope of current operation
static float gProgressScopeStart = 0, gProgressScopeSize = 0, gProgress = 0;
static double gProgressScopeTime, gProgressScopeDuration;
static time_t gProgressScopeTime, gProgressScopeDuration;
// Set to 1 when both graphics pages are the same (except for the progress bar)
static int gPagesIdentical = 0;
@ -102,13 +99,11 @@ static char text[MAX_ROWS][MAX_COLS];
static int text_cols = 0, text_rows = 0;
static int text_col = 0, text_row = 0, text_top = 0;
static int show_text = 0;
static int show_text_ever = 0; // has show_text ever been 1?
static char menu[MENU_MAX_ROWS][MENU_MAX_COLS];
static int show_menu = 0;
static int menu_top = 0, menu_items = 0, menu_sel = 0;
static int menu_show_start = 0; // this is line which menu display is starting at
static int max_menu_rows;
// Key event input queue
static pthread_mutex_t key_queue_mutex = PTHREAD_MUTEX_INITIALIZER;
@ -116,46 +111,20 @@ static pthread_cond_t key_queue_cond = PTHREAD_COND_INITIALIZER;
static int key_queue[256], key_queue_len = 0;
static volatile char key_pressed[KEY_MAX + 1];
// Return the current time as a double (including fractions of a second).
static double now() {
struct timeval tv;
gettimeofday(&tv, NULL);
return tv.tv_sec + tv.tv_usec / 1000000.0;
}
// Draw the given frame over the installation overlay animation. The
// background is not cleared or draw with the base icon first; we
// assume that the frame already contains some other frame of the
// animation. Does nothing if no overlay animation is defined.
// Should only be called with gUpdateMutex locked.
static void draw_install_overlay_locked(int frame) {
if (gInstallationOverlay == NULL) return;
gr_surface surface = gInstallationOverlay[frame];
int iconWidth = gr_get_width(surface);
int iconHeight = gr_get_height(surface);
gr_blit(surface, 0, 0, iconWidth, iconHeight,
ui_parameters.install_overlay_offset_x,
ui_parameters.install_overlay_offset_y);
}
// Clear the screen and draw the currently selected background icon (if any).
// Should only be called with gUpdateMutex locked.
static void draw_background_locked(int icon)
static void draw_background_locked(gr_surface icon)
{
gPagesIdentical = 0;
gr_color(0, 0, 0, 255);
gr_fill(0, 0, gr_fb_width(), gr_fb_height());
if (icon) {
gr_surface surface = gBackgroundIcon[icon];
int iconWidth = gr_get_width(surface);
int iconHeight = gr_get_height(surface);
int iconWidth = gr_get_width(icon);
int iconHeight = gr_get_height(icon);
int iconX = (gr_fb_width() - iconWidth) / 2;
int iconY = (gr_fb_height() - iconHeight) / 2;
gr_blit(surface, 0, 0, iconWidth, iconHeight, iconX, iconY);
if (icon == BACKGROUND_ICON_INSTALLING) {
draw_install_overlay_locked(gInstallingFrame);
}
gr_blit(icon, 0, 0, iconWidth, iconHeight, iconX, iconY);
}
}
@ -163,39 +132,35 @@ static void draw_background_locked(int icon)
// Should only be called with gUpdateMutex locked.
static void draw_progress_locked()
{
if (gCurrentIcon == BACKGROUND_ICON_INSTALLING) {
draw_install_overlay_locked(gInstallingFrame);
if (gProgressBarType == PROGRESSBAR_TYPE_NONE) return;
int iconHeight = gr_get_height(gBackgroundIcon[BACKGROUND_ICON_INSTALLING]);
int width = gr_get_width(gProgressBarEmpty);
int height = gr_get_height(gProgressBarEmpty);
int dx = (gr_fb_width() - width)/2;
int dy = (3*gr_fb_height() + iconHeight - 2*height)/4;
// Erase behind the progress bar (in case this was a progress-only update)
gr_color(0, 0, 0, 255);
gr_fill(dx, dy, width, height);
if (gProgressBarType == PROGRESSBAR_TYPE_NORMAL) {
float progress = gProgressScopeStart + gProgress * gProgressScopeSize;
int pos = (int) (progress * width);
if (pos > 0) {
gr_blit(gProgressBarFill, 0, 0, pos, height, dx, dy);
}
if (pos < width-1) {
gr_blit(gProgressBarEmpty, pos, 0, width-pos, height, dx+pos, dy);
}
}
if (gProgressBarType != PROGRESSBAR_TYPE_NONE) {
int iconHeight = gr_get_height(gBackgroundIcon[BACKGROUND_ICON_INSTALLING]);
int width = gr_get_width(gProgressBarEmpty);
int height = gr_get_height(gProgressBarEmpty);
int dx = (gr_fb_width() - width)/2;
int dy = (3*gr_fb_height() + iconHeight - 2*height)/4;
// Erase behind the progress bar (in case this was a progress-only update)
gr_color(0, 0, 0, 255);
gr_fill(dx, dy, width, height);
if (gProgressBarType == PROGRESSBAR_TYPE_NORMAL) {
float progress = gProgressScopeStart + gProgress * gProgressScopeSize;
int pos = (int) (progress * width);
if (pos > 0) {
gr_blit(gProgressBarFill, 0, 0, pos, height, dx, dy);
}
if (pos < width-1) {
gr_blit(gProgressBarEmpty, pos, 0, width-pos, height, dx+pos, dy);
}
}
if (gProgressBarType == PROGRESSBAR_TYPE_INDETERMINATE) {
static int frame = 0;
gr_blit(gProgressBarIndeterminate[frame], 0, 0, width, height, dx, dy);
frame = (frame + 1) % ui_parameters.indeterminate_frames;
}
if (gProgressBarType == PROGRESSBAR_TYPE_INDETERMINATE) {
static int frame = 0;
gr_blit(gProgressBarIndeterminate[frame], 0, 0, width, height, dx, dy);
frame = (frame + 1) % PROGRESSBAR_INDETERMINATE_STATES;
}
}
@ -222,10 +187,8 @@ static void draw_screen_locked(void)
gr_color(0, 0, 0, 160);
gr_fill(0, 0, gr_fb_width(), gr_fb_height());
int total_rows = gr_fb_height() / CHAR_HEIGHT;
int i = 0;
int j = 0;
int offset = 0; // offset of separating bar under menus
int row = 0; // current row that we are drawing on
if (show_menu) {
gr_color(MENU_TEXT_COLOR);
@ -238,8 +201,8 @@ static void draw_screen_locked(void)
row++;
}
if (menu_items - menu_show_start + menu_top >= max_menu_rows)
j = max_menu_rows - menu_top;
if (menu_items - menu_show_start + menu_top >= MAX_ROWS)
j = MAX_ROWS - menu_top;
else
j = menu_items - menu_show_start;
@ -254,29 +217,14 @@ static void draw_screen_locked(void)
draw_text_line(i - menu_show_start, menu[i]);
}
row++;
if (row >= max_menu_rows)
break;
}
if (menu_items <= max_menu_rows)
offset = 1;
gr_fill(0, (row-offset)*CHAR_HEIGHT+CHAR_HEIGHT/2-1,
gr_fb_width(), (row-offset)*CHAR_HEIGHT+CHAR_HEIGHT/2+1);
gr_fill(0, row*CHAR_HEIGHT+CHAR_HEIGHT/2-1,
gr_fb_width(), row*CHAR_HEIGHT+CHAR_HEIGHT/2+1);
}
gr_color(NORMAL_TEXT_COLOR);
int cur_row = text_row;
int available_rows = total_rows - row - 1;
int start_row = row + 1;
if (available_rows < MAX_ROWS)
cur_row = (cur_row + (MAX_ROWS - available_rows)) % MAX_ROWS;
else
start_row = total_rows - MAX_ROWS;
int r;
for (r = 0; r < (available_rows < MAX_ROWS ? available_rows : MAX_ROWS); r++) {
draw_text_line(start_row + r, text[(cur_row + r) % MAX_ROWS]);
for (; row < text_rows; ++row) {
draw_text_line(row, text[(row+text_top) % text_rows]);
}
}
}
@ -299,7 +247,7 @@ static void update_progress_locked(void)
draw_screen_locked(); // Must redraw the whole screen
gPagesIdentical = 1;
} else {
draw_progress_locked(); // Draw only the progress bar and overlays
draw_progress_locked(); // Draw only the progress bar
}
gr_flip();
}
@ -307,130 +255,97 @@ static void update_progress_locked(void)
// Keeps the progress bar updated, even when the process is otherwise busy.
static void *progress_thread(void *cookie)
{
double interval = 1.0 / ui_parameters.update_fps;
for (;;) {
double start = now();
usleep(1000000 / PROGRESSBAR_INDETERMINATE_FPS);
pthread_mutex_lock(&gUpdateMutex);
int redraw = 0;
// update the installation animation, if active
// skip this if we have a text overlay (too expensive to update)
if (gCurrentIcon == BACKGROUND_ICON_INSTALLING &&
ui_parameters.installing_frames > 0 &&
!show_text) {
gInstallingFrame =
(gInstallingFrame + 1) % ui_parameters.installing_frames;
redraw = 1;
}
// update the progress bar animation, if active
// skip this if we have a text overlay (too expensive to update)
if (gProgressBarType == PROGRESSBAR_TYPE_INDETERMINATE && !show_text) {
redraw = 1;
update_progress_locked();
}
// move the progress bar forward on timed intervals, if configured
int duration = gProgressScopeDuration;
if (gProgressBarType == PROGRESSBAR_TYPE_NORMAL && duration > 0) {
double elapsed = now() - gProgressScopeTime;
int elapsed = time(NULL) - gProgressScopeTime;
float progress = 1.0 * elapsed / duration;
if (progress > 1.0) progress = 1.0;
if (progress > gProgress) {
gProgress = progress;
redraw = 1;
update_progress_locked();
}
}
if (redraw) update_progress_locked();
pthread_mutex_unlock(&gUpdateMutex);
double end = now();
// minimum of 20ms delay between frames
double delay = interval - (end-start);
if (delay < 0.02) delay = 0.02;
usleep((long)(delay * 1000000));
}
return NULL;
}
static int rel_sum = 0;
static int input_callback(int fd, short revents, void *data)
{
struct input_event ev;
int ret;
int fake_key = 0;
ret = ev_get_input(fd, revents, &ev);
if (ret)
return -1;
if (ev.type == EV_SYN) {
return 0;
} else if (ev.type == EV_REL) {
if (ev.code == REL_Y) {
// accumulate the up or down motion reported by
// the trackball. When it exceeds a threshold
// (positive or negative), fake an up/down
// key event.
rel_sum += ev.value;
if (rel_sum > 3) {
fake_key = 1;
ev.type = EV_KEY;
ev.code = KEY_DOWN;
ev.value = 1;
rel_sum = 0;
} else if (rel_sum < -3) {
fake_key = 1;
ev.type = EV_KEY;
ev.code = KEY_UP;
ev.value = 1;
rel_sum = 0;
}
}
} else {
rel_sum = 0;
}
if (ev.type != EV_KEY || ev.code > KEY_MAX)
return 0;
pthread_mutex_lock(&key_queue_mutex);
if (!fake_key) {
// our "fake" keys only report a key-down event (no
// key-up), so don't record them in the key_pressed
// table.
key_pressed[ev.code] = ev.value;
}
const int queue_max = sizeof(key_queue) / sizeof(key_queue[0]);
if (ev.value > 0 && key_queue_len < queue_max) {
key_queue[key_queue_len++] = ev.code;
pthread_cond_signal(&key_queue_cond);
}
pthread_mutex_unlock(&key_queue_mutex);
if (ev.value > 0 && device_toggle_display(key_pressed, ev.code)) {
pthread_mutex_lock(&gUpdateMutex);
show_text = !show_text;
if (show_text) show_text_ever = 1;
update_screen_locked();
pthread_mutex_unlock(&gUpdateMutex);
}
if (ev.value > 0 && device_reboot_now(key_pressed, ev.code)) {
android_reboot(ANDROID_RB_RESTART, 0, 0);
}
return 0;
}
// Reads input events, handles special hot keys, and adds to the key queue.
static void *input_thread(void *cookie)
{
int rel_sum = 0;
int fake_key = 0;
for (;;) {
if (!ev_wait(-1))
ev_dispatch();
// wait for the next key event
struct input_event ev;
do {
ev_get(&ev, 0);
if (ev.type == EV_SYN) {
continue;
} else if (ev.type == EV_REL) {
if (ev.code == REL_Y) {
// accumulate the up or down motion reported by
// the trackball. When it exceeds a threshold
// (positive or negative), fake an up/down
// key event.
rel_sum += ev.value;
if (rel_sum > 3) {
fake_key = 1;
ev.type = EV_KEY;
ev.code = KEY_DOWN;
ev.value = 1;
rel_sum = 0;
} else if (rel_sum < -3) {
fake_key = 1;
ev.type = EV_KEY;
ev.code = KEY_UP;
ev.value = 1;
rel_sum = 0;
}
}
} else {
rel_sum = 0;
}
} while (ev.type != EV_KEY || ev.code > KEY_MAX);
pthread_mutex_lock(&key_queue_mutex);
if (!fake_key) {
// our "fake" keys only report a key-down event (no
// key-up), so don't record them in the key_pressed
// table.
key_pressed[ev.code] = ev.value;
}
fake_key = 0;
const int queue_max = sizeof(key_queue) / sizeof(key_queue[0]);
if (ev.value > 0 && key_queue_len < queue_max) {
key_queue[key_queue_len++] = ev.code;
pthread_cond_signal(&key_queue_cond);
}
pthread_mutex_unlock(&key_queue_mutex);
if (ev.value > 0 && device_toggle_display(key_pressed, ev.code)) {
pthread_mutex_lock(&gUpdateMutex);
show_text = !show_text;
update_screen_locked();
pthread_mutex_unlock(&gUpdateMutex);
}
if (ev.value > 0 && device_reboot_now(key_pressed, ev.code)) {
reboot(RB_AUTOBOOT);
}
}
return NULL;
}
@ -439,13 +354,10 @@ void ui_init(void)
{
ui_has_initialized = 1;
gr_init();
ev_init(input_callback, NULL);
ev_init();
text_col = text_row = 0;
text_rows = gr_fb_height() / CHAR_HEIGHT;
max_menu_rows = text_rows - MIN_LOG_ROWS;
if (max_menu_rows > MENU_MAX_ROWS)
max_menu_rows = MENU_MAX_ROWS;
if (text_rows > MAX_ROWS) text_rows = MAX_ROWS;
text_top = 1;
@ -456,47 +368,13 @@ void ui_init(void)
for (i = 0; BITMAPS[i].name != NULL; ++i) {
int result = res_create_surface(BITMAPS[i].name, BITMAPS[i].surface);
if (result < 0) {
LOGE("Missing bitmap %s\n(Code %d)\n", BITMAPS[i].name, result);
}
}
gProgressBarIndeterminate = malloc(ui_parameters.indeterminate_frames *
sizeof(gr_surface));
for (i = 0; i < ui_parameters.indeterminate_frames; ++i) {
char filename[40];
// "indeterminate01.png", "indeterminate02.png", ...
sprintf(filename, "indeterminate%02d", i+1);
int result = res_create_surface(filename, gProgressBarIndeterminate+i);
if (result < 0) {
LOGE("Missing bitmap %s\n(Code %d)\n", filename, result);
}
}
if (ui_parameters.installing_frames > 0) {
gInstallationOverlay = malloc(ui_parameters.installing_frames *
sizeof(gr_surface));
for (i = 0; i < ui_parameters.installing_frames; ++i) {
char filename[40];
// "icon_installing_overlay01.png",
// "icon_installing_overlay02.png", ...
sprintf(filename, "icon_installing_overlay%02d", i+1);
int result = res_create_surface(filename, gInstallationOverlay+i);
if (result < 0) {
LOGE("Missing bitmap %s\n(Code %d)\n", filename, result);
if (result == -2) {
LOGI("Bitmap %s missing header\n", BITMAPS[i].name);
} else {
LOGE("Missing bitmap %s\n(Code %d)\n", BITMAPS[i].name, result);
}
*BITMAPS[i].surface = NULL;
}
// Adjust the offset to account for the positioning of the
// base image on the screen.
if (gBackgroundIcon[BACKGROUND_ICON_INSTALLING] != NULL) {
gr_surface bg = gBackgroundIcon[BACKGROUND_ICON_INSTALLING];
ui_parameters.install_overlay_offset_x +=
(gr_fb_width() - gr_get_width(bg)) / 2;
ui_parameters.install_overlay_offset_y +=
(gr_fb_height() - gr_get_height(bg)) / 2;
}
} else {
gInstallationOverlay = NULL;
}
pthread_t t;
@ -524,7 +402,7 @@ char *ui_copy_image(int icon, int *width, int *height, int *bpp) {
void ui_set_background(int icon)
{
pthread_mutex_lock(&gUpdateMutex);
gCurrentIcon = icon;
gCurrentIcon = gBackgroundIcon[icon];
update_screen_locked();
pthread_mutex_unlock(&gUpdateMutex);
}
@ -545,7 +423,7 @@ void ui_show_progress(float portion, int seconds)
gProgressBarType = PROGRESSBAR_TYPE_NORMAL;
gProgressScopeStart += gProgressScopeSize;
gProgressScopeSize = portion;
gProgressScopeTime = now();
gProgressScopeTime = time(NULL);
gProgressScopeDuration = seconds;
gProgress = 0;
update_progress_locked();
@ -655,17 +533,14 @@ int ui_start_menu(char** headers, char** items, int initial_selection) {
for (; i < MENU_MAX_ROWS; ++i) {
if (items[i-menu_top] == NULL) break;
strcpy(menu[i], MENU_ITEM_HEADER);
strncpy(menu[i] + MENU_ITEM_HEADER_LENGTH, items[i-menu_top], MENU_MAX_COLS - 1 - MENU_ITEM_HEADER_LENGTH);
menu[i][MENU_MAX_COLS-1] = '\0';
strncpy(menu[i] + MENU_ITEM_HEADER_LENGTH, items[i-menu_top], text_cols-1 - MENU_ITEM_HEADER_LENGTH);
menu[i][text_cols-1] = '\0';
}
if (gShowBackButton && ui_menu_level > 0) {
if (gShowBackButton) {
strcpy(menu[i], " - +++++Go Back+++++");
++i;
}
strcpy(menu[i], " ");
++i;
menu_items = i - menu_top;
show_menu = 1;
@ -673,7 +548,7 @@ int ui_start_menu(char** headers, char** items, int initial_selection) {
update_screen_locked();
}
pthread_mutex_unlock(&gUpdateMutex);
if (gShowBackButton && ui_menu_level > 0) {
if (gShowBackButton) {
return menu_items - 1;
}
return menu_items;
@ -686,16 +561,16 @@ int ui_menu_select(int sel) {
old_sel = menu_sel;
menu_sel = sel;
if (menu_sel < 0) menu_sel = menu_items-1 + menu_sel;
if (menu_sel >= menu_items-1) menu_sel = menu_sel - menu_items+1;
if (menu_sel < 0) menu_sel = menu_items + menu_sel;
if (menu_sel >= menu_items) menu_sel = menu_sel - menu_items;
if (menu_sel < menu_show_start && menu_show_start > 0) {
menu_show_start = menu_sel;
}
if (menu_sel - menu_show_start + menu_top >= max_menu_rows) {
menu_show_start = menu_sel + menu_top - max_menu_rows + 1;
if (menu_sel - menu_show_start + menu_top >= text_rows) {
menu_show_start = menu_sel + menu_top - text_rows + 1;
}
sel = menu_sel;
@ -724,68 +599,23 @@ int ui_text_visible()
return visible;
}
int ui_text_ever_visible()
{
pthread_mutex_lock(&gUpdateMutex);
int ever_visible = show_text_ever;
pthread_mutex_unlock(&gUpdateMutex);
return ever_visible;
}
void ui_show_text(int visible)
{
pthread_mutex_lock(&gUpdateMutex);
show_text = visible;
if (show_text) show_text_ever = 1;
update_screen_locked();
pthread_mutex_unlock(&gUpdateMutex);
}
// Return true if USB is connected.
static int usb_connected() {
int fd = open("/sys/class/android_usb/android0/state", O_RDONLY);
if (fd < 0) {
printf("failed to open /sys/class/android_usb/android0/state: %s\n",
strerror(errno));
return 0;
}
char buf;
/* USB is connected if android_usb state is CONNECTED or CONFIGURED */
int connected = (read(fd, &buf, 1) == 1) && (buf == 'C');
if (close(fd) < 0) {
printf("failed to close /sys/class/android_usb/android0/state: %s\n",
strerror(errno));
}
return connected;
}
int ui_wait_key()
{
pthread_mutex_lock(&key_queue_mutex);
// Time out after UI_WAIT_KEY_TIMEOUT_SEC, unless a USB cable is
// plugged in.
do {
struct timeval now;
struct timespec timeout;
gettimeofday(&now, NULL);
timeout.tv_sec = now.tv_sec;
timeout.tv_nsec = now.tv_usec * 1000;
timeout.tv_sec += UI_WAIT_KEY_TIMEOUT_SEC;
int rc = 0;
while (key_queue_len == 0 && rc != ETIMEDOUT) {
rc = pthread_cond_timedwait(&key_queue_cond, &key_queue_mutex,
&timeout);
}
} while (usb_connected() && key_queue_len == 0);
int key = -1;
if (key_queue_len > 0) {
key = key_queue[0];
memcpy(&key_queue[0], &key_queue[1], sizeof(int) * --key_queue_len);
while (key_queue_len == 0) {
pthread_cond_wait(&key_queue_cond, &key_queue_mutex);
}
int key = key_queue[0];
memcpy(&key_queue[0], &key_queue[1], sizeof(int) * --key_queue_len);
pthread_mutex_unlock(&key_queue_mutex);
return key;
}

View File

@ -30,7 +30,6 @@ LOCAL_STATIC_LIBRARIES += libflashutils libmtdutils libmmcutils libbmlutils
LOCAL_STATIC_LIBRARIES += $(TARGET_RECOVERY_UPDATER_LIBS) $(TARGET_RECOVERY_UPDATER_EXTRA_LIBS)
LOCAL_STATIC_LIBRARIES += libapplypatch libedify libmtdutils libminzip libz
LOCAL_STATIC_LIBRARIES += libmincrypt libbz
LOCAL_STATIC_LIBRARIES += libminelf libcrecovery
LOCAL_STATIC_LIBRARIES += libcutils libstdc++ libc
LOCAL_C_INCLUDES += $(LOCAL_PATH)/..
@ -61,9 +60,9 @@ $(inc) : libs := $(TARGET_RECOVERY_UPDATER_LIBS)
$(inc) : $(inc).list
$(hide) mkdir -p $(dir $@)
$(hide) echo "" > $@
$(hide) $(foreach lib,$(libs),echo "extern void Register_$(lib)(void);" >> $@;)
$(hide) $(foreach lib,$(libs),echo "extern void Register_$(lib)(void);" >> $@)
$(hide) echo "void RegisterDeviceExtensions() {" >> $@
$(hide) $(foreach lib,$(libs),echo " Register_$(lib)();" >> $@;)
$(hide) $(foreach lib,$(libs),echo " Register_$(lib)();" >> $@)
$(hide) echo "}" >> $@
$(call intermediates-dir-for,EXECUTABLES,updater)/updater.o : $(inc)
@ -74,3 +73,9 @@ LOCAL_MODULE := updater
LOCAL_FORCE_STATIC_EXECUTABLE := true
include $(BUILD_EXECUTABLE)
file := $(PRODUCT_OUT)/utilities/update-binary
ALL_PREBUILT += $(file)
$(file) : $(TARGET_OUT)/bin/updater | $(ACP)
$(transform-prebuilt-to-target)

View File

@ -25,15 +25,12 @@
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <fcntl.h>
#include <time.h>
#include "cutils/misc.h"
#include "cutils/properties.h"
#include "edify/expr.h"
#include "mincrypt/sha.h"
#include "minzip/DirUtil.h"
#include "minelf/Retouch.h"
#include "mounts.h"
#include "mtdutils/mtdutils.h"
#include "updater.h"
@ -179,23 +176,19 @@ done:
}
// format(fs_type, partition_type, location, fs_size)
// format(fs_type, partition_type, location)
//
// fs_type="yaffs2" partition_type="MTD" location=partition fs_size=<bytes>
// fs_type="ext4" partition_type="EMMC" location=device fs_size=<bytes>
// if fs_size == 0, then make_ext4fs uses the entire partition.
// if fs_size > 0, that is the size to use
// if fs_size < 0, then reserve that many bytes at the end of the partition
// fs_type="yaffs2" partition_type="MTD" location=partition
// fs_type="ext4" partition_type="EMMC" location=device
Value* FormatFn(const char* name, State* state, int argc, Expr* argv[]) {
char* result = NULL;
if (argc != 4) {
return ErrorAbort(state, "%s() expects 4 args, got %d", name, argc);
if (argc != 3) {
return ErrorAbort(state, "%s() expects 3 args, got %d", name, argc);
}
char* fs_type;
char* partition_type;
char* location;
char* fs_size;
if (ReadArgs(state, argv, 4, &fs_type, &partition_type, &location, &fs_size) < 0) {
if (ReadArgs(state, argv, 3, &fs_type, &partition_type, &location) < 0) {
return NULL;
}
@ -242,7 +235,8 @@ Value* FormatFn(const char* name, State* state, int argc, Expr* argv[]) {
result = location;
#ifdef USE_EXT4
} else if (strcmp(fs_type, "ext4") == 0) {
int status = make_ext4fs(location, atoll(fs_size));
reset_ext4fs_info();
int status = make_ext4fs(location, NULL, NULL, 0, 0, 0);
if (status != 0) {
fprintf(stderr, "%s: make_ext4fs failed (%d) on %s",
name, status, location);
@ -455,119 +449,6 @@ Value* PackageExtractFileFn(const char* name, State* state,
}
// retouch_binaries(lib1, lib2, ...)
Value* RetouchBinariesFn(const char* name, State* state,
int argc, Expr* argv[]) {
UpdaterInfo* ui = (UpdaterInfo*)(state->cookie);
char **retouch_entries = ReadVarArgs(state, argc, argv);
if (retouch_entries == NULL) {
return StringValue(strdup("t"));
}
// some randomness from the clock
int32_t override_base;
bool override_set = false;
int32_t random_base = time(NULL) % 1024;
// some more randomness from /dev/random
FILE *f_random = fopen("/dev/random", "rb");
uint16_t random_bits = 0;
if (f_random != NULL) {
fread(&random_bits, 2, 1, f_random);
random_bits = random_bits % 1024;
fclose(f_random);
}
random_base = (random_base + random_bits) % 1024;
// make sure we never randomize to zero; this let's us look at a file
// and know for sure whether it has been processed; important in the
// crash recovery process
if (random_base == 0) random_base = 1;
// make sure our randomization is page-aligned
random_base *= -0x1000;
override_base = random_base;
int i = 0;
bool success = true;
while (i < (argc - 1)) {
success = success && retouch_one_library(retouch_entries[i],
retouch_entries[i+1],
random_base,
override_set ?
NULL :
&override_base);
if (!success)
ErrorAbort(state, "Failed to retouch '%s'.", retouch_entries[i]);
free(retouch_entries[i]);
free(retouch_entries[i+1]);
i += 2;
if (success && override_base != 0) {
random_base = override_base;
override_set = true;
}
}
if (i < argc) {
free(retouch_entries[i]);
success = false;
}
free(retouch_entries);
if (!success) {
Value* v = malloc(sizeof(Value));
v->type = VAL_STRING;
v->data = NULL;
v->size = -1;
return v;
}
return StringValue(strdup("t"));
}
// undo_retouch_binaries(lib1, lib2, ...)
Value* UndoRetouchBinariesFn(const char* name, State* state,
int argc, Expr* argv[]) {
UpdaterInfo* ui = (UpdaterInfo*)(state->cookie);
char **retouch_entries = ReadVarArgs(state, argc, argv);
if (retouch_entries == NULL) {
return StringValue(strdup("t"));
}
int i = 0;
bool success = true;
int32_t override_base;
while (i < (argc-1)) {
success = success && retouch_one_library(retouch_entries[i],
retouch_entries[i+1],
0 /* undo => offset==0 */,
NULL);
if (!success)
ErrorAbort(state, "Failed to unretouch '%s'.",
retouch_entries[i]);
free(retouch_entries[i]);
free(retouch_entries[i+1]);
i += 2;
}
if (i < argc) {
free(retouch_entries[i]);
success = false;
}
free(retouch_entries);
if (!success) {
Value* v = malloc(sizeof(Value));
v->type = VAL_STRING;
v->data = NULL;
v->size = -1;
return v;
}
return StringValue(strdup("t"));
}
// symlink target src1 src2 ...
// unlinks any previously existing src1, src2, etc before creating symlinks.
Value* SymlinkFn(const char* name, State* state, int argc, Expr* argv[]) {
@ -800,41 +681,33 @@ static bool write_raw_image_cb(const unsigned char* data,
return false;
}
// write_raw_image(filename_or_blob, partition)
// write_raw_image(file, partition)
Value* WriteRawImageFn(const char* name, State* state, int argc, Expr* argv[]) {
char* result = NULL;
Value* partition_value;
Value* contents;
if (ReadValueArgs(state, argv, 2, &contents, &partition_value) < 0) {
char* partition;
char* filename;
if (ReadArgs(state, argv, 2, &filename, &partition) < 0) {
return NULL;
}
if (partition_value->type != VAL_STRING) {
ErrorAbort(state, "partition argument to %s must be string", name);
goto done;
}
char* partition = partition_value->data;
if (strlen(partition) == 0) {
ErrorAbort(state, "partition argument to %s can't be empty", name);
goto done;
}
if (contents->type == VAL_STRING && strlen((char*) contents->data) == 0) {
if (strlen(filename) == 0) {
ErrorAbort(state, "file argument to %s can't be empty", name);
goto done;
}
char* filename = contents->data;
if (0 == restore_raw_partition(NULL, partition, filename))
result = strdup(partition);
else {
else
result = strdup("");
goto done;
}
done:
if (result != partition) FreeValue(partition_value);
FreeValue(contents);
if (result != partition) free(partition);
free(filename);
return StringValue(result);
}
@ -1107,7 +980,7 @@ Value* Sha1CheckFn(const char* name, State* state, int argc, Expr* argv[]) {
return args[i];
}
// Read a local file and return its contents (the Value* returned
// Read a local file and return its contents (the char* returned
// is actually a FileContents*).
Value* ReadFileFn(const char* name, State* state, int argc, Expr* argv[]) {
if (argc != 1) {
@ -1120,7 +993,7 @@ Value* ReadFileFn(const char* name, State* state, int argc, Expr* argv[]) {
v->type = VAL_BLOB;
FileContents fc;
if (LoadFileContents(filename, &fc, RETOUCH_DONT_MASK) != 0) {
if (LoadFileContents(filename, &fc) != 0) {
ErrorAbort(state, "%s() loading \"%s\" failed: %s",
name, filename, strerror(errno));
free(filename);
@ -1147,8 +1020,6 @@ void RegisterInstallFunctions() {
RegisterFunction("delete_recursive", DeleteFn);
RegisterFunction("package_extract_dir", PackageExtractDirFn);
RegisterFunction("package_extract_file", PackageExtractFileFn);
RegisterFunction("retouch_binaries", RetouchBinariesFn);
RegisterFunction("undo_retouch_binaries", UndoRetouchBinariesFn);
RegisterFunction("symlink", SymlinkFn);
RegisterFunction("set_perm", SetPermFn);
RegisterFunction("set_perm_recursive", SetPermFn);

View File

@ -1,8 +1,11 @@
LOCAL_PATH := $(call my-dir)
ifndef BOARD_HAS_SMALL_RECOVERY
include $(CLEAR_VARS)
LOCAL_MODULE := fix_permissions
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_TAGS := eng
LOCAL_MODULE_CLASS := RECOVERY_EXECUTABLES
LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/sbin
LOCAL_SRC_FILES := $(LOCAL_MODULE)
@ -10,7 +13,7 @@ include $(BUILD_PREBUILT)
include $(CLEAR_VARS)
LOCAL_MODULE := parted
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_TAGS := eng
LOCAL_MODULE_CLASS := RECOVERY_EXECUTABLES
LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/sbin
LOCAL_SRC_FILES := $(LOCAL_MODULE)
@ -18,53 +21,52 @@ include $(BUILD_PREBUILT)
include $(CLEAR_VARS)
LOCAL_MODULE := sdparted
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_TAGS := eng
LOCAL_MODULE_CLASS := RECOVERY_EXECUTABLES
LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/sbin
LOCAL_SRC_FILES := $(LOCAL_MODULE)
include $(BUILD_PREBUILT)
# include $(CLEAR_VARS)
# LOCAL_MODULE := e2fsck
# LOCAL_MODULE_TAGS := optional
# LOCAL_MODULE_CLASS := RECOVERY_EXECUTABLES
# LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/sbin
# LOCAL_SRC_FILES := $(LOCAL_MODULE)
# include $(BUILD_PREBUILT)
# include $(CLEAR_VARS)
# LOCAL_MODULE := tune2fs
# LOCAL_MODULE_TAGS := optional
# LOCAL_MODULE_CLASS := RECOVERY_EXECUTABLES
# LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/sbin
# LOCAL_SRC_FILES := $(LOCAL_MODULE)
# include $(BUILD_PREBUILT)
# include $(CLEAR_VARS)
# LOCAL_MODULE := mke2fs
# LOCAL_MODULE_TAGS := optional
# LOCAL_MODULE_CLASS := RECOVERY_EXECUTABLES
# LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/sbin
# ifeq ($(BOARD_MKE2FS),)
# LOCAL_SRC_FILES := $(LOCAL_MODULE)
# else
# LOCAL_SRC_FILES := ../../../$(BOARD_MKE2FS)
# endif
# include $(BUILD_PREBUILT)
ifneq ($(TARGET_RECOVERY_FSTAB),)
BOARD_RECOVERY_RFS_CHECK := $(shell grep rfs $(TARGET_RECOVERY_FSTAB))
else
BOARD_RECOVERY_RFS_CHECK := $(shell grep rfs $(TARGET_DEVICE_DIR)/recovery.fstab)
endif
include $(CLEAR_VARS)
LOCAL_MODULE := e2fsck
LOCAL_MODULE_TAGS := eng
LOCAL_MODULE_CLASS := RECOVERY_EXECUTABLES
LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/sbin
LOCAL_SRC_FILES := $(LOCAL_MODULE)
include $(BUILD_PREBUILT)
include $(CLEAR_VARS)
LOCAL_MODULE := tune2fs
LOCAL_MODULE_TAGS := eng
LOCAL_MODULE_CLASS := RECOVERY_EXECUTABLES
LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/sbin
LOCAL_SRC_FILES := $(LOCAL_MODULE)
include $(BUILD_PREBUILT)
ifeq ($(BOARD_HAS_LARGE_FILESYSTEM),true)
include $(CLEAR_VARS)
LOCAL_MODULE := mke2fs
LOCAL_MODULE_TAGS := eng
LOCAL_MODULE_CLASS := RECOVERY_EXECUTABLES
LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/sbin
ifeq ($(BOARD_MKE2FS),)
LOCAL_SRC_FILES := $(LOCAL_MODULE)
else
LOCAL_SRC_FILES := ../../../$(BOARD_MKE2FS)
endif
include $(BUILD_PREBUILT)
endif
BOARD_RECOVERY_RFS_CHECK := $(shell grep rfs $(TARGET_DEVICE_DIR)/recovery.fstab)
ifneq ($(BOARD_RECOVERY_RFS_CHECK),)
include $(CLEAR_VARS)
LOCAL_MODULE := fat.format
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_TAGS := eng
LOCAL_MODULE_CLASS := RECOVERY_EXECUTABLES
LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/sbin
LOCAL_SRC_FILES := $(LOCAL_MODULE)
include $(BUILD_PREBUILT)
endif

View File

@ -173,7 +173,7 @@ int verify_file(const char* path, const RSAPublicKey *pKeys, unsigned int numKey
// the signing tool appends after the signature itself.
if (RSA_verify(pKeys+i, eocd + eocd_size - 6 - RSANUMBYTES,
RSANUMBYTES, sha1)) {
LOGI("whole-file signature verified against key %d\n", i);
LOGI("whole-file signature verified\n");
free(eocd);
return VERIFY_SUCCESS;
}