diff --git a/Android.mk b/Android.mk index 8fa9ce9..d5ec12f 100644 --- a/Android.mk +++ b/Android.mk @@ -8,17 +8,35 @@ commands_recovery_local_path := $(LOCAL_PATH) # LOCAL_CPP_EXTENSION := .c LOCAL_SRC_FILES := \ - extendedcommands.c \ - nandroid.c \ - legacy.c \ - commands.c \ - recovery.c \ - bootloader.c \ - firmware.c \ - install.c \ - roots.c \ - ui.c \ - verifier.c + extendedcommands.c \ + nandroid.c \ + legacy.c \ + commands.c \ + recovery.c \ + install.c \ + roots.c \ + ui.c \ + verifier.c + +LOCAL_SRC_FILES += \ + reboot.c \ + setprop.c + +ifndef BOARD_HAS_NO_MISC_PARTITION + LOCAL_SRC_FILES += \ + firmware.c \ + bootloader.c +else + LOCAL_CFLAGS += -DBOARD_HAS_NO_MISC_PARTITION +endif + +ifdef BOARD_RECOVERY_IGNORE_BOOTABLES + LOCAL_CFLAGS += -DBOARD_RECOVERY_IGNORE_BOOTABLES +endif + +ifdef BOARD_HIJACK_RECOVERY_PATH + LOCAL_CFLAGS += -DBOARD_HIJACK_RECOVERY_PATH=\"$(BOARD_HIJACK_RECOVERY_PATH)\" +endif LOCAL_SRC_FILES += test_roots.c @@ -26,8 +44,8 @@ LOCAL_MODULE := recovery LOCAL_FORCE_STATIC_EXECUTABLE := true -RECOVERY_VERSION := ClockworkMod Recovery v2.5.0.1 -LOCAL_CFLAGS := -DRECOVERY_VERSION="$(RECOVERY_VERSION)" +RECOVERY_VERSION := ClockworkMod Recovery v2.5.0.8 +LOCAL_CFLAGS += -DRECOVERY_VERSION="$(RECOVERY_VERSION)" RECOVERY_API_VERSION := 3 LOCAL_CFLAGS += -DRECOVERY_API_VERSION=$(RECOVERY_API_VERSION) @@ -59,6 +77,14 @@ ifdef BOARD_DATA_FILESYSTEM LOCAL_CFLAGS += -DDATA_FILESYSTEM=\"$(BOARD_DATA_FILESYSTEM)\" endif +ifdef BOARD_DATADATA_DEVICE + LOCAL_CFLAGS += -DDATADATA_DEVICE=\"$(BOARD_DATADATA_DEVICE)\" +endif + +ifdef BOARD_DATADATA_FILESYSTEM + LOCAL_CFLAGS += -DDATADATA_FILESYSTEM=\"$(BOARD_DATADATA_FILESYSTEM)\" +endif + ifdef BOARD_CACHE_DEVICE LOCAL_CFLAGS += -DCACHE_DEVICE=\"$(BOARD_CACHE_DEVICE)\" endif @@ -67,10 +93,38 @@ ifdef BOARD_CACHE_FILESYSTEM LOCAL_CFLAGS += -DCACHE_FILESYSTEM=\"$(BOARD_CACHE_FILESYSTEM)\" endif +ifdef BOARD_SYSTEM_DEVICE + LOCAL_CFLAGS += -DSYSTEM_DEVICE=\"$(BOARD_SYSTEM_DEVICE)\" +endif + +ifdef BOARD_SYSTEM_FILESYSTEM + LOCAL_CFLAGS += -DSYSTEM_FILESYSTEM=\"$(BOARD_SYSTEM_FILESYSTEM)\" +endif + ifdef BOARD_HAS_DATADATA LOCAL_CFLAGS += -DHAS_DATADATA endif +ifdef BOARD_DATA_FILESYSTEM_OPTIONS + LOCAL_CFLAGS += -DDATA_FILESYSTEM_OPTIONS=\"$(BOARD_DATA_FILESYSTEM_OPTIONS)\" +endif + +ifdef BOARD_DATADATA_FILESYSTEM_OPTIONS + LOCAL_CFLAGS += -DDATADATA_FILESYSTEM_OPTIONS=\"$(BOARD_DATADATA_FILESYSTEM_OPTIONS)\" +endif + +ifdef BOARD_CACHE_FILESYSTEM_OPTIONS + LOCAL_CFLAGS += -DCACHE_FILESYSTEM_OPTIONS=\"$(BOARD_CACHE_FILESYSTEM_OPTIONS)\" +endif + +ifdef BOARD_SYSTEM_FILESYSTEM_OPTIONS + LOCAL_CFLAGS += -DSYSTEM_FILESYSTEM_OPTIONS=\"$(BOARD_SYSTEM_FILESYSTEM_OPTIONS)\" +endif + +ifdef BOARD_HAS_MTD_CACHE + LOCAL_CFLAGS += -DBOARD_HAS_MTD_CACHE +endif + # This binary is in the recovery ramdisk, which is otherwise a copy of root. # It gets copied there in config/Makefile. LOCAL_MODULE_TAGS suppresses # a (redundant) copy of the binary in /system/bin for user builds. @@ -93,7 +147,8 @@ LOCAL_STATIC_LIBRARIES += libstdc++ libc include $(BUILD_EXECUTABLE) -RECOVERY_LINKS := amend busybox flash_image dump_image mkyaffs2image unyaffs erase_image nandroid +RECOVERY_LINKS := amend busybox flash_image dump_image mkyaffs2image unyaffs erase_image nandroid reboot + # nc is provided by external/netcat SYMLINKS := $(addprefix $(TARGET_RECOVERY_ROOT_OUT)/sbin/,$(RECOVERY_LINKS)) $(SYMLINKS): RECOVERY_BINARY := $(LOCAL_MODULE) @@ -156,6 +211,7 @@ include $(commands_recovery_local_path)/tools/Android.mk include $(commands_recovery_local_path)/edify/Android.mk include $(commands_recovery_local_path)/updater/Android.mk include $(commands_recovery_local_path)/applypatch/Android.mk +include $(commands_recovery_local_path)/utilities/Android.mk commands_recovery_local_path := endif # TARGET_ARCH == arm diff --git a/commands.c b/commands.c index 40c4461..8db0aba 100644 --- a/commands.c +++ b/commands.c @@ -626,11 +626,13 @@ cmd_write_firmware_image(const char *name, void *cookie, return 1; } +#ifndef BOARD_HAS_NO_MISC_PARTITION if (remember_firmware_update(type, context.data, context.total_bytes)) { LOGE("Can't store %s image\n", type); free(context.data); return 1; } +#endif return 0; } diff --git a/default_recovery_ui.c b/default_recovery_ui.c index 2711f14..e93e95f 100644 --- a/default_recovery_ui.c +++ b/default_recovery_ui.c @@ -27,8 +27,8 @@ char* MENU_ITEMS[] = { "reboot system now", "wipe data/factory reset", "wipe cache partition", "install zip from sdcard", - "nandroid", - "partitions menu", + "backup and restore", + "mounts and storage", "advanced", NULL }; @@ -54,10 +54,12 @@ int device_reboot_now(volatile char* key_pressed, int key_code) { int device_handle_key(int key_code, int visible) { if (visible) { switch (key_code) { + case KEY_CAPSLOCK: case KEY_DOWN: case KEY_VOLUMEDOWN: return HIGHLIGHT_DOWN; + case KEY_LEFTSHIFT: case KEY_UP: case KEY_VOLUMEUP: return HIGHLIGHT_UP; @@ -69,6 +71,7 @@ int device_handle_key(int key_code, int visible) { if (!get_allow_toggle_display()) return GO_BACK; break; + case KEY_LEFTBRACE: case KEY_ENTER: case BTN_MOUSE: case KEY_CENTER: diff --git a/extendedcommands.c b/extendedcommands.c index 9310305..047f416 100644 --- a/extendedcommands.c +++ b/extendedcommands.c @@ -61,7 +61,9 @@ void toggle_script_asserts() int install_zip(const char* packagefilepath) { ui_print("\n-- Installing: %s\n", packagefilepath); +#ifndef BOARD_HAS_NO_MISC_PARTITION set_sdcard_update_bootloader_message(); +#endif int status = install_package(packagefilepath); ui_reset_progress(); if (status != INSTALL_SUCCESS) { @@ -69,9 +71,11 @@ int install_zip(const char* packagefilepath) ui_print("Installation aborted.\n"); return 1; } +#ifndef BOARD_HAS_NO_MISC_PARTITION if (firmware_update_pending()) { ui_print("\nReboot via menu to complete\ninstallation.\n"); } +#endif ui_set_background(BACKGROUND_ICON_NONE); ui_print("\nInstall from sdcard complete.\n"); return 0; @@ -414,6 +418,10 @@ void show_mount_usb_storage_menu() int confirm_selection(const char* title, const char* confirm) { + struct stat info; + if (0 == stat("/sdcard/clockworkmod/.no_confirm", &info)) + return 1; + char* confirm_headers[] = { title, " THIS CAN NOT BE UNDONE.", "", NULL }; char* items[] = { "No", "No", @@ -470,7 +478,7 @@ int format_non_mtd_device(const char* root) void show_partition_menu() { - static char* headers[] = { "Mount and unmount partitions", + static char* headers[] = { "Mounts and Storage Menu", "", NULL }; @@ -792,6 +800,8 @@ void show_advanced_menu() "Wipe Battery Stats", "Report Error", "Key Test", + "Partition SD Card", + "Fix Permissions", NULL }; @@ -809,9 +819,15 @@ void show_advanced_menu() { if (0 != ensure_root_path_mounted("DATA:")) break; - if (confirm_selection( "Confirm wipe?", "Yes - Wipe Dalvik Cache")) + ensure_root_path_mounted("SDEXT:"); + ensure_root_path_mounted("CACHE:"); + if (confirm_selection( "Confirm wipe?", "Yes - Wipe Dalvik Cache")) { __system("rm -r /data/dalvik-cache"); + __system("rm -r /cache/dalvik-cache"); + __system("rm -r /sd-ext/dalvik-cache"); + } ensure_root_path_unmounted("DATA:"); + ui_print("Dalvik Cache wiped.\n"); break; } case 2: @@ -836,6 +852,57 @@ void show_advanced_menu() ui_print("Key: %d\n", key); } while (action != GO_BACK); + break; + } + case 5: + { + static char* ext_sizes[] = { "128M", + "256M", + "512M", + "1024M", + NULL }; + + static char* swap_sizes[] = { "0M", + "32M", + "64M", + "128M", + "256M", + NULL }; + + static char* ext_headers[] = { "Ext Size", "", NULL }; + static char* swap_headers[] = { "Swap Size", "", NULL }; + + int ext_size = get_menu_selection(ext_headers, ext_sizes, 0); + if (ext_size == GO_BACK) + continue; + + int swap_size = get_menu_selection(swap_headers, swap_sizes, 0); + if (swap_size == GO_BACK) + continue; + + char sddevice[256]; + const RootInfo *ri = get_root_info_for_path("SDCARD:"); + strcpy(sddevice, ri->device); + // we only want the mmcblk, not the partition + sddevice[strlen("/dev/block/mmcblkX")] = NULL; + char cmd[PATH_MAX]; + setenv("SDPATH", sddevice, 1); + sprintf(cmd, "sdparted -es %s -ss %s -efs ext3 -s", ext_sizes[ext_size], swap_sizes[swap_size]); + ui_print("Partitioning SD Card... please wait...\n"); + if (0 == __system(cmd)) + ui_print("Done!\n"); + else + ui_print("An error occured while partitioning your SD Card. Please see /tmp/recovery.log for more details.\n"); + break; + } + case 6: + { + ensure_root_path_mounted("SYSTEM:"); + ensure_root_path_mounted("DATA:"); + ui_print("Fixing permissions...\n"); + __system("fix_permissions"); + ui_print("Done!\n"); + break; } } } @@ -866,7 +933,7 @@ void write_fstab_root(char *root_path, FILE *file) } fprintf(file, "%s ", info->mount_point); - fprintf(file, "%s rw\n", info->filesystem); + fprintf(file, "%s %s\n", info->filesystem, info->filesystem_options == NULL ? "rw" : info->filesystem_options); } void create_fstab() @@ -896,5 +963,5 @@ void handle_failure(int ret) return; mkdir("/sdcard/clockworkmod", S_IRWXU); __system("cp /tmp/recovery.log /sdcard/clockworkmod/recovery.log"); - ui_print("/tmp/recovery.log was copied to /sdcard/clockworkmod/recovery.log. Please open ROM Manager to report the issue."); + ui_print("/tmp/recovery.log was copied to /sdcard/clockworkmod/recovery.log. Please open ROM Manager to report the issue.\n"); } \ No newline at end of file diff --git a/install.c b/install.c index 088f976..8e778f8 100644 --- a/install.c +++ b/install.c @@ -42,6 +42,68 @@ #define ASSUMED_UPDATE_BINARY_NAME "META-INF/com/google/android/update-binary" #define PUBLIC_KEYS_FILE "/res/keys" +// The update binary ask us to install a firmware file on reboot. Set +// that up. Takes ownership of type and filename. +static int +handle_firmware_update(char* type, char* filename, ZipArchive* zip) { + unsigned int data_size; + const ZipEntry* entry = NULL; + + if (strncmp(filename, "PACKAGE:", 8) == 0) { + entry = mzFindZipEntry(zip, filename+8); + if (entry == NULL) { + LOGE("Failed to find \"%s\" in package", filename+8); + return INSTALL_ERROR; + } + data_size = entry->uncompLen; + } else { + struct stat st_data; + if (stat(filename, &st_data) < 0) { + LOGE("Error stat'ing %s: %s\n", filename, strerror(errno)); + return INSTALL_ERROR; + } + data_size = st_data.st_size; + } + + LOGI("type is %s; size is %d; file is %s\n", + type, data_size, filename); + + char* data = malloc(data_size); + if (data == NULL) { + LOGI("Can't allocate %d bytes for firmware data\n", data_size); + return INSTALL_ERROR; + } + + if (entry) { + if (mzReadZipEntry(zip, entry, data, data_size) == false) { + LOGE("Failed to read \"%s\" from package", filename+8); + return INSTALL_ERROR; + } + } else { + FILE* f = fopen(filename, "rb"); + if (f == NULL) { + LOGE("Failed to open %s: %s\n", filename, strerror(errno)); + return INSTALL_ERROR; + } + if (fread(data, 1, data_size, f) != data_size) { + LOGE("Failed to read firmware data: %s\n", strerror(errno)); + return INSTALL_ERROR; + } + fclose(f); + } + +#ifndef BOARD_HAS_NO_MISC_PARTITION + if (remember_firmware_update(type, data, data_size)) { + LOGE("Can't store %s image\n", type); + free(data); + return INSTALL_ERROR; + } +#endif + free(filename); + + return INSTALL_SUCCESS; +} + // If the package contains an update binary, extract it and run it. static int try_update_binary(const char *path, ZipArchive *zip) { diff --git a/killrecovery.sh b/killrecovery.sh index f215250..352cb4b 100755 --- a/killrecovery.sh +++ b/killrecovery.sh @@ -5,4 +5,18 @@ rm /cache/update.zip touch /tmp/.ignorebootmessage kill $(ps | grep /sbin/adbd) kill $(ps | grep /sbin/recovery) -exit 1 \ No newline at end of file + +# On the Galaxy S, the recovery comes test signed, but the +# recovery is not automatically restarted. +if [ -f /init.smdkc110.rc ] +then + /sbin/recovery & +fi + +# Droid X +if [ -f /init.mapphone_cdma.rc ] +then + /sbin/recovery & +fi + +exit 1 diff --git a/nandroid.c b/nandroid.c index 00afbd9..35ad641 100644 --- a/nandroid.c +++ b/nandroid.c @@ -133,6 +133,7 @@ int nandroid_backup(const char* backup_path) sprintf(tmp, "mkdir -p %s", backup_path); __system(tmp); +#ifndef BOARD_RECOVERY_IGNORE_BOOTABLES ui_print("Backing up boot...\n"); sprintf(tmp, "%s/%s", backup_path, "boot.img"); ret = dump_image("boot", tmp, NULL); @@ -143,7 +144,8 @@ int nandroid_backup(const char* backup_path) sprintf(tmp, "%s/%s", backup_path, "recovery.img"); ret = dump_image("recovery", tmp, NULL); if (0 != ret) - return print_and_error("Error while dumping boot image!\n"); + return print_and_error("Error while dumping recovery image!\n"); +#endif if (0 != (ret = nandroid_backup_partition(backup_path, "SYSTEM:"))) return ret; @@ -198,23 +200,40 @@ int nandroid_backup(const char* backup_path) typedef int (*format_function)(char* root); +static void ensure_directory(const char* dir) { + char tmp[PATH_MAX]; + sprintf(tmp, "mkdir -p %s", dir); + __system(tmp); +} + int nandroid_restore_partition_extended(const char* backup_path, const char* root, int umount_when_finished) { int ret = 0; char mount_point[PATH_MAX]; translate_root_path(root, mount_point, PATH_MAX); char* name = basename(mount_point); + 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; + } + + ensure_directory(mount_point); + unyaffs_callback callback = NULL; if (0 != stat("/sdcard/clockworkmod/.hidenandroidprogress", &file_info)) { callback = yaffs_callback; } 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 (0 != (ret = format_root_device(root))) { ui_print("Error while formatting %s!\n", root); return ret; @@ -225,8 +244,6 @@ int nandroid_restore_partition_extended(const char* backup_path, const char* roo return ret; } - char tmp[PATH_MAX]; - sprintf(tmp, "%s/%s.img", backup_path, name); if (0 != (ret = unyaffs(tmp, mount_point, callback))) { ui_print("Error while restoring %s!\n", mount_point); return ret; @@ -260,6 +277,7 @@ int nandroid_restore(const char* backup_path, int restore_boot, int restore_syst return print_and_error("MD5 mismatch!\n"); int ret; +#ifndef BOARD_RECOVERY_IGNORE_BOOTABLES if (restore_boot) { ui_print("Erasing boot before restore...\n"); @@ -272,6 +290,7 @@ int nandroid_restore(const char* backup_path, int restore_boot, int restore_syst return ret; } } +#endif if (restore_system && 0 != (ret = nandroid_restore_partition(backup_path, "SYSTEM:"))) return ret; @@ -284,34 +303,14 @@ int nandroid_restore(const char* backup_path, int restore_boot, int restore_syst return ret; #endif - if (restore_data) - { - struct statfs s; - sprintf(tmp, "%s/.android_secure.img", backup_path); - if (0 != (ret = statfs(tmp, &s))) - { - ui_print(".android_secure.img not found. Skipping restore of applications on external storage."); - } - else - { - __system("mkdir -p /sdcard/.android_secure"); - if (0 != (ret = nandroid_restore_partition_extended(backup_path, "SDCARD:/.android_secure", 0))) - return ret; - } - } + if (restore_data && 0 != (ret = nandroid_restore_partition_extended(backup_path, "SDCARD:/.android_secure", 0))) + return ret; if (restore_cache && 0 != (ret = nandroid_restore_partition_extended(backup_path, "CACHE:", 0))) return ret; - if (restore_sdext) - { - struct statfs s; - sprintf(tmp, "%s/sd-ext.img", backup_path); - if (0 != (ret = statfs(tmp, &s))) - ui_print("sd-ext.img not found. Skipping restore of /sd-ext."); - else if (0 != (ret = nandroid_restore_partition(backup_path, "SDEXT:"))) - return ret; - } + if (restore_sdext && 0 != (ret = nandroid_restore_partition(backup_path, "SDEXT:"))) + return ret; sync(); ui_set_background(BACKGROUND_ICON_NONE); diff --git a/reboot.c b/reboot.c new file mode 100644 index 0000000..04aa9ae --- /dev/null +++ b/reboot.c @@ -0,0 +1,72 @@ +#include +#include +#include +#include +#include +#include + +int reboot_main(int argc, char *argv[]) +{ + int ret; + int nosync = 0; + int poweroff = 0; + int force = 0; + + opterr = 0; + do { + int c; + + c = getopt(argc, argv, "npf"); + + if (c == EOF) { + break; + } + + switch (c) { + case 'n': + nosync = 1; + break; + case 'p': + poweroff = 1; + break; + case 'f': + force = 1; + break; + case '?': + fprintf(stderr, "usage: %s [-n] [-p] [rebootcommand]\n", argv[0]); + exit(EXIT_FAILURE); + } + } while (1); + + if(argc > optind + 1) { + fprintf(stderr, "%s: too many arguments\n", argv[0]); + exit(EXIT_FAILURE); + } + + if(!nosync) + sync(); + + if(force || argc > optind) { + if(poweroff) + ret = __reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, LINUX_REBOOT_CMD_POWER_OFF, NULL); + else if(argc > optind) + ret = __reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, LINUX_REBOOT_CMD_RESTART2, argv[optind]); + else + ret = reboot(RB_AUTOBOOT); + } else { + if(poweroff) { + property_set("ctl.start", "poweroff"); + ret = 0; + } else { + property_set("ctl.start", "reboot"); + ret = 0; + } + } + + if(ret < 0) { + perror("reboot"); + exit(EXIT_FAILURE); + } + fprintf(stderr, "reboot returned\n"); + return 0; +} diff --git a/recovery.c b/recovery.c index 7a6ba03..dc43290 100644 --- a/recovery.c +++ b/recovery.c @@ -177,7 +177,9 @@ static void get_args(int *argc, char ***argv) { struct bootloader_message boot; memset(&boot, 0, sizeof(boot)); +#ifndef BOARD_HAS_NO_MISC_PARTITION get_bootloader_message(&boot); // this may fail, leaving a zeroed structure +#endif if (boot.command[0] != 0 && boot.command[0] != 255) { LOGI("Boot command: %.*s\n", sizeof(boot.command), boot.command); @@ -234,9 +236,12 @@ get_args(int *argc, char ***argv) { strlcat(boot.recovery, (*argv)[i], sizeof(boot.recovery)); strlcat(boot.recovery, "\n", sizeof(boot.recovery)); } +#ifndef BOARD_HAS_NO_MISC_PARTITION set_bootloader_message(&boot); +#endif } +#ifndef BOARD_HAS_NO_MISC_PARTITION void set_sdcard_update_bootloader_message() { struct bootloader_message boot; @@ -245,6 +250,7 @@ set_sdcard_update_bootloader_message() { strlcpy(boot.recovery, "recovery\n", sizeof(boot.recovery)); set_bootloader_message(&boot); } +#endif // 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 @@ -282,10 +288,12 @@ finish_recovery(const char *send_intent) { check_and_fclose(log, LOG_FILE); } +#ifndef BOARD_HAS_NO_MISC_PARTITION // Reset to mormal system boot so recovery won't cycle indefinitely. struct bootloader_message boot; memset(&boot, 0, sizeof(boot)); set_bootloader_message(&boot); +#endif // Remove the command file, so recovery won't repeat indefinitely. char path[PATH_MAX] = ""; @@ -484,7 +492,9 @@ prompt_and_wait() { if (confirm_selection("Confirm install?", "Yes - Install /sdcard/update.zip")) { ui_print("\n-- Install from sdcard...\n"); +#ifndef BOARD_HAS_NO_MISC_PARTITION set_sdcard_update_bootloader_message(); +#endif int status = install_package(SDCARD_PACKAGE_FILE); if (status != INSTALL_SUCCESS) { ui_set_background(BACKGROUND_ICON_ERROR); @@ -492,7 +502,16 @@ prompt_and_wait() { } else if (!ui_text_visible()) { return; // reboot if logs aren't visible } else { +#ifndef BOARD_HAS_NO_MISC_PARTITION + if (firmware_update_pending()) { + ui_print("\nReboot via menu to complete\n" + "installation.\n"); + } else { + ui_print("\nInstall from sdcard complete.\n"); + } +#else ui_print("\nInstall from sdcard complete.\n"); +#endif } } break; @@ -535,10 +554,14 @@ main(int argc, char **argv) { return amend_main(argc, argv); if (strstr(argv[0], "nandroid")) return nandroid_main(argc, argv); + if (strstr(argv[0], "reboot")) + return reboot_main(argc, argv); + if (strstr(argv[0], "setprop")) + return setprop_main(argc, argv); return busybox_driver(argc, argv); } - create_fstab(); __system("/sbin/postrecoveryboot.sh"); + create_fstab(); int is_user_initiated_recovery = 0; time_t start = time(NULL); @@ -629,6 +652,11 @@ main(int argc, char **argv) { if (status != INSTALL_SUCCESS && !is_user_initiated_recovery) ui_set_background(BACKGROUND_ICON_ERROR); if (status != INSTALL_SUCCESS || ui_text_visible()) prompt_and_wait(); +#ifndef BOARD_HAS_NO_MISC_PARTITION + // If there is a radio image pending, reboot now to install it. + maybe_install_firmware_update(send_intent); +#endif + // Otherwise, get ready to boot the main system... finish_recovery(send_intent); ui_print("Rebooting...\n"); diff --git a/roots.c b/roots.c index da10ee7..474ea1d 100644 --- a/roots.c +++ b/roots.c @@ -39,20 +39,20 @@ static const char g_raw[] = "@\0g_raw"; static const char g_package_file[] = "@\0g_package_file"; static RootInfo g_roots[] = { - { "BOOT:", g_mtd_device, NULL, "boot", NULL, g_raw }, - { "CACHE:", CACHE_DEVICE, NULL, "cache", "/cache", CACHE_FILESYSTEM }, - { "DATA:", DATA_DEVICE, NULL, "userdata", "/data", DATA_FILESYSTEM }, + { "BOOT:", g_mtd_device, NULL, "boot", NULL, g_raw, NULL }, + { "CACHE:", CACHE_DEVICE, NULL, "cache", "/cache", CACHE_FILESYSTEM, CACHE_FILESYSTEM_OPTIONS }, + { "DATA:", DATA_DEVICE, NULL, "userdata", "/data", DATA_FILESYSTEM, DATA_FILESYSTEM_OPTIONS }, #ifdef HAS_DATADATA - { "DATADATA:", DATADATA_DEVICE, NULL, "datadata", "/datadata", DATADATA_FILESYSTEM }, + { "DATADATA:", DATADATA_DEVICE, NULL, "datadata", "/datadata", DATADATA_FILESYSTEM, DATADATA_FILESYSTEM_OPTIONS }, #endif - { "MISC:", g_mtd_device, NULL, "misc", NULL, g_raw }, - { "PACKAGE:", NULL, NULL, NULL, NULL, g_package_file }, - { "RECOVERY:", g_mtd_device, NULL, "recovery", "/", g_raw }, - { "SDCARD:", SDCARD_DEVICE_PRIMARY, SDCARD_DEVICE_SECONDARY, NULL, "/sdcard", "vfat" }, - { "SDEXT:", SDEXT_DEVICE, NULL, NULL, "/sd-ext", SDEXT_FILESYSTEM }, - { "SYSTEM:", g_mtd_device, NULL, "system", "/system", "yaffs2" }, - { "MBM:", g_mtd_device, NULL, "mbm", NULL, g_raw }, - { "TMP:", NULL, NULL, NULL, "/tmp", NULL }, + { "MISC:", g_mtd_device, NULL, "misc", NULL, g_raw, NULL }, + { "PACKAGE:", NULL, NULL, NULL, NULL, g_package_file, NULL }, + { "RECOVERY:", g_mtd_device, NULL, "recovery", "/", g_raw, NULL }, + { "SDCARD:", SDCARD_DEVICE_PRIMARY, SDCARD_DEVICE_SECONDARY, NULL, "/sdcard", "vfat", NULL }, + { "SDEXT:", SDEXT_DEVICE, NULL, NULL, "/sd-ext", SDEXT_FILESYSTEM, NULL }, + { "SYSTEM:", SYSTEM_DEVICE, NULL, "system", "/system", SYSTEM_FILESYSTEM, SYSTEM_FILESYSTEM_OPTIONS }, + { "MBM:", g_mtd_device, NULL, "mbm", NULL, g_raw, NULL }, + { "TMP:", NULL, NULL, NULL, "/tmp", NULL, NULL }, }; #define NUM_ROOTS (sizeof(g_roots) / sizeof(g_roots[0])) @@ -207,14 +207,15 @@ is_root_path_mounted(const char *root_path) return internal_root_mounted(info) >= 0; } -static int mount_internal(const char* device, const char* mount_point, const char* filesystem) +static int mount_internal(const char* device, const char* mount_point, const char* filesystem, const char* filesystem_options) { - if (strcmp(filesystem, "auto") != 0) { + if (strcmp(filesystem, "auto") != 0 && filesystem_options == NULL) { return mount(device, mount_point, filesystem, MS_NOATIME | MS_NODEV | MS_NODIRATIME, ""); } else { char mount_cmd[PATH_MAX]; - sprintf(mount_cmd, "mount -onoatime,nodiratime,nodev %s %s", device, mount_point); + const char* options = filesystem_options == NULL ? "noatime,nodiratime,nodev" : filesystem_options; + sprintf(mount_cmd, "mount -t %s -o%s %s %s", filesystem, options, device, mount_point); return __system(mount_cmd); } } @@ -259,7 +260,7 @@ ensure_root_path_mounted(const char *root_path) } mkdir(info->mount_point, 0755); // in case it doesn't already exist - if (mount_internal(info->device, info->mount_point, info->filesystem)) { + if (mount_internal(info->device, info->mount_point, info->filesystem, info->filesystem_options)) { if (info->device2 == NULL) { LOGE("Can't mount %s\n(%s)\n", info->device, strerror(errno)); return -1; @@ -311,7 +312,12 @@ get_root_mtd_partition(const char *root_path) if (info == NULL || info->device != g_mtd_device || info->partition_name == NULL) { +#ifdef BOARD_HAS_MTD_CACHE + if (strcmp(root_path, "CACHE:") != 0) + return NULL; +#else return NULL; +#endif } mtd_scan_partitions(); return mtd_find_partition_by_name(info->partition_name); @@ -339,7 +345,7 @@ format_root_device(const char *root) LOGW("format_root_device: can't resolve \"%s\"\n", root); return -1; } - if (info->mount_point != NULL) { + if (info->mount_point != NULL && info->device == g_mtd_device) { /* Don't try to format a mounted device. */ int ret = ensure_root_path_unmounted(root); @@ -377,6 +383,6 @@ format_root_device(const char *root) } } } - + return format_non_mtd_device(root); } diff --git a/roots.h b/roots.h index e777093..3ebae2b 100644 --- a/roots.h +++ b/roots.h @@ -21,11 +21,11 @@ #include "mtdutils/mtdutils.h" #ifndef SDCARD_DEVICE_PRIMARY -#define SDCARD_DEVICE_PRIMARY "/dev/block/mmcblk0" +#define SDCARD_DEVICE_PRIMARY "/dev/block/mmcblk0p1" #endif #ifndef SDCARD_DEVICE_SECONDARY -#define SDCARD_DEVICE_SECONDARY "/dev/block/mmcblk0p1" +#define SDCARD_DEVICE_SECONDARY "/dev/block/mmcblk0" #endif #ifndef SDEXT_DEVICE @@ -60,6 +60,31 @@ #define CACHE_FILESYSTEM "yaffs2" #endif +#ifndef SYSTEM_DEVICE +#define SYSTEM_DEVICE g_mtd_device +#endif + +#ifndef SYSTEM_FILESYSTEM +#define SYSTEM_FILESYSTEM "yaffs2" +#endif + +#ifndef DATA_FILESYSTEM_OPTIONS +#define DATA_FILESYSTEM_OPTIONS NULL +#endif + +#ifndef CACHE_FILESYSTEM_OPTIONS +#define CACHE_FILESYSTEM_OPTIONS NULL +#endif + +#ifndef DATADATA_FILESYSTEM_OPTIONS +#define DATADATA_FILESYSTEM_OPTIONS NULL +#endif + +#ifndef SYSTEM_FILESYSTEM_OPTIONS +#define SYSTEM_FILESYSTEM_OPTIONS NULL +#endif + + /* Any of the "root_path" arguments can be paths with relative * components, like "SYSTEM:a/b/c". */ @@ -107,6 +132,7 @@ typedef struct { const char *partition_name; const char *mount_point; const char *filesystem; + const char *filesystem_options; } RootInfo; #endif // RECOVERY_ROOTS_H_ diff --git a/setprop.c b/setprop.c new file mode 100644 index 0000000..63ad2b4 --- /dev/null +++ b/setprop.c @@ -0,0 +1,18 @@ +#include + +#include + +int setprop_main(int argc, char *argv[]) +{ + if(argc != 3) { + fprintf(stderr,"usage: setprop \n"); + return 1; + } + + if(property_set(argv[1], argv[2])){ + fprintf(stderr,"could not set property\n"); + return 1; + } + + return 0; +} diff --git a/utilities/Android.mk b/utilities/Android.mk new file mode 100644 index 0000000..dc79704 --- /dev/null +++ b/utilities/Android.mk @@ -0,0 +1,41 @@ +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) +LOCAL_MODULE := e2fsck +LOCAL_MODULE_TAGS := eng +LOCAL_MODULE_CLASS := RECOVERY_EXECUTABLES +LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/sbin +LOCAL_SRC_FILES := $(LOCAL_MODULE) +include $(BUILD_PREBUILT) + +include $(CLEAR_VARS) +LOCAL_MODULE := fix_permissions +LOCAL_MODULE_TAGS := eng +LOCAL_MODULE_CLASS := RECOVERY_EXECUTABLES +LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/sbin +LOCAL_SRC_FILES := $(LOCAL_MODULE) +include $(BUILD_PREBUILT) + +include $(CLEAR_VARS) +LOCAL_MODULE := parted +LOCAL_MODULE_TAGS := eng +LOCAL_MODULE_CLASS := RECOVERY_EXECUTABLES +LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/sbin +LOCAL_SRC_FILES := $(LOCAL_MODULE) +include $(BUILD_PREBUILT) + +include $(CLEAR_VARS) +LOCAL_MODULE := sdparted +LOCAL_MODULE_TAGS := eng +LOCAL_MODULE_CLASS := RECOVERY_EXECUTABLES +LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/sbin +LOCAL_SRC_FILES := $(LOCAL_MODULE) +include $(BUILD_PREBUILT) + +include $(CLEAR_VARS) +LOCAL_MODULE := tune2fs +LOCAL_MODULE_TAGS := eng +LOCAL_MODULE_CLASS := RECOVERY_EXECUTABLES +LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/sbin +LOCAL_SRC_FILES := $(LOCAL_MODULE) +include $(BUILD_PREBUILT) diff --git a/utilities/e2fsck b/utilities/e2fsck new file mode 100644 index 0000000..2844a1d Binary files /dev/null and b/utilities/e2fsck differ diff --git a/utilities/fix_permissions b/utilities/fix_permissions new file mode 100644 index 0000000..ee4b067 --- /dev/null +++ b/utilities/fix_permissions @@ -0,0 +1,476 @@ +#! /system/bin/sh +# +# Warning: if you want to run this script in cm-recovery change the above to #!/sbin/sh +# +# fix_permissions - fixes permissions on Android data directories after upgrade +# shade@chemlab.org +# +# original concept: http://blog.elsdoerfer.name/2009/05/25/android-fix-package-uid-mismatches/ +# implementation by: Cyanogen +# improved by: ankn, smeat, thenefield, farmatito, rikupw, Kastro +# +# v1.1-v1.31r3 - many improvements and concepts from XDA developers. +# v1.34 through v2.00 - A lot of frustration [by Kastro] +# v2.01 - Completely rewrote the script for SPEED, thanks for the input farmatito +# /data/data depth recursion is tweaked; +# fixed single mode; +# functions created for modularity; +# logging can be disabled via CLI for more speed; +# runtime computation added to end (Runtime: mins secs); +# progress (current # of total) added to screen; +# fixed CLI argument parsing, now you can have more than one option!; +# debug cli option; +# verbosity can be disabled via CLI option for less noise;; +# [by Kastro, (XDA: k4str0), twitter;mattcarver] +# v2.02 - ignore com.htc.resources.apk if it exists and minor code cleanups, +# fix help text, implement simulated run (-s) [farmatito] +# v2.03 - fixed chown group ownership output [Kastro] + +VERSION="2.03" + +# Defaults +DEBUG=0 # Debug off by default +LOGGING=1 # Logging on by default +VERBOSE=1 # Verbose on by default + +# Messages +UID_MSG="Changing user ownership for:" +GID_MSG="Changing group ownership for:" +PERM_MSG="Changing permissions for:" + +# Programs needed +ECHO="busybox echo" +GREP="busybox grep" +EGREP="busybox egrep" +CAT="busybox cat" +CHOWN="busybox chown" +CHMOD="busybox chmod" +MOUNT="busybox mount" +UMOUNT="busybox umount" +CUT="busybox cut" +FIND="busybox find" +LS="busybox ls" +TR="busybox tr" +TEE="busybox tee" +TEST="busybox test" +SED="busybox sed" +RM="busybox rm" +WC="busybox wc" +EXPR="busybox expr" +DATE="busybox date" + +# Initialise vars +CODEPATH="" +UID="" +GID="" +PACKAGE="" +REMOVE=0 +NOSYSTEM=0 +ONLY_ONE="" +SIMULATE=0 +SYSREMOUNT=0 +SYSMOUNT=0 +DATAMOUNT=0 +SYSSDMOUNT=0 +FP_STARTTIME=$( $DATE +"%m-%d-%Y %H:%M:%S" ) +FP_STARTEPOCH=$( $DATE +%s ) + +fp_usage() +{ + $ECHO "Usage $0 [OPTIONS] [APK_PATH]" + $ECHO " -d turn on debug" + $ECHO " -f fix only package APK_PATH" + $ECHO " -l disable logging for this run (faster)" + $ECHO " -r remove stale data directories" + $ECHO " of uninstalled packages while fixing permissions" + $ECHO " -s simulate only" + $ECHO " -u check only non-system directories" + $ECHO " -v disable verbosity for this run (less output)" + $ECHO " -V print version" + $ECHO " -h this help" +} + +fp_parseargs() +{ + # Parse options + while $TEST $# -ne 0; do + case "$1" in + -d) + DEBUG=1 + ;; + -f) + if $TEST $# -lt 2; then + $ECHO "$0: missing argument for option $1" + exit 1 + else + if $TEST $( $ECHO $2 | $CUT -c1 ) != "-"; then + ONLY_ONE=$2 + shift; + else + $ECHO "$0: missing argument for option $1" + exit 1 + fi + fi + ;; + -r) + REMOVE=1 + ;; + -s) + SIMULATE=1 + ;; + -l) + if $TEST $LOGGING -eq 0; then + LOGGING=1 + else + LOGGING=0 + fi + ;; + -v) + if $TEST $VERBOSE -eq 0; then + VERBOSE=1 + else + VERBOSE=0 + fi + ;; + -u) + NOSYSTEM=1 + ;; + -V) + $ECHO "$0 $VERSION" + exit 0 + ;; + -h) + fp_usage + exit 0 + ;; + -*) + $ECHO "$0: unknown option $1" + $ECHO + fp_usage + exit 1 + ;; + esac + shift; + done +} + +fp_print() +{ + MSG=$@ + if $TEST $LOGGING -eq 1; then + $ECHO $MSG | $TEE -a $LOG_FILE + else + $ECHO $MSG + fi +} + +fp_start() +{ + if $TEST $SIMULATE -eq 0 ; then + if $TEST $( $GREP -c " /system " "/proc/mounts" ) -ne 0; then + DEVICE=$( $GREP " /system " "/proc/mounts" | $CUT -d ' ' -f1 ) + if $TEST $DEBUG -eq 1; then + fp_print "/system mounted on $DEVICE" + fi + if $TEST $( $GREP " /system " "/proc/mounts" | $GREP -c " ro " ) -ne 0; then + $MOUNT -o remount,rw $DEVICE /system + SYSREMOUNT=1 + fi + else + $MOUNT /system > /dev/null 2>&1 + SYSMOUNT=1 + fi + + if $TEST $( $GREP -c " /data " "/proc/mounts" ) -eq 0; then + $MOUNT /data > /dev/null 2>&1 + DATAMOUNT=1 + fi + + if $TEST -e /dev/block/mmcblk0p2 && $TEST $( $GREP -c " /system/sd " "/proc/mounts" ) -eq 0; then + $MOUNT /system/sd > /dev/null 2>&1 + SYSSDMOUNT=1 + fi + fi + if $TEST $( $MOUNT | $GREP -c /sdcard ) -eq 0; then + LOG_FILE="/data/fix_permissions.log" + else + LOG_FILE="/sdcard/fix_permissions.log" + fi + if $TEST ! -e "$LOG_FILE"; then + > $LOG_FILE + fi + + fp_print "$0 $VERSION started at $FP_STARTTIME" +} + +fp_chown_uid() +{ + FP_OLDUID=$1 + FP_UID=$2 + FP_FILE=$3 + + #if user ownership doesn't equal then change them + if $TEST "$FP_OLDUID" != "$FP_UID"; then + if $TEST $VERBOSE -ne 0; then + fp_print "$UID_MSG $FP_FILE from '$FP_OLDUID' to '$FP_UID'" + fi + if $TEST $SIMULATE -eq 0; then + $CHOWN $FP_UID "$FP_FILE" + fi + fi +} + +fp_chown_gid() +{ + FP_OLDGID=$1 + FP_GID=$2 + FP_FILE=$3 + + #if group ownership doesn't equal then change them + if $TEST "$FP_OLDGID" != "$FP_GID"; then + if $TEST $VERBOSE -ne 0; then + fp_print "$GID_MSG $FP_FILE from '$FP_OLDGID' to '$FP_GID'" + fi + if $TEST $SIMULATE -eq 0; then + $CHOWN :$FP_GID "$FP_FILE" + fi + fi +} + +fp_chmod() +{ + FP_OLDPER=$1 + FP_OLDPER=$( $ECHO $FP_OLDPER | cut -c2-10 ) + FP_PERSTR=$2 + FP_PERNUM=$3 + FP_FILE=$4 + + #if the permissions are not equal + if $TEST "$FP_OLDPER" != "$FP_PERSTR"; then + if $TEST $VERBOSE -ne 0; then + fp_print "$PERM_MSG $FP_FILE from '$FP_OLDPER' to '$FP_PERSTR' ($FP_PERNUM)" + fi + #change the permissions + if $TEST $SIMULATE -eq 0; then + $CHMOD $FP_PERNUM "$FP_FILE" + fi + fi +} + +fp_all() +{ + FP_NUMS=$( $CAT /data/system/packages.xml | $EGREP "^ /dev/null 2>&1 + fi + + if $TEST $SYSSDMOUNT -eq 1; then + $UMOUNT /system/sd > /dev/null 2>&1 + fi + + if $TEST $SYSMOUNT -eq 1; then + $UMOUNT /system > /dev/null 2>&1 + fi + + if $TEST $DATAMOUNT -eq 1; then + $UMOUNT /data > /dev/null 2>&1 + fi + + FP_ENDTIME=$( $DATE +"%m-%d-%Y %H:%M:%S" ) + FP_ENDEPOCH=$( $DATE +%s ) + + date_diff $FP_STARTEPOCH $FP_ENDEPOCH + + fp_print "$0 $VERSION ended at $FP_ENDTIME (Runtime:${FP_DDM}m${FP_DDS}s)" +} + +#MAIN SCRIPT + +fp_parseargs $@ +fp_start +if $TEST "$ONLY_ONE" != "" -a "$ONLY_ONE" != "0" ; then + fp_single "$ONLY_ONE" +else + fp_all +fi +fp_end diff --git a/utilities/parted b/utilities/parted new file mode 100644 index 0000000..bb3d432 Binary files /dev/null and b/utilities/parted differ diff --git a/utilities/sdparted b/utilities/sdparted new file mode 100644 index 0000000..d2a46a4 --- /dev/null +++ b/utilities/sdparted @@ -0,0 +1,637 @@ +#!/sbin/sh + +# do logging, if not excluded with -x +LOGFILE="/data/sdparted.log" +[ "$1" != "-x" ] && echo "$0" "$@" >> "$LOGFILE" && "$0" -x "$@" 2>&1 | tee -a "$LOGFILE" && exit +shift + +ShowError() { echo ; echo " err: $1" ; echo ; exit 1 ; } + +ShowMessage() { echo ; echo " msg: $1" ; } + +ShowHelp() { + +cat <. + default=total sdcard size - (ext + swap) + + --extsize|-es SIZE[MG] set the size of the ext partition to . + default=$EXTSIZE + + --swapsize|-ss SIZE[MG] set the size of the swap partition to . + if set to 0, no swap partition will be created. + default=$SWAPSIZE + + --extfs|-efs TYPE set the filesystem of ext partition to . + valid types=ext2, ext3, ext4 + default=$EXTFS + + + --upgradefs|-ufs TYPE upgrades existing ext partition to . + this operation will NOT wipe your sdcard and + cannot be used with any partition creation options. + valid types=ext3, ext4 + + --downgradefs|-dfs TYPE downgrades existing ext partition to . + this operation will NOT wipe your sdcard and + cannot be used with any partition creation options. + valid types=ext2 + + + --interactive|-i interactive mode + + --help|-h display this help + + --printonly|-po display sdcard information + + --silent|-s do not prompt user, not even initial warning. + + +examples: + $SCRIPTNAME creates swap=$SWAPSIZE ext2=$EXTSIZE fat32=remaining free space + $SCRIPTNAME -efs ext4 creates swap=$SWAPSIZE ext4=$EXTSIZE fat32=remaining free space + $SCRIPTNAME -fs 1.5G -efs ext3 creates swap=$SWAPSIZE ext3=$EXTSIZE fat32=1536 + $SCRIPTNAME -es 256M -ss 0 creates no swap ext2=256 fat32=remaining free space + $SCRIPTNAME -ufs ext4 upgrades ext partition to ext4 + +DONEHELP + +} + +UserAbort() { + + WHILEEXIT= + + while [ -z "$WHILEEXIT" ] + do + echo -n "do you want to continue? (Y/n) " + read response + echo + [ "$response" = "Y" ] || [ "$response" = "n" ] || [ "$response" = "N" ] && WHILEEXIT="$response" + done + + echo "$response" > /dev/null 2>&1 >>"$LOGFILE" + + [ "$response" != "Y" ] + +} + +UnmountAll () { + + # unmount all partitions so we can work with $SDPATH + # i'm assuming no more than 3 partitions + # maybe make a little more elegant later + echo -n "unmounting all partitions..." + umount "$FATPATH" > /dev/null 2>&1 >>"$LOGFILE" + umount "$EXTPATH" > /dev/null 2>&1 >>"$LOGFILE" + umount "$SWAPPATH" > /dev/null 2>&1 >>"$LOGFILE" + echo "done" + echo + +} + + +CheckReqs() { + + echo -n "checking script requirements..." + # check for valid sdcard + [ -e $SDPATH ] || ShowError "$SDPATH does not exist!" + + # look for necessary programs + [ -e $CMPARTED ] || ShowError "$CMPARTED does not exist!" + [ -e $CMTUNE2FS ] || ShowError "$CMTUNE2FS does not exist!" + [ -e $CME2FSCK ] || ShowError "$CME2FSCK does not exist!" + + # verify cm-v1.4 + PARTEDREV=`"$CMPARTED" "$SDPATH" version | grep Parted | cut -d" " -f3` + [ "$PARTEDREV" == "1.8.8.1.179-aef3" ] || ShowError "you are not using parted v1.8.8.1.179-aef3!" + echo "done" + echo + +} + +CheckTableType() { + + TABLETYPE=`"$CMPARTED" "$SDPATH" print | grep Table: | cut -d" " -f3` + + [ "$TABLETYPE" == "loop" -o "$TABLETYPE" == "msdos" ] && TTISOK=1 || TTISOK=0 + [ "$TABLETYPE" == "loop" ] && TTISLOOP=1 || TTISLOOP=0 + [ "$TABLETYPE" == "msdos" ] && TTISMSDOS=1 || TTISMOSDOS=0 + +} + +ValidateExtArg() { + + FUNC_RET="nonzero" + + # validating argument + [ "$1" != "ext2" ] && [ "$1" != "ext3" ] && [ "$1" != "ext4" ] && FUNC_RET= + + [ -z "$FUNC_RET" ] && [ -z "$IMODE" ] && ShowError "$1 is not a valid filesystem." + [ -z "$FUNC_RET" ] && [ -n "$IMODE" ] && ShowMessage "$1 is not a valid filesystem." + + # return valid argument + [ -n "$FUNC_RET" ] && FUNC_RET="$1" + +} + +ValidateSizeArg() { + + # check for zero-length arg to protect expr length + [ -z "$1" ] && ShowError "zero-length argument passed to size-validator" + + SIZEMB= + ARGLEN=`expr length $1` + SIZELEN=$(($ARGLEN-1)) + SIZEARG=`expr substr $1 1 $SIZELEN` + SIZEUNIT=`expr substr $1 $ARGLEN 1` + + # check if SIZEARG is an integer + if [ $SIZEARG -eq $SIZEARG 2> /dev/null ] ; then + # look for G + [ "$SIZEUNIT" == "G" ] && SIZEMB=$(($SIZEARG * 1024)) + # look for M + [ "$SIZEUNIT" == "M" ] && SIZEMB=$SIZEARG + # no units on arg AND prevents using bogus size units + [ -z "$SIZEMB" ] && [ $SIZEUNIT -eq $SIZEUNIT 2> /dev/null ] && SIZEMB=$1 + # check if SIZEARG is a floating point number, GB only + elif [ `expr index "$SIZEARG" .` != 0 ] && [ "$SIZEUNIT" == "G" ] ; then + INT=`echo "$SIZEARG" | cut -d"." -f1` + FRAC=`echo "$SIZEARG" | cut -d"." -f2` + SIGDIGITS=`expr length $FRAC` + + [ -z "$INT" ] && INT=0 + INTMB=$(($INT * 1024)) + FRACMB=$((($FRAC * 1024) / (10**$SIGDIGITS))) + SIZEMB=$(($INTMB + $FRACMB)) + # it's not a valid size + else + [ -z "$IMODE" ] && ShowError "$1 is not a valid size" + fi + + [ -z "$SIZEMB" ] && [ -n "$IMODE" ] && ShowMessage "$1 is not a valid size" + + # return valid argument in MB + FUNC_RET=$SIZEMB + +} + +CalculatePartitions() { + + # get size of sdcard in MB & do some math + SDSIZEMB=`"$CMPARTED" "$SDPATH" unit MB print | grep $SDPATH | cut -d" " -f3` + SDSIZE=${SDSIZEMB%MB} + [ -n "$FATSIZE" ] || FATSIZE=$(($SDSIZE - $EXTSIZE - $SWAPSIZE)) + EXTEND=$(($FATSIZE + $EXTSIZE)) + SWAPEND=$(($EXTEND + $SWAPSIZE)) + + # check for fatsize of 0 + [ $FATSIZE -le 0 ] && ShowError "must have a fat32 partition greater than 0MB" + + # check for zero-length sdsize... + # indicative of parted not reporting length + # correctly b/c of error on sdcard + [ -z "$SDSIZE" ] && ShowError "zero-length argument passed to partition-calculator" + + # make sure we're not being asked to do the impossible + [ $(($FATSIZE + $EXTSIZE + $SWAPSIZE)) -gt $SDSIZE ] && [ -z "$IMODE" ] && ShowError "sum of requested partitions is greater than sdcard size" + +} + + +UpgradeDowngradeOnly() { + + if [ -n "$UEXTFSONLY" ] ; then + echo + [ -n "$CREATEPART" ] && ShowError "cannot use upgrade option when creating partitions, use -efs instead" + [ -n "$DEXTFSONLY" ] && ShowError "cannot upgrade AND downgrade, it just doesn't make sense" + echo "you have chosen to upgrade $EXTPATH to $UEXTFSONLY." + echo "this action will NOT delete any data from sdcard." + echo + [ -z "$SILENTRUN" ] && UserAbort && ShowError "script canceled by user" + echo + UpgradeExt "$UEXTFSONLY" + ShowCardInfo + elif [ -n "$DEXTFSONLY" ] ; then + echo + [ -n "$CREATEPART" ] && ShowError "cannot use downgrade option when creating partitions." + [ -n "$UEXTFSONLY" ] && ShowError "cannot downgrade AND upgrade, it just doesn't make sense." + echo "you have chosen to downgrade $EXTPATH to $DEXTFSONLY." + echo "this action will NOT delete any data from sdcard." + echo + [ -z "$SILENTRUN" ] && UserAbort && ShowError "script canceled by user" + echo + DowngradeExt "$DEXTFSONLY" + ShowCardInfo + fi + +} + +PrepareSdCard() { + + echo + if [ $TTISOK -eq 0 ] ; then + echo "partition 1 may not be aligned to cylinder boundaries." + echo "to continue, this must be corrected." + elif [ $TTISLOOP -gt 0 ] ; then + echo "your sdcard's partition table type is $TABLETYPE." + echo "to continue, partition table must be set to 'msdos'." + elif [ $TTISMSDOS -gt 0 ] ; then + # just a reminder..in a later version, + # i may implement resizing of partitions, + # so this will be unnecessary. but until then... + echo "to continue, all existing partitions must be removed." + else + # this is not good, and should never happen + # if it does, there is a serious problem + ShowError "sdcard failed table type check." + fi + + echo + echo "this action will remove all data from your sdcard." + echo + [ -z "$SILENTRUN" ] && UserAbort && ShowError "script canceled by user" + + [ $TTISOK -eq 0 ] && echo -n "correcting cylinder boundaries..." + [ $TTISLOOP -gt 0 ] && echo -n "setting partition table to msdos..." + [ $TTISMSDOS -gt 0 ] && echo -n "removing all partitions..." + + "$CMPARTED" -s "$SDPATH" mklabel msdos 2>&1 >>"$LOGFILE" + echo "done" + echo + +} + +ShowActions() { + + echo + echo "total size of sdcard=$SDSIZEMB" + echo + echo "the following actions will be performed:" + echo " -create $FATSIZE""MB fat32 partition" + [ $EXTSIZE -gt 0 ] && echo " -create $EXTSIZE""MB ext2 partition" + [ $SWAPSIZE -gt 0 ] && echo " -create $SWAPSIZE""MB swap partition" + [ "$EXTFS" != "ext2" ] && echo " -ext2 partition will be upgraded to $EXTFS" + echo + [ -z "$SILENTRUN" ] && UserAbort && ShowError "script canceled by user" + echo + +} + +ShowCardInfo() { + + CheckTableType + + echo + echo "retrieving current sdcard information..." + + if [ $TTISOK -gt 0 ] ; then + echo + parted "$SDPATH" print + echo + echo "script log is located @ /data/sdparted.log" + exit 0 + else + echo + echo "partition 1 may not be aligned to cylinder boundaries." + ShowError "cannot complete print operation." + fi + echo + +} + + +PartitionSdCard() { + + echo "performing selected actions..." + echo + + if [ $FATSIZE -gt 0 ] ; then + echo -n "creating fat32 partition..." + "$CMPARTED" -s "$SDPATH" mkpartfs primary fat32 0 "$FATSIZE"MB 2>&1 >>"$LOGFILE" + echo "done" + fi + + if [ $EXTSIZE -gt 0 ] ; then + echo -n "creating ext2 partition..." + "$CMPARTED" -s "$SDPATH" mkpartfs primary ext2 "$FATSIZE"MB "$EXTEND"MB 2>&1 >>"$LOGFILE" + echo "done" + fi + + if [ $SWAPSIZE -gt 0 ] ; then + echo -n "creating swap partition..." + "$CMPARTED" -s "$SDPATH" mkpartfs primary linux-swap "$EXTEND"MB "$SWAPEND"MB 2>&1 >>"$LOGFILE" + echo "done" + fi + echo + +} + +UpgradeExt() { + + # check for no upgrade + [ "$1" == "ext2" ] && return + # check for ext partition + [ ! -e "$EXTPATH" ] && ShowError "$EXTPATH does not exist" + + # have to use -m switch for this check b/c parted incorrectly + # reports all ext partitions as ext2 when running print + CHECKEXTFS=`"$CMPARTED" -m "$SDPATH" print | grep ext | cut -d":" -f5` + [ "$CHECKEXTFS" == "$1" ] && ShowError "$EXTPATH is already $1" + + # grabbed the code bits for ext3 from upgrade_fs(credit:cyanogen) + # check for ext2...must upgrade to ext3 first b4 ext4 + if [ "$1" == "ext3" -o "$1" == "ext4" ] ; then + echo -n "adding journaling to $EXTPATH..." + umount /system/sd > /dev/null 2>&1 >>"$LOGFILE" + "$CME2FSCK" -p "$EXTPATH" 2>&1 >>"$LOGFILE" + "$CMTUNE2FS" -c0 -i0 -j "$EXTPATH" 2>&1 >>"$LOGFILE" + echo "done" + fi + + # and got convert to ext4 from xda-forum(credit:Denkai) + if [ "$1" == "ext4" ] ; then + echo -n "converting $EXTPATH to ext4 filesystem..." + umount /system/sd > /dev/null 2>&1 >>"$LOGFILE" + "$CMTUNE2FS" -O extents,uninit_bg,dir_index "$EXTPATH" 2>&1 >>"$LOGFILE" + "$CME2FSCK" -fpDC0 "$EXTPATH" 2>&1 >>"$LOGFILE" + echo "done" + fi + echo + +} + +DowngradeExt() { + + # check for ext partition + [ ! -e "$EXTPATH" ] && ShowError "$EXTPATH does not exist" + + # have to use print for this check b/c parted incorrectly + # reports all ext partitions as ext2 when running print + CHECKEXTFS=`"$CMPARTED" -m "$SDPATH" print | grep ext | cut -d":" -f5` + [ "$CHECKEXTFS" == "$1" ] && ShowError "$EXTPATH is already $1" + + if [ "$CHECKEXTFS" == "ext4" -o "$1" == "ext3" ] ; then + # interweb says downgrading from ext4 is not possible + # without a backup/restore procedure. + # if i figure it out, i'll implement it. + ShowError "downgrading from ext4 is not currently supported" + fi + + if [ "$1" == "ext2" ] ; then + echo -n "removing journaling from $EXTPATH..." + umount /system/sd > /dev/null 2>&1 >>"$LOGFILE" + "$CMTUNE2FS" -O ^has_journal "$EXTPATH" 2>&1 >>"$LOGFILE" + "$CME2FSCK" -fp "$EXTPATH" 2>&1 >>"$LOGFILE" + echo "done" + fi + echo + +} + + +Interactive() { + +cat < /dev/null 2>&1 >>"$LOGFILE" + + ValidateSizeArg "$SWAPRESP" + SWAPTEST="$FUNC_RET" + [ -n "$SWAPTEST" ] && [ $SWAPTEST -gt $SDSIZE ] && ShowMessage "$SWAPRESP > available space($(($SDSIZE))M)." && SWAPTEST= + done + + SWAPSIZE=$SWAPTEST + +} + +GetExtSize() { + + EXTTEST= + + while [ -z "$EXTTEST" ] + do + echo + echo -n "ext partition size [default=$EXTSIZE]: " + read EXTRESP + + [ -z "$EXTRESP" ] && EXTRESP="$EXTSIZE" + echo "$EXTRESP" > /dev/null 2>&1 >>"$LOGFILE" + + ValidateSizeArg "$EXTRESP" + EXTTEST="$FUNC_RET" + + [ -n "$EXTTEST" ] && [ $EXTTEST -gt $(($SDSIZE - $SWAPSIZE)) ] && ShowMessage "$EXTRESP > available space($(($SDSIZE - $SWAPSIZE))M)." && EXTTEST= + done + + EXTSIZE=$EXTTEST + +} + +GetExtType() { + + FSTEST= + + while [ -z "$FSTEST" ] + do + echo + echo -n "ext partition type [default=$EXTFS]: " + read FSRESP + + [ -z "$FSRESP" ] && FSRESP="$EXTFS" + echo "$FSRESP" > /dev/null 2>&1 >>"$LOGFILE" + + ValidateExtArg "$FSRESP" + FSTEST="$FUNC_RET" + done + + EXTFS="$FSTEST" + +} + +GetFatSize() { + + FATTEST= + + while [ -z "$FATTEST" ] + do + echo + echo -n "fat partition size [default=$FATSIZE]: " + read FATRESP + + [ -z "$FATRESP" ] && FATRESP="$FATSIZE" + echo "$FATRESP" > /dev/null 2>&1 >>"$LOGFILE" + + ValidateSizeArg "$FATRESP" + FATTEST="$FUNC_RET" + + [ -n "$FATTEST" ] && [ $FATTEST -gt $FATSIZE ] && ShowMessage "$FATRESP > available space($(($SDSIZE - $SWAPSIZE - $EXTSIZE))M)." && FATTEST= + [ -n "$FATTEST" ] && [ $FATTEST -le 0 ] && ShowMessage "must have a fat32 partition greater than 0MB" && FATTEST= + done + + FATSIZE=$FATTEST + +} + + +SCRIPTNAME="sdparted" +SCRIPTREV="0.6" +MYNAME="51dusty" + +IMODE= +SILENTRUN= +CREATEPART= +FUNC_RET= + +UEXTFSONLY= +DEXTFSONLY= + +TTISOK= +TTISLOOP= +TTISMSDOS= + +SDSIZE= +SDSIZEMB= +if [ -z "$SDPATH" ] +then + SDPATH="/dev/block/mmcblk0" +else + echo Found SDPATH=$SDPATH +fi + +FATSIZE= +FATTYPE="fat32" +FATPATH=$SDPATH"p1" + +EXTSIZE=512 +EXTFS="ext2" +EXTPATH=$SDPATH"p2" +EXTEND= + +SWAPSIZE=32 +SWAPTYPE="linux-swap" +SWAPPATH=$SDPATH"p3" +SWAPEND= + +CMPARTED="/sbin/parted" +CMTUNE2FS="/sbin/tune2fs" +CME2FSCK="/sbin/e2fsck" + +# give the output some breathing room +echo "$SCRIPTREV" >> "$LOGFILE" +echo + +# check for arguments +while [ $# -gt 0 ] ; do + case "$1" in + + -h|--help) ShowHelp ; exit 0 ;; + + -fs|--fatsize) shift ; ValidateSizeArg "$1" ; FATSIZE="$FUNC_RET" ; CREATEPART="$1" ;; + -es|--extsize) shift ; ValidateSizeArg "$1" ; EXTSIZE="$FUNC_RET" ; CREATEPART="$1" ;; + -ss|--swapsize) shift ; ValidateSizeArg "$1" ; SWAPSIZE="$FUNC_RET" ; CREATEPART="$1" ;; + -efs|--extfs) shift ; ValidateExtArg "$1" ; EXTFS="$FUNC_RET" ; CREATEPART="$1" ;; + + -ufs|--upgradefs) shift ; ValidateExtArg "$1" ; UEXTFSONLY="$FUNC_RET" ;; + -dfs|--downgradefs) shift ; ValidateExtArg "$1" ; DEXTFSONLY="$FUNC_RET" ;; + + -i|--interactive) IMODE="$1" ;; + + -s|--silent) SILENTRUN="$1" ;; + + -po|--printonly) ShowCardInfo ;; + + *) ShowHelp ; ShowError "unknown argument '$1'" ;; + + esac + shift +done + +# can't do silent when in interactive mode +[ -n "$IMODE" ] && SILENTRUN= + +# make sure sdcard exists and all needed files are here +CheckReqs + +# unmount all +UnmountAll + +# upgrade only? downgrade only? +UpgradeDowngradeOnly + +# check table +CheckTableType + +# prep card +PrepareSdCard + +# check for interactive mode +[ -n "$IMODE" ] && Interactive + +# do some math +CalculatePartitions + +# last chance to cancel +ShowActions + +# partition card +PartitionSdCard + +# upgrade fs if necessary +UpgradeExt "$EXTFS" + +# say goodbye and show print output +ShowCardInfo diff --git a/utilities/tune2fs b/utilities/tune2fs new file mode 100755 index 0000000..4bd02f6 Binary files /dev/null and b/utilities/tune2fs differ