Update to latest AOSP master

Merge in latest commits from AOSP master and fix merge conflicts
This commit is contained in:
Dees_Troy
2013-09-04 18:35:08 +00:00
50 changed files with 1337 additions and 551 deletions
+22 -7
View File
@@ -40,15 +40,27 @@ LOCAL_MODULE := recovery
#LOCAL_FORCE_STATIC_EXECUTABLE := true
RECOVERY_API_VERSION := 3
RECOVERY_FSTAB_VERSION := 2
LOCAL_CFLAGS += -DRECOVERY_API_VERSION=$(RECOVERY_API_VERSION)
#LOCAL_STATIC_LIBRARIES := \
# libext4_utils \
# libext4_utils_static \
# libsparse_static \
# libminzip \
# libz \
# libmtdutils \
# libmincrypt \
# libminadbd \
# libpixelflinger_static
# libminui \
# libpixelflinger_static \
# libpng \
# libfs_mgr \
# libcutils \
# liblog \
# libselinux \
# libstdc++ \
# libm \
# libc
LOCAL_C_INCLUDES += bionic external/stlport/stlport
@@ -67,7 +79,7 @@ ifeq ($(TARGET_USERIMAGES_USE_EXT4), true)
LOCAL_C_INCLUDES += system/extras/ext4_utils
LOCAL_SHARED_LIBRARIES += libext4_utils
endif
LOCAL_C_INCLUDES += external/libselinux/include
ifeq ($(HAVE_SELINUX), true)
#LOCAL_C_INCLUDES += external/libselinux/include
#LOCAL_STATIC_LIBRARIES += libselinux
@@ -90,11 +102,11 @@ endif
# TODO: Build the ramdisk image in a more principled way.
LOCAL_MODULE_TAGS := eng
ifeq ($(TARGET_RECOVERY_UI_LIB),)
#ifeq ($(TARGET_RECOVERY_UI_LIB),)
LOCAL_SRC_FILES += default_device.cpp
else
LOCAL_STATIC_LIBRARIES += $(TARGET_RECOVERY_UI_LIB)
endif
#else
# LOCAL_STATIC_LIBRARIES += $(TARGET_RECOVERY_UI_LIB)
#endif
LOCAL_C_INCLUDES += system/extras/ext4_utils
@@ -289,6 +301,9 @@ LOCAL_MODULE := libaosprecovery
LOCAL_MODULE_TAGS := eng
LOCAL_MODULES_TAGS = optional
LOCAL_CFLAGS =
ifneq ($(wildcard system/core/libmincrypt/rsa_e_3.c),)
LOCAL_CFLAGS += -DHAS_EXPONENT
endif
LOCAL_SRC_FILES = adb_install.cpp bootloader.cpp verifier.cpp mtdutils/mtdutils.c
LOCAL_SHARED_LIBRARIES += libc liblog libcutils libmtdutils
LOCAL_STATIC_LIBRARIES += libmincrypt
+1
View File
@@ -47,3 +47,4 @@
# ************************************************
# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
# ************************************************
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/recovery_intermediates)
+129 -18
View File
@@ -39,7 +39,8 @@ static int GenerateTarget(FileContents* source_file,
const char* source_filename,
const char* target_filename,
const uint8_t target_sha1[SHA_DIGEST_SIZE],
size_t target_size);
size_t target_size,
const Value* bonus_data);
static int mtd_partitions_scanned = 0;
@@ -420,18 +421,111 @@ int WriteToPartition(unsigned char* data, size_t len,
break;
case EMMC:
;
FILE* f = fopen(partition, "wb");
if (fwrite(data, 1, len, f) != len) {
printf("short write writing to %s (%s)\n",
partition, strerror(errno));
{
size_t start = 0;
int success = 0;
int fd = open(partition, O_RDWR | O_SYNC);
if (fd < 0) {
printf("failed to open %s: %s\n", partition, strerror(errno));
return -1;
}
if (fclose(f) != 0) {
int attempt;
for (attempt = 0; attempt < 10; ++attempt) {
size_t next_sync = start + (1<<20);
printf("raw O_SYNC write %s attempt %d start at %d\n", partition, attempt+1, start);
lseek(fd, start, SEEK_SET);
while (start < len) {
size_t to_write = len - start;
if (to_write > 4096) to_write = 4096;
ssize_t written = write(fd, data+start, to_write);
if (written < 0) {
if (errno == EINTR) {
written = 0;
} else {
printf("failed write writing to %s (%s)\n",
partition, strerror(errno));
return -1;
}
}
start += written;
if (start >= next_sync) {
fsync(fd);
next_sync = start + (1<<20);
}
}
fsync(fd);
// drop caches so our subsequent verification read
// won't just be reading the cache.
sync();
int dc = open("/proc/sys/vm/drop_caches", O_WRONLY);
write(dc, "3\n", 2);
close(dc);
sleep(1);
printf(" caches dropped\n");
// verify
lseek(fd, 0, SEEK_SET);
unsigned char buffer[4096];
start = len;
size_t p;
for (p = 0; p < len; p += sizeof(buffer)) {
size_t to_read = len - p;
if (to_read > sizeof(buffer)) to_read = sizeof(buffer);
size_t so_far = 0;
while (so_far < to_read) {
ssize_t read_count = read(fd, buffer+so_far, to_read-so_far);
if (read_count < 0) {
if (errno == EINTR) {
read_count = 0;
} else {
printf("verify read error %s at %d: %s\n",
partition, p, strerror(errno));
return -1;
}
}
if ((size_t)read_count < to_read) {
printf("short verify read %s at %d: %d %d %s\n",
partition, p, read_count, to_read, strerror(errno));
}
so_far += read_count;
}
if (memcmp(buffer, data+p, to_read)) {
printf("verification failed starting at %d\n", p);
start = p;
break;
}
}
if (start == len) {
printf("verification read succeeded (attempt %d)\n", attempt+1);
success = true;
break;
}
sleep(2);
}
if (!success) {
printf("failed to verify after all attempts\n");
return -1;
}
if (close(fd) != 0) {
printf("error closing %s (%s)\n", partition, strerror(errno));
return -1;
}
// hack: sync and sleep after closing in hopes of getting
// the data actually onto flash.
printf("sleeping after close\n");
sync();
sleep(5);
break;
}
}
free(copy);
@@ -472,7 +566,7 @@ int ParseSha1(const char* str, uint8_t* digest) {
// Search an array of sha1 strings for one matching the given sha1.
// Return the index of the match on success, or -1 if no match is
// found.
int FindMatchingPatch(uint8_t* sha1, const char** patch_sha1_str,
int FindMatchingPatch(uint8_t* sha1, char* const * const patch_sha1_str,
int num_patches) {
int i;
uint8_t patch_sha1[SHA_DIGEST_SIZE];
@@ -584,6 +678,14 @@ int CacheSizeCheck(size_t bytes) {
}
}
static void print_short_sha1(const uint8_t sha1[SHA_DIGEST_SIZE]) {
int i;
const char* hex = "0123456789abcdef";
for (i = 0; i < 4; ++i) {
putchar(hex[(sha1[i]>>4) & 0xf]);
putchar(hex[sha1[i] & 0xf]);
}
}
// This function applies binary patches to files in a way that is safe
// (the original file is not touched until we have the desired
@@ -617,8 +719,9 @@ int applypatch(const char* source_filename,
size_t target_size,
int num_patches,
char** const patch_sha1_str,
Value** patch_data) {
printf("\napplying patch to %s\n", source_filename);
Value** patch_data,
Value* bonus_data) {
printf("patch %s: ", source_filename);
if (target_filename[0] == '-' &&
target_filename[1] == '\0') {
@@ -644,8 +747,9 @@ int applypatch(const char* source_filename,
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.
printf("\"%s\" is already target; no patch needed\n",
target_filename);
printf("already ");
print_short_sha1(target_sha1);
putchar('\n');
free(source_file.data);
return 0;
}
@@ -699,7 +803,7 @@ int applypatch(const char* source_filename,
int result = GenerateTarget(&source_file, source_patch_value,
&copy_file, copy_patch_value,
source_filename, target_filename,
target_sha1, target_size);
target_sha1, target_size, bonus_data);
free(source_file.data);
free(copy_file.data);
@@ -713,7 +817,8 @@ static int GenerateTarget(FileContents* source_file,
const char* source_filename,
const char* target_filename,
const uint8_t target_sha1[SHA_DIGEST_SIZE],
size_t target_size) {
size_t target_size,
const Value* bonus_data) {
int retry = 1;
SHA_CTX ctx;
int output;
@@ -766,8 +871,10 @@ static int GenerateTarget(FileContents* source_file,
enough_space =
(free_space > (256 << 10)) && // 256k (two-block) minimum
(free_space > (target_size * 3 / 2)); // 50% margin of error
printf("target %ld bytes; free space %ld bytes; retry %d; enough %d\n",
(long)target_size, (long)free_space, retry, enough_space);
if (!enough_space) {
printf("target %ld bytes; free space %ld bytes; retry %d; enough %d\n",
(long)target_size, (long)free_space, retry, enough_space);
}
}
if (!enough_space) {
@@ -802,7 +909,7 @@ static int GenerateTarget(FileContents* source_file,
unlink(source_filename);
size_t free_space = FreeSpaceForFile(target_fs);
printf("(now %ld bytes free for target)\n", (long)free_space);
printf("(now %ld bytes free for target) ", (long)free_space);
}
}
@@ -867,7 +974,7 @@ static int GenerateTarget(FileContents* source_file,
} else if (header_bytes_read >= 8 &&
memcmp(header, "IMGDIFF2", 8) == 0) {
result = ApplyImagePatch(source_to_use->data, source_to_use->size,
patch, sink, token, &ctx);
patch, sink, token, &ctx, bonus_data);
} else {
printf("Unknown patch file format\n");
return 1;
@@ -898,6 +1005,10 @@ static int GenerateTarget(FileContents* source_file,
if (memcmp(current_target_sha1, target_sha1, SHA_DIGEST_SIZE) != 0) {
printf("patch did not produce expected sha1\n");
return 1;
} else {
printf("now ");
print_short_sha1(target_sha1);
putchar('\n');
}
if (output < 0) {
+5 -3
View File
@@ -55,7 +55,8 @@ int applypatch(const char* source_filename,
size_t target_size,
int num_patches,
char** const patch_sha1_str,
Value** patch_data);
Value** patch_data,
Value* bonus_data);
int applypatch_check(const char* filename,
int num_patches,
char** const patch_sha1_str);
@@ -64,7 +65,7 @@ int LoadFileContents(const char* filename, FileContents* file,
int retouch_flag);
int SaveFileContents(const char* filename, const FileContents* file);
void FreeFileContents(FileContents* file);
int FindMatchingPatch(uint8_t* sha1, const char** patch_sha1_str,
int FindMatchingPatch(uint8_t* sha1, char* const * const patch_sha1_str,
int num_patches);
// bsdiff.c
@@ -79,7 +80,8 @@ int ApplyBSDiffPatchMem(const unsigned char* old_data, ssize_t old_size,
// imgpatch.c
int ApplyImagePatch(const unsigned char* old_data, ssize_t old_size,
const Value* patch,
SinkFn sink, void* token, SHA_CTX* ctx);
SinkFn sink, void* token, SHA_CTX* ctx,
const Value* bonus_data);
// freecache.c
int MakeFreeSpaceOnCache(size_t bytes_needed);
+49 -8
View File
@@ -111,6 +111,14 @@
*
* After the header there are 'chunk count' bsdiff patches; the offset
* of each from the beginning of the file is specified in the header.
*
* This tool can take an optional file of "bonus data". This is an
* extra file of data that is appended to chunk #1 after it is
* compressed (it must be a CHUNK_DEFLATE chunk). The same file must
* be available (and passed to applypatch with -b) when applying the
* patch. This is used to reduce the size of recovery-from-boot
* patches by combining the boot image with recovery ramdisk
* information that is stored on the system partition.
*/
#include <errno.h>
@@ -772,21 +780,45 @@ void DumpChunks(ImageChunk* chunks, int num_chunks) {
}
int main(int argc, char** argv) {
if (argc != 4 && argc != 5) {
usage:
printf("usage: %s [-z] <src-img> <tgt-img> <patch-file>\n",
argv[0]);
return 2;
}
int zip_mode = 0;
if (strcmp(argv[1], "-z") == 0) {
if (argc >= 2 && strcmp(argv[1], "-z") == 0) {
zip_mode = 1;
--argc;
++argv;
}
size_t bonus_size = 0;
unsigned char* bonus_data = NULL;
if (argc >= 3 && strcmp(argv[1], "-b") == 0) {
struct stat st;
if (stat(argv[2], &st) != 0) {
printf("failed to stat bonus file %s: %s\n", argv[2], strerror(errno));
return 1;
}
bonus_size = st.st_size;
bonus_data = malloc(bonus_size);
FILE* f = fopen(argv[2], "rb");
if (f == NULL) {
printf("failed to open bonus file %s: %s\n", argv[2], strerror(errno));
return 1;
}
if (fread(bonus_data, 1, bonus_size, f) != bonus_size) {
printf("failed to read bonus file %s: %s\n", argv[2], strerror(errno));
return 1;
}
fclose(f);
argc -= 2;
argv += 2;
}
if (argc != 4) {
usage:
printf("usage: %s [-z] [-b <bonus-file>] <src-img> <tgt-img> <patch-file>\n",
argv[0]);
return 2;
}
int num_src_chunks;
ImageChunk* src_chunks;
@@ -909,6 +941,8 @@ int main(int argc, char** argv) {
// Compute bsdiff patches for each chunk's data (the uncompressed
// data, in the case of deflate chunks).
DumpChunks(src_chunks, num_src_chunks);
printf("Construct patches for %d chunks...\n", num_tgt_chunks);
unsigned char** patch_data = malloc(num_tgt_chunks * sizeof(unsigned char*));
size_t* patch_size = malloc(num_tgt_chunks * sizeof(size_t));
@@ -923,6 +957,13 @@ int main(int argc, char** argv) {
patch_data[i] = MakePatch(src_chunks, tgt_chunks+i, patch_size+i);
}
} else {
if (i == 1 && bonus_data) {
printf(" using %d bytes of bonus data for chunk %d\n", bonus_size, i);
src_chunks[i].data = realloc(src_chunks[i].data, src_chunks[i].len + bonus_size);
memcpy(src_chunks[i].data+src_chunks[i].len, bonus_data, bonus_size);
src_chunks[i].len += bonus_size;
}
patch_data[i] = MakePatch(src_chunks+i, tgt_chunks+i, patch_size+i);
}
printf("patch %3d is %d bytes (of %d)\n",
+17 -4
View File
@@ -37,7 +37,8 @@
*/
int ApplyImagePatch(const unsigned char* old_data, ssize_t old_size,
const Value* patch,
SinkFn sink, void* token, SHA_CTX* ctx) {
SinkFn sink, void* token, SHA_CTX* ctx,
const Value* bonus_data) {
ssize_t pos = 12;
char* header = patch->data;
if (patch->size < 12) {
@@ -123,6 +124,12 @@ int ApplyImagePatch(const unsigned char* old_data, ssize_t old_size,
// Decompress the source data; the chunk header tells us exactly
// how big we expect it to be when decompressed.
// Note: expanded_len will include the bonus data size if
// the patch was constructed with bonus data. The
// deflation will come up 'bonus_size' bytes short; these
// must be appended from the bonus_data value.
size_t bonus_size = (i == 1 && bonus_data != NULL) ? bonus_data->size : 0;
unsigned char* expanded_source = malloc(expanded_len);
if (expanded_source == NULL) {
printf("failed to allocate %d bytes for expanded_source\n",
@@ -153,13 +160,19 @@ int ApplyImagePatch(const unsigned char* old_data, ssize_t old_size,
printf("source inflation returned %d\n", ret);
return -1;
}
// We should have filled the output buffer exactly.
if (strm.avail_out != 0) {
printf("source inflation short by %d bytes\n", strm.avail_out);
// We should have filled the output buffer exactly, except
// for the bonus_size.
if (strm.avail_out != bonus_size) {
printf("source inflation short by %d bytes\n", strm.avail_out-bonus_size);
return -1;
}
inflateEnd(&strm);
if (bonus_size) {
memcpy(expanded_source + (expanded_len - bonus_size),
bonus_data->data, bonus_size);
}
// Next, apply the bsdiff patch (in memory) to the uncompressed
// data.
unsigned char* uncompressed_target_data;
+21 -2
View File
@@ -100,6 +100,21 @@ static int ParsePatchArgs(int argc, char** argv,
}
int PatchMode(int argc, char** argv) {
Value* bonus = NULL;
if (argc >= 3 && strcmp(argv[1], "-b") == 0) {
FileContents fc;
if (LoadFileContents(argv[2], &fc, RETOUCH_DONT_MASK) != 0) {
printf("failed to load bonus file %s\n", argv[2]);
return 1;
}
bonus = malloc(sizeof(Value));
bonus->type = VAL_BLOB;
bonus->size = fc.size;
bonus->data = (char*)fc.data;
argc -= 2;
argv += 2;
}
if (argc < 6) {
return 2;
}
@@ -120,7 +135,7 @@ int PatchMode(int argc, char** argv) {
}
int result = applypatch(argv[1], argv[2], argv[3], target_size,
num_patches, sha1s, patches);
num_patches, sha1s, patches, bonus);
int i;
for (i = 0; i < num_patches; ++i) {
@@ -130,6 +145,10 @@ int PatchMode(int argc, char** argv) {
free(p);
}
}
if (bonus) {
free(bonus->data);
free(bonus);
}
free(sha1s);
free(patches);
@@ -163,7 +182,7 @@ int main(int argc, char** argv) {
if (argc < 2) {
usage:
printf(
"usage: %s <src-file> <tgt-file> <tgt-sha1> <tgt-size> "
"usage: %s [-b <bonus-file>] <src-file> <tgt-file> <tgt-sha1> <tgt-size> "
"[<src-sha1>:<patch> ...]\n"
" or %s -c <file> [<sha1> ...]\n"
" or %s -s <bytes>\n"
+106 -38
View File
@@ -14,6 +14,9 @@
* limitations under the License.
*/
/*
#include <fs_mgr.h>
*/
#include "bootloader.h"
#include "common.h"
extern "C" {
@@ -27,38 +30,42 @@ extern "C" {
#include <sys/stat.h>
#include <unistd.h>
static char device_type = 'e'; // e for emmc or m for mtd, default is emmc
static char device_name[256];
/*
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);
static int get_bootloader_message_block(struct bootloader_message *out, const Volume* v);
static int set_bootloader_message_block(const struct bootloader_message *in, const Volume* v);
*/
int get_bootloader_message(struct bootloader_message *out) {
Volume* v = NULL;//volume_for_path("/misc");
if (v == NULL) {
//volume_for_path("/misc");
if (device_name[0] == 0) {
LOGE("Cannot load volume /misc!\n");
return -1;
}
if (strcmp(v->fs_type, "mtd") == 0) {
return get_bootloader_message_mtd(out, v);
} else if (strcmp(v->fs_type, "emmc") == 0) {
return get_bootloader_message_block(out, v);
if (device_type == 'm') {
return get_bootloader_message_mtd_name(out);
} else if (device_type == 'e') {
return get_bootloader_message_block_name(out);
}
LOGE("unknown misc partition fs_type \"%s\"\n", v->fs_type);
LOGE("unknown misc partition fs_type \"%c\"\n", device_type);
return -1;
}
int set_bootloader_message(const struct bootloader_message *in) {
Volume* v = NULL;//volume_for_path("/misc");
if (v == NULL) {
//volume_for_path("/misc");
if (device_name[0] == 0) {
LOGE("Cannot load volume /misc!\n");
return -1;
}
if (strcmp(v->fs_type, "mtd") == 0) {
return set_bootloader_message_mtd(in, v);
} else if (strcmp(v->fs_type, "emmc") == 0) {
return set_bootloader_message_block(in, v);
if (device_type == 'm') {
return set_bootloader_message_mtd_name(in, device_name);
} else if (device_type == 'e') {
return set_bootloader_message_block_name(in, device_name);
}
LOGE("unknown misc partition fs_type \"%s\"\n", v->fs_type);
LOGE("unknown misc partition type \"%c\"\n", device_type);
return -1;
}
@@ -68,27 +75,27 @@ int set_bootloader_message(const struct bootloader_message *in) {
static const int MISC_PAGES = 3; // number of pages to save
static const int MISC_COMMAND_PAGE = 1; // bootloader command is this page
/*
static int get_bootloader_message_mtd(struct bootloader_message *out,
const Volume* v) {
size_t write_size;
mtd_scan_partitions();
const MtdPartition *part = mtd_find_partition_by_name(v->device);
const MtdPartition *part = mtd_find_partition_by_name(v->blk_device);
if (part == NULL || mtd_partition_info(part, NULL, NULL, &write_size)) {
LOGE("Can't find %s\n", v->device);
LOGE("Can't find %s\n", v->blk_device);
return -1;
}
MtdReadContext *read = mtd_read_partition(part);
if (read == NULL) {
LOGE("Can't open %s\n(%s)\n", v->device, strerror(errno));
LOGE("Can't open %s\n(%s)\n", v->blk_device, strerror(errno));
return -1;
}
const ssize_t size = write_size * MISC_PAGES;
char data[size];
ssize_t r = mtd_read_data(read, data, size);
if (r != size) LOGE("Can't read %s\n(%s)\n", v->device, strerror(errno));
if (r != size) LOGE("Can't read %s\n(%s)\n", v->blk_device, strerror(errno));
mtd_read_close(read);
if (r != size) return -1;
@@ -99,22 +106,22 @@ static int set_bootloader_message_mtd(const struct bootloader_message *in,
const Volume* v) {
size_t write_size;
mtd_scan_partitions();
const MtdPartition *part = mtd_find_partition_by_name(v->device);
const MtdPartition *part = mtd_find_partition_by_name(v->blk_device);
if (part == NULL || mtd_partition_info(part, NULL, NULL, &write_size)) {
LOGE("Can't find %s\n", v->device);
LOGE("Can't find %s\n", v->blk_device);
return -1;
}
MtdReadContext *read = mtd_read_partition(part);
if (read == NULL) {
LOGE("Can't open %s\n(%s)\n", v->device, strerror(errno));
LOGE("Can't open %s\n(%s)\n", v->blk_device, strerror(errno));
return -1;
}
ssize_t size = write_size * MISC_PAGES;
char data[size];
ssize_t r = mtd_read_data(read, data, size);
if (r != size) LOGE("Can't read %s\n(%s)\n", v->device, strerror(errno));
if (r != size) LOGE("Can't read %s\n(%s)\n", v->blk_device, strerror(errno));
mtd_read_close(read);
if (r != size) return -1;
@@ -122,22 +129,61 @@ static int set_bootloader_message_mtd(const struct bootloader_message *in,
MtdWriteContext *write = mtd_write_partition(part);
if (write == NULL) {
LOGE("Can't open %s\n(%s)\n", v->device, strerror(errno));
LOGE("Can't open %s\n(%s)\n", v->blk_device, strerror(errno));
return -1;
}
if (mtd_write_data(write, data, size) != size) {
LOGE("Can't write %s\n(%s)\n", v->device, strerror(errno));
LOGE("Can't write %s\n(%s)\n", v->blk_device, strerror(errno));
mtd_write_close(write);
return -1;
}
if (mtd_write_close(write)) {
LOGE("Can't finish %s\n(%s)\n", v->device, strerror(errno));
LOGE("Can't finish %s\n(%s)\n", v->blk_device, strerror(errno));
return -1;
}
LOGI("Set boot command \"%s\"\n", in->command[0] != 255 ? in->command : "");
return 0;
}
*/
void set_device_type(char new_type) {
device_type = new_type;
}
void set_device_name(const char* new_name) {
if (strlen(new_name) >= sizeof(device_name)) {
LOGE("New device name of '%s' is too large for bootloader.cpp\n", new_name);
} else {
strcpy(device_name, new_name);
}
}
int get_bootloader_message_mtd_name(struct bootloader_message *out) {
size_t write_size;
mtd_scan_partitions();
const MtdPartition *part = mtd_find_partition_by_name(device_name);
if (part == NULL || mtd_partition_info(part, NULL, NULL, &write_size)) {
LOGE("Can't find %s\n", device_name);
return -1;
}
MtdReadContext *read = mtd_read_partition(part);
if (read == NULL) {
LOGE("Can't open %s\n(%s)\n", device_name, strerror(errno));
return -1;
}
const ssize_t size = write_size * MISC_PAGES;
char data[size];
ssize_t r = mtd_read_data(read, data, size);
if (r != size) LOGE("Can't read %s\n(%s)\n", device_name, strerror(errno));
mtd_read_close(read);
if (r != size) return -1;
memcpy(out, &data[write_size * MISC_COMMAND_PAGE], sizeof(*out));
return 0;
}
int set_bootloader_message_mtd_name(const struct bootloader_message *in,
const char* mtd_name) {
@@ -203,23 +249,23 @@ static void wait_for_device(const char* fn) {
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");
wait_for_device(v->blk_device);
FILE* f = fopen(v->blk_device, "rb");
if (f == NULL) {
LOGE("Can't open %s\n(%s)\n", v->device, strerror(errno));
LOGE("Can't open %s\n(%s)\n", v->blk_device, strerror(errno));
return -1;
}
struct bootloader_message temp;
int count = fread(&temp, sizeof(temp), 1, f);
if (count != 1) {
LOGE("Failed reading %s\n(%s)\n", v->device, strerror(errno));
LOGE("Failed reading %s\n(%s)\n", v->blk_device, strerror(errno));
return -1;
}
if (fclose(f) != 0) {
LOGE("Failed closing %s\n(%s)\n", v->device, strerror(errno));
LOGE("Failed closing %s\n(%s)\n", v->blk_device, strerror(errno));
return -1;
}
memcpy(out, &temp, sizeof(temp));
@@ -228,23 +274,45 @@ 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");
wait_for_device(v->blk_device);
FILE* f = fopen(v->blk_device, "wb");
if (f == NULL) {
LOGE("Can't open %s\n(%s)\n", v->device, strerror(errno));
LOGE("Can't open %s\n(%s)\n", v->blk_device, strerror(errno));
return -1;
}
int count = fwrite(in, sizeof(*in), 1, f);
if (count != 1) {
LOGE("Failed writing %s\n(%s)\n", v->device, strerror(errno));
LOGE("Failed writing %s\n(%s)\n", v->blk_device, strerror(errno));
return -1;
}
if (fclose(f) != 0) {
LOGE("Failed closing %s\n(%s)\n", v->device, strerror(errno));
LOGE("Failed closing %s\n(%s)\n", v->blk_device, strerror(errno));
return -1;
}
return 0;
}
*/
int get_bootloader_message_block_name(struct bootloader_message *out) {
wait_for_device(device_name);
FILE* f = fopen(device_name, "rb");
if (f == NULL) {
LOGE("Can't open %s\n(%s)\n", device_name, strerror(errno));
return -1;
}
struct bootloader_message temp;
int count = fread(&temp, sizeof(temp), 1, f);
if (count != 1) {
LOGE("Failed reading %s\n(%s)\n", device_name, strerror(errno));
return -1;
}
if (fclose(f) != 0) {
LOGE("Failed closing %s\n(%s)\n", device_name, strerror(errno));
return -1;
}
memcpy(out, &temp, sizeof(temp));
return 0;
}
int set_bootloader_message_block_name(const struct bootloader_message *in,
const char* block_name) {
+7
View File
@@ -48,10 +48,17 @@ struct bootloader_message {
/* Read and write the bootloader command from the "misc" partition.
* These return zero on success.
*/
/*
int get_bootloader_message(struct bootloader_message *out);
int set_bootloader_message(const struct bootloader_message *in);
*/
void set_device_type(char new_type);
void set_device_name(const char* new_name);
int get_bootloader_message_mtd_name(struct bootloader_message *out);
int set_bootloader_message_mtd_name(const struct bootloader_message *in, const char* mtd_name);
int get_bootloader_message_block_name(struct bootloader_message *out);
int set_bootloader_message_block_name(const struct bootloader_message *in, const char* block_name);
void get_args(int *argc, char ***argv);
+4 -18
View File
@@ -18,6 +18,7 @@
#define RECOVERY_COMMON_H
#include <stdio.h>
#include <stdarg.h>
#ifdef __cplusplus
extern "C" {
@@ -44,28 +45,13 @@ static long tmplog_offset = 0;
#define STRINGIFY(x) #x
#define EXPAND(x) STRINGIFY(x)
typedef struct {
const char* mount_point; // eg. "/cache". must live in the root directory.
const char* fs_type; // "yaffs2" or "ext4" or "vfat"
const char* device; // MTD partition name if fs_type == "yaffs"
// block device if fs_type == "ext4" or "vfat"
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).
} Volume;
typedef struct fstab_rec Volume;
// fopen a file, mounting volumes and making parent dirs as necessary.
FILE* fopen_path(const char *path, const char *mode);
//void ui_print(const char* format, ...);
#ifdef __cplusplus
}
#endif
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

+93
View File
@@ -0,0 +1,93 @@
Copyright (c) 2011, Raph Levien (firstname.lastname@gmail.com), Copyright (c) 2012, Cyreal (cyreal.org)
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
http://scripts.sil.org/OFL
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.
+6
View File
@@ -0,0 +1,6 @@
The images in this directory were generated using the font
Inconsolata, which is released under the OFL license and was obtained
from:
https://code.google.com/p/googlefontdirectory/source/browse/ofl/inconsolata/
+1 -77
View File
@@ -174,86 +174,10 @@ try_update_binary(const char *path, ZipArchive *zip, int* wipe_cache) {
return INSTALL_SUCCESS;
}
// Reads a file containing one or more public keys as produced by
// DumpPublicKey: this is an RSAPublicKey struct as it would appear
// as a C source literal, eg:
//
// "{64,0xc926ad21,{1795090719,...,-695002876},{-857949815,...,1175080310}}"
//
// (Note that the braces and commas in this example are actual
// characters the parser expects to find in the file; the ellipses
// indicate more numbers omitted from this example.)
//
// The file may contain multiple keys in this format, separated by
// commas. The last key must not be followed by a comma.
//
// Returns NULL if the file failed to parse, or if it contain zero keys.
RSAPublicKey*
load_keys(const char* filename, int* numKeys) {
RSAPublicKey* out = NULL;
*numKeys = 0;
FILE* f = fopen(filename, "r");
if (f == NULL) {
LOGE("opening %s: %s\n", filename, strerror(errno));
goto exit;
}
{
int i;
bool done = false;
while (!done) {
++*numKeys;
out = (RSAPublicKey*)realloc(out, *numKeys * sizeof(RSAPublicKey));
RSAPublicKey* key = out + (*numKeys - 1);
if (fscanf(f, " { %i , 0x%x , { %u",
&(key->len), &(key->n0inv), &(key->n[0])) != 3) {
goto exit;
}
if (key->len != RSANUMWORDS) {
LOGE("key length (%d) does not match expected size\n", key->len);
goto exit;
}
for (i = 1; i < key->len; ++i) {
if (fscanf(f, " , %u", &(key->n[i])) != 1) goto exit;
}
if (fscanf(f, " } , { %u", &(key->rr[0])) != 1) goto exit;
for (i = 1; i < key->len; ++i) {
if (fscanf(f, " , %u", &(key->rr[i])) != 1) goto exit;
}
fscanf(f, " } } ");
// if the line ends in a comma, this file has more keys.
switch (fgetc(f)) {
case ',':
// more keys to come.
break;
case EOF:
done = true;
break;
default:
LOGE("unexpected character between keys\n");
goto exit;
}
}
}
fclose(f);
return out;
exit:
if (f) fclose(f);
free(out);
*numKeys = 0;
return NULL;
}
static int
really_install_package(const char *path, int* wipe_cache)
{
ui->SetBackground(RecoveryUI::INSTALLING);
ui->SetBackground(RecoveryUI::INSTALLING_UPDATE);
ui->Print("Finding update package...\n");
ui->SetProgressType(RecoveryUI::INDETERMINATE);
LOGI("Update location: %s\n", path);
+1 -1
View File
@@ -24,7 +24,7 @@
extern "C" {
#endif
enum { INSTALL_SUCCESS, INSTALL_ERROR, INSTALL_CORRUPT };
enum { INSTALL_SUCCESS, INSTALL_ERROR, INSTALL_CORRUPT, INSTALL_NONE };
// Install the package specified by root_path. If INSTALL_SUCCESS is
// returned and *wipe_cache is true on exit, caller should wipe the
// cache partition.
-2
View File
@@ -29,8 +29,6 @@
#include "adb.h"
#include <private/android_filesystem_config.h>
#include <linux/capability.h>
#include <linux/prctl.h>
#if ADB_TRACE
ADB_MUTEX_DEFINE( D_lock );
+12 -2
View File
@@ -9,11 +9,21 @@ LOCAL_C_INCLUDES +=\
LOCAL_STATIC_LIBRARY := libpng
LOCAL_MODULE := libminui
ifeq ($(TARGET_RECOVERY_PIXEL_FORMAT),"RGBX_8888")
# This used to compare against values in double-quotes (which are just
# ordinary characters in this context). Strip double-quotes from the
# value so that either will work.
ifeq ($(subst ",,$(TARGET_RECOVERY_PIXEL_FORMAT)),RGBX_8888)
LOCAL_CFLAGS += -DRECOVERY_RGBX
endif
ifeq ($(TARGET_RECOVERY_PIXEL_FORMAT),"BGRA_8888")
ifeq ($(subst ",,$(TARGET_RECOVERY_PIXEL_FORMAT)),BGRA_8888)
LOCAL_CFLAGS += -DRECOVERY_BGRA
endif
ifneq ($(TARGET_RECOVERY_OVERSCAN_PERCENT),)
LOCAL_CFLAGS += -DOVERSCAN_PERCENT=$(TARGET_RECOVERY_OVERSCAN_PERCENT)
else
LOCAL_CFLAGS += -DOVERSCAN_PERCENT=0
endif
include $(BUILD_STATIC_LIBRARY)
+85 -32
View File
@@ -44,20 +44,24 @@
#define PIXEL_SIZE 2
#endif
#define NUM_BUFFERS 2
typedef struct {
GGLSurface texture;
GGLSurface* texture;
unsigned cwidth;
unsigned cheight;
unsigned ascent;
} GRFont;
static GRFont *gr_font = 0;
static GGLContext *gr_context = 0;
static GGLSurface gr_font_texture;
static GGLSurface gr_framebuffer[2];
static GGLSurface gr_framebuffer[NUM_BUFFERS];
static GGLSurface gr_mem_surface;
static unsigned gr_active_fb = 0;
static unsigned double_buffering = 0;
static int overscan_percent = OVERSCAN_PERCENT;
static int overscan_offset_x = 0;
static int overscan_offset_y = 0;
static int gr_fb_fd = -1;
static int gr_vt_fd = -1;
@@ -130,6 +134,9 @@ static int get_framebuffer(GGLSurface *fb)
return -1;
}
overscan_offset_x = vi.xres * overscan_percent / 100;
overscan_offset_y = vi.yres * overscan_percent / 100;
fb->version = sizeof(*fb);
fb->width = vi.xres;
fb->height = vi.yres;
@@ -169,7 +176,7 @@ static void get_memory_surface(GGLSurface* ms) {
static void set_active_framebuffer(unsigned n)
{
if (n > 1 || !double_buffering) return;
vi.yres_virtual = vi.yres * PIXEL_SIZE;
vi.yres_virtual = vi.yres * NUM_BUFFERS;
vi.yoffset = n * vi.yres;
vi.bits_per_pixel = PIXEL_SIZE * 8;
if (ioctl(gr_fb_fd, FBIOPUT_VSCREENINFO, &vi) < 0) {
@@ -216,15 +223,20 @@ void gr_font_size(int *x, int *y)
*y = gr_font->cheight;
}
int gr_text(int x, int y, const char *s)
int gr_text(int x, int y, const char *s, int bold)
{
GGLContext *gl = gr_context;
GRFont *font = gr_font;
unsigned off;
y -= font->ascent;
if (!font->texture) return x;
gl->bindTexture(gl, &font->texture);
bold = bold && (font->texture->height != font->cheight);
x += overscan_offset_x;
y += overscan_offset_y;
gl->bindTexture(gl, font->texture);
gl->texEnvi(gl, GGL_TEXTURE_ENV, GGL_TEXTURE_ENV_MODE, GGL_REPLACE);
gl->texGeni(gl, GGL_S, GGL_TEXTURE_GEN_MODE, GGL_ONE_TO_ONE);
gl->texGeni(gl, GGL_T, GGL_TEXTURE_GEN_MODE, GGL_ONE_TO_ONE);
@@ -233,7 +245,8 @@ int gr_text(int x, int y, const char *s)
while((off = *s++)) {
off -= 32;
if (off < 96) {
gl->texCoord2i(gl, (off * font->cwidth) - x, 0 - y);
gl->texCoord2i(gl, (off * font->cwidth) - x,
(bold ? font->cheight : 0) - y);
gl->recti(gl, x, y, x + font->cwidth, y + font->cheight);
}
x += font->cwidth;
@@ -242,19 +255,50 @@ int gr_text(int x, int y, const char *s)
return x;
}
void gr_fill(int x, int y, int w, int h)
void gr_texticon(int x, int y, gr_surface icon) {
if (gr_context == NULL || icon == NULL) {
return;
}
GGLContext* gl = gr_context;
x += overscan_offset_x;
y += overscan_offset_y;
gl->bindTexture(gl, (GGLSurface*) icon);
gl->texEnvi(gl, GGL_TEXTURE_ENV, GGL_TEXTURE_ENV_MODE, GGL_REPLACE);
gl->texGeni(gl, GGL_S, GGL_TEXTURE_GEN_MODE, GGL_ONE_TO_ONE);
gl->texGeni(gl, GGL_T, GGL_TEXTURE_GEN_MODE, GGL_ONE_TO_ONE);
gl->enable(gl, GGL_TEXTURE_2D);
int w = gr_get_width(icon);
int h = gr_get_height(icon);
gl->texCoord2i(gl, -x, -y);
gl->recti(gl, x, y, x+gr_get_width(icon), y+gr_get_height(icon));
}
void gr_fill(int x1, int y1, int x2, int y2)
{
x1 += overscan_offset_x;
y1 += overscan_offset_y;
x2 += overscan_offset_x;
y2 += overscan_offset_y;
GGLContext *gl = gr_context;
gl->disable(gl, GGL_TEXTURE_2D);
gl->recti(gl, x, y, w, h);
gl->recti(gl, x1, y1, x2, y2);
}
void gr_blit(gr_surface source, int sx, int sy, int w, int h, int dx, int dy) {
if (gr_context == NULL) {
if (gr_context == NULL || source == NULL) {
return;
}
GGLContext *gl = gr_context;
dx += overscan_offset_x;
dy += overscan_offset_y;
gl->bindTexture(gl, (GGLSurface*) source);
gl->texEnvi(gl, GGL_TEXTURE_ENV, GGL_TEXTURE_ENV_MODE, GGL_REPLACE);
gl->texGeni(gl, GGL_S, GGL_TEXTURE_GEN_MODE, GGL_ONE_TO_ONE);
@@ -280,31 +324,40 @@ unsigned int gr_get_height(gr_surface surface) {
static void gr_init_font(void)
{
GGLSurface *ftex;
unsigned char *bits, *rle;
unsigned char *in, data;
gr_font = calloc(sizeof(*gr_font), 1);
ftex = &gr_font->texture;
bits = malloc(font.width * font.height);
int res = res_create_surface("font", (void**)&(gr_font->texture));
if (res == 0) {
// The font image should be a 96x2 array of character images. The
// columns are the printable ASCII characters 0x20 - 0x7f. The
// top row is regular text; the bottom row is bold.
gr_font->cwidth = gr_font->texture->width / 96;
gr_font->cheight = gr_font->texture->height / 2;
} else {
printf("failed to read font: res=%d\n", res);
ftex->version = sizeof(*ftex);
ftex->width = font.width;
ftex->height = font.height;
ftex->stride = font.width;
ftex->data = (void*) bits;
ftex->format = GGL_PIXEL_FORMAT_A_8;
// fall back to the compiled-in font.
gr_font->texture = malloc(sizeof(*gr_font->texture));
gr_font->texture->width = font.width;
gr_font->texture->height = font.height;
gr_font->texture->stride = font.width;
in = font.rundata;
while((data = *in++)) {
memset(bits, (data & 0x80) ? 255 : 0, data & 0x7f);
bits += (data & 0x7f);
unsigned char* bits = malloc(font.width * font.height);
gr_font->texture->data = (void*) bits;
unsigned char data;
unsigned char* in = font.rundata;
while((data = *in++)) {
memset(bits, (data & 0x80) ? 255 : 0, data & 0x7f);
bits += (data & 0x7f);
}
gr_font->cwidth = font.cwidth;
gr_font->cheight = font.cheight;
}
gr_font->cwidth = font.cwidth;
gr_font->cheight = font.cheight;
gr_font->ascent = font.cheight - 2;
// interpret the grayscale as alpha
gr_font->texture->format = GGL_PIXEL_FORMAT_A_8;
}
int gr_init(void)
@@ -364,12 +417,12 @@ void gr_exit(void)
int gr_fb_width(void)
{
return gr_framebuffer[0].width;
return gr_framebuffer[0].width - 2*overscan_offset_x;
}
int gr_fb_height(void)
{
return gr_framebuffer[0].height;
return gr_framebuffer[0].height - 2*overscan_offset_y;
}
gr_pixel *gr_fb_data(void)
+4 -2
View File
@@ -36,8 +36,9 @@ 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);
void gr_fill(int x1, int y1, int x2, int y2);
int gr_text(int x, int y, const char *s, int bold);
void gr_texticon(int x, int y, gr_surface icon);
int gr_measure(const char *s);
void gr_font_size(int *x, int *y);
@@ -71,6 +72,7 @@ void ev_dispatch(void);
// Returns 0 if no error, else negative.
int res_create_surface(const char* name, gr_surface* pSurface);
int res_create_localized_surface(const char* name, gr_surface* pSurface);
void res_free_surface(gr_surface surface);
#ifdef __cplusplus
+153 -10
View File
@@ -33,6 +33,8 @@
#include "minui.h"
extern char* locale;
// libpng gives "undefined reference to 'pow'" errors, and I have no
// idea how to convince the build system to link with -lm. We don't
// need this functionality (it's used for gamma adjustment) so provide
@@ -91,22 +93,25 @@ int res_create_surface(const char* name, gr_surface* pSurface) {
png_set_sig_bytes(png_ptr, sizeof(header));
png_read_info(png_ptr, info_ptr);
size_t width = info_ptr->width;
size_t height = info_ptr->height;
size_t stride = 4 * width;
size_t pixelSize = stride * height;
int color_type, bit_depth;
size_t width, height;
png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth,
&color_type, NULL, NULL, NULL);
int channels = png_get_channels(png_ptr, info_ptr);
int color_type = info_ptr->color_type;
int bit_depth = info_ptr->bit_depth;
int channels = info_ptr->channels;
if (!(bit_depth == 8 &&
((channels == 3 && color_type == PNG_COLOR_TYPE_RGB) ||
(channels == 4 && color_type == PNG_COLOR_TYPE_RGBA) ||
(channels == 1 && color_type == PNG_COLOR_TYPE_PALETTE)))) {
(channels == 1 && (color_type == PNG_COLOR_TYPE_PALETTE ||
color_type == PNG_COLOR_TYPE_GRAY))))) {
return -7;
goto exit;
}
size_t stride = (color_type == PNG_COLOR_TYPE_GRAY ? 1 : 4) * width;
size_t pixelSize = stride * height;
surface = malloc(sizeof(GGLSurface) + pixelSize);
if (surface == NULL) {
result = -8;
@@ -118,8 +123,8 @@ int res_create_surface(const char* name, gr_surface* pSurface) {
surface->height = height;
surface->stride = width; /* Yes, pixels, not bytes */
surface->data = pData;
surface->format = (channels == 3) ?
GGL_PIXEL_FORMAT_RGBX_8888 : GGL_PIXEL_FORMAT_RGBA_8888;
surface->format = (channels == 3) ? GGL_PIXEL_FORMAT_RGBX_8888 :
((color_type == PNG_COLOR_TYPE_PALETTE ? GGL_PIXEL_FORMAT_RGBA_8888 : GGL_PIXEL_FORMAT_L_8));
int alpha = 0;
if (color_type == PNG_COLOR_TYPE_PALETTE) {
@@ -129,6 +134,9 @@ int res_create_surface(const char* name, gr_surface* pSurface) {
png_set_tRNS_to_alpha(png_ptr);
alpha = 1;
}
if (color_type == PNG_COLOR_TYPE_GRAY) {
alpha = 1;
}
unsigned int y;
if (channels == 3 || (channels == 1 && !alpha)) {
@@ -173,6 +181,141 @@ exit:
return result;
}
static int matches_locale(const char* loc) {
if (locale == NULL) return 0;
if (strcmp(loc, locale) == 0) return 1;
// if loc does *not* have an underscore, and it matches the start
// of locale, and the next character in locale *is* an underscore,
// that's a match. For instance, loc == "en" matches locale ==
// "en_US".
int i;
for (i = 0; loc[i] != 0 && loc[i] != '_'; ++i);
if (loc[i] == '_') return 0;
return (strncmp(locale, loc, i) == 0 && locale[i] == '_');
}
int res_create_localized_surface(const char* name, gr_surface* pSurface) {
char resPath[256];
GGLSurface* surface = NULL;
int result = 0;
unsigned char header[8];
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");
if (fp == NULL) {
result = -1;
goto exit;
}
size_t bytesRead = fread(header, 1, sizeof(header), fp);
if (bytesRead != sizeof(header)) {
result = -2;
goto exit;
}
if (png_sig_cmp(header, 0, sizeof(header))) {
result = -3;
goto exit;
}
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (!png_ptr) {
result = -4;
goto exit;
}
info_ptr = png_create_info_struct(png_ptr);
if (!info_ptr) {
result = -5;
goto exit;
}
if (setjmp(png_jmpbuf(png_ptr))) {
result = -6;
goto exit;
}
png_init_io(png_ptr, fp);
png_set_sig_bytes(png_ptr, sizeof(header));
png_read_info(png_ptr, info_ptr);
int color_type, bit_depth;
size_t width, height;
png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth,
&color_type, NULL, NULL, NULL);
int channels = png_get_channels(png_ptr, info_ptr);
if (!(bit_depth == 8 &&
(channels == 1 && color_type == PNG_COLOR_TYPE_GRAY))) {
return -7;
goto exit;
}
unsigned char* row = malloc(width);
int y;
for (y = 0; y < height; ++y) {
png_read_row(png_ptr, row, NULL);
int w = (row[1] << 8) | row[0];
int h = (row[3] << 8) | row[2];
int len = row[4];
char* loc = row+5;
if (y+1+h >= height || matches_locale(loc)) {
printf(" %20s: %s (%d x %d @ %d)\n", name, loc, w, h, y);
surface = malloc(sizeof(GGLSurface));
if (surface == NULL) {
result = -8;
goto exit;
}
unsigned char* pData = malloc(w*h);
surface->version = sizeof(GGLSurface);
surface->width = w;
surface->height = h;
surface->stride = w; /* Yes, pixels, not bytes */
surface->data = pData;
surface->format = GGL_PIXEL_FORMAT_A_8;
int i;
for (i = 0; i < h; ++i, ++y) {
png_read_row(png_ptr, row, NULL);
memcpy(pData + i*w, row, w);
}
*pSurface = (gr_surface) surface;
break;
} else {
int i;
for (i = 0; i < h; ++i, ++y) {
png_read_row(png_ptr, row, NULL);
}
}
}
exit:
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
if (fp != NULL) {
fclose(fp);
}
if (result < 0) {
if (surface) {
free(surface);
}
}
return result;
}
void res_free_surface(gr_surface surface) {
GGLSurface* pSurface = (GGLSurface*) surface;
if (pSurface) {
+2 -6
View File
@@ -8,15 +8,11 @@ LOCAL_SRC_FILES := \
Inlines.c \
Zip.c
LOCAL_C_INCLUDES += \
LOCAL_C_INCLUDES := \
external/zlib \
external/safe-iop/include
ifeq ($(HAVE_SELINUX),true)
LOCAL_C_INCLUDES += external/libselinux/include
LOCAL_STATIC_LIBRARIES += libselinux
LOCAL_CFLAGS += -DHAVE_SELINUX
endif
LOCAL_STATIC_LIBRARIES := libselinux
LOCAL_MODULE := libminzip
-5
View File
@@ -145,24 +145,19 @@ dirCreateHierarchy(const char *path, int mode,
} else if (ds == DMISSING) {
int err;
#ifdef HAVE_SELINUX
char *secontext = NULL;
if (sehnd) {
selabel_lookup(sehnd, &secontext, cpath, mode);
setfscreatecon(secontext);
}
#endif
err = mkdir(cpath, mode);
#ifdef HAVE_SELINUX
if (secontext) {
freecon(secontext);
setfscreatecon(NULL);
}
#endif
if (err != 0) {
free(cpath);
-4
View File
@@ -24,12 +24,8 @@
extern "C" {
#endif
#ifdef HAVE_SELINUX
#include <selinux/selinux.h>
#include <selinux/label.h>
#else
struct selabel_handle;
#endif
/* Like "mkdir -p", try to guarantee that all directories
* specified in path are present, creating as many directories
+4 -4
View File
@@ -95,16 +95,16 @@ int sysLoadFileInShmem(int fd, MemMapping* pMap)
if (memPtr == NULL)
return -1;
actual = read(fd, memPtr, length);
pMap->baseAddr = pMap->addr = memPtr;
pMap->baseLength = pMap->length = length;
actual = TEMP_FAILURE_RETRY(read(fd, memPtr, length));
if (actual != length) {
LOGE("only read %d of %d bytes\n", (int) actual, (int) length);
sysReleaseShmem(pMap);
return -1;
}
pMap->baseAddr = pMap->addr = memPtr;
pMap->baseLength = pMap->length = length;
return 0;
}
+5 -5
View File
@@ -985,6 +985,7 @@ bool mzExtractRecursive(const ZipArchive *pArchive,
unsigned int i;
bool seenMatch = false;
int ok = true;
int extractCount = 0;
for (i = 0; i < pArchive->numEntries; i++) {
ZipEntry *pEntry = pArchive->pEntries + i;
if (pEntry->fileNameLen < zipDirLen) {
@@ -1115,23 +1116,19 @@ bool mzExtractRecursive(const ZipArchive *pArchive,
* Open the target for writing.
*/
#ifdef HAVE_SELINUX
char *secontext = NULL;
if (sehnd) {
selabel_lookup(sehnd, &secontext, targetFile, UNZIP_FILEMODE);
setfscreatecon(secontext);
}
#endif
int fd = creat(targetFile, UNZIP_FILEMODE);
#ifdef HAVE_SELINUX
if (secontext) {
freecon(secontext);
setfscreatecon(NULL);
}
#endif
if (fd < 0) {
LOGE("Can't create target file \"%s\": %s\n",
@@ -1154,13 +1151,16 @@ bool mzExtractRecursive(const ZipArchive *pArchive,
break;
}
LOGD("Extracted file \"%s\"\n", targetFile);
LOGV("Extracted file \"%s\"\n", targetFile);
++extractCount;
}
}
if (callback != NULL) callback(targetFile, cookie);
}
LOGD("Extracted %d file(s)\n", extractCount);
free(helper.buf);
free(zpath);
-4
View File
@@ -18,12 +18,8 @@
extern "C" {
#endif
#ifdef HAVE_SELINUX
#include <selinux/selinux.h>
#include <selinux/label.h>
#else
struct selabel_handle;
#endif
/*
* One entry in the Zip archive. Treat this as opaque -- use accessors below.
+2 -2
View File
@@ -50,8 +50,8 @@ LOCAL_MODULE_PATH := $(PRODUCT_OUT)/utilities
LOCAL_UNSTRIPPED_PATH := $(PRODUCT_OUT)/symbols/utilities
LOCAL_MODULE_STEM := bml_over_mtd
LOCAL_C_INCLUDES += bootable/recovery/mtdutils
LOCAL_STATIC_LIBRARIES := libmtdutils libcutils libc
LOCAL_FORCE_STATIC_EXECUTABLE := true
LOCAL_STATIC_LIBRARIES := libmtdutils
LOCAL_SHARED_LIBRARIES := libcutils liblog libc
include $(BUILD_EXECUTABLE)
endif
+135 -16
View File
@@ -15,11 +15,13 @@
*/
#include <ctype.h>
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <getopt.h>
#include <limits.h>
#include <linux/input.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -27,7 +29,6 @@
#include <sys/types.h>
#include <time.h>
#include <unistd.h>
#include <dirent.h>
#include "bootloader.h"
#include "common.h"
@@ -70,15 +71,17 @@ static const struct option OPTIONS[] = {
{ "wipe_cache", no_argument, NULL, 'c' },
{ "show_text", no_argument, NULL, 't' },
{ "just_exit", no_argument, NULL, 'x' },
{ "nandroid", no_argument, NULL, 'n' },
{ "locale", required_argument, NULL, 'l' },
{ NULL, 0, NULL, 0 },
};
#define LAST_LOG_FILE "/cache/recovery/last_log"
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 *LAST_INSTALL_FILE = "/cache/recovery/last_install";
static const char *LOCALE_FILE = "/cache/recovery/last_locale";
static const char *CACHE_ROOT = "/cache";
static const char *SDCARD_ROOT = "/sdcard";
static const char *TEMPORARY_LOG_FILE = "/tmp/recovery.log";
@@ -86,6 +89,7 @@ static const char *TEMPORARY_INSTALL_FILE = "/tmp/last_install";
static const char *SIDELOAD_TEMP_DIR = "/tmp/sideload";
RecoveryUI* ui = NULL;
char* locale = NULL;
/*
* The recovery tool communicates with the main system through /cache files.
@@ -212,6 +216,7 @@ get_args(int *argc, char ***argv) {
if (*argc <= 1) {
FILE *fp = fopen_path(COMMAND_FILE, "r");
if (fp != NULL) {
char *token;
char *argv0 = (*argv)[0];
*argv = (char **) malloc(sizeof(char *) * MAX_ARGS);
(*argv)[0] = argv0; // use the same program name
@@ -219,7 +224,12 @@ get_args(int *argc, char ***argv) {
char buf[MAX_ARG_LENGTH];
for (*argc = 1; *argc < MAX_ARGS; ++*argc) {
if (!fgets(buf, sizeof(buf), fp)) break;
(*argv)[*argc] = strdup(strtok(buf, "\r\n")); // Strip newline.
token = strtok(buf, "\r\n");
if (token != NULL) {
(*argv)[*argc] = strdup(token); // Strip newline.
} else {
--*argc;
}
}
check_and_fclose(fp, COMMAND_FILE);
@@ -273,6 +283,21 @@ copy_log_file(const char* source, const char* destination, int append) {
}
}
// Rename last_log -> last_log.1 -> last_log.2 -> ... -> last_log.$max
// Overwrites any existing last_log.$max.
static void
rotate_last_logs(int max) {
char oldfn[256];
char newfn[256];
int i;
for (i = max-1; i >= 0; --i) {
snprintf(oldfn, sizeof(oldfn), (i==0) ? LAST_LOG_FILE : (LAST_LOG_FILE ".%d"), i);
snprintf(newfn, sizeof(newfn), LAST_LOG_FILE ".%d", i+1);
// ignore errors
rename(oldfn, newfn);
}
}
// clear the recovery command and prepare to boot a (hopefully working) system,
// copy our log file to cache as well (for the system to read), and
@@ -291,6 +316,18 @@ finish_recovery(const char *send_intent) {
}
}
// Save the locale to cache, so if recovery is next started up
// without a --locale argument (eg, directly from the bootloader)
// it will use the last-known locale.
if (locale != NULL) {
LOGI("Saving locale \"%s\"\n", locale);
FILE* fp = fopen_path(LOCALE_FILE, "w");
fwrite(locale, 1, strlen(locale), fp);
fflush(fp);
fsync(fileno(fp));
check_and_fclose(fp, LOCALE_FILE);
}
// Copy logs to cache so the system can find out what happened.
copy_log_file(TEMPORARY_LOG_FILE, LOG_FILE, true);
copy_log_file(TEMPORARY_LOG_FILE, LAST_LOG_FILE, false);
@@ -317,8 +354,7 @@ finish_recovery(const char *send_intent) {
static int
erase_volume(const char *volume) {
return !PartitionManager.Wipe_By_Path(volume);
ui->SetBackground(RecoveryUI::INSTALLING);
ui->SetBackground(RecoveryUI::ERASING);
ui->SetProgressType(RecoveryUI::INDETERMINATE);
ui->Print("Formatting %s...\n", volume);
@@ -671,11 +707,22 @@ wipe_data(int confirm, Device* device) {
}
static void
prompt_and_wait(Device* device) {
prompt_and_wait(Device* device, int status) {
const char* const* headers = prepend_title(device->GetMenuHeaders());
for (;;) {
finish_recovery(NULL);
switch (status) {
case INSTALL_SUCCESS:
case INSTALL_NONE:
ui->SetBackground(RecoveryUI::NO_COMMAND);
break;
case INSTALL_ERROR:
case INSTALL_CORRUPT:
ui->SetBackground(RecoveryUI::ERROR);
break;
}
ui->SetProgressType(RecoveryUI::EMPTY);
int chosen_item = get_menu_selection(headers, device->GetMenuItems(), 0, 0, device);
@@ -685,7 +732,6 @@ prompt_and_wait(Device* device) {
// statement below.
chosen_item = device->InvokeMenuItem(chosen_item);
int status;
int wipe_cache;
switch (chosen_item) {
case Device::REBOOT:
@@ -775,6 +821,43 @@ print_property(const char *key, const char *name, void *cookie) {
printf("%s=%s\n", key, name);
}
static void
load_locale_from_cache() {
FILE* fp = fopen_path(LOCALE_FILE, "r");
char buffer[80];
if (fp != NULL) {
fgets(buffer, sizeof(buffer), fp);
int j = 0;
unsigned int i;
for (i = 0; i < sizeof(buffer) && buffer[i]; ++i) {
if (!isspace(buffer[i])) {
buffer[j++] = buffer[i];
}
}
buffer[j] = 0;
locale = strdup(buffer);
check_and_fclose(fp, LOCALE_FILE);
}
}
static RecoveryUI* gCurrentUI = NULL;
void
ui_print(const char* format, ...) {
char buffer[256];
va_list ap;
va_start(ap, format);
vsnprintf(buffer, sizeof(buffer), format, ap);
va_end(ap);
if (gCurrentUI != NULL) {
gCurrentUI->Print("%s", buffer);
} else {
fputs(buffer, stdout);
}
}
int
main(int argc, char **argv) {
// Recovery needs to install world-readable files, so clear umask
@@ -824,12 +907,17 @@ main(int argc, char **argv) {
gui_loadResources();
PartitionManager.Mount_By_Path("/cache", true);
load_volume_table();
ensure_path_mounted(LAST_LOG_FILE);
rotate_last_logs(5);
get_args(&argc, &argv);
int previous_runs = 0;
const char *send_intent = NULL;
const char *update_package = NULL;
int wipe_data = 0, wipe_cache = 0;
int wipe_data = 0, wipe_cache = 0, show_text = 0;
bool just_exit = false;
bool perform_backup = false;
@@ -841,16 +929,29 @@ main(int argc, char **argv) {
case 'u': update_package = optarg; break;
case 'w': wipe_data = wipe_cache = 1; break;
case 'c': wipe_cache = 1; break;
case 't': ui->ShowText(true); break;
case 't': show_text = 1; break;
case 'x': just_exit = true; break;
case 'n': perform_backup = true; LOGI("nandroid\n"); break;
case 'l': locale = optarg; break;
case '?':
LOGE("Invalid command argument\n");
continue;
}
}
#ifdef HAVE_SELINUX
if (locale == NULL) {
load_locale_from_cache();
}
printf("locale is [%s]\n", locale);
Device* device = make_device();
ui = device->GetUI();
gCurrentUI = ui;
ui->Init();
ui->SetLocale(locale);
ui->SetBackground(RecoveryUI::NONE);
if (show_text) ui->ShowText(true);
struct selinux_opt seopts[] = {
{ SELABEL_OPT_PATH, "/file_contexts" }
};
@@ -861,7 +962,6 @@ main(int argc, char **argv) {
fprintf(stderr, "Warning: No file_contexts\n");
ui->Print("Warning: No file_contexts\n");
}
#endif
//device->StartRecovery();
@@ -936,8 +1036,19 @@ main(int argc, char **argv) {
LOGE("Cache wipe (requested by package) failed.");
}
}
if (status != INSTALL_SUCCESS) ui->Print("Installation aborted.\n");
*/
if (status != INSTALL_SUCCESS) {
ui->Print("Installation aborted.\n");
// If this is an eng or userdebug build, then automatically
// turn the text display on if the script fails so the error
// message is visible.
char buffer[PROPERTY_VALUE_MAX+1];
property_get("ro.build.fingerprint", buffer, "");
if (strstr(buffer, ":userdebug/") || strstr(buffer, ":eng/")) {
ui->ShowText(true);
}
}
} else if (wipe_data) {
if (!OpenRecoveryScript::Insert_ORS_Command("wipe data\n"))
status = INSTALL_ERROR;
@@ -952,7 +1063,8 @@ main(int argc, char **argv) {
status = INSTALL_ERROR;
if (status != INSTALL_SUCCESS) ui->Print("Cache wipe failed.\n");
} else if (!just_exit) {
status = INSTALL_ERROR; // No command specified
status = INSTALL_NONE; // No command specified
ui->SetBackground(RecoveryUI::NO_COMMAND);
}
}
@@ -998,6 +1110,13 @@ main(int argc, char **argv) {
PartitionManager.UnMount_By_Path("/system", false);
}
if (status == INSTALL_ERROR || status == INSTALL_CORRUPT) {
ui->SetBackground(RecoveryUI::ERROR);
}
if (status != INSTALL_SUCCESS || ui->IsTextVisible()) {
prompt_and_wait(device, status);
}
// Otherwise, get ready to boot the main system...
finish_recovery(send_intent);
ui->Print("Rebooting...\n");
Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

+30 -118
View File
@@ -23,6 +23,7 @@
#include <ctype.h>
extern "C" {
#include <fs_mgr.h>
#include "mtdutils/mtdutils.h"
#include "mtdutils/mounts.h"
}
@@ -31,115 +32,41 @@ extern "C" {
#include "make_ext4fs.h"
#include "partitions.hpp"
static int num_volumes = 0;
static Volume* device_volumes = NULL;
static struct fstab *fstab = NULL;
extern struct selabel_handle *sehandle;
static int parse_options(char* options, Volume* volume) {
char* option;
while ((option = strtok(options, ","))) {
options = NULL;
void load_volume_table()
{
int i;
int ret;
if (strncmp(option, "flags=", 6) == 0) continue;
if (strncmp(option, "length=", 7) == 0) {
volume->length = strtoll(option+7, NULL, 10);
} else {
LOGE("bad option \"%s\"\n", option);
return -1;
}
}
return 0;
}
void load_volume_table() {
int alloc = 2;
device_volumes = (Volume*)malloc(alloc * sizeof(Volume));
// Insert an entry for /tmp, which is the ramdisk and is always mounted.
device_volumes[0].mount_point = "/tmp";
device_volumes[0].fs_type = "ramdisk";
device_volumes[0].device = NULL;
device_volumes[0].device2 = NULL;
device_volumes[0].length = 0;
num_volumes = 1;
FILE* fstab = fopen("/etc/recovery.fstab", "r");
if (fstab == NULL) {
LOGE("failed to open /etc/recovery.fstab (%s)\n", strerror(errno));
fstab = fs_mgr_read_fstab("/etc/recovery.fstab");
if (!fstab) {
LOGE("failed to read /etc/recovery.fstab\n");
return;
}
char buffer[1024];
int i;
while (fgets(buffer, sizeof(buffer)-1, fstab)) {
for (i = 0; buffer[i] && isspace(buffer[i]); ++i);
if (buffer[i] == '\0' || buffer[i] == '#') continue;
char* original = strdup(buffer);
char* mount_point = strtok(buffer+i, " \t\n");
char* fs_type = strtok(NULL, " \t\n");
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;
}
}
if (mount_point && fs_type && device) {
while (num_volumes >= alloc) {
alloc *= 2;
device_volumes = (Volume*)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].device = strdup(device);
device_volumes[num_volumes].device2 =
device2 ? strdup(device2) : NULL;
device_volumes[num_volumes].length = 0;
if (parse_options(options, device_volumes + num_volumes) != 0) {
LOGE("skipping malformed recovery.fstab line: %s\n", original);
} else {
++num_volumes;
}
} else {
LOGE("skipping malformed recovery.fstab line: %s\n", original);
}
free(original);
ret = fs_mgr_add_entry(fstab, "/tmp", "ramdisk", "ramdisk", 0);
if (ret < 0 ) {
LOGE("failed to add /tmp entry to fstab\n");
fs_mgr_free_fstab(fstab);
fstab = NULL;
return;
}
fclose(fstab);
printf("recovery filesystem table\n");
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);
for (i = 0; i < fstab->num_entries; ++i) {
Volume* v = &fstab->recs[i];
printf(" %d %s %s %s %lld\n", i, v->mount_point, v->fs_type,
v->blk_device, v->length);
}
printf("\n");
}
Volume* volume_for_path(const char* path) {
int i;
for (i = 0; i < num_volumes; ++i) {
Volume* v = device_volumes+i;
int len = strlen(v->mount_point);
if (strncmp(path, v->mount_point, len) == 0 &&
(path[len] == '\0' || path[len] == '/')) {
return v;
}
}
return NULL;
return fs_mgr_get_entry_for_mount_point(fstab, path);
}
int ensure_path_mounted(const char* path) {
@@ -177,27 +104,19 @@ int ensure_path_mounted(const char* path) {
// mount an MTD partition as a YAFFS2 filesystem.
mtd_scan_partitions();
const MtdPartition* partition;
partition = mtd_find_partition_by_name(v->device);
partition = mtd_find_partition_by_name(v->blk_device);
if (partition == NULL) {
LOGE("failed to find \"%s\" partition to mount at \"%s\"\n",
v->device, v->mount_point);
v->blk_device, v->mount_point);
return -1;
}
return mtd_mount_partition(partition, v->mount_point, v->fs_type, 0);
} else if (strcmp(v->fs_type, "ext4") == 0 ||
strcmp(v->fs_type, "vfat") == 0) {
result = mount(v->device, v->mount_point, v->fs_type,
result = mount(v->blk_device, v->mount_point, v->fs_type,
MS_NOATIME | MS_NODEV | MS_NODIRATIME, "");
if (result == 0) return 0;
if (v->device2) {
LOGW("failed to mount %s (%s); trying %s\n",
v->device, strerror(errno), v->device2);
result = mount(v->device2, v->mount_point, v->fs_type,
MS_NOATIME | MS_NODEV | MS_NODIRATIME, "");
if (result == 0) return 0;
}
LOGE("failed to mount %s (%s)\n", v->mount_point, strerror(errno));
return -1;
}
@@ -265,38 +184,31 @@ int format_volume(const char* volume) {
if (strcmp(v->fs_type, "yaffs2") == 0 || strcmp(v->fs_type, "mtd") == 0) {
mtd_scan_partitions();
const MtdPartition* partition = mtd_find_partition_by_name(v->device);
const MtdPartition* partition = mtd_find_partition_by_name(v->blk_device);
if (partition == NULL) {
LOGE("format_volume: no MTD partition \"%s\"\n", v->device);
LOGE("format_volume: no MTD partition \"%s\"\n", v->blk_device);
return -1;
}
MtdWriteContext *write = mtd_write_partition(partition);
if (write == NULL) {
LOGW("format_volume: can't open MTD \"%s\"\n", v->device);
LOGW("format_volume: can't open MTD \"%s\"\n", v->blk_device);
return -1;
} else if (mtd_erase_blocks(write, -1) == (off_t) -1) {
LOGW("format_volume: can't erase MTD \"%s\"\n", v->device);
LOGW("format_volume: can't erase MTD \"%s\"\n", v->blk_device);
mtd_write_close(write);
return -1;
} else if (mtd_write_close(write)) {
LOGW("format_volume: can't close MTD \"%s\"\n", v->device);
LOGW("format_volume: can't close MTD \"%s\"\n", v->blk_device);
return -1;
}
return 0;
}
if (strcmp(v->fs_type, "ext4") == 0) {
#ifdef USE_EXT4
/*
int result = make_ext4fs(v->device, v->length, volume, sehandle);
*/
int result = 0;
#else
int result = 0;
#endif
int result = make_ext4fs(v->blk_device, v->length, volume, sehandle);
if (result != 0) {
LOGE("format_volume: make_extf4fs failed on %s\n", v->device);
LOGE("format_volume: make_extf4fs failed on %s\n", v->blk_device);
return -1;
}
return 0;
+138 -43
View File
@@ -40,8 +40,8 @@ int twgr_text(int x, int y, const char *s);
}
#include "data.hpp"
#define CHAR_WIDTH 10
#define CHAR_HEIGHT 18
static int char_width;
static int char_height;
// There's only (at most) one of these objects, and global callbacks
// (for pthread_create, and the input event system) need to find it,
@@ -58,6 +58,7 @@ static double now() {
ScreenRecoveryUI::ScreenRecoveryUI() :
currentIcon(NONE),
installingFrame(0),
rtl_locale(false),
progressBarType(EMPTY),
progressScopeStart(0),
progressScopeSize(0),
@@ -84,7 +85,13 @@ ScreenRecoveryUI::ScreenRecoveryUI() :
indeterminate_frames(6),
installing_frames(7),
install_overlay_offset_x(13),
install_overlay_offset_y(190) {
install_overlay_offset_y(190),
overlay_offset_x(-1),
overlay_offset_y(-1) {
for (int i = 0; i < 5; i++)
backgroundIcon[i] = NULL;
pthread_mutex_init(&updateMutex, NULL);
self = this;
}
@@ -95,12 +102,12 @@ ScreenRecoveryUI::ScreenRecoveryUI() :
// animation. Does nothing if no overlay animation is defined.
// Should only be called with updateMutex locked.
void ScreenRecoveryUI::draw_install_overlay_locked(int frame) {
if (installationOverlay == NULL) return;
if (installationOverlay == NULL || overlay_offset_x < 0) return;
gr_surface surface = installationOverlay[frame];
int iconWidth = gr_get_width(surface);
int iconHeight = gr_get_height(surface);
gr_blit(surface, 0, 0, iconWidth, iconHeight,
install_overlay_offset_x, install_overlay_offset_y);
overlay_offset_x, overlay_offset_y);
}
// Clear the screen and draw the currently selected background icon (if any).
@@ -113,14 +120,26 @@ void ScreenRecoveryUI::draw_background_locked(Icon icon)
if (icon) {
gr_surface surface = backgroundIcon[icon];
gr_surface text_surface = backgroundText[icon];
int iconWidth = gr_get_width(surface);
int iconHeight = gr_get_height(surface);
int textWidth = gr_get_width(text_surface);
int textHeight = gr_get_height(text_surface);
int iconX = (gr_fb_width() - iconWidth) / 2;
int iconY = (gr_fb_height() - iconHeight) / 2;
int iconY = (gr_fb_height() - (iconHeight+textHeight+40)) / 2;
int textX = (gr_fb_width() - textWidth) / 2;
int textY = ((gr_fb_height() - (iconHeight+textHeight+40)) / 2) + iconHeight + 40;
gr_blit(surface, 0, 0, iconWidth, iconHeight, iconX, iconY);
if (icon == INSTALLING) {
if (icon == INSTALLING_UPDATE || icon == ERASING) {
draw_install_overlay_locked(installingFrame);
}
gr_color(255, 255, 255, 255);
gr_texticon(textX, textY, text_surface);
}
}
@@ -130,12 +149,12 @@ void ScreenRecoveryUI::draw_progress_locked()
{
if (currentIcon == ERROR) return;
if (currentIcon == INSTALLING) {
if (currentIcon == INSTALLING_UPDATE || currentIcon == ERASING) {
draw_install_overlay_locked(installingFrame);
}
if (progressBarType != EMPTY) {
int iconHeight = gr_get_height(backgroundIcon[INSTALLING]);
int iconHeight = gr_get_height(backgroundIcon[INSTALLING_UPDATE]);
int width = gr_get_width(progressBarEmpty);
int height = gr_get_height(progressBarEmpty);
@@ -150,27 +169,42 @@ void ScreenRecoveryUI::draw_progress_locked()
float p = progressScopeStart + progress * progressScopeSize;
int pos = (int) (p * width);
if (pos > 0) {
gr_blit(progressBarFill, 0, 0, pos, height, dx, dy);
}
if (pos < width-1) {
gr_blit(progressBarEmpty, pos, 0, width-pos, height, dx+pos, dy);
if (rtl_locale) {
// Fill the progress bar from right to left.
if (pos > 0) {
gr_blit(progressBarFill, width-pos, 0, pos, height, dx+width-pos, dy);
}
if (pos < width-1) {
gr_blit(progressBarEmpty, 0, 0, width-pos, height, dx, dy);
}
} else {
// Fill the progress bar from left to right.
if (pos > 0) {
gr_blit(progressBarFill, 0, 0, pos, height, dx, dy);
}
if (pos < width-1) {
gr_blit(progressBarEmpty, pos, 0, width-pos, height, dx+pos, dy);
}
}
}
if (progressBarType == INDETERMINATE) {
static int frame = 0;
gr_blit(progressBarIndeterminate[frame], 0, 0, width, height, dx, dy);
frame = (frame + 1) % indeterminate_frames;
// in RTL locales, we run the animation backwards, which
// makes the spinner spin the other way.
if (rtl_locale) {
frame = (frame + indeterminate_frames - 1) % indeterminate_frames;
} else {
frame = (frame + 1) % indeterminate_frames;
}
}
}
}
void ScreenRecoveryUI::draw_text_line(int row, const char* t) {
if (t[0] != '\0') {
twgr_text(0, (row+1)*CHAR_HEIGHT-1, t);
}
}
#define C_HEADER 247,0,6
#define C_MENU 0,106,157
#define C_LOG 249,194,0
// Redraw everything on the screen. Does not flip pages.
// Should only be called with updateMutex locked.
@@ -183,30 +217,46 @@ void ScreenRecoveryUI::draw_screen_locked()
gr_color(0, 0, 0, 160);
gr_fill(0, 0, gr_fb_width(), gr_fb_height());
int y = 0;
int i = 0;
if (show_menu) {
gr_color(64, 96, 255, 255);
gr_fill(0, (menu_top+menu_sel) * CHAR_HEIGHT,
gr_fb_width(), (menu_top+menu_sel+1)*CHAR_HEIGHT+1);
gr_color(C_HEADER, 255);
for (; i < menu_top + menu_items; ++i) {
if (i == menu_top) gr_color(C_MENU, 255);
if (i == menu_top + menu_sel) {
// draw the highlight bar
gr_fill(0, y-2, gr_fb_width(), y+char_height+2);
// white text of selected item
gr_color(255, 255, 255, 255);
draw_text_line(i, menu[i]);
gr_color(64, 96, 255, 255);
if (menu[i][0]) gr_text(4, y, menu[i], 1);
gr_color(C_MENU, 255);
} else {
draw_text_line(i, menu[i]);
if (menu[i][0]) gr_text(4, y, menu[i], i < menu_top);
}
y += char_height+4;
}
gr_fill(0, i*CHAR_HEIGHT+CHAR_HEIGHT/2-1,
gr_fb_width(), i*CHAR_HEIGHT+CHAR_HEIGHT/2+1);
gr_color(C_MENU, 255);
y += 4;
gr_fill(0, y, gr_fb_width(), y+2);
y += 4;
++i;
}
gr_color(255, 255, 0, 255);
gr_color(C_LOG, 255);
for (; i < text_rows; ++i) {
draw_text_line(i, text[(i+text_top) % text_rows]);
// display from the bottom up, until we hit the top of the
// screen, the bottom of the menu, or we've displayed the
// entire text buffer.
int ty;
int row = (text_top+text_rows-1) % text_rows;
for (int ty = gr_fb_height() - char_height, count = 0;
ty > y+2 && count < text_rows;
ty -= char_height, ++count) {
gr_text(4, ty, text[row], 0);
--row;
if (row < 0) row = text_rows-1;
}
}
}
@@ -248,7 +298,8 @@ void ScreenRecoveryUI::progress_loop() {
// update the installation animation, if active
// skip this if we have a text overlay (too expensive to update)
if (currentIcon == INSTALLING && installing_frames > 0 && !show_text) {
if ((currentIcon == INSTALLING_UPDATE || currentIcon == ERASING) &&
installing_frames > 0 && !show_text) {
installingFrame = (installingFrame + 1) % installing_frames;
redraw = 1;
}
@@ -289,23 +340,40 @@ void ScreenRecoveryUI::LoadBitmap(const char* filename, gr_surface* surface) {
}
}
void ScreenRecoveryUI::LoadLocalizedBitmap(const char* filename, gr_surface* surface) {
int result = res_create_localized_surface(filename, surface);
if (result < 0) {
LOGE("missing bitmap %s\n(Code %d)\n", filename, result);
}
}
void ScreenRecoveryUI::Init()
{
gr_init();
gr_font_size(&char_width, &char_height);
text_col = text_row = 0;
text_rows = gr_fb_height() / CHAR_HEIGHT;
text_rows = gr_fb_height() / char_height;
if (text_rows > kMaxRows) text_rows = kMaxRows;
text_top = 1;
text_cols = gr_fb_width() / CHAR_WIDTH;
text_cols = gr_fb_width() / char_width;
if (text_cols > kMaxCols - 1) text_cols = kMaxCols - 1;
LoadBitmap("icon_installing", &backgroundIcon[INSTALLING]);
LoadBitmap("icon_installing", &backgroundIcon[INSTALLING_UPDATE]);
backgroundIcon[ERASING] = backgroundIcon[INSTALLING_UPDATE];
LoadBitmap("icon_error", &backgroundIcon[ERROR]);
backgroundIcon[NO_COMMAND] = backgroundIcon[ERROR];
LoadBitmap("progress_empty", &progressBarEmpty);
LoadBitmap("progress_fill", &progressBarFill);
LoadLocalizedBitmap("installing_text", &backgroundText[INSTALLING_UPDATE]);
LoadLocalizedBitmap("erasing_text", &backgroundText[ERASING]);
LoadLocalizedBitmap("no_command_text", &backgroundText[NO_COMMAND]);
LoadLocalizedBitmap("error_text", &backgroundText[ERROR]);
int i;
progressBarIndeterminate = (gr_surface*)malloc(indeterminate_frames *
@@ -327,14 +395,6 @@ void ScreenRecoveryUI::Init()
sprintf(filename, "icon_installing_overlay%02d", i+1);
LoadBitmap(filename, installationOverlay+i);
}
// Adjust the offset to account for the positioning of the
// base image on the screen.
if (backgroundIcon[INSTALLING] != NULL) {
gr_surface bg = backgroundIcon[INSTALLING];
install_overlay_offset_x += (gr_fb_width() - gr_get_width(bg)) / 2;
install_overlay_offset_y += (gr_fb_height() - gr_get_height(bg)) / 2;
}
} else {
installationOverlay = NULL;
}
@@ -344,11 +404,46 @@ void ScreenRecoveryUI::Init()
RecoveryUI::Init();
}
void ScreenRecoveryUI::SetLocale(const char* locale) {
if (locale) {
char* lang = strdup(locale);
for (char* p = lang; *p; ++p) {
if (*p == '_') {
*p = '\0';
break;
}
}
// A bit cheesy: keep an explicit list of supported languages
// that are RTL.
if (strcmp(lang, "ar") == 0 || // Arabic
strcmp(lang, "fa") == 0 || // Persian (Farsi)
strcmp(lang, "he") == 0 || // Hebrew (new language code)
strcmp(lang, "iw") == 0 || // Hebrew (old language code)
strcmp(lang, "ur") == 0) { // Urdu
rtl_locale = true;
}
free(lang);
}
}
void ScreenRecoveryUI::SetBackground(Icon icon)
{
pthread_mutex_lock(&updateMutex);
// Adjust the offset to account for the positioning of the
// base image on the screen.
if (backgroundIcon[icon] != NULL) {
gr_surface bg = backgroundIcon[icon];
gr_surface text = backgroundText[icon];
overlay_offset_x = install_overlay_offset_x + (gr_fb_width() - gr_get_width(bg)) / 2;
overlay_offset_y = install_overlay_offset_y +
(gr_fb_height() - (gr_get_height(bg) + gr_get_height(text) + 40)) / 2;
}
currentIcon = icon;
update_screen_locked();
pthread_mutex_unlock(&updateMutex);
}
+7 -4
View File
@@ -29,6 +29,7 @@ class ScreenRecoveryUI : public RecoveryUI {
ScreenRecoveryUI();
void Init();
void SetLocale(const char* locale);
// overall recovery state ("background image")
void SetBackground(Icon icon);
@@ -55,9 +56,11 @@ class ScreenRecoveryUI : public RecoveryUI {
private:
Icon currentIcon;
int installingFrame;
bool rtl_locale;
pthread_mutex_t updateMutex;
gr_surface backgroundIcon[3];
gr_surface backgroundIcon[5];
gr_surface backgroundText[5];
gr_surface *installationOverlay;
gr_surface *progressBarIndeterminate;
gr_surface progressBarEmpty;
@@ -73,7 +76,7 @@ class ScreenRecoveryUI : public RecoveryUI {
bool pagesIdentical;
static const int kMaxCols = 96;
static const int kMaxRows = 32;
static const int kMaxRows = 96;
// Log text overlay, displayed when a magic key is pressed
char text[kMaxRows][kMaxCols];
@@ -92,11 +95,11 @@ class ScreenRecoveryUI : public RecoveryUI {
int indeterminate_frames;
int installing_frames;
int install_overlay_offset_x, install_overlay_offset_y;
int overlay_offset_x, overlay_offset_y;
void draw_install_overlay_locked(int frame);
void draw_background_locked(Icon icon);
void draw_progress_locked();
void draw_text_line(int row, const char* t);
void draw_screen_locked();
void update_screen_locked();
void update_progress_locked();
@@ -104,7 +107,7 @@ class ScreenRecoveryUI : public RecoveryUI {
void progress_loop();
void LoadBitmap(const char* filename, gr_surface* surface);
void LoadLocalizedBitmap(const char* filename, gr_surface* surface);
};
#endif // RECOVERY_UI_H
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
+25
View File
@@ -0,0 +1,25 @@
-----BEGIN CERTIFICATE-----
MIIENjCCAx6gAwIBAgIJAKhkCO1dDYMaMA0GCSqGSIb3DQEBBQUAMG8xCzAJBgNV
BAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1Nb3VudGFpbiBW
aWV3MQ8wDQYDVQQKEwZHb29nbGUxEDAOBgNVBAsTB0FuZHJvaWQxEDAOBgNVBAMT
B1Rlc3QxMjMwHhcNMTIwNzI1MTg1NzAzWhcNMzkxMjExMTg1NzAzWjBvMQswCQYD
VQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNTW91bnRhaW4g
VmlldzEPMA0GA1UEChMGR29vZ2xlMRAwDgYDVQQLEwdBbmRyb2lkMRAwDgYDVQQD
EwdUZXN0MTIzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAu8WwMN9x
4Mz7YgkG2qy9g8/kl5ZoYrUM0ApHhaITAcL7RXLZaNipCf0w/YjYTQgj+75MK30x
TsnPeWNOEwA62gkHrZyyWfxBRO6kBYuIuI4roGDBJOmKQ1OEaDeIRKu7q5V8v3Cs
0wQDAQWTbhpxBZr9UYFgJUg8XWBfPrGJLVwsoiy4xrMhoTlNZKHfwOMMqVtSHkZX
qydYrcIzyjh+TO0e/xSNQ8MMRRbtqWgCHN6Rzhog3IHZu0RaPoukariopjXM/s0V
gTm3rHDHCOpna2pNblyiFlvbkoCs769mtNmx/yrDShO30jg/xaG8RypKDvTChzOT
oWW/XQ5VEXjbHwIDAQABo4HUMIHRMB0GA1UdDgQWBBRlT2dEZJY1tmUM8mZ0xnhS
GdD9TTCBoQYDVR0jBIGZMIGWgBRlT2dEZJY1tmUM8mZ0xnhSGdD9TaFzpHEwbzEL
MAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDU1vdW50
YWluIFZpZXcxDzANBgNVBAoTBkdvb2dsZTEQMA4GA1UECxMHQW5kcm9pZDEQMA4G
A1UEAxMHVGVzdDEyM4IJAKhkCO1dDYMaMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcN
AQEFBQADggEBAHqnXHtE+h3hvGmHh24GT51vGAYLc68WUUtCVlMIU85zQ757wlxZ
BmRypZ1i9hSqnXj5n+mETV5rFX3g2gvdAPVHkRycuDa2aUdZSE8cW4Z6qYFx6SaD
e+3SyXokpUquW64RuHJrf/yd/FnGjneBe3Qpm2reuzGWNH90qZGdbsfNaCm5kx2L
X+ZNHM3CcGMLaphY5++sM0JxSEcju5EK33ZYgLf4YdlbyMp8LDFVNd7ff0SFi9fF
0ZlAsJWoS3QmVCj2744BFdsCu7UHpnYpG6X3MT4SHAawdOaT5zSuaCl2xx6H0O7t
w/Fvbl/KVD1ZmLHgBKjDMNSh0OB9mSsDWpw=
-----END CERTIFICATE-----
+12
View File
@@ -120,6 +120,18 @@ int main(int argc, char **argv) {
bool Cache_Wipe = false, Factory_Reset = false, Perform_Backup = false;
{
TWPartition* misc = PartitionManager.Find_Partition_By_Path("/misc");
if (misc != NULL) {
if (misc->Current_File_System == "emmc") {
set_device_type('e');
set_device_name(misc->Actual_Block_Device.c_str());
} else if (misc->Current_File_System == "mtd") {
set_device_type('m');
set_device_name(misc->MTD_Name.c_str());
} else {
LOGERR("Unknown file system for /misc\n");
}
}
get_args(&argc, &argv);
int index, index2, len;
+28 -9
View File
@@ -47,7 +47,8 @@ static RecoveryUI* self = NULL;
RecoveryUI::RecoveryUI() :
key_queue_len(0),
key_last_down(-1) {
key_last_down(-1),
key_down_time(0) {
pthread_mutex_init(&key_queue_mutex, NULL);
pthread_cond_init(&key_queue_cond, NULL);
self = this;
@@ -111,19 +112,29 @@ int RecoveryUI::input_callback(int fd, short revents, void* data)
// updown == 1 for key down events; 0 for key up events
void RecoveryUI::process_key(int key_code, int updown) {
bool register_key = false;
bool long_press = false;
const long long_threshold = CLOCKS_PER_SEC * 750 / 1000;
pthread_mutex_lock(&key_queue_mutex);
key_pressed[key_code] = updown;
if (updown) {
key_last_down = key_code;
key_down_time = clock();
} else {
if (key_last_down == key_code)
if (key_last_down == key_code) {
long duration = clock() - key_down_time;
if (duration > long_threshold) {
long_press = true;
}
register_key = true;
}
key_last_down = -1;
}
pthread_mutex_unlock(&key_queue_mutex);
if (register_key) {
NextCheckKeyIsLong(long_press);
switch (CheckKey(key_code)) {
case RecoveryUI::IGNORE:
break;
@@ -139,18 +150,23 @@ void RecoveryUI::process_key(int key_code, int updown) {
break;
case RecoveryUI::ENQUEUE:
pthread_mutex_lock(&key_queue_mutex);
const int queue_max = sizeof(key_queue) / sizeof(key_queue[0]);
if (key_queue_len < queue_max) {
key_queue[key_queue_len++] = key_code;
pthread_cond_signal(&key_queue_cond);
}
pthread_mutex_unlock(&key_queue_mutex);
EnqueueKey(key_code);
break;
}
}
}
void RecoveryUI::EnqueueKey(int key_code) {
pthread_mutex_lock(&key_queue_mutex);
const int queue_max = sizeof(key_queue) / sizeof(key_queue[0]);
if (key_queue_len < queue_max) {
key_queue[key_queue_len++] = key_code;
pthread_cond_signal(&key_queue_cond);
}
pthread_mutex_unlock(&key_queue_mutex);
}
// Reads input events, handles special hot keys, and adds to the key queue.
void* RecoveryUI::input_thread(void *cookie)
{
@@ -227,3 +243,6 @@ void RecoveryUI::FlushKeys() {
RecoveryUI::KeyAction RecoveryUI::CheckKey(int key) {
return RecoveryUI::ENQUEUE;
}
void RecoveryUI::NextCheckKeyIsLong(bool is_long_press) {
}
+11 -1
View File
@@ -19,6 +19,7 @@
#include <linux/input.h>
#include <pthread.h>
#include <time.h>
// Abstract class for controlling the user interface during recovery.
class RecoveryUI {
@@ -30,8 +31,11 @@ class RecoveryUI {
// Initialize the object; called before anything else.
virtual void Init();
// After calling Init(), you can tell the UI what locale it is operating in.
virtual void SetLocale(const char* locale) { }
// Set the overall recovery state ("background image").
enum Icon { NONE, INSTALLING, ERROR };
enum Icon { NONE, INSTALLING_UPDATE, ERASING, NO_COMMAND, ERROR };
virtual void SetBackground(Icon icon) = 0;
// --- progress indicator ---
@@ -76,6 +80,8 @@ class RecoveryUI {
enum KeyAction { ENQUEUE, TOGGLE, REBOOT, IGNORE };
virtual KeyAction CheckKey(int key);
virtual void NextCheckKeyIsLong(bool is_long_press);
// --- menu display ---
// Display some header text followed by a menu of items, which appears
@@ -92,6 +98,9 @@ class RecoveryUI {
// statements will be displayed.
virtual void EndMenu() = 0;
protected:
void EnqueueKey(int key_code);
private:
// Key event input queue
pthread_mutex_t key_queue_mutex;
@@ -99,6 +108,7 @@ private:
int key_queue[256], key_queue_len;
char key_pressed[KEY_MAX + 1]; // under key_queue_mutex
int key_last_down; // under key_queue_mutex
clock_t key_down_time; // under key_queue_mutex
int rel_sum;
pthread_t input_t;
+2 -7
View File
@@ -32,18 +32,13 @@ LOCAL_STATIC_LIBRARIES = \
endif
endif
ifeq ($(HAVE_SELINUX), true)
LOCAL_C_INCLUDES += external/libselinux/include
LOCAL_STATIC_LIBRARIES += libselinux
LOCAL_CFLAGS += -DHAVE_SELINUX
endif # HAVE_SELINUX
LOCAL_STATIC_LIBRARIES += $(TARGET_RECOVERY_UPDATER_LIBS) $(TARGET_RECOVERY_UPDATER_EXTRA_LIBS)
LOCAL_STATIC_LIBRARIES += libapplypatch libedify libmtdutils libminzip libz
LOCAL_STATIC_LIBRARIES += libflashutils libmmcutils libbmlutils
LOCAL_STATIC_LIBRARIES += libmincrypt libbz
LOCAL_STATIC_LIBRARIES += libminelf
LOCAL_STATIC_LIBRARIES += libcutils libstdc++ libc
LOCAL_STATIC_LIBRARIES += libcutils liblog libstdc++ libc
LOCAL_STATIC_LIBRARIES += libselinux
LOCAL_C_INCLUDES += $(LOCAL_PATH)/..
# Each library in TARGET_RECOVERY_UPDATER_LIBS should have a function
+30 -8
View File
@@ -78,23 +78,19 @@ Value* MountFn(const char* name, State* state, int argc, Expr* argv[]) {
goto done;
}
#ifdef HAVE_SELINUX
char *secontext = NULL;
if (sehandle) {
selabel_lookup(sehandle, &secontext, mount_point, 0755);
setfscreatecon(secontext);
}
#endif
mkdir(mount_point, 0755);
#ifdef HAVE_SELINUX
if (secontext) {
freecon(secontext);
setfscreatecon(NULL);
}
#endif
if (strcmp(partition_type, "MTD") == 0) {
mtd_scan_partitions();
@@ -456,6 +452,26 @@ Value* PackageExtractFileFn(const char* name, State* state,
}
}
// Create all parent directories of name, if necessary.
static int make_parents(char* name) {
char* p;
for (p = name + (strlen(name)-1); p > name; --p) {
if (*p != '/') continue;
*p = '\0';
if (make_parents(name) < 0) return -1;
int result = mkdir(name, 0700);
if (result == 0) fprintf(stderr, "symlink(): created [%s]\n", name);
*p = '/';
if (result == 0 || errno == EEXIST) {
// successfully created or already existed; we're done
return 0;
} else {
fprintf(stderr, "failed to mkdir %s: %s\n", name, strerror(errno));
return -1;
}
}
return 0;
}
// symlink target src1 src2 ...
// unlinks any previously existing src1, src2, etc before creating symlinks.
@@ -483,6 +499,11 @@ Value* SymlinkFn(const char* name, State* state, int argc, Expr* argv[]) {
++bad;
}
}
if (make_parents(srcs[i])) {
fprintf(stderr, "%s: failed to symlink %s to %s: making parents failed\n",
name, srcs[i], target);
++bad;
}
if (symlink(target, srcs[i]) < 0) {
fprintf(stderr, "%s: failed to symlink %s to %s: %s\n",
name, srcs[i], target, strerror(errno));
@@ -504,7 +525,8 @@ Value* SetPermFn(const char* name, State* state, int argc, Expr* argv[]) {
int min_args = 4 + (recursive ? 1 : 0);
if (argc < min_args) {
return ErrorAbort(state, "%s() expects %d+ args, got %d", name, argc);
return ErrorAbort(state, "%s() expects %d+ args, got %d",
name, min_args, argc);
}
char** args = ReadVarArgs(state, argc, argv);
@@ -626,7 +648,7 @@ Value* FileGetPropFn(const char* name, State* state, int argc, Expr* argv[]) {
buffer = malloc(st.st_size+1);
if (buffer == NULL) {
ErrorAbort(state, "%s: failed to alloc %d bytes", name, st.st_size+1);
ErrorAbort(state, "%s: failed to alloc %lld bytes", name, st.st_size+1);
goto done;
}
@@ -638,7 +660,7 @@ Value* FileGetPropFn(const char* name, State* state, int argc, Expr* argv[]) {
}
if (fread(buffer, 1, st.st_size, f) != st.st_size) {
ErrorAbort(state, "%s: failed to read %d bytes from %s",
ErrorAbort(state, "%s: failed to read %lld bytes from %s",
name, st.st_size+1, filename);
fclose(f);
goto done;
@@ -823,7 +845,7 @@ Value* ApplyPatchFn(const char* name, State* state, int argc, Expr* argv[]) {
int result = applypatch(source_filename, target_filename,
target_sha1, target_size,
patchcount, patch_sha_str, patches);
patchcount, patch_sha_str, patches, NULL);
for (i = 0; i < patchcount; ++i) {
FreeValue(patches[i]);
-2
View File
@@ -105,7 +105,6 @@ int main(int argc, char** argv) {
return 6;
}
#ifdef HAVE_SELINUX
struct selinux_opt seopts[] = {
{ SELABEL_OPT_PATH, "/file_contexts" }
};
@@ -116,7 +115,6 @@ int main(int argc, char** argv) {
fprintf(stderr, "Warning: No file_contexts\n");
fprintf(cmd_pipe, "ui_print Warning: No file_contexts\n");
}
#endif
// Evaluate the parsed script.
-4
View File
@@ -20,12 +20,8 @@
#include <stdio.h>
#include "minzip/Zip.h"
#ifdef HAVE_SELINUX
#include <selinux/selinux.h>
#include <selinux/label.h>
#else
struct selabel_handle;
#endif
typedef struct {
FILE* cmd_pipe;
+109 -77
View File
@@ -29,82 +29,6 @@
#define PUBLIC_KEYS_FILE "/res/keys"
// Reads a file containing one or more public keys as produced by
// DumpPublicKey: this is an RSAPublicKey struct as it would appear
// as a C source literal, eg:
//
// "{64,0xc926ad21,{1795090719,...,-695002876},{-857949815,...,1175080310}}"
//
// (Note that the braces and commas in this example are actual
// characters the parser expects to find in the file; the ellipses
// indicate more numbers omitted from this example.)
//
// The file may contain multiple keys in this format, separated by
// commas. The last key must not be followed by a comma.
//
// Returns NULL if the file failed to parse, or if it contain zero keys.
static RSAPublicKey*
load_keys(const char* filename, int* numKeys) {
RSAPublicKey* out = NULL;
*numKeys = 0;
FILE* f = fopen(filename, "r");
if (f == NULL) {
printf("opening %s: %s\n", filename, strerror(errno));
goto exit;
}
{
int i;
bool done = false;
while (!done) {
++*numKeys;
out = (RSAPublicKey*)realloc(out, *numKeys * sizeof(RSAPublicKey));
RSAPublicKey* key = out + (*numKeys - 1);
if (fscanf(f, " { %i , 0x%x , { %u",
&(key->len), &(key->n0inv), &(key->n[0])) != 3) {
goto exit;
}
if (key->len != RSANUMWORDS) {
printf("key length (%d) does not match expected size\n", key->len);
goto exit;
}
for (i = 1; i < key->len; ++i) {
if (fscanf(f, " , %u", &(key->n[i])) != 1) goto exit;
}
if (fscanf(f, " } , { %u", &(key->rr[0])) != 1) goto exit;
for (i = 1; i < key->len; ++i) {
if (fscanf(f, " , %u", &(key->rr[i])) != 1) goto exit;
}
fscanf(f, " } } ");
// if the line ends in a comma, this file has more keys.
switch (fgetc(f)) {
case ',':
// more keys to come.
break;
case EOF:
done = true;
break;
default:
printf("unexpected character between keys\n");
goto exit;
}
}
}
fclose(f);
return out;
exit:
if (f) fclose(f);
free(out);
*numKeys = 0;
return NULL;
}
// Look for an RSA signature embedded in the .ZIP file comment given
// the path to the zip. Verify it matches one of the given public
// keys.
@@ -120,6 +44,7 @@ int verify_file(const char* path) {
LOGE("Failed to load keys\n");
return VERIFY_FAILURE;
}
/*
LOGI("%d key(s) loaded from %s\n\n RSA Key:\n\n", numKeys, PUBLIC_KEYS_FILE);
int rsa_size = sizeof(RSAPublicKey);
unsigned char* ptr = (unsigned char*) loadedKeys;
@@ -129,7 +54,7 @@ int verify_file(const char* path) {
printf("%02x ", valuedees);
ptr++;
}
printf("\n\n");
printf("\n\n");*/
FILE* f = fopen(path, "rb");
if (f == NULL) {
@@ -274,6 +199,8 @@ int verify_file(const char* path) {
LOGI("whole-file signature verified against key %d\n", i);
free(eocd);
return VERIFY_SUCCESS;
} else {
LOGI("failed to verify against key %d\n", i);
}
LOGI("i: %i, eocd_size: %i, RSANUMBYTES: %i, returned %i\n", i, eocd_size, RSANUMBYTES, dees);
}
@@ -281,3 +208,108 @@ int verify_file(const char* path) {
LOGE("failed to verify whole-file signature\n");
return VERIFY_FAILURE;
}
// Reads a file containing one or more public keys as produced by
// DumpPublicKey: this is an RSAPublicKey struct as it would appear
// as a C source literal, eg:
//
// "{64,0xc926ad21,{1795090719,...,-695002876},{-857949815,...,1175080310}}"
//
// For key versions newer than the original 2048-bit e=3 keys
// supported by Android, the string is preceded by a version
// identifier, eg:
//
// "v2 {64,0xc926ad21,{1795090719,...,-695002876},{-857949815,...,1175080310}}"
//
// (Note that the braces and commas in this example are actual
// characters the parser expects to find in the file; the ellipses
// indicate more numbers omitted from this example.)
//
// The file may contain multiple keys in this format, separated by
// commas. The last key must not be followed by a comma.
//
// Returns NULL if the file failed to parse, or if it contain zero keys.
RSAPublicKey*
load_keys(const char* filename, int* numKeys) {
RSAPublicKey* out = NULL;
*numKeys = 0;
FILE* f = fopen(filename, "r");
if (f == NULL) {
LOGE("opening %s: %s\n", filename, strerror(errno));
goto exit;
}
{
int i;
bool done = false;
while (!done) {
++*numKeys;
out = (RSAPublicKey*)realloc(out, *numKeys * sizeof(RSAPublicKey));
RSAPublicKey* key = out + (*numKeys - 1);
#ifdef HAS_EXPONENT
char start_char;
if (fscanf(f, " %c", &start_char) != 1) goto exit;
if (start_char == '{') {
// a version 1 key has no version specifier.
key->exponent = 3;
} else if (start_char == 'v') {
int version;
if (fscanf(f, "%d {", &version) != 1) goto exit;
if (version == 2) {
key->exponent = 65537;
} else {
goto exit;
}
}
if (fscanf(f, " %i , 0x%x , { %u",
#else
if (fscanf(f, " { %i , 0x%x , { %u",
#endif
&(key->len), &(key->n0inv), &(key->n[0])) != 3) {
goto exit;
}
if (key->len != RSANUMWORDS) {
LOGE("key length (%d) does not match expected size\n", key->len);
goto exit;
}
for (i = 1; i < key->len; ++i) {
if (fscanf(f, " , %u", &(key->n[i])) != 1) goto exit;
}
if (fscanf(f, " } , { %u", &(key->rr[0])) != 1) goto exit;
for (i = 1; i < key->len; ++i) {
if (fscanf(f, " , %u", &(key->rr[i])) != 1) goto exit;
}
fscanf(f, " } } ");
// if the line ends in a comma, this file has more keys.
switch (fgetc(f)) {
case ',':
// more keys to come.
break;
case EOF:
done = true;
break;
default:
LOGE("unexpected character between keys\n");
goto exit;
}
#ifdef HAS_EXPONENT
LOGI("read key e=%d\n", key->exponent);
#endif
}
}
fclose(f);
return out;
exit:
if (f) fclose(f);
free(out);
*numKeys = 0;
return NULL;
}
+2
View File
@@ -30,6 +30,8 @@ static const float VERIFICATION_PROGRESS_FRACTION = 0.25;
*/
int verify_file(const char* path);
RSAPublicKey* load_keys(const char* filename, int* numKeys);
#define VERIFY_SUCCESS 0
#define VERIFY_FAILURE 1
+64 -8
View File
@@ -18,6 +18,7 @@
#include <stdlib.h>
#include <stdarg.h>
#include "common.h"
#include "verifier.h"
#include "ui.h"
@@ -56,7 +57,45 @@ RSAPublicKey test_key =
9135381, 1625809335, -1490225159, -1342673351,
1117190829, -57654514, 1825108855, -1281819325,
1111251351, -1726129724, 1684324211, -1773988491,
367251975, 810756730, -1941182952, 1175080310 }
367251975, 810756730, -1941182952, 1175080310 },
3
};
RSAPublicKey test_f4_key =
{ 64, 0xc9bd1f21,
{ 293133087u, 3210546773u, 865313125u, 250921607u,
3158780490u, 943703457u, 1242806226u, 2986289859u,
2942743769u, 2457906415u, 2719374299u, 1783459420u,
149579627u, 3081531591u, 3440738617u, 2788543742u,
2758457512u, 1146764939u, 3699497403u, 2446203424u,
1744968926u, 1159130537u, 2370028300u, 3978231572u,
3392699980u, 1487782451u, 1180150567u, 2841334302u,
3753960204u, 961373345u, 3333628321u, 748825784u,
2978557276u, 1566596926u, 1613056060u, 2600292737u,
1847226629u, 50398611u, 1890374404u, 2878700735u,
2286201787u, 1401186359u, 619285059u, 731930817u,
2340993166u, 1156490245u, 2992241729u, 151498140u,
318782170u, 3480838990u, 2100383433u, 4223552555u,
3628927011u, 4247846280u, 1759029513u, 4215632601u,
2719154626u, 3490334597u, 1751299340u, 3487864726u,
3668753795u, 4217506054u, 3748782284u, 3150295088u },
{ 1772626313u, 445326068u, 3477676155u, 1758201194u,
2986784722u, 491035581u, 3922936562u, 702212696u,
2979856666u, 3324974564u, 2488428922u, 3056318590u,
1626954946u, 664714029u, 398585816u, 3964097931u,
3356701905u, 2298377729u, 2040082097u, 3025491477u,
539143308u, 3348777868u, 2995302452u, 3602465520u,
212480763u, 2691021393u, 1307177300u, 704008044u,
2031136606u, 1054106474u, 3838318865u, 2441343869u,
1477566916u, 700949900u, 2534790355u, 3353533667u,
336163563u, 4106790558u, 2701448228u, 1571536379u,
1103842411u, 3623110423u, 1635278839u, 1577828979u,
910322800u, 715583630u, 138128831u, 1017877531u,
2289162787u, 447994798u, 1897243165u, 4121561445u,
4150719842u, 2131821093u, 2262395396u, 3305771534u,
980753571u, 3256525190u, 3128121808u, 1072869975u,
3507939515u, 4229109952u, 118381341u, 2209831334u },
65537
};
RecoveryUI* ui = NULL;
@@ -75,13 +114,10 @@ class FakeUI : public RecoveryUI {
bool IsTextVisible() { return false; }
bool WasTextEverVisible() { return false; }
void Print(const char* fmt, ...) {
char buf[256];
va_list ap;
va_start(ap, fmt);
vsnprintf(buf, 256, fmt, ap);
vfprintf(stderr, fmt, ap);
va_end(ap);
fputs(buf, stderr);
}
void StartMenu(const char* const * headers, const char* const * items,
@@ -90,15 +126,35 @@ class FakeUI : public RecoveryUI {
void EndMenu() { }
};
void
ui_print(const char* format, ...) {
va_list ap;
va_start(ap, format);
vfprintf(stdout, format, ap);
va_end(ap);
}
int main(int argc, char **argv) {
if (argc != 2) {
fprintf(stderr, "Usage: %s <package>\n", argv[0]);
if (argc < 2 || argc > 4) {
fprintf(stderr, "Usage: %s [-f4 | -file <keys>] <package>\n", argv[0]);
return 2;
}
RSAPublicKey* key = &test_key;
int num_keys = 1;
++argv;
if (strcmp(argv[0], "-f4") == 0) {
++argv;
key = &test_f4_key;
} else if (strcmp(argv[0], "-file") == 0) {
++argv;
key = load_keys(argv[0], &num_keys);
++argv;
}
ui = new FakeUI();
int result = verify_file(argv[1]);
int result = verify_file(*argv, key, num_keys);
if (result == VERIFY_SUCCESS) {
printf("SUCCESS\n");
return 0;
+15
View File
@@ -73,9 +73,24 @@ expect_fail() {
run_command $WORK_DIR/verifier_test $WORK_DIR/package.zip && fail
}
expect_succeed_f4() {
testname "$1 (should succeed)"
$ADB push $DATA_DIR/$1 $WORK_DIR/package.zip
run_command $WORK_DIR/verifier_test -f4 $WORK_DIR/package.zip || fail
}
expect_fail_f4() {
testname "$1 (should fail)"
$ADB push $DATA_DIR/$1 $WORK_DIR/package.zip
run_command $WORK_DIR/verifier_test -f4 $WORK_DIR/package.zip && fail
}
expect_fail unsigned.zip
expect_fail jarsigned.zip
expect_succeed otasigned.zip
expect_fail_f4 otasigned.zip
expect_succeed_f4 otasigned_f4.zip
expect_fail otasigned_f4.zip
expect_fail random.zip
expect_fail fake-eocd.zip
expect_fail alter-metadata.zip