Merge branch 'gingerbread' of git://github.com/CyanogenMod/android_bootable_recovery into gingerbread
This commit is contained in:
commit
3681b91861
@ -19,20 +19,25 @@ LOCAL_SRC_FILES := \
|
||||
extendedcommands.c \
|
||||
nandroid.c \
|
||||
../../system/core/toolbox/reboot.c \
|
||||
firmware.c \
|
||||
edifyscripting.c \
|
||||
setprop.c
|
||||
|
||||
ADDITIONAL_RECOVERY_FILES := $(shell echo $$ADDITIONAL_RECOVERY_FILES)
|
||||
LOCAL_SRC_FILES += $(ADDITIONAL_RECOVERY_FILES)
|
||||
|
||||
LOCAL_MODULE := recovery
|
||||
|
||||
LOCAL_FORCE_STATIC_EXECUTABLE := true
|
||||
|
||||
ifdef I_AM_KOUSH
|
||||
RECOVERY_NAME := ClockworkMod Recovery
|
||||
LOCAL_CFLAGS += -DI_AM_KOUSH
|
||||
else
|
||||
RECOVERY_NAME := CWM-based Recovery
|
||||
endif
|
||||
|
||||
RECOVERY_VERSION := $(RECOVERY_NAME) v4.0.1.5
|
||||
RECOVERY_VERSION := $(RECOVERY_NAME) v5.0.2.3
|
||||
|
||||
LOCAL_CFLAGS += -DRECOVERY_VERSION="$(RECOVERY_VERSION)"
|
||||
RECOVERY_API_VERSION := 2
|
||||
|
150
bootloader.c
150
bootloader.c
@ -179,3 +179,153 @@ static int set_bootloader_message_block(const struct bootloader_message *in,
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Update Image
|
||||
*
|
||||
* - will be stored in the "cache" partition
|
||||
* - bad blocks will be ignored, like boot.img and recovery.img
|
||||
* - the first block will be the image header (described below)
|
||||
* - the size is in BYTES, inclusive of the header
|
||||
* - offsets are in BYTES from the start of the update header
|
||||
* - two raw bitmaps will be included, the "busy" and "fail" bitmaps
|
||||
* - for dream, the bitmaps will be 320x480x16bpp RGB565
|
||||
*/
|
||||
|
||||
#define UPDATE_MAGIC "MSM-RADIO-UPDATE"
|
||||
#define UPDATE_MAGIC_SIZE 16
|
||||
#define UPDATE_VERSION 0x00010000
|
||||
|
||||
struct update_header {
|
||||
unsigned char MAGIC[UPDATE_MAGIC_SIZE];
|
||||
|
||||
unsigned version;
|
||||
unsigned size;
|
||||
|
||||
unsigned image_offset;
|
||||
unsigned image_length;
|
||||
|
||||
unsigned bitmap_width;
|
||||
unsigned bitmap_height;
|
||||
unsigned bitmap_bpp;
|
||||
|
||||
unsigned busy_bitmap_offset;
|
||||
unsigned busy_bitmap_length;
|
||||
|
||||
unsigned fail_bitmap_offset;
|
||||
unsigned fail_bitmap_length;
|
||||
};
|
||||
|
||||
int write_update_for_bootloader(
|
||||
const char *update, int update_length,
|
||||
int bitmap_width, int bitmap_height, int bitmap_bpp,
|
||||
const char *busy_bitmap, const char *fail_bitmap) {
|
||||
if (ensure_path_unmounted("/cache")) {
|
||||
LOGE("Can't unmount /cache\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
const MtdPartition *part = mtd_find_partition_by_name("cache");
|
||||
if (part == NULL) {
|
||||
LOGE("Can't find cache\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
MtdWriteContext *write = mtd_write_partition(part);
|
||||
if (write == NULL) {
|
||||
LOGE("Can't open cache\n(%s)\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Write an invalid (zero) header first, to disable any previous
|
||||
* update and any other structured contents (like a filesystem),
|
||||
* and as a placeholder for the amount of space required.
|
||||
*/
|
||||
|
||||
struct update_header header;
|
||||
memset(&header, 0, sizeof(header));
|
||||
const ssize_t header_size = sizeof(header);
|
||||
if (mtd_write_data(write, (char*) &header, header_size) != header_size) {
|
||||
LOGE("Can't write header to cache\n(%s)\n", strerror(errno));
|
||||
mtd_write_close(write);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Write each section individually block-aligned, so we can write
|
||||
* each block independently without complicated buffering.
|
||||
*/
|
||||
|
||||
memcpy(&header.MAGIC, UPDATE_MAGIC, UPDATE_MAGIC_SIZE);
|
||||
header.version = UPDATE_VERSION;
|
||||
header.size = header_size;
|
||||
|
||||
off_t image_start_pos = mtd_erase_blocks(write, 0);
|
||||
header.image_length = update_length;
|
||||
if ((int) header.image_offset == -1 ||
|
||||
mtd_write_data(write, update, update_length) != update_length) {
|
||||
LOGE("Can't write update to cache\n(%s)\n", strerror(errno));
|
||||
mtd_write_close(write);
|
||||
return -1;
|
||||
}
|
||||
off_t busy_start_pos = mtd_erase_blocks(write, 0);
|
||||
header.image_offset = mtd_find_write_start(write, image_start_pos);
|
||||
|
||||
header.bitmap_width = bitmap_width;
|
||||
header.bitmap_height = bitmap_height;
|
||||
header.bitmap_bpp = bitmap_bpp;
|
||||
|
||||
int bitmap_length = (bitmap_bpp + 7) / 8 * bitmap_width * bitmap_height;
|
||||
|
||||
header.busy_bitmap_length = busy_bitmap != NULL ? bitmap_length : 0;
|
||||
if ((int) header.busy_bitmap_offset == -1 ||
|
||||
mtd_write_data(write, busy_bitmap, bitmap_length) != bitmap_length) {
|
||||
LOGE("Can't write bitmap to cache\n(%s)\n", strerror(errno));
|
||||
mtd_write_close(write);
|
||||
return -1;
|
||||
}
|
||||
off_t fail_start_pos = mtd_erase_blocks(write, 0);
|
||||
header.busy_bitmap_offset = mtd_find_write_start(write, busy_start_pos);
|
||||
|
||||
header.fail_bitmap_length = fail_bitmap != NULL ? bitmap_length : 0;
|
||||
if ((int) header.fail_bitmap_offset == -1 ||
|
||||
mtd_write_data(write, fail_bitmap, bitmap_length) != bitmap_length) {
|
||||
LOGE("Can't write bitmap to cache\n(%s)\n", strerror(errno));
|
||||
mtd_write_close(write);
|
||||
return -1;
|
||||
}
|
||||
mtd_erase_blocks(write, 0);
|
||||
header.fail_bitmap_offset = mtd_find_write_start(write, fail_start_pos);
|
||||
|
||||
/* Write the header last, after all the blocks it refers to, so that
|
||||
* when the magic number is installed everything is valid.
|
||||
*/
|
||||
|
||||
if (mtd_write_close(write)) {
|
||||
LOGE("Can't finish writing cache\n(%s)\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
write = mtd_write_partition(part);
|
||||
if (write == NULL) {
|
||||
LOGE("Can't reopen cache\n(%s)\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (mtd_write_data(write, (char*) &header, header_size) != header_size) {
|
||||
LOGE("Can't rewrite header to cache\n(%s)\n", strerror(errno));
|
||||
mtd_write_close(write);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (mtd_erase_blocks(write, 0) != image_start_pos) {
|
||||
LOGE("Misalignment rewriting cache\n(%s)\n", strerror(errno));
|
||||
mtd_write_close(write);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (mtd_write_close(write)) {
|
||||
LOGE("Can't finish header of cache\n(%s)\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
@ -233,7 +233,24 @@ Value* InstallZipFn(const char* name, State* state, int argc, Expr* argv[]) {
|
||||
return StringValue(strdup(path));
|
||||
}
|
||||
|
||||
Value* MountFn(const char* name, State* state, int argc, Expr* argv[]) {
|
||||
char* result = NULL;
|
||||
if (argc != 1) {
|
||||
return ErrorAbort(state, "%s() expects 1 args, got %d", name, argc);
|
||||
}
|
||||
char* path;
|
||||
if (ReadArgs(state, argv, 1, &path) < 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (0 != ensure_path_mounted(path))
|
||||
return StringValue(strdup(""));
|
||||
|
||||
return StringValue(strdup(path));
|
||||
}
|
||||
|
||||
void RegisterRecoveryHooks() {
|
||||
RegisterFunction("mount", MountFn);
|
||||
RegisterFunction("format", FormatFn);
|
||||
RegisterFunction("ui_print", UIPrintFn);
|
||||
RegisterFunction("run_program", RunProgramFn);
|
||||
|
@ -40,6 +40,7 @@
|
||||
#include "flashutils/flashutils.h"
|
||||
#include "edify/expr.h"
|
||||
#include <libgen.h>
|
||||
#include "mtdutils/mtdutils.h"
|
||||
|
||||
|
||||
int signature_check_enabled = 1;
|
||||
@ -81,11 +82,13 @@ char* INSTALL_MENU_ITEMS[] = { "choose zip from sdcard",
|
||||
"apply /sdcard/update.zip",
|
||||
"toggle signature verification",
|
||||
"toggle script asserts",
|
||||
"choose zip from internal sdcard",
|
||||
NULL };
|
||||
#define ITEM_CHOOSE_ZIP 0
|
||||
#define ITEM_APPLY_SDCARD 1
|
||||
#define ITEM_SIG_CHECK 2
|
||||
#define ITEM_ASSERTS 3
|
||||
#define ITEM_CHOOSE_ZIP_INT 4
|
||||
|
||||
void show_install_update_menu()
|
||||
{
|
||||
@ -93,6 +96,10 @@ void show_install_update_menu()
|
||||
"",
|
||||
NULL
|
||||
};
|
||||
|
||||
if (volume_for_path("/emmc") == NULL)
|
||||
INSTALL_MENU_ITEMS[ITEM_CHOOSE_ZIP_INT] = NULL;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
int chosen_item = get_menu_selection(headers, INSTALL_MENU_ITEMS, 0, 0);
|
||||
@ -111,7 +118,10 @@ void show_install_update_menu()
|
||||
break;
|
||||
}
|
||||
case ITEM_CHOOSE_ZIP:
|
||||
show_choose_zip_menu();
|
||||
show_choose_zip_menu("/sdcard/");
|
||||
break;
|
||||
case ITEM_CHOOSE_ZIP_INT:
|
||||
show_choose_zip_menu("/emmc/");
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
@ -301,10 +311,10 @@ char* choose_file_menu(const char* directory, const char* fileExtensionOrDirecto
|
||||
return return_value;
|
||||
}
|
||||
|
||||
void show_choose_zip_menu()
|
||||
void show_choose_zip_menu(const char *mount_point)
|
||||
{
|
||||
if (ensure_path_mounted("/sdcard") != 0) {
|
||||
LOGE ("Can't mount /sdcard\n");
|
||||
if (ensure_path_mounted(mount_point) != 0) {
|
||||
LOGE ("Can't mount %s\n", mount_point);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -313,7 +323,7 @@ void show_choose_zip_menu()
|
||||
NULL
|
||||
};
|
||||
|
||||
char* file = choose_file_menu("/sdcard/", ".zip", headers);
|
||||
char* file = choose_file_menu(mount_point, ".zip", headers);
|
||||
if (file == NULL)
|
||||
return;
|
||||
static char* confirm_install = "Confirm install?";
|
||||
@ -410,6 +420,70 @@ int confirm_selection(const char* title, const char* confirm)
|
||||
#define TUNE2FS_BIN "/sbin/tune2fs"
|
||||
#define E2FSCK_BIN "/sbin/e2fsck"
|
||||
|
||||
int format_device(const char *device, const char *path, const char *fs_type) {
|
||||
Volume* v = volume_for_path(path);
|
||||
if (v == NULL) {
|
||||
// no /sdcard? let's assume /data/media
|
||||
if (strstr(path, "/sdcard") == path && is_data_media()) {
|
||||
return format_unknown_device(NULL, path, NULL);
|
||||
}
|
||||
// silent failure for sd-ext
|
||||
if (strcmp(path, "/sd-ext") == 0)
|
||||
return -1;
|
||||
LOGE("unknown volume \"%s\"\n", path);
|
||||
return -1;
|
||||
}
|
||||
if (strcmp(fs_type, "ramdisk") == 0) {
|
||||
// you can't format the ramdisk.
|
||||
LOGE("can't format_volume \"%s\"", path);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (strcmp(v->mount_point, path) != 0) {
|
||||
return format_unknown_device(v->device, path, NULL);
|
||||
}
|
||||
|
||||
if (ensure_path_unmounted(path) != 0) {
|
||||
LOGE("format_volume failed to unmount \"%s\"\n", v->mount_point);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (strcmp(fs_type, "yaffs2") == 0 || strcmp(fs_type, "mtd") == 0) {
|
||||
mtd_scan_partitions();
|
||||
const MtdPartition* partition = mtd_find_partition_by_name(device);
|
||||
if (partition == NULL) {
|
||||
LOGE("format_volume: no MTD partition \"%s\"\n", device);
|
||||
return -1;
|
||||
}
|
||||
|
||||
MtdWriteContext *write = mtd_write_partition(partition);
|
||||
if (write == NULL) {
|
||||
LOGW("format_volume: can't open MTD \"%s\"\n", device);
|
||||
return -1;
|
||||
} else if (mtd_erase_blocks(write, -1) == (off_t) -1) {
|
||||
LOGW("format_volume: can't erase MTD \"%s\"\n", device);
|
||||
mtd_write_close(write);
|
||||
return -1;
|
||||
} else if (mtd_write_close(write)) {
|
||||
LOGW("format_volume: can't close MTD \"%s\"\n",device);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (strcmp(fs_type, "ext4") == 0) {
|
||||
reset_ext4fs_info();
|
||||
int result = make_ext4fs(device, NULL, NULL, 0, 0, 0);
|
||||
if (result != 0) {
|
||||
LOGE("format_volume: make_extf4fs failed on %s\n", device);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
return format_unknown_device(device, path, fs_type);
|
||||
}
|
||||
|
||||
int format_unknown_device(const char *device, const char* path, const char *fs_type)
|
||||
{
|
||||
LOGI("Formatting unknown device.\n");
|
||||
@ -729,7 +803,32 @@ int run_and_remove_extendedcommand()
|
||||
ui_print("Timed out waiting for SD card... continuing anyways.");
|
||||
}
|
||||
|
||||
ui_print("Verifying SD Card marker...\n");
|
||||
struct stat st;
|
||||
if (stat("/sdcard/clockworkmod/.salted_hash", &st) != 0) {
|
||||
ui_print("SD Card marker not found...\n");
|
||||
if (volume_for_path("/emmc") != NULL) {
|
||||
ui_print("Checking Internal SD Card marker...\n");
|
||||
ensure_path_unmounted("/sdcard");
|
||||
if (ensure_path_mounted_at_mount_point("/emmc", "/sdcard") != 0) {
|
||||
ui_print("Internal SD Card marker not found... continuing anyways.\n");
|
||||
// unmount everything, and remount as normal
|
||||
ensure_path_unmounted("/emmc");
|
||||
ensure_path_unmounted("/sdcard");
|
||||
|
||||
ensure_path_mounted("/sdcard");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sprintf(tmp, "/tmp/%s", basename(EXTENDEDCOMMAND_SCRIPT));
|
||||
int ret;
|
||||
#ifdef I_AM_KOUSH
|
||||
if (0 != (ret = before_run_script(tmp))) {
|
||||
ui_print("Error processing ROM Manager script. Please verify that you are performing the backup, restore, or ROM installation from ROM Manager v4.4.0.0 or higher.\n");
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
return run_script(tmp);
|
||||
}
|
||||
|
||||
@ -901,9 +1000,9 @@ void show_advanced_menu()
|
||||
__system("rm -r /data/dalvik-cache");
|
||||
__system("rm -r /cache/dalvik-cache");
|
||||
__system("rm -r /sd-ext/dalvik-cache");
|
||||
ui_print("Dalvik Cache wiped.\n");
|
||||
}
|
||||
ensure_path_unmounted("/data");
|
||||
ui_print("Dalvik Cache wiped.\n");
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
|
131
firmware.c
Normal file
131
firmware.c
Normal file
@ -0,0 +1,131 @@
|
||||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "bootloader.h"
|
||||
#include "common.h"
|
||||
#include "firmware.h"
|
||||
#include "roots.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <sys/reboot.h>
|
||||
|
||||
static const char *update_type = NULL;
|
||||
static const char *update_data = NULL;
|
||||
static int update_length = 0;
|
||||
|
||||
int remember_firmware_update(const char *type, const char *data, int length) {
|
||||
if (update_type != NULL || update_data != NULL) {
|
||||
LOGE("Multiple firmware images\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
update_type = type;
|
||||
update_data = data;
|
||||
update_length = length;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Return true if there is a firmware update pending.
|
||||
int firmware_update_pending() {
|
||||
return update_data != NULL && update_length > 0;
|
||||
}
|
||||
|
||||
/* Bootloader / Recovery Flow
|
||||
*
|
||||
* On every boot, the bootloader will read the bootloader_message
|
||||
* from flash and check the command field. The bootloader should
|
||||
* deal with the command field not having a 0 terminator correctly
|
||||
* (so as to not crash if the block is invalid or corrupt).
|
||||
*
|
||||
* The bootloader will have to publish the partition that contains
|
||||
* the bootloader_message to the linux kernel so it can update it.
|
||||
*
|
||||
* if command == "boot-recovery" -> boot recovery.img
|
||||
* else if command == "update-radio" -> update radio image (below)
|
||||
* else if command == "update-hboot" -> update hboot image (below)
|
||||
* else -> boot boot.img (normal boot)
|
||||
*
|
||||
* Radio/Hboot Update Flow
|
||||
* 1. the bootloader will attempt to load and validate the header
|
||||
* 2. if the header is invalid, status="invalid-update", goto #8
|
||||
* 3. display the busy image on-screen
|
||||
* 4. if the update image is invalid, status="invalid-radio-image", goto #8
|
||||
* 5. attempt to update the firmware (depending on the command)
|
||||
* 6. if successful, status="okay", goto #8
|
||||
* 7. if failed, and the old image can still boot, status="failed-update"
|
||||
* 8. write the bootloader_message, leaving the recovery field
|
||||
* unchanged, updating status, and setting command to
|
||||
* "boot-recovery"
|
||||
* 9. reboot
|
||||
*
|
||||
* The bootloader will not modify or erase the cache partition.
|
||||
* It is recovery's responsibility to clean up the mess afterwards.
|
||||
*/
|
||||
|
||||
int maybe_install_firmware_update(const char *send_intent) {
|
||||
if (update_data == NULL || update_length == 0) return 0;
|
||||
|
||||
/* We destroy the cache partition to pass the update image to the
|
||||
* bootloader, so all we can really do afterwards is wipe cache and reboot.
|
||||
* Set up this instruction now, in case we're interrupted while writing.
|
||||
*/
|
||||
|
||||
struct bootloader_message boot;
|
||||
memset(&boot, 0, sizeof(boot));
|
||||
strlcpy(boot.command, "boot-recovery", sizeof(boot.command));
|
||||
strlcpy(boot.recovery, "recovery\n--wipe_cache\n", sizeof(boot.command));
|
||||
if (send_intent != NULL) {
|
||||
strlcat(boot.recovery, "--send_intent=", sizeof(boot.recovery));
|
||||
strlcat(boot.recovery, send_intent, sizeof(boot.recovery));
|
||||
strlcat(boot.recovery, "\n", sizeof(boot.recovery));
|
||||
}
|
||||
if (set_bootloader_message(&boot)) return -1;
|
||||
|
||||
int width = 0, height = 0, bpp = 0;
|
||||
char *busy_image = ui_copy_image(
|
||||
BACKGROUND_ICON_FIRMWARE_INSTALLING, &width, &height, &bpp);
|
||||
char *fail_image = ui_copy_image(
|
||||
BACKGROUND_ICON_FIRMWARE_ERROR, &width, &height, &bpp);
|
||||
|
||||
ui_print("Writing %s image...\n", update_type);
|
||||
if (write_update_for_bootloader(
|
||||
update_data, update_length,
|
||||
width, height, bpp, busy_image, fail_image)) {
|
||||
LOGE("Can't write %s image\n(%s)\n", update_type, strerror(errno));
|
||||
format_volume("/cache"); // Attempt to clean cache up, at least.
|
||||
return -1;
|
||||
}
|
||||
|
||||
free(busy_image);
|
||||
free(fail_image);
|
||||
|
||||
/* The update image is fully written, so now we can instruct the bootloader
|
||||
* to install it. (After doing so, it will come back here, and we will
|
||||
* wipe the cache and reboot into the system.)
|
||||
*/
|
||||
snprintf(boot.command, sizeof(boot.command), "update-%s", update_type);
|
||||
if (set_bootloader_message(&boot)) {
|
||||
format_volume("/cache");
|
||||
return -1;
|
||||
}
|
||||
|
||||
reboot(RB_AUTOBOOT);
|
||||
|
||||
// Can't reboot? WTF?
|
||||
LOGE("Can't reboot\n");
|
||||
return -1;
|
||||
}
|
@ -92,6 +92,12 @@ handle_firmware_update(char* type, char* filename, ZipArchive* zip) {
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
if (remember_firmware_update(type, data, data_size)) {
|
||||
LOGE("Can't store %s image\n", type);
|
||||
free(data);
|
||||
return INSTALL_ERROR;
|
||||
}
|
||||
|
||||
free(filename);
|
||||
|
||||
return INSTALL_SUCCESS;
|
||||
|
@ -1,4 +1,12 @@
|
||||
#!/sbin/sh
|
||||
cd $1
|
||||
md5sum *img > nandroid.md5
|
||||
return $?
|
||||
rm -f /tmp/nandroid.md5
|
||||
md5sum * .* > /tmp/nandroid.md5
|
||||
cp /tmp/nandroid.md5 .
|
||||
# need this because wildcard seems to cause md5sum to return 1
|
||||
if [ -f nandroid.md5 ]
|
||||
then
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
fi
|
105
nandroid.c
105
nandroid.c
@ -101,15 +101,17 @@ typedef void (*file_event_callback)(const char* filename);
|
||||
typedef int (*nandroid_backup_handler)(const char* backup_path, const char* backup_file_image, int callback);
|
||||
|
||||
static int mkyaffs2image_wrapper(const char* backup_path, const char* backup_file_image, int callback) {
|
||||
return mkyaffs2image(backup_path, backup_file_image, 0, callback ? yaffs_callback : NULL);
|
||||
char backup_file_image_with_extension[PATH_MAX];
|
||||
sprintf(backup_file_image_with_extension, "%s.img", backup_file_image);
|
||||
return mkyaffs2image(backup_path, backup_file_image_with_extension, 0, callback ? yaffs_callback : NULL);
|
||||
}
|
||||
|
||||
static int tar_compress_wrapper(const char* backup_path, const char* backup_file_image, int callback) {
|
||||
char tmp[PATH_MAX];
|
||||
if (strcmp(backup_path, "/data") == 0 && volume_for_path("/sdcard") == NULL)
|
||||
sprintf(tmp, "cd $(dirname %s) ; tar cvf %s --exclude 'media' $(basename %s) ; exit $?", backup_path, backup_file_image, backup_path);
|
||||
sprintf(tmp, "cd $(dirname %s) ; tar cvf %s.tar --exclude 'media' $(basename %s) ; exit $?", backup_path, backup_file_image, backup_path);
|
||||
else
|
||||
sprintf(tmp, "cd $(dirname %s) ; tar cvf %s $(basename %s) ; exit $?", backup_path, backup_file_image, backup_path);
|
||||
sprintf(tmp, "cd $(dirname %s) ; tar cvf %s.tar $(basename %s) ; exit $?", backup_path, backup_file_image, backup_path);
|
||||
|
||||
FILE *fp = __popen(tmp, "r");
|
||||
if (fp == NULL) {
|
||||
@ -132,7 +134,6 @@ static nandroid_backup_handler get_backup_handler(const char *backup_path) {
|
||||
ui_print("Unable to find volume.\n");
|
||||
return NULL;
|
||||
}
|
||||
scan_mounted_volumes();
|
||||
MountedVolume *mv = find_mounted_volume_by_mount_point(v->mount_point);
|
||||
if (mv == NULL) {
|
||||
ui_print("Unable to find mounted volume: %s\n", v->mount_point);
|
||||
@ -143,14 +144,15 @@ static nandroid_backup_handler get_backup_handler(const char *backup_path) {
|
||||
return tar_compress_wrapper;
|
||||
}
|
||||
|
||||
char str[255];
|
||||
char* partition;
|
||||
property_get("ro.cwm.prefer_tar", str, "false");
|
||||
if (strcmp("true", str) != 0) {
|
||||
// cwr5, we prefer tar for everything except yaffs2
|
||||
if (strcmp("yaffs2", mv->filesystem) == 0) {
|
||||
return mkyaffs2image_wrapper;
|
||||
}
|
||||
|
||||
if (strcmp("yaffs2", mv->filesystem) == 0) {
|
||||
char str[255];
|
||||
char* partition;
|
||||
property_get("ro.cwm.prefer_tar", str, "true");
|
||||
if (strcmp("true", str) != 0) {
|
||||
return mkyaffs2image_wrapper;
|
||||
}
|
||||
|
||||
@ -163,7 +165,7 @@ int nandroid_backup_partition_extended(const char* backup_path, const char* moun
|
||||
char* name = basename(mount_point);
|
||||
|
||||
struct stat file_info;
|
||||
int callback = stat("/sdcard/clockworkmod/.hidenandroidprogress", &file_info) == 0;
|
||||
int callback = stat("/sdcard/clockworkmod/.hidenandroidprogress", &file_info) != 0;
|
||||
|
||||
ui_print("Backing up %s...\n", name);
|
||||
if (0 != (ret = ensure_path_mounted(mount_point) != 0)) {
|
||||
@ -172,7 +174,15 @@ int nandroid_backup_partition_extended(const char* backup_path, const char* moun
|
||||
}
|
||||
compute_directory_stats(mount_point);
|
||||
char tmp[PATH_MAX];
|
||||
sprintf(tmp, "%s/%s.img", backup_path, name);
|
||||
scan_mounted_volumes();
|
||||
Volume *v = volume_for_path(mount_point);
|
||||
MountedVolume *mv = NULL;
|
||||
if (v != NULL)
|
||||
mv = find_mounted_volume_by_mount_point(v->mount_point);
|
||||
if (mv == NULL || mv->filesystem == NULL)
|
||||
sprintf(tmp, "%s/%s.auto", backup_path, name);
|
||||
else
|
||||
sprintf(tmp, "%s/%s.%s", backup_path, name, mv->filesystem);
|
||||
nandroid_backup_handler backup_handler = get_backup_handler(mount_point);
|
||||
if (backup_handler == NULL) {
|
||||
ui_print("Error finding an appropriate backup handler.\n");
|
||||
@ -357,6 +367,7 @@ static nandroid_restore_handler get_restore_handler(const char *backup_path) {
|
||||
return tar_extract_wrapper;
|
||||
}
|
||||
|
||||
// cwr 5, we prefer tar for everything unless it is yaffs2
|
||||
char str[255];
|
||||
char* partition;
|
||||
property_get("ro.cwm.prefer_tar", str, "false");
|
||||
@ -374,37 +385,83 @@ static nandroid_restore_handler get_restore_handler(const char *backup_path) {
|
||||
int nandroid_restore_partition_extended(const char* backup_path, const char* mount_point, int umount_when_finished) {
|
||||
int ret = 0;
|
||||
char* name = basename(mount_point);
|
||||
|
||||
|
||||
nandroid_restore_handler restore_handler = NULL;
|
||||
const char *filesystems[] = { "yaffs2", "ext2", "ext3", "ext4", "vfat", NULL };
|
||||
const char* backup_filesystem = NULL;
|
||||
Volume *vol = volume_for_path(mount_point);
|
||||
const char *device = NULL;
|
||||
if (vol != NULL)
|
||||
device = vol->device;
|
||||
|
||||
char tmp[PATH_MAX];
|
||||
sprintf(tmp, "%s/%s.img", backup_path, name);
|
||||
struct stat file_info;
|
||||
if (0 != (ret = statfs(tmp, &file_info))) {
|
||||
ui_print("%s.img not found. Skipping restore of %s.\n", name, mount_point);
|
||||
return 0;
|
||||
// can't find the backup, it may be the new backup format?
|
||||
// iterate through the backup types
|
||||
printf("couldn't find default\n");
|
||||
char *filesystem;
|
||||
int i = 0;
|
||||
while ((filesystem = filesystems[i]) != NULL) {
|
||||
sprintf(tmp, "%s/%s.%s.img", backup_path, name, filesystem);
|
||||
if (0 == (ret = statfs(tmp, &file_info))) {
|
||||
backup_filesystem = filesystem;
|
||||
restore_handler = unyaffs_wrapper;
|
||||
break;
|
||||
}
|
||||
sprintf(tmp, "%s/%s.%s.tar", backup_path, name, filesystem);
|
||||
if (0 == (ret = statfs(tmp, &file_info))) {
|
||||
backup_filesystem = filesystem;
|
||||
restore_handler = tar_extract_wrapper;
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
if (backup_filesystem == NULL || restore_handler == NULL) {
|
||||
ui_print("%s.img not found. Skipping restore of %s.\n", name, mount_point);
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
printf("Found new backup image: %s\n", tmp);
|
||||
}
|
||||
|
||||
// If the fs_type of this volume is "auto", let's revert to using a
|
||||
// rm -rf, rather than trying to do a ext3/ext4/whatever format.
|
||||
// This is because some phones (like DroidX) will freak out if you
|
||||
// reformat the /system or /data partitions, and not boot due to
|
||||
// a locked bootloader.
|
||||
// The "auto" fs type preserves the file system, and does not
|
||||
// trigger that lock.
|
||||
// Or of volume does not exist (.android_secure), just rm -rf.
|
||||
if (vol == NULL || 0 == strcmp(vol->fs_type, "auto"))
|
||||
backup_filesystem = NULL;
|
||||
}
|
||||
|
||||
ensure_directory(mount_point);
|
||||
|
||||
int callback = stat("/sdcard/clockworkmod/.hidenandroidprogress", &file_info) == 0;
|
||||
int callback = stat("/sdcard/clockworkmod/.hidenandroidprogress", &file_info) != 0;
|
||||
|
||||
ui_print("Restoring %s...\n", name);
|
||||
/*
|
||||
if (0 != (ret = ensure_root_path_unmounted(root))) {
|
||||
ui_print("Can't unmount %s!\n", mount_point);
|
||||
return ret;
|
||||
if (backup_filesystem == NULL) {
|
||||
if (0 != (ret = format_volume(mount_point))) {
|
||||
ui_print("Error while formatting %s!\n", mount_point);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
*/
|
||||
if (0 != (ret = format_volume(mount_point))) {
|
||||
else if (0 != (ret = format_device(device, mount_point, backup_filesystem))) {
|
||||
ui_print("Error while formatting %s!\n", mount_point);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
if (0 != (ret = ensure_path_mounted(mount_point))) {
|
||||
ui_print("Can't mount %s!\n", mount_point);
|
||||
return ret;
|
||||
}
|
||||
|
||||
nandroid_restore_handler restore_handler = get_restore_handler(mount_point);
|
||||
|
||||
if (restore_handler == NULL)
|
||||
restore_handler = get_restore_handler(mount_point);
|
||||
if (restore_handler == NULL) {
|
||||
ui_print("Error finding an appropriate restore handler.\n");
|
||||
return -2;
|
||||
|
@ -946,6 +946,9 @@ main(int argc, char **argv) {
|
||||
prompt_and_wait();
|
||||
}
|
||||
|
||||
// If there is a radio image pending, reboot now to install it.
|
||||
maybe_install_firmware_update(send_intent);
|
||||
|
||||
// Otherwise, get ready to boot the main system...
|
||||
finish_recovery(send_intent);
|
||||
if(!poweroff)
|
||||
|
BIN
res/images/icon_firmware_error.png
Normal file
BIN
res/images/icon_firmware_error.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 7.9 KiB |
BIN
res/images/icon_firmware_install.png
Executable file
BIN
res/images/icon_firmware_install.png
Executable file
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
5
ui.c
5
ui.c
@ -66,6 +66,8 @@ static const struct { gr_surface* surface; const char *name; } BITMAPS[] = {
|
||||
{ &gBackgroundIcon[BACKGROUND_ICON_INSTALLING], "icon_installing" },
|
||||
{ &gBackgroundIcon[BACKGROUND_ICON_ERROR], "icon_error" },
|
||||
{ &gBackgroundIcon[BACKGROUND_ICON_CLOCKWORK], "icon_clockwork" },
|
||||
{ &gBackgroundIcon[BACKGROUND_ICON_FIRMWARE_INSTALLING], "icon_firmware_install" },
|
||||
{ &gBackgroundIcon[BACKGROUND_ICON_FIRMWARE_ERROR], "icon_firmware_error" },
|
||||
{ &gProgressBarIndeterminate[0], "indeterminate1" },
|
||||
{ &gProgressBarIndeterminate[1], "indeterminate2" },
|
||||
{ &gProgressBarIndeterminate[2], "indeterminate3" },
|
||||
@ -168,7 +170,8 @@ static void draw_text_line(int row, const char* t) {
|
||||
}
|
||||
}
|
||||
|
||||
#define MENU_TEXT_COLOR 255, 160, 49, 255
|
||||
//#define MENU_TEXT_COLOR 255, 160, 49, 255
|
||||
#define MENU_TEXT_COLOR 0, 191, 255, 255
|
||||
#define NORMAL_TEXT_COLOR 200, 200, 200, 255
|
||||
#define HEADER_TEXT_COLOR NORMAL_TEXT_COLOR
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user