Home | History | Annotate | Download | only in fastboot
      1 /*
      2  * Copyright (C) 2008 The Android Open Source Project
      3  * All rights reserved.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions
      7  * are met:
      8  *  * Redistributions of source code must retain the above copyright
      9  *    notice, this list of conditions and the following disclaimer.
     10  *  * Redistributions in binary form must reproduce the above copyright
     11  *    notice, this list of conditions and the following disclaimer in
     12  *    the documentation and/or other materials provided with the
     13  *    distribution.
     14  *
     15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     16  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     17  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
     18  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
     19  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
     20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
     21  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
     22  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
     23  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
     24  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
     25  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     26  * SUCH DAMAGE.
     27  */
     28 
     29 #include <stdio.h>
     30 #include <stdlib.h>
     31 #include <stdarg.h>
     32 #include <string.h>
     33 #include <sys/time.h>
     34 
     35 #include "fastboot.h"
     36 
     37 double now()
     38 {
     39     struct timeval tv;
     40     gettimeofday(&tv, NULL);
     41     return (double)tv.tv_sec + (double)tv.tv_usec / 1000000;
     42 }
     43 
     44 char *mkmsg(const char *fmt, ...)
     45 {
     46     char buf[256];
     47     char *s;
     48     va_list ap;
     49 
     50     va_start(ap, fmt);
     51     vsprintf(buf, fmt, ap);
     52     va_end(ap);
     53 
     54     s = strdup(buf);
     55     if (s == 0) die("out of memory");
     56     return s;
     57 }
     58 
     59 #define OP_DOWNLOAD   1
     60 #define OP_COMMAND    2
     61 #define OP_QUERY      3
     62 #define OP_NOTICE     4
     63 
     64 typedef struct Action Action;
     65 
     66 struct Action
     67 {
     68     unsigned op;
     69     Action *next;
     70 
     71     char cmd[64];
     72     void *data;
     73     unsigned size;
     74 
     75     const char *msg;
     76     int (*func)(Action *a, int status, char *resp);
     77 
     78     double start;
     79 };
     80 
     81 static Action *action_list = 0;
     82 static Action *action_last = 0;
     83 
     84 static int cb_default(Action *a, int status, char *resp)
     85 {
     86     if (status) {
     87         fprintf(stderr,"FAILED (%s)\n", resp);
     88     } else {
     89         double split = now();
     90         fprintf(stderr,"OKAY [%7.3fs]\n", (split - a->start));
     91         a->start = split;
     92     }
     93     return status;
     94 }
     95 
     96 static Action *queue_action(unsigned op, const char *fmt, ...)
     97 {
     98     Action *a;
     99     va_list ap;
    100 
    101     a = calloc(1, sizeof(Action));
    102     if (a == 0) die("out of memory");
    103 
    104     va_start(ap, fmt);
    105     vsprintf(a->cmd, fmt, ap);
    106     va_end(ap);
    107 
    108     if (action_last) {
    109         action_last->next = a;
    110     } else {
    111         action_list = a;
    112     }
    113     action_last = a;
    114     a->op = op;
    115     a->func = cb_default;
    116 
    117     a->start = -1;
    118 
    119     return a;
    120 }
    121 
    122 void fb_queue_erase(const char *ptn)
    123 {
    124     Action *a;
    125     a = queue_action(OP_COMMAND, "erase:%s", ptn);
    126     a->msg = mkmsg("erasing '%s'", ptn);
    127 }
    128 
    129 void fb_queue_flash(const char *ptn, void *data, unsigned sz)
    130 {
    131     Action *a;
    132 
    133     a = queue_action(OP_DOWNLOAD, "");
    134     a->data = data;
    135     a->size = sz;
    136     a->msg = mkmsg("sending '%s' (%d KB)", ptn, sz / 1024);
    137 
    138     a = queue_action(OP_COMMAND, "flash:%s", ptn);
    139     a->msg = mkmsg("writing '%s'", ptn);
    140 }
    141 
    142 static int match(char *str, const char **value, unsigned count)
    143 {
    144     const char *val;
    145     unsigned n;
    146     int len;
    147 
    148     for (n = 0; n < count; n++) {
    149         const char *val = value[n];
    150         int len = strlen(val);
    151         int match;
    152 
    153         if ((len > 1) && (val[len-1] == '*')) {
    154             len--;
    155             match = !strncmp(val, str, len);
    156         } else {
    157             match = !strcmp(val, str);
    158         }
    159 
    160         if (match) return 1;
    161     }
    162 
    163     return 0;
    164 }
    165 
    166 
    167 
    168 static int cb_check(Action *a, int status, char *resp, int invert)
    169 {
    170     const char **value = a->data;
    171     unsigned count = a->size;
    172     unsigned n;
    173     int yes;
    174 
    175     if (status) {
    176         fprintf(stderr,"FAILED (%s)\n", resp);
    177         return status;
    178     }
    179 
    180     yes = match(resp, value, count);
    181     if (invert) yes = !yes;
    182 
    183     if (yes) {
    184         double split = now();
    185         fprintf(stderr,"OKAY [%7.3fs]\n", (split - a->start));
    186         a->start = split;
    187         return 0;
    188     }
    189 
    190     fprintf(stderr,"FAILED\n\n");
    191     fprintf(stderr,"Device %s is '%s'.\n", a->cmd + 7, resp);
    192     fprintf(stderr,"Update %s '%s'",
    193             invert ? "rejects" : "requires", value[0]);
    194     for (n = 1; n < count; n++) {
    195         fprintf(stderr," or '%s'", value[n]);
    196     }
    197     fprintf(stderr,".\n\n");
    198     return -1;
    199 }
    200 
    201 static int cb_require(Action *a, int status, char *resp)
    202 {
    203     return cb_check(a, status, resp, 0);
    204 }
    205 
    206 static int cb_reject(Action *a, int status, char *resp)
    207 {
    208     return cb_check(a, status, resp, 1);
    209 }
    210 
    211 void fb_queue_require(const char *var, int invert, unsigned nvalues, const char **value)
    212 {
    213     Action *a;
    214     a = queue_action(OP_QUERY, "getvar:%s", var);
    215     a->data = value;
    216     a->size = nvalues;
    217     a->msg = mkmsg("checking %s", var);
    218     a->func = invert ? cb_reject : cb_require;
    219     if (a->data == 0) die("out of memory");
    220 }
    221 
    222 static int cb_display(Action *a, int status, char *resp)
    223 {
    224     if (status) {
    225         fprintf(stderr, "%s FAILED (%s)\n", a->cmd, resp);
    226         return status;
    227     }
    228     fprintf(stderr, "%s: %s\n", (char*) a->data, resp);
    229     return 0;
    230 }
    231 
    232 void fb_queue_display(const char *var, const char *prettyname)
    233 {
    234     Action *a;
    235     a = queue_action(OP_QUERY, "getvar:%s", var);
    236     a->data = strdup(prettyname);
    237     if (a->data == 0) die("out of memory");
    238     a->func = cb_display;
    239 }
    240 
    241 static int cb_do_nothing(Action *a, int status, char *resp)
    242 {
    243     fprintf(stderr,"\n");
    244     return 0;
    245 }
    246 
    247 void fb_queue_reboot(void)
    248 {
    249     Action *a = queue_action(OP_COMMAND, "reboot");
    250     a->func = cb_do_nothing;
    251     a->msg = "rebooting";
    252 }
    253 
    254 void fb_queue_command(const char *cmd, const char *msg)
    255 {
    256     Action *a = queue_action(OP_COMMAND, cmd);
    257     a->msg = msg;
    258 }
    259 
    260 void fb_queue_download(const char *name, void *data, unsigned size)
    261 {
    262     Action *a = queue_action(OP_DOWNLOAD, "");
    263     a->data = data;
    264     a->size = size;
    265     a->msg = mkmsg("downloading '%s'", name);
    266 }
    267 
    268 void fb_queue_notice(const char *notice)
    269 {
    270     Action *a = queue_action(OP_NOTICE, "");
    271     a->data = (void*) notice;
    272 }
    273 
    274 void fb_execute_queue(usb_handle *usb)
    275 {
    276     Action *a;
    277     char resp[FB_RESPONSE_SZ+1];
    278     int status;
    279 
    280     a = action_list;
    281     resp[FB_RESPONSE_SZ] = 0;
    282 
    283     double start = -1;
    284     for (a = action_list; a; a = a->next) {
    285         a->start = now();
    286         if (start < 0) start = a->start;
    287         if (a->msg) {
    288             // fprintf(stderr,"%30s... ",a->msg);
    289             fprintf(stderr,"%s...\n",a->msg);
    290         }
    291         if (a->op == OP_DOWNLOAD) {
    292             status = fb_download_data(usb, a->data, a->size);
    293             status = a->func(a, status, status ? fb_get_error() : "");
    294             if (status) break;
    295         } else if (a->op == OP_COMMAND) {
    296             status = fb_command(usb, a->cmd);
    297             status = a->func(a, status, status ? fb_get_error() : "");
    298             if (status) break;
    299         } else if (a->op == OP_QUERY) {
    300             status = fb_command_response(usb, a->cmd, resp);
    301             status = a->func(a, status, status ? fb_get_error() : resp);
    302             if (status) break;
    303         } else if (a->op == OP_NOTICE) {
    304             fprintf(stderr,"%s\n",(char*)a->data);
    305         } else {
    306             die("bogus action");
    307         }
    308     }
    309 
    310     fprintf(stderr,"finished. total time: %.3fs\n", (now() - start));
    311 }
    312 
    313