working recovery image!
diff --git a/default_recovery_ui.c b/default_recovery_ui.c
index 025ee98..3514477 100644
--- a/default_recovery_ui.c
+++ b/default_recovery_ui.c
@@ -27,6 +27,7 @@
"apply sdcard:update.zip",
"wipe data/factory reset",
"wipe cache partition",
+ "install zip from sdcard",
"toggle signature verification",
"toggle script asserts",
NULL };
@@ -56,6 +57,9 @@
case KEY_ENTER:
case BTN_MOUSE:
return SELECT_ITEM;
+ case KEY_BACKSPACE:
+ case KEY_END:
+ return GO_BACK;
}
}
diff --git a/extendedcommands.c b/extendedcommands.c
index b2aacc9..4ef23f7 100644
--- a/extendedcommands.c
+++ b/extendedcommands.c
@@ -12,6 +12,10 @@
#include <time.h>
#include <unistd.h>
+#include <sys/wait.h>
+#include <sys/limits.h>
+#include <dirent.h>
+
#include "bootloader.h"
#include "common.h"
#include "cutils/properties.h"
@@ -35,5 +39,100 @@
void toggle_script_asserts()
{
script_assert_enabled = !script_assert_enabled;
- ui_print("Script Asserts: %s\n", signature_check_enabled ? "Enabled" : "Disabled");
+ ui_print("Script Asserts: %s\n", script_assert_enabled ? "Enabled" : "Disabled");
+}
+
+void show_choose_zip_menu()
+{
+ static char* headers[] = { "Choose a zip or press POWER to return",
+ "",
+ NULL };
+
+ char path[PATH_MAX] = "";
+ DIR *dir;
+ struct dirent *de;
+ int total = 0;
+ int i;
+ char** files;
+ char** list;
+
+ if (ensure_root_path_mounted("SDCARD:") != 0) {
+ LOGE ("Can't mount /sdcard\n");
+ return;
+ }
+
+ dir = opendir("/sdcard");
+ if (dir == NULL) {
+ LOGE("Couldn't open /sdcard");
+ return;
+ }
+
+ const char *extension = ".zip";
+ const int extension_length = strlen(extension);
+
+ while ((de=readdir(dir)) != NULL) {
+ if (de->d_name[0] != '.' && strlen(de->d_name) > extension_length && strcmp(de->d_name + strlen(de->d_name) - extension_length, extension) == 0) {
+ total++;
+ }
+ }
+
+ if (total==0) {
+ LOGE("No tar archives found\n");
+ if(closedir(dir) < 0) {
+ LOGE("Failed to close directory /sdcard");
+ return;
+ }
+ }
+ else {
+ files = (char**) malloc((total+1)*sizeof(char*));
+ files[total]=NULL;
+
+ list = (char**) malloc((total+1)*sizeof(char*));
+ list[total]=NULL;
+
+ rewinddir(dir);
+
+ i = 0;
+ while ((de = readdir(dir)) != NULL) {
+ if (de->d_name[0] != '.' && strlen(de->d_name) > extension_length && strcmp(de->d_name + strlen(de->d_name) - extension_length, extension) == 0) {
+ files[i] = (char*) malloc(strlen("/sdcard/")+strlen(de->d_name)+1);
+ strcpy(files[i], "/sdcard/");
+ strcat(files[i], de->d_name);
+
+ list[i] = (char*) malloc(strlen(de->d_name)+1);
+ strcpy(list[i], de->d_name);
+
+ i++;
+ }
+ }
+
+ if (closedir(dir) <0) {
+ LOGE("Failure closing directory /sdcard\n");
+ return;
+ }
+
+ int chosen_item = get_menu_selection(headers, list, 1);
+ if (chosen_item >= 0 && chosen_item != GO_BACK) {
+ char sdcard_package_file[1024];
+ strcpy(sdcard_package_file, "SDCARD:");
+ strcat(sdcard_package_file, files[chosen_item] + strlen("/sdcard"));
+
+ ui_print("\n-- Install from sdcard...\n");
+ set_sdcard_update_bootloader_message();
+ int status = install_package(sdcard_package_file);
+ if (status != INSTALL_SUCCESS) {
+ ui_set_background(BACKGROUND_ICON_ERROR);
+ ui_print("Installation aborted.\n");
+ } else if (!ui_text_visible()) {
+ return; // reboot if logs aren't visible
+ } else {
+ if (firmware_update_pending()) {
+ ui_print("\nReboot via menu to complete\n"
+ "installation.\n");
+ } else {
+ ui_print("\nInstall from sdcard complete.\n");
+ }
+ }
+ }
+ }
}
\ No newline at end of file
diff --git a/extendedcommands.h b/extendedcommands.h
index 5b82960..a4d4992 100644
--- a/extendedcommands.h
+++ b/extendedcommands.h
@@ -2,4 +2,10 @@
extern int script_assert_enabled;
void
-toggle_signature_check();
\ No newline at end of file
+toggle_signature_check();
+
+void
+toggle_script_asserts();
+
+void
+show_choose_zip_menu();
\ No newline at end of file
diff --git a/install.c b/install.c
index 3a37b4a..5768960 100644
--- a/install.c
+++ b/install.c
@@ -106,7 +106,7 @@
const ZipEntry* binary_entry =
mzFindZipEntry(zip, ASSUMED_UPDATE_BINARY_NAME);
if (binary_entry == NULL) {
- return INSTALL_UPDATE_BINARY_MISSING;
+ return INSTALL_ERROR;
}
char* binary = "/tmp/update_binary";
@@ -242,17 +242,21 @@
// Update should take the rest of the progress bar.
ui_print("Installing update...\n");
- int result = try_update_binary(path, zip);
- if (result == INSTALL_UPDATE_BINARY_MISSING)
- {
- if (register_package_root(zip, path) < 0) {
- LOGE("Can't register package root\n");
- return INSTALL_ERROR;
- }
- const ZipEntry *script_entry;
- script_entry = find_update_script(zip);
- result = handle_update_script(zip, script_entry);
+ // Try installing via the update-script first, because we
+ // have more control over the asserts it may contain.
+ // If it does not exist, try the update-binary.
+ if (register_package_root(zip, path) < 0) {
+ LOGE("Can't register package root\n");
+ return INSTALL_ERROR;
}
+ const ZipEntry *script_entry;
+ script_entry = find_update_script(zip);
+ int result = handle_update_script(zip, script_entry);
+ if (result == INSTALL_UPDATE_SCRIPT_MISSING)
+ {
+ result = try_update_binary(path, zip);
+ }
+
register_package_root(NULL, NULL); // Unregister package root
return result;
}
diff --git a/install.h b/install.h
index 42c1444..3ee814b 100644
--- a/install.h
+++ b/install.h
@@ -19,7 +19,7 @@
#include "common.h"
-enum { INSTALL_SUCCESS, INSTALL_ERROR, INSTALL_CORRUPT, INSTALL_UPDATE_BINARY_MISSING };
+enum { INSTALL_SUCCESS, INSTALL_ERROR, INSTALL_CORRUPT, INSTALL_UPDATE_SCRIPT_MISSING };
int install_package(const char *root_path);
#endif // RECOVERY_INSTALL_H_
diff --git a/legacy.c b/legacy.c
index dab06ad..cf903ce 100644
--- a/legacy.c
+++ b/legacy.c
@@ -90,7 +90,7 @@
char* script_data;
if (read_data(zip, update_script_entry, &script_data, &script_len) < 0) {
LOGE("Can't read update script\n");
- return INSTALL_ERROR;
+ return INSTALL_UPDATE_SCRIPT_MISSING;
}
/* Parse the script. Note that the script and parse tree are never freed.
diff --git a/recovery.c b/recovery.c
index b857610..7a12e10 100644
--- a/recovery.c
+++ b/recovery.c
@@ -212,7 +212,7 @@
set_bootloader_message(&boot);
}
-static void
+void
set_sdcard_update_bootloader_message()
{
struct bootloader_message boot;
@@ -303,7 +303,7 @@
return new_headers;
}
-static int
+int
get_menu_selection(char** headers, char** items, int menu_only) {
// throw away keys pressed previously, so user doesn't
// accidentally trigger menu items.
@@ -334,6 +334,8 @@
break;
case NO_ACTION:
break;
+ case GO_BACK:
+ return GO_BACK;
}
} else if (!menu_only) {
chosen_item = action;
@@ -439,6 +441,9 @@
case ITEM_ASSERTS:
toggle_script_asserts();
break;
+ case ITEM_INSTALL_ZIP:
+ show_choose_zip_menu();
+ break;
}
}
}
diff --git a/recovery_ui.h b/recovery_ui.h
index 1aabbdf..4d3d3e2 100644
--- a/recovery_ui.h
+++ b/recovery_ui.h
@@ -61,13 +61,15 @@
#define HIGHLIGHT_UP -2
#define HIGHLIGHT_DOWN -3
#define SELECT_ITEM -4
+#define GO_BACK -5
#define ITEM_REBOOT 0
#define ITEM_APPLY_SDCARD 1
#define ITEM_WIPE_DATA 2
#define ITEM_WIPE_CACHE 3
-#define ITEM_SIG_CHECK 4
-#define ITEM_ASSERTS 5
+#define ITEM_INSTALL_ZIP 4
+#define ITEM_SIG_CHECK 5
+#define ITEM_ASSERTS 6
// Header text to display above the main menu.
extern char* MENU_HEADERS[];
@@ -75,4 +77,10 @@
// Text of menu items.
extern char* MENU_ITEMS[];
+int
+get_menu_selection(char** headers, char** items, int menu_only);
+
+void
+set_sdcard_update_bootloader_message();
+
#endif