1dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*
2dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project
3dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * All rights reserved.
4dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *
5dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Redistribution and use in source and binary forms, with or without
6dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * modification, are permitted provided that the following conditions
7dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * are met:
8dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *  * Redistributions of source code must retain the above copyright
9dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *    notice, this list of conditions and the following disclaimer.
10dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *  * Redistributions in binary form must reproduce the above copyright
11dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *    notice, this list of conditions and the following disclaimer in
125ae3f93f3bafbeb1fc9a3324475c58c725749c5eAnatol Pomazau *    the documentation and/or other materials provided with the
13dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *    distribution.
14dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *
15dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
225ae3f93f3bafbeb1fc9a3324475c58c725749c5eAnatol Pomazau * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * SUCH DAMAGE.
27dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
28dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
29c8ba5366da7e23ebf1cd76bcf49449b878563102Anatol Pomazau#include "fastboot.h"
30e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg#include "fs.h"
31c8ba5366da7e23ebf1cd76bcf49449b878563102Anatol Pomazau
3281c632e4dacb14c4afa8a1f166faa1bbacce4d8fColin Cross#include <errno.h>
333ab8b859c24fcdee49a48ded183e42690775eeddElliott Hughes#include <stdarg.h>
345957c1ffe79b34d8b1859f9f11644d1007193cbcMark Salyzyn#include <stdio.h>
355957c1ffe79b34d8b1859f9f11644d1007193cbcMark Salyzyn#include <stdlib.h>
36dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <string.h>
37c8ba5366da7e23ebf1cd76bcf49449b878563102Anatol Pomazau#include <sys/stat.h>
38c8ba5366da7e23ebf1cd76bcf49449b878563102Anatol Pomazau#include <sys/types.h>
39c8ba5366da7e23ebf1cd76bcf49449b878563102Anatol Pomazau#include <unistd.h>
40230d160a718333651f7ca1557404f96682795b37Anatol Pomazau
41c8ba5366da7e23ebf1cd76bcf49449b878563102Anatol Pomazau#define ARRAY_SIZE(x)           (sizeof(x)/sizeof(x[0]))
42dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
43dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define OP_DOWNLOAD   1
44dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define OP_COMMAND    2
45dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define OP_QUERY      3
46dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define OP_NOTICE     4
47e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg#define OP_DOWNLOAD_SPARSE 5
48e6f3e9bd2656fe132f829ed035fdea0cb111369dDmitry Grinberg#define OP_WAIT_FOR_DISCONNECT 6
49dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
50dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projecttypedef struct Action Action;
51dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
52c8ba5366da7e23ebf1cd76bcf49449b878563102Anatol Pomazau#define CMD_SIZE 64
53c8ba5366da7e23ebf1cd76bcf49449b878563102Anatol Pomazau
54fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughesstruct Action {
55dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    unsigned op;
56fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    Action* next;
57dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
58c8ba5366da7e23ebf1cd76bcf49449b878563102Anatol Pomazau    char cmd[CMD_SIZE];
59fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    const char* prod;
60fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    void* data;
61fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes
62fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    // The protocol only supports 32-bit sizes, so you'll have to break
63fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    // anything larger into chunks.
64fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes    uint32_t size;
65dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
66dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    const char *msg;
67b3748de33f651597259f52e4645571a1da2e32ddElliott Hughes    int (*func)(Action* a, int status, const char* resp);
68cb6e22b687eee5a47c642620d2e995b60f60f3e7Daniel Sandler
69cb6e22b687eee5a47c642620d2e995b60f60f3e7Daniel Sandler    double start;
70dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project};
71dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
72dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic Action *action_list = 0;
73dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic Action *action_last = 0;
74dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
75c8ba5366da7e23ebf1cd76bcf49449b878563102Anatol Pomazau
76c8ba5366da7e23ebf1cd76bcf49449b878563102Anatol Pomazau
77c8ba5366da7e23ebf1cd76bcf49449b878563102Anatol Pomazau
780b156638307db890e5539b52521fd24beb3440cbDavid Pursellbool fb_getvar(Transport* transport, const std::string& key, std::string* value) {
792fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes    std::string cmd = "getvar:";
802fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes    cmd += key;
812fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes
822fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes    char buf[FB_RESPONSE_SZ + 1];
832fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes    memset(buf, 0, sizeof(buf));
840b156638307db890e5539b52521fd24beb3440cbDavid Pursell    if (fb_command_response(transport, cmd.c_str(), buf)) {
852fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes      return false;
862fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes    }
872fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes    *value = buf;
882fd45a9cea9d31375a44ba36b065c2f8a2999993Elliott Hughes    return true;
8980f2d036a9dff894df27961c4aed300f1a5ebbc4Colin Cross}
9080f2d036a9dff894df27961c4aed300f1a5ebbc4Colin Cross
91b3748de33f651597259f52e4645571a1da2e32ddElliott Hughesstatic int cb_default(Action* a, int status, const char* resp) {
92dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (status) {
93dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fprintf(stderr,"FAILED (%s)\n", resp);
94dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else {
95cb6e22b687eee5a47c642620d2e995b60f60f3e7Daniel Sandler        double split = now();
96cb6e22b687eee5a47c642620d2e995b60f60f3e7Daniel Sandler        fprintf(stderr,"OKAY [%7.3fs]\n", (split - a->start));
97cb6e22b687eee5a47c642620d2e995b60f60f3e7Daniel Sandler        a->start = split;
98dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
99dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return status;
100dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
101dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
102dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic Action *queue_action(unsigned op, const char *fmt, ...)
103dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
104dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    va_list ap;
10550b3995d027b53f24bbba099b3b6884d5845b614Bruce Beare    size_t cmdsize;
106dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
107b3748de33f651597259f52e4645571a1da2e32ddElliott Hughes    Action* a = reinterpret_cast<Action*>(calloc(1, sizeof(Action)));
108b3748de33f651597259f52e4645571a1da2e32ddElliott Hughes    if (a == nullptr) die("out of memory");
109dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
110dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    va_start(ap, fmt);
11150b3995d027b53f24bbba099b3b6884d5845b614Bruce Beare    cmdsize = vsnprintf(a->cmd, sizeof(a->cmd), fmt, ap);
112dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    va_end(ap);
113dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
11450b3995d027b53f24bbba099b3b6884d5845b614Bruce Beare    if (cmdsize >= sizeof(a->cmd)) {
11550b3995d027b53f24bbba099b3b6884d5845b614Bruce Beare        free(a);
11650b3995d027b53f24bbba099b3b6884d5845b614Bruce Beare        die("Command length (%d) exceeds maximum size (%d)", cmdsize, sizeof(a->cmd));
11750b3995d027b53f24bbba099b3b6884d5845b614Bruce Beare    }
11850b3995d027b53f24bbba099b3b6884d5845b614Bruce Beare
119dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (action_last) {
120dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        action_last->next = a;
121dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else {
122dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        action_list = a;
123dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
124dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    action_last = a;
125dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    a->op = op;
126dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    a->func = cb_default;
127cb6e22b687eee5a47c642620d2e995b60f60f3e7Daniel Sandler
128cb6e22b687eee5a47c642620d2e995b60f60f3e7Daniel Sandler    a->start = -1;
129cb6e22b687eee5a47c642620d2e995b60f60f3e7Daniel Sandler
130dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return a;
131dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
132dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
133b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenbergvoid fb_set_active(const char *slot)
134b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg{
135b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg    Action *a;
136b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg    a = queue_action(OP_COMMAND, "set_active:%s", slot);
137b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg    a->msg = mkmsg("Setting current slot to '%s'", slot);
138b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg}
139b7bd4ae529148e7f4d830d98ea0a75bdc5d1ac17Daniel Rosenberg
140dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid fb_queue_erase(const char *ptn)
141dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
142dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    Action *a;
143dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    a = queue_action(OP_COMMAND, "erase:%s", ptn);
144dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    a->msg = mkmsg("erasing '%s'", ptn);
145dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
146dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1478d7ddb35d510824e50833a9b31ae6486393b1436Alexander Levitskiyvoid fb_queue_flash(const char *ptn, void *data, unsigned sz)
148dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
149dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    Action *a;
150dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
151dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    a = queue_action(OP_DOWNLOAD, "");
152dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    a->data = data;
153dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    a->size = sz;
154dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    a->msg = mkmsg("sending '%s' (%d KB)", ptn, sz / 1024);
155dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
156dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    a = queue_action(OP_COMMAND, "flash:%s", ptn);
157dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    a->msg = mkmsg("writing '%s'", ptn);
158dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
159dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1609da9ac5b2a109fa61826bc2609011ea84f175c28Josh Gaovoid fb_queue_flash_sparse(const char* ptn, struct sparse_file* s, unsigned sz, size_t current,
1619da9ac5b2a109fa61826bc2609011ea84f175c28Josh Gao                           size_t total) {
162f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    Action *a;
163f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
164f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    a = queue_action(OP_DOWNLOAD_SPARSE, "");
165f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    a->data = s;
166f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    a->size = 0;
1679da9ac5b2a109fa61826bc2609011ea84f175c28Josh Gao    a->msg = mkmsg("sending sparse '%s' %zu/%zu (%d KB)", ptn, current, total, sz / 1024);
168f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
169f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross    a = queue_action(OP_COMMAND, "flash:%s", ptn);
1709da9ac5b2a109fa61826bc2609011ea84f175c28Josh Gao    a->msg = mkmsg("writing '%s' %zu/%zu", ptn, current, total);
171f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross}
172f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross
173b3748de33f651597259f52e4645571a1da2e32ddElliott Hughesstatic int match(const char* str, const char** value, unsigned count) {
174dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    unsigned n;
175dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
176dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for (n = 0; n < count; n++) {
177dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        const char *val = value[n];
178dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        int len = strlen(val);
179dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        int match;
180dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
181dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if ((len > 1) && (val[len-1] == '*')) {
182dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            len--;
183dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            match = !strncmp(val, str, len);
184dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else {
185dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            match = !strcmp(val, str);
186dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
187dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
188dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (match) return 1;
189dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
190dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
191dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return 0;
192dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
193dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
194dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
195dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
196b3748de33f651597259f52e4645571a1da2e32ddElliott Hughesstatic int cb_check(Action* a, int status, const char* resp, int invert)
197dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
198b3748de33f651597259f52e4645571a1da2e32ddElliott Hughes    const char** value = reinterpret_cast<const char**>(a->data);
199dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    unsigned count = a->size;
200dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    unsigned n;
201dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int yes;
202dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
203dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (status) {
204dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fprintf(stderr,"FAILED (%s)\n", resp);
205dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return status;
206dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
207dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
208b98762f7824c291dc5d9a9b757af434ef31d8c81Wink Saville    if (a->prod) {
209b98762f7824c291dc5d9a9b757af434ef31d8c81Wink Saville        if (strcmp(a->prod, cur_product) != 0) {
210b98762f7824c291dc5d9a9b757af434ef31d8c81Wink Saville            double split = now();
211b98762f7824c291dc5d9a9b757af434ef31d8c81Wink Saville            fprintf(stderr,"IGNORE, product is %s required only for %s [%7.3fs]\n",
212b98762f7824c291dc5d9a9b757af434ef31d8c81Wink Saville                    cur_product, a->prod, (split - a->start));
213b98762f7824c291dc5d9a9b757af434ef31d8c81Wink Saville            a->start = split;
214b98762f7824c291dc5d9a9b757af434ef31d8c81Wink Saville            return 0;
215b98762f7824c291dc5d9a9b757af434ef31d8c81Wink Saville        }
216b98762f7824c291dc5d9a9b757af434ef31d8c81Wink Saville    }
217b98762f7824c291dc5d9a9b757af434ef31d8c81Wink Saville
218dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    yes = match(resp, value, count);
219dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (invert) yes = !yes;
220dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
221dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (yes) {
222cb6e22b687eee5a47c642620d2e995b60f60f3e7Daniel Sandler        double split = now();
223cb6e22b687eee5a47c642620d2e995b60f60f3e7Daniel Sandler        fprintf(stderr,"OKAY [%7.3fs]\n", (split - a->start));
224cb6e22b687eee5a47c642620d2e995b60f60f3e7Daniel Sandler        a->start = split;
225dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return 0;
226dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
227dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
228dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fprintf(stderr,"FAILED\n\n");
229dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fprintf(stderr,"Device %s is '%s'.\n", a->cmd + 7, resp);
230dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fprintf(stderr,"Update %s '%s'",
231dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            invert ? "rejects" : "requires", value[0]);
232dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for (n = 1; n < count; n++) {
233dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fprintf(stderr," or '%s'", value[n]);
234dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
235dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fprintf(stderr,".\n\n");
236dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return -1;
237dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
238dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
239b3748de33f651597259f52e4645571a1da2e32ddElliott Hughesstatic int cb_require(Action*a, int status, const char* resp) {
240dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return cb_check(a, status, resp, 0);
241dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
242dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
243b3748de33f651597259f52e4645571a1da2e32ddElliott Hughesstatic int cb_reject(Action* a, int status, const char* resp) {
244dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return cb_check(a, status, resp, 1);
245dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
246dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
247b98762f7824c291dc5d9a9b757af434ef31d8c81Wink Savillevoid fb_queue_require(const char *prod, const char *var,
248fc79767fc26d8782403e7b1afa7b93d518a86b19Elliott Hughes                      bool invert, size_t nvalues, const char **value)
249dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
250dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    Action *a;
251dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    a = queue_action(OP_QUERY, "getvar:%s", var);
252b98762f7824c291dc5d9a9b757af434ef31d8c81Wink Saville    a->prod = prod;
253dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    a->data = value;
254dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    a->size = nvalues;
255dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    a->msg = mkmsg("checking %s", var);
256dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    a->func = invert ? cb_reject : cb_require;
257b3748de33f651597259f52e4645571a1da2e32ddElliott Hughes    if (a->data == nullptr) die("out of memory");
258dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
259dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
260b3748de33f651597259f52e4645571a1da2e32ddElliott Hughesstatic int cb_display(Action* a, int status, const char* resp) {
261dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (status) {
262dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fprintf(stderr, "%s FAILED (%s)\n", a->cmd, resp);
263dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return status;
264dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
265dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fprintf(stderr, "%s: %s\n", (char*) a->data, resp);
266dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return 0;
267dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
268dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
269dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid fb_queue_display(const char *var, const char *prettyname)
270dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
271dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    Action *a;
272dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    a = queue_action(OP_QUERY, "getvar:%s", var);
273dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    a->data = strdup(prettyname);
274b3748de33f651597259f52e4645571a1da2e32ddElliott Hughes    if (a->data == nullptr) die("out of memory");
275dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    a->func = cb_display;
276dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
277dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
278b3748de33f651597259f52e4645571a1da2e32ddElliott Hughesstatic int cb_save(Action* a, int status, const char* resp) {
279b98762f7824c291dc5d9a9b757af434ef31d8c81Wink Saville    if (status) {
280b98762f7824c291dc5d9a9b757af434ef31d8c81Wink Saville        fprintf(stderr, "%s FAILED (%s)\n", a->cmd, resp);
281b98762f7824c291dc5d9a9b757af434ef31d8c81Wink Saville        return status;
282b98762f7824c291dc5d9a9b757af434ef31d8c81Wink Saville    }
283b3748de33f651597259f52e4645571a1da2e32ddElliott Hughes    strncpy(reinterpret_cast<char*>(a->data), resp, a->size);
284b98762f7824c291dc5d9a9b757af434ef31d8c81Wink Saville    return 0;
285b98762f7824c291dc5d9a9b757af434ef31d8c81Wink Saville}
286b98762f7824c291dc5d9a9b757af434ef31d8c81Wink Saville
287b98762f7824c291dc5d9a9b757af434ef31d8c81Wink Savillevoid fb_queue_query_save(const char *var, char *dest, unsigned dest_size)
288b98762f7824c291dc5d9a9b757af434ef31d8c81Wink Saville{
289b98762f7824c291dc5d9a9b757af434ef31d8c81Wink Saville    Action *a;
290b98762f7824c291dc5d9a9b757af434ef31d8c81Wink Saville    a = queue_action(OP_QUERY, "getvar:%s", var);
291b98762f7824c291dc5d9a9b757af434ef31d8c81Wink Saville    a->data = (void *)dest;
292b98762f7824c291dc5d9a9b757af434ef31d8c81Wink Saville    a->size = dest_size;
293b98762f7824c291dc5d9a9b757af434ef31d8c81Wink Saville    a->func = cb_save;
294b98762f7824c291dc5d9a9b757af434ef31d8c81Wink Saville}
295b98762f7824c291dc5d9a9b757af434ef31d8c81Wink Saville
296b3748de33f651597259f52e4645571a1da2e32ddElliott Hughesstatic int cb_do_nothing(Action*, int , const char*) {
297dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fprintf(stderr,"\n");
298dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return 0;
299dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
300dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
301dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid fb_queue_reboot(void)
302dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
303dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    Action *a = queue_action(OP_COMMAND, "reboot");
304dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    a->func = cb_do_nothing;
305dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    a->msg = "rebooting";
306dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
307dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
308dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid fb_queue_command(const char *cmd, const char *msg)
309dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
310dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    Action *a = queue_action(OP_COMMAND, cmd);
311dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    a->msg = msg;
312dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
313dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
314dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid fb_queue_download(const char *name, void *data, unsigned size)
315dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
316dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    Action *a = queue_action(OP_DOWNLOAD, "");
317dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    a->data = data;
318dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    a->size = size;
319dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    a->msg = mkmsg("downloading '%s'", name);
320dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
321dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
322dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid fb_queue_notice(const char *notice)
323dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
324dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    Action *a = queue_action(OP_NOTICE, "");
325dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    a->data = (void*) notice;
326dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
327dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
328157b00171a06f9ac2fd25ee3a86e801e896713d6Mark Wachslervoid fb_queue_wait_for_disconnect(void)
329157b00171a06f9ac2fd25ee3a86e801e896713d6Mark Wachsler{
330157b00171a06f9ac2fd25ee3a86e801e896713d6Mark Wachsler    queue_action(OP_WAIT_FOR_DISCONNECT, "");
331157b00171a06f9ac2fd25ee3a86e801e896713d6Mark Wachsler}
332157b00171a06f9ac2fd25ee3a86e801e896713d6Mark Wachsler
3330b156638307db890e5539b52521fd24beb3440cbDavid Pursellint fb_execute_queue(Transport* transport)
334dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
335dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    Action *a;
336dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char resp[FB_RESPONSE_SZ+1];
337eb31c0bdc0eac0898f01cdc1737cea94269f8f27Brian Carlstrom    int status = 0;
338dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
339dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    a = action_list;
34013081c6915220db03886b177f1a8e0b2c63467c9Scott Anderson    if (!a)
34113081c6915220db03886b177f1a8e0b2c63467c9Scott Anderson        return status;
342dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    resp[FB_RESPONSE_SZ] = 0;
343dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
344cb6e22b687eee5a47c642620d2e995b60f60f3e7Daniel Sandler    double start = -1;
345dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for (a = action_list; a; a = a->next) {
346cb6e22b687eee5a47c642620d2e995b60f60f3e7Daniel Sandler        a->start = now();
347cb6e22b687eee5a47c642620d2e995b60f60f3e7Daniel Sandler        if (start < 0) start = a->start;
348dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (a->msg) {
34963e5205cd2f693bbfa54411f2dd20354bd30ffd8Brian Swetland            // fprintf(stderr,"%30s... ",a->msg);
35063e5205cd2f693bbfa54411f2dd20354bd30ffd8Brian Swetland            fprintf(stderr,"%s...\n",a->msg);
351dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
352dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (a->op == OP_DOWNLOAD) {
3530b156638307db890e5539b52521fd24beb3440cbDavid Pursell            status = fb_download_data(transport, a->data, a->size);
354dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            status = a->func(a, status, status ? fb_get_error() : "");
355dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (status) break;
356dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else if (a->op == OP_COMMAND) {
3570b156638307db890e5539b52521fd24beb3440cbDavid Pursell            status = fb_command(transport, a->cmd);
358dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            status = a->func(a, status, status ? fb_get_error() : "");
359dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (status) break;
360dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else if (a->op == OP_QUERY) {
3610b156638307db890e5539b52521fd24beb3440cbDavid Pursell            status = fb_command_response(transport, a->cmd, resp);
362dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            status = a->func(a, status, status ? fb_get_error() : resp);
363dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (status) break;
364dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else if (a->op == OP_NOTICE) {
365dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fprintf(stderr,"%s\n",(char*)a->data);
366f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross        } else if (a->op == OP_DOWNLOAD_SPARSE) {
3670b156638307db890e5539b52521fd24beb3440cbDavid Pursell            status = fb_download_data_sparse(transport, reinterpret_cast<sparse_file*>(a->data));
368f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross            status = a->func(a, status, status ? fb_get_error() : "");
369f838788e6a4d57634a53eb597ee76a597feffcb5Colin Cross            if (status) break;
370157b00171a06f9ac2fd25ee3a86e801e896713d6Mark Wachsler        } else if (a->op == OP_WAIT_FOR_DISCONNECT) {
3710b156638307db890e5539b52521fd24beb3440cbDavid Pursell            transport->WaitForDisconnect();
372dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else {
373dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            die("bogus action");
374dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
375dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
376cb6e22b687eee5a47c642620d2e995b60f60f3e7Daniel Sandler
377cb6e22b687eee5a47c642620d2e995b60f60f3e7Daniel Sandler    fprintf(stderr,"finished. total time: %.3fs\n", (now() - start));
378eb31c0bdc0eac0898f01cdc1737cea94269f8f27Brian Carlstrom    return status;
379dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
380