Home | History | Annotate | Download | only in updater
      1 /*
      2  * Copyright (C) 2009 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include <errno.h>
     18 #include <stdarg.h>
     19 #include <stdio.h>
     20 #include <stdlib.h>
     21 #include <string.h>
     22 #include <sys/stat.h>
     23 #include <unistd.h>
     24 
     25 #include "edify/expr.h"
     26 #include "firmware.h"
     27 #include "mincrypt/sha.h"
     28 #include "minzip/Zip.h"
     29 #include "mtdutils/mounts.h"
     30 #include "updater/updater.h"
     31 
     32 Value* UpdateFn(const char* name, State* state, int argc, Expr* argv[]) {
     33     if (argc != 7) {
     34         return ErrorAbort(state, "%s() expects 7 args, got %d", name, argc);
     35     }
     36 
     37     char* type = strrchr(name, '_');
     38     if (type == NULL || *(type+1) == '\0') {
     39         return ErrorAbort(state, "%s() couldn't get type from function name",
     40                           name);
     41     }
     42     ++type;
     43 
     44     Value* image;
     45     Value* width_string;
     46     Value* height_string;
     47     Value* bpp_string;
     48     Value* busy;
     49     Value* fail;
     50     Value* expected_sha1_string;
     51     if (ReadValueArgs(state, argv, 7, &image,
     52                       &width_string, &height_string, &bpp_string,
     53                       &busy, &fail, &expected_sha1_string) < 0) {
     54         return NULL;
     55     }
     56 
     57     // close the package
     58     ZipArchive* za = ((UpdaterInfo*)(state->cookie))->package_zip;
     59     mzCloseZipArchive(za);
     60     ((UpdaterInfo*)(state->cookie))->package_zip = NULL;
     61 
     62     // Try to unmount /cache.  If we fail (because we're running in an
     63     // older recovery that still has the package file open), try to
     64     // remount it read-only.  If that fails, abort.
     65     sync();
     66     scan_mounted_volumes();
     67     MountedVolume* vol = find_mounted_volume_by_mount_point("/cache");
     68     int result = unmount_mounted_volume(vol);
     69     if (result != 0) {
     70         printf("%s(): failed to unmount cache (%d: %s)\n",
     71                name, result, strerror(errno));
     72 
     73         result = remount_read_only(vol);
     74         if (result != 0) {
     75             printf("%s(): failed to remount cache (%d: %s)\n",
     76                    name, result, strerror(errno));
     77             return StringValue(strdup(""));
     78         } else {
     79             printf("%s(): remounted cache\n", name);
     80         }
     81         sync();
     82     } else {
     83         printf("%s(): unmounted cache\n", name);
     84     }
     85 
     86     int width = 0, height = 0, bpp = 0;
     87 
     88     if (width_string->type != VAL_STRING ||
     89         (width = strtol(width_string->data, NULL, 10)) == 0) {
     90         printf("%s(): bad width argument", name);
     91     }
     92     if (height_string->type != VAL_STRING ||
     93         (height = strtol(height_string->data, NULL, 10)) == 0) {
     94         printf("%s(): bad height argument", name);
     95     }
     96     if (bpp_string->type != VAL_STRING ||
     97         (bpp = strtol(bpp_string->data, NULL, 10)) == 0) {
     98         printf("%s(): bad bpp argument", name);
     99     }
    100 
    101     if (image->type != VAL_BLOB) {
    102         printf("image argument is not blob (is type %d)\n", image->type);
    103         goto done;
    104     }
    105 
    106     uint8_t expected_sha1[SHA_DIGEST_SIZE];
    107     char* data = expected_sha1_string->data;
    108     if (expected_sha1_string->type != VAL_STRING ||
    109         strlen(data) != SHA_DIGEST_SIZE*2) {
    110         printf("%s(): bad expected_sha1 argument", name);
    111         goto done;
    112     }
    113     printf("expected sha1 is: ");
    114     int i;
    115     for (i = 0; i < SHA_DIGEST_SIZE; ++i) {
    116         char temp = data[i*2+2];
    117         data[i*2+2] = '\0';
    118         expected_sha1[i] = strtol(data+i*2, NULL, 16);
    119         data[i*2+2] = temp;
    120         printf("%02x", expected_sha1[i]);
    121     }
    122     printf("\n");
    123 
    124     install_firmware_update(
    125         type,
    126         image->data,
    127         image->size,
    128         width, height, bpp,
    129         busy->size > 0 ? busy->data : NULL,
    130         fail->size > 0 ? fail->data : NULL,
    131         "/tmp/recovery.log",
    132         expected_sha1);
    133     printf("%s: install_firmware_update returned!\n", name);
    134 
    135   done:
    136     FreeValue(image);
    137     FreeValue(width_string);
    138     FreeValue(height_string);
    139     FreeValue(bpp_string);
    140     FreeValue(busy);
    141     FreeValue(fail);
    142     // install_firmware_update should reboot.  If it returns, it failed.
    143     return StringValue(strdup(""));
    144 }
    145 
    146 void Register_librecovery_updater_htc() {
    147     fprintf(stderr, "installing HTC updater extensions\n");
    148 
    149     RegisterFunction("htc.install_radio", UpdateFn);
    150     RegisterFunction("htc.install_hboot", UpdateFn);
    151 }
    152