diff options
author | Dees_Troy <dees_troy@teamw.in> | 2013-04-02 22:22:16 +0200 |
---|---|---|
committer | Dees_Troy <dees_troy@teamw.in> | 2013-04-04 20:57:34 +0200 |
commit | 2673cec07a4740f86438b50cfe1b70b258a9a8c8 (patch) | |
tree | 3133d98e33eba4fab9760f9a4a54aeac83107119 /twinstall.cpp | |
parent | Add partition list GUI element (diff) | |
download | android_bootable_recovery-2673cec07a4740f86438b50cfe1b70b258a9a8c8.tar android_bootable_recovery-2673cec07a4740f86438b50cfe1b70b258a9a8c8.tar.gz android_bootable_recovery-2673cec07a4740f86438b50cfe1b70b258a9a8c8.tar.bz2 android_bootable_recovery-2673cec07a4740f86438b50cfe1b70b258a9a8c8.tar.lz android_bootable_recovery-2673cec07a4740f86438b50cfe1b70b258a9a8c8.tar.xz android_bootable_recovery-2673cec07a4740f86438b50cfe1b70b258a9a8c8.tar.zst android_bootable_recovery-2673cec07a4740f86438b50cfe1b70b258a9a8c8.zip |
Diffstat (limited to '')
-rw-r--r-- | twinstall.cpp | 349 |
1 files changed, 97 insertions, 252 deletions
diff --git a/twinstall.cpp b/twinstall.cpp index e1133c01e..e7d23ecaf 100644 --- a/twinstall.cpp +++ b/twinstall.cpp @@ -1,18 +1,3 @@ -/* - * Copyright (C) 2007 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 <ctype.h> #include <errno.h> @@ -25,7 +10,7 @@ #include <string.h> #include <stdio.h> -#include "common.h" +#include "twcommon.h" #include "mincrypt/rsa.h" #include "mincrypt/sha.h" #include "minui/minui.h" @@ -33,290 +18,150 @@ #include "minzip/Zip.h" #include "mtdutils/mounts.h" #include "mtdutils/mtdutils.h" -#include "roots.h" #include "verifier.h" -#include "ui.h" #include "variables.h" #include "data.hpp" #include "partitions.hpp" #include "twrpDigest.hpp" #include "twrp-functions.hpp" +extern "C" { + #include "gui/gui.h" +} -extern RecoveryUI* ui; - -#define ASSUMED_UPDATE_BINARY_NAME "META-INF/com/google/android/update-binary" -#define PUBLIC_KEYS_FILE "/res/keys" - -// Default allocation of progress bar segments to operations -static const int VERIFICATION_PROGRESS_TIME = 60; -static const float VERIFICATION_PROGRESS_FRACTION = 0.25; -static const float DEFAULT_FILES_PROGRESS_FRACTION = 0.4; -static const float DEFAULT_IMAGE_PROGRESS_FRACTION = 0.1; - -enum { INSTALL_SUCCESS, INSTALL_ERROR, INSTALL_CORRUPT }; - -// If the package contains an update binary, extract it and run it. -static int -try_update_binary(const char *path, ZipArchive *zip, int* wipe_cache) { - const ZipEntry* binary_entry = - mzFindZipEntry(zip, ASSUMED_UPDATE_BINARY_NAME); - if (binary_entry == NULL) { - mzCloseZipArchive(zip); - return INSTALL_CORRUPT; - } +static int Run_Update_Binary(const char *path, ZipArchive *Zip, int* wipe_cache) { + const ZipEntry* binary_location = mzFindZipEntry(Zip, ASSUMED_UPDATE_BINARY_NAME); + string Temp_Binary = "/tmp/updater"; + int binary_fd, ret_val, pipe_fd[2], status, zip_verify; + char buffer[1024]; + const char** args = (const char**)malloc(sizeof(char*) * 5); + FILE* child_data; - const char* binary = "/tmp/update_binary"; - unlink(binary); - int fd = creat(binary, 0755); - if (fd < 0) { - mzCloseZipArchive(zip); - LOGE("Can't make %s\n", binary); - return INSTALL_ERROR; - } - bool ok = mzExtractZipEntryToFile(zip, binary_entry, fd); - close(fd); - mzCloseZipArchive(zip); + if (binary_location == NULL) { + mzCloseZipArchive(Zip); + return INSTALL_CORRUPT; + } - if (!ok) { - LOGE("Can't copy %s\n", ASSUMED_UPDATE_BINARY_NAME); - return INSTALL_ERROR; - } + // Delete any existing updater + if (TWFunc::Path_Exists(Temp_Binary) && unlink(Temp_Binary.c_str()) != 0) { + LOGINFO("Unable to unlink '%s'\n", Temp_Binary.c_str()); + } - int pipefd[2]; - pipe(pipefd); + binary_fd = creat(Temp_Binary.c_str(), 0755); + if (binary_fd < 0) { + mzCloseZipArchive(Zip); + LOGERR("Could not create file for updater extract in '%s'\n", Temp_Binary.c_str()); + return INSTALL_ERROR; + } - // When executing the update binary contained in the package, the - // arguments passed are: - // - // - the version number for this interface - // - // - an fd to which the program can write in order to update the - // progress bar. The program can write single-line commands: - // - // progress <frac> <secs> - // fill up the next <frac> part of of the progress bar - // over <secs> seconds. If <secs> is zero, use - // set_progress commands to manually control the - // progress of this segment of the bar - // - // set_progress <frac> - // <frac> should be between 0.0 and 1.0; sets the - // progress bar within the segment defined by the most - // recent progress command. - // - // firmware <"hboot"|"radio"> <filename> - // arrange to install the contents of <filename> in the - // given partition on reboot. - // - // (API v2: <filename> may start with "PACKAGE:" to - // indicate taking a file from the OTA package.) - // - // (API v3: this command no longer exists.) - // - // ui_print <string> - // display <string> on the screen. - // - // - the name of the package zip file. - // + ret_val = mzExtractZipEntryToFile(Zip, binary_location, binary_fd); + close(binary_fd); + mzCloseZipArchive(Zip); - const char** args = (const char**)malloc(sizeof(char*) * 5); - args[0] = binary; - args[1] = EXPAND(RECOVERY_API_VERSION); // defined in Android.mk - char* temp = (char*)malloc(10); - sprintf(temp, "%d", pipefd[1]); - args[2] = temp; - args[3] = (char*)path; - args[4] = NULL; + if (!ret_val) { + LOGERR("Could not extract '%s'\n", ASSUMED_UPDATE_BINARY_NAME); + return INSTALL_ERROR; + } - pid_t pid = fork(); - if (pid == 0) { - close(pipefd[0]); - execv(binary, (char* const*)args); - fprintf(stdout, "E:Can't run %s (%s)\n", binary, strerror(errno)); - _exit(-1); - } - close(pipefd[1]); + pipe(pipe_fd); + + args[0] = Temp_Binary.c_str(); + args[1] = EXPAND(RECOVERY_API_VERSION); + char* temp = (char*)malloc(10); + sprintf(temp, "%d", pipe_fd[1]); + args[2] = temp; + args[3] = (char*)path; + args[4] = NULL; + + pid_t pid = fork(); + if (pid == 0) { + close(pipe_fd[0]); + execv(Temp_Binary.c_str(), (char* const*)args); + printf("E:Can't execute '%s'\n", Temp_Binary.c_str()); + _exit(-1); + } + close(pipe_fd[1]); - *wipe_cache = 0; + *wipe_cache = 0; - char buffer[1024]; - FILE* from_child = fdopen(pipefd[0], "r"); - while (fgets(buffer, sizeof(buffer), from_child) != NULL) { - char* command = strtok(buffer, " \n"); + DataManager::GetValue(TW_SIGNED_ZIP_VERIFY_VAR, zip_verify); + child_data = fdopen(pipe_fd[0], "r"); + while (fgets(buffer, sizeof(buffer), child_data) != NULL) { + char* command = strtok(buffer, " \n"); if (command == NULL) { continue; } else if (strcmp(command, "progress") == 0) { - char* fraction_s = strtok(NULL, " \n"); - char* seconds_s = strtok(NULL, " \n"); + char* fraction_char = strtok(NULL, " \n"); + char* seconds_char = strtok(NULL, " \n"); - float fraction = strtof(fraction_s, NULL); - int seconds = strtol(seconds_s, NULL, 10); + float fraction_float = strtof(fraction_char, NULL); + int seconds_float = strtol(seconds_char, NULL, 10); - ui->ShowProgress(fraction * (1-VERIFICATION_PROGRESS_FRACTION), seconds); + if (zip_verify) + DataManager::ShowProgress(fraction_float * (1 - VERIFICATION_PROGRESS_FRACTION), seconds_float); + else + DataManager::ShowProgress(fraction_float, seconds_float); } else if (strcmp(command, "set_progress") == 0) { - char* fraction_s = strtok(NULL, " \n"); - float fraction = strtof(fraction_s, NULL); - ui->SetProgress(fraction); + char* fraction_char = strtok(NULL, " \n"); + float fraction_float = strtof(fraction_char, NULL); + DataManager::SetProgress(fraction_float); } else if (strcmp(command, "ui_print") == 0) { - char* str = strtok(NULL, "\n"); - if (str) { - ui->Print("%s", str); + char* display_value = strtok(NULL, "\n"); + if (display_value) { + gui_print("%s", display_value); } else { - ui->Print("\n"); + gui_print("\n"); } } else if (strcmp(command, "wipe_cache") == 0) { *wipe_cache = 1; } else if (strcmp(command, "clear_display") == 0) { - //ui->SetBackground(RecoveryUI::NONE); + // Do nothing, not supported by TWRP } else { - LOGE("unknown command [%s]\n", command); - } - } - fclose(from_child); - - int status; - waitpid(pid, &status, 0); - if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { - LOGE("Error in %s\n(Status %d)\n", path, WEXITSTATUS(status)); - return INSTALL_ERROR; - } - - return INSTALL_SUCCESS; -} - -// Reads a file containing one or more public keys as produced by -// DumpPublicKey: this is an RSAPublicKey struct as it would appear -// as a C source literal, eg: -// -// "{64,0xc926ad21,{1795090719,...,-695002876},{-857949815,...,1175080310}}" -// -// (Note that the braces and commas in this example are actual -// characters the parser expects to find in the file; the ellipses -// indicate more numbers omitted from this example.) -// -// The file may contain multiple keys in this format, separated by -// commas. The last key must not be followed by a comma. -// -// Returns NULL if the file failed to parse, or if it contain zero keys. -static RSAPublicKey* -load_keys(const char* filename, int* numKeys) { - RSAPublicKey* out = NULL; - *numKeys = 0; - - FILE* f = fopen(filename, "r"); - if (f == NULL) { - LOGE("opening %s: %s\n", filename, strerror(errno)); - goto exit; - } - - { - int i; - bool done = false; - while (!done) { - ++*numKeys; - out = (RSAPublicKey*)realloc(out, *numKeys * sizeof(RSAPublicKey)); - RSAPublicKey* key = out + (*numKeys - 1); - if (fscanf(f, " { %i , 0x%x , { %u", - &(key->len), &(key->n0inv), &(key->n[0])) != 3) { - goto exit; - } - if (key->len != RSANUMWORDS) { - LOGE("key length (%d) does not match expected size\n", key->len); - goto exit; - } - for (i = 1; i < key->len; ++i) { - if (fscanf(f, " , %u", &(key->n[i])) != 1) goto exit; - } - if (fscanf(f, " } , { %u", &(key->rr[0])) != 1) goto exit; - for (i = 1; i < key->len; ++i) { - if (fscanf(f, " , %u", &(key->rr[i])) != 1) goto exit; - } - fscanf(f, " } } "); - - // if the line ends in a comma, this file has more keys. - switch (fgetc(f)) { - case ',': - // more keys to come. - break; - - case EOF: - done = true; - break; - - default: - LOGE("unexpected character between keys\n"); - goto exit; - } + LOGERR("unknown command [%s]\n", command); } - } + } + fclose(child_data); - fclose(f); - return out; + waitpid(pid, &status, 0); + if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { + LOGERR("Error executing updater binary in zip '%s'\n", path); + return INSTALL_ERROR; + } -exit: - if (f) fclose(f); - free(out); - *numKeys = 0; - return NULL; + return INSTALL_SUCCESS; } extern "C" int TWinstall_zip(const char* path, int* wipe_cache) { - int err, zip_verify, md5_return; + int ret_val, zip_verify, md5_return, key_count; twrpDigest md5sum; string strpath = path; - ui_print("Installing '%s'...\n", path); + ZipArchive Zip; - if (!PartitionManager.Mount_By_Path(path, 0)) { - LOGE("Failed to mount '%s'\n", path); - return -1; - } - - ui_print("Checking for MD5 file...\n"); + gui_print("Installing '%s'...\nChecking for MD5 file...\n", path); md5sum.setfn(strpath); md5_return = md5sum.verify_md5digest(); if (md5_return == -2) { // MD5 did not match. - LOGE("Zip MD5 does not match.\nUnable to install zip.\n"); + LOGERR("Zip MD5 does not match.\nUnable to install zip.\n"); return INSTALL_CORRUPT; } else if (md5_return == -1) { - ui_print("Skipping MD5 check: no MD5 file found.\n"); + gui_print("Skipping MD5 check: no MD5 file found.\n"); } else if (md5_return == 0) - ui_print("Zip MD5 matched.\n"); // MD5 found and matched. + gui_print("Zip MD5 matched.\n"); // MD5 found and matched. DataManager::GetValue(TW_SIGNED_ZIP_VERIFY_VAR, zip_verify); + DataManager::SetProgress(0); if (zip_verify) { - ui_print("Verifying zip signature...\n"); - int numKeys; - RSAPublicKey* loadedKeys = load_keys(PUBLIC_KEYS_FILE, &numKeys); - if (loadedKeys == NULL) { - LOGE("Failed to load keys\n"); - return -1; - } - LOGI("%d key(s) loaded from %s\n", numKeys, PUBLIC_KEYS_FILE); - - // Give verification half the progress bar... - ui->Print("Verifying update package...\n"); - ui->SetProgressType(RecoveryUI::DETERMINATE); - ui->ShowProgress(VERIFICATION_PROGRESS_FRACTION, VERIFICATION_PROGRESS_TIME); - - err = verify_file(path, loadedKeys, numKeys); - free(loadedKeys); - LOGI("verify_file returned %d\n", err); - if (err != VERIFY_SUCCESS) { - LOGE("signature verification failed\n"); + gui_print("Verifying zip signature...\n"); + ret_val = verify_file(path); + if (ret_val != VERIFY_SUCCESS) { + LOGERR("Zip signature verification failed: %i\n", ret_val); return -1; } } - /* Try to open the package. - */ - ZipArchive zip; - err = mzOpenZipArchive(path, &zip); - if (err != 0) { - LOGE("Can't open %s\n(%s)\n", path, err != -1 ? strerror(err) : "bad"); - return INSTALL_CORRUPT; - } - - /* Verify and install the contents of the package. - */ - return try_update_binary(path, &zip, wipe_cache); + ret_val = mzOpenZipArchive(path, &Zip); + if (ret_val != 0) { + LOGERR("Zip file is corrupt!\n", path); + return INSTALL_CORRUPT; + } + return Run_Update_Binary(path, &Zip, wipe_cache); } |