diff --git a/Android.mk b/Android.mk index e4a3ad0..ab3a6fd 100644 --- a/Android.mk +++ b/Android.mk @@ -19,6 +19,7 @@ LOCAL_SRC_FILES := \ extendedcommands.c \ nandroid.c \ reboot.c \ + edifyscripting.c \ setprop.c LOCAL_MODULE := recovery @@ -55,7 +56,7 @@ endif LOCAL_STATIC_LIBRARIES += libext4_utils libz LOCAL_STATIC_LIBRARIES += libminzip libunz libmincrypt -LOCAL_STATIC_LIBRARIES += libbusybox libclearsilverregex libmkyaffs2image libunyaffs liberase_image libdump_image libflash_image +LOCAL_STATIC_LIBRARIES += libedify libbusybox libclearsilverregex libmkyaffs2image libunyaffs liberase_image libdump_image libflash_image LOCAL_STATIC_LIBRARIES += libflashutils libmtdutils libmmcutils libbmlutils LOCAL_STATIC_LIBRARIES += libminui libpixelflinger_static libpng libcutils diff --git a/edifyscripting.c b/edifyscripting.c new file mode 100644 index 0000000..3b0d4c9 --- /dev/null +++ b/edifyscripting.c @@ -0,0 +1,267 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include "bootloader.h" +#include "common.h" +#include "cutils/properties.h" +#include "firmware.h" +#include "install.h" +#include "minui/minui.h" +#include "minzip/DirUtil.h" +#include "roots.h" +#include "recovery_ui.h" + +#include "../../external/yaffs2/yaffs2/utils/mkyaffs2image.h" +#include "../../external/yaffs2/yaffs2/utils/unyaffs.h" + +#include "extendedcommands.h" +#include "nandroid.h" +#include "mounts.h" +#include "flashutils/flashutils.h" +#include "edify/expr.h" +#include "mtdutils/mtdutils.h" +#include "mmcutils/mmcutils.h" +//#include "edify/parser.h" + +Value* UIPrintFn(const char* name, State* state, int argc, Expr* argv[]) { + char** args = ReadVarArgs(state, argc, argv); + if (args == NULL) { + return NULL; + } + + int size = 0; + int i; + for (i = 0; i < argc; ++i) { + size += strlen(args[i]); + } + char* buffer = malloc(size+1); + size = 0; + for (i = 0; i < argc; ++i) { + strcpy(buffer+size, args[i]); + size += strlen(args[i]); + free(args[i]); + } + free(args); + buffer[size] = '\0'; + + char* line = strtok(buffer, "\n"); + while (line) { + ui_print("%s\n", line); + line = strtok(NULL, "\n"); + } + + return StringValue(buffer); +} + +Value* RunProgramFn(const char* name, State* state, int argc, Expr* argv[]) { + if (argc < 1) { + return ErrorAbort(state, "%s() expects at least 1 arg", name); + } + char** args = ReadVarArgs(state, argc, argv); + if (args == NULL) { + return NULL; + } + + char** args2 = malloc(sizeof(char*) * (argc+1)); + memcpy(args2, args, sizeof(char*) * argc); + args2[argc] = NULL; + + fprintf(stderr, "about to run program [%s] with %d args\n", args2[0], argc); + + pid_t child = fork(); + if (child == 0) { + execv(args2[0], args2); + fprintf(stderr, "run_program: execv failed: %s\n", strerror(errno)); + _exit(1); + } + int status; + waitpid(child, &status, 0); + if (WIFEXITED(status)) { + if (WEXITSTATUS(status) != 0) { + fprintf(stderr, "run_program: child exited with status %d\n", + WEXITSTATUS(status)); + } + } else if (WIFSIGNALED(status)) { + fprintf(stderr, "run_program: child terminated by signal %d\n", + WTERMSIG(status)); + } + + int i; + for (i = 0; i < argc; ++i) { + free(args[i]); + } + free(args); + free(args2); + + char buffer[20]; + sprintf(buffer, "%d", status); + + return StringValue(strdup(buffer)); +} + +Value* FormatFn(const char* name, State* state, int argc, Expr* argv[]) { + char* result = NULL; + if (argc != 1) { + return ErrorAbort(state, "%s() expects 1 arg, got %d", name, argc); + } + + char *path; + if (ReadArgs(state, argv, 1, &path) < 0) { + return NULL; + } + + ui_print("Formatting %s...\n", path); + if (0 != format_volume(path)) { + free(path); + return StringValue(strdup("")); + } + +done: + return StringValue(strdup(path)); +} + +Value* BackupFn(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 != nandroid_backup(path)) + return StringValue(strdup("")); + + return StringValue(strdup(path)); +} + +Value* RestoreFn(const char* name, State* state, int argc, Expr* argv[]) { + if (argc < 1) { + return ErrorAbort(state, "%s() expects at least 1 arg", name); + } + char** args = ReadVarArgs(state, argc, argv); + if (args == NULL) { + return NULL; + } + + char** args2 = malloc(sizeof(char*) * (argc+1)); + memcpy(args2, args, sizeof(char*) * argc); + args2[argc] = NULL; + + char* path = strdup(args2[0]); + int restoreboot = 1; + int restoresystem = 1; + int restoredata = 1; + int restorecache = 1; + int restoresdext = 1; + int i; + for (i = 1; i < argc; i++) + { + if (args2[i] == NULL) + continue; + if (strcmp(args2[i], "noboot") == 0) + restoreboot = 0; + else if (strcmp(args2[i], "nosystem") == 0) + restoresystem = 0; + else if (strcmp(args2[i], "nodata") == 0) + restoredata = 0; + else if (strcmp(args2[i], "nocache") == 0) + restorecache = 0; + else if (strcmp(args2[i], "nosd-ext") == 0) + restoresdext = 0; + } + + for (i = 0; i < argc; ++i) { + free(args[i]); + } + free(args); + free(args2); + + if (0 != nandroid_restore(path, restoreboot, restoresystem, restoredata, restorecache, restoresdext)) { + free(path); + return StringValue(strdup("")); + } + + return StringValue(path); +} + +Value* InstallZipFn(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 != install_zip(path)) + return StringValue(strdup("")); + + return StringValue(strdup(path)); +} + +void RegisterRecoveryHooks() { + RegisterFunction("format", FormatFn); + RegisterFunction("ui_print", UIPrintFn); + RegisterFunction("run_program", RunProgramFn); + RegisterFunction("backup_rom", BackupFn); + RegisterFunction("restore_rom", RestoreFn); + RegisterFunction("install_zip", InstallZipFn); +} + +static int hasInitializedEdify = 0; +int run_script_from_buffer(char* script_data, int script_len, char* filename) +{ + if (!hasInitializedEdify) { + RegisterBuiltins(); + RegisterRecoveryHooks(); + FinishRegistration(); + hasInitializedEdify = 1; + } + + Expr* root; + int error_count = 0; + yy_scan_bytes(script_data, script_len); + int error = yyparse(&root, &error_count); + printf("parse returned %d; %d errors encountered\n", error, error_count); + if (error == 0 || error_count > 0) { + //ExprDump(0, root, buffer); + + State state; + state.cookie = NULL; + state.script = script_data; + state.errmsg = NULL; + + char* result = Evaluate(&state, root); + if (result == NULL) { + printf("result was NULL, message is: %s\n", + (state.errmsg == NULL ? "(NULL)" : state.errmsg)); + free(state.errmsg); + return -1; + } else { + printf("result is [%s]\n", result); + } + } + return 0; +} diff --git a/extendedcommands.c b/extendedcommands.c index 7eec4c0..ad83a0a 100644 --- a/extendedcommands.c +++ b/extendedcommands.c @@ -37,6 +37,7 @@ #include "nandroid.h" #include "mounts.h" #include "flashutils/flashutils.h" +#include "edify/expr.h" int signature_check_enabled = 1; int script_assert_enabled = 1; @@ -474,7 +475,7 @@ void show_partition_menu() for (i = 0; i < DEVICE_COUNT; i++) { - options[DEVICE_COUNT + i] = devices[i][0]; + options[MOUNTABLE_COUNT + i] = devices[i][0]; } options[MOUNTABLE_COUNT + DEVICE_COUNT] = "mount USB storage"; @@ -522,33 +523,52 @@ int extendedcommand_file_exists() return 0 == stat(EXTENDEDCOMMAND_SCRIPT, &file_info); } -int run_script_from_buffer(char* script_data, int script_len, char* filename) -{ - ui_print("not yet implemented.\n"); - return -1; +int edify_main(int argc, char** argv) { + load_volume_table(); + process_volumes(); + RegisterBuiltins(); + RegisterRecoveryHooks(); + FinishRegistration(); - /* - const AmCommandList *commands = parseAmendScript(script_data, script_len); - if (commands == NULL) { - printf("Syntax error in update script\n"); + if (argc != 2) { + printf("edify \n"); return 1; - } else { - printf("Parsed %.*s\n", script_len, filename); } - int ret = execCommandList((ExecContext *)1, commands); - if (ret != 0) { - int num = ret; - char *line = NULL, *next = script_data; - while (next != NULL && ret-- > 0) { - line = next; - next = memchr(line, '\n', script_data + script_len - line); - if (next != NULL) *next++ = '\0'; + FILE* f = fopen(argv[1], "r"); + if (f == NULL) { + printf("%s: %s: No such file or directory\n", argv[0], argv[1]); + return 1; + } + char buffer[8192]; + int size = fread(buffer, 1, 8191, f); + fclose(f); + buffer[size] = '\0'; + + Expr* root; + int error_count = 0; + yy_scan_bytes(buffer, size); + int error = yyparse(&root, &error_count); + printf("parse returned %d; %d errors encountered\n", error, error_count); + if (error == 0 || error_count > 0) { + + //ExprDump(0, root, buffer); + + State state; + state.cookie = NULL; + state.script = buffer; + state.errmsg = NULL; + + char* result = Evaluate(&state, root); + if (result == NULL) { + printf("result was NULL, message is: %s\n", + (state.errmsg == NULL ? "(NULL)" : state.errmsg)); + free(state.errmsg); + } else { + printf("result is [%s]\n", result); } - printf("Failure at line %d:\n%s\n", num, next ? line : "(not found)"); - return 1; } - */ + return 0; } int run_script(char* filename) @@ -928,7 +948,7 @@ int bml_check_volume(const char *path) { return 0; } - ui_print("%s may be rfs. Checking...\n"); + ui_print("%s may be rfs. Checking...\n", path); char tmp[PATH_MAX]; sprintf(tmp, "mount -t rfs %s %s", vol->device, path); int ret = __system(tmp); @@ -958,8 +978,9 @@ void process_volumes() { ui_set_show_text(1); ui_print("Filesystems need to be converted to ext4.\n"); ui_print("A backup and restore will now take place.\n"); - ui_print("If anything goes wrong, your back will be\n"); - ui_print("named before-ext4-convert.\n"); + ui_print("If anything goes wrong, your backup will be\n"); + ui_print("named before-ext4-convert. Try restoring it\n"); + ui_print("in case of error.\n"); nandroid_backup("/sdcard/clockworkmod/backup/before-ext4-convert"); nandroid_restore("/sdcard/clockworkmod/backup/before-ext4-convert", 1, 1, 1, 1, 1); diff --git a/recovery.c b/recovery.c index 5e25e68..4fa4587 100644 --- a/recovery.c +++ b/recovery.c @@ -766,6 +766,8 @@ main(int argc, char **argv) { { if (strstr(argv[0], "flash_image") != NULL) return flash_image_main(argc, argv); + if (strstr(argv[0], "edify") != NULL) + return edify_main(argc, argv); if (strstr(argv[0], "dump_image") != NULL) return dump_image_main(argc, argv); if (strstr(argv[0], "erase_image") != NULL)