blob: 6a52b12bbda325e8dc80d9609bd73a4a156d19fd [file] [log] [blame]
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001/*
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
Anatol Pomazau5ae3f932012-02-28 07:21:08 -080012 * the documentation and/or other materials provided with the
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080013 * 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
Anatol Pomazau5ae3f932012-02-28 07:21:08 -080022 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080023 * 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 */
Aaron Wisnerdb511202018-06-26 15:38:35 -050028#include "engine.h"
Anatol Pomazauc8ba5362011-12-15 17:50:18 -080029
Colin Cross81c632e2013-01-23 19:13:43 -080030#include <errno.h>
Elliott Hughes3ab8b852015-08-25 19:34:13 -070031#include <stdarg.h>
Mark Salyzyn5957c1f2014-04-30 14:05:28 -070032#include <stdio.h>
33#include <stdlib.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080034#include <string.h>
Anatol Pomazauc8ba5362011-12-15 17:50:18 -080035#include <sys/stat.h>
Anatol Pomazauc8ba5362011-12-15 17:50:18 -080036#include <sys/types.h>
37#include <unistd.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080038
Elliott Hughes5620d222018-03-28 08:20:00 -070039#include <memory>
40#include <vector>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080041
Elliott Hughes5620d222018-03-28 08:20:00 -070042#include <android-base/stringprintf.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080043
Jerry Zhang769a9c12018-05-15 17:02:50 -070044#include "constants.h"
Elliott Hughes11ff3452018-04-09 13:58:41 -070045#include "transport.h"
46
Elliott Hughes5620d222018-03-28 08:20:00 -070047enum Op {
48 OP_DOWNLOAD,
49 OP_COMMAND,
50 OP_QUERY,
51 OP_NOTICE,
52 OP_DOWNLOAD_SPARSE,
53 OP_WAIT_FOR_DISCONNECT,
54 OP_DOWNLOAD_FD,
55 OP_UPLOAD,
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080056};
57
Elliott Hughes5620d222018-03-28 08:20:00 -070058struct Action {
59 Action(Op op, const std::string& cmd) : op(op), cmd(cmd) {}
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080060
Elliott Hughes5620d222018-03-28 08:20:00 -070061 Op op;
62 std::string cmd;
63 std::string msg;
Anatol Pomazauc8ba5362011-12-15 17:50:18 -080064
Elliott Hughes5620d222018-03-28 08:20:00 -070065 std::string product;
Anatol Pomazauc8ba5362011-12-15 17:50:18 -080066
Elliott Hughes5620d222018-03-28 08:20:00 -070067 void* data = nullptr;
68 // The protocol only supports 32-bit sizes, so you'll have to break
69 // anything larger into multiple chunks.
70 uint32_t size = 0;
71
72 int fd = -1;
73
74 int (*func)(Action& a, int status, const char* resp) = nullptr;
75
76 double start = -1;
77};
78
79static std::vector<std::unique_ptr<Action>> action_list;
Aaron Wisnerdb511202018-06-26 15:38:35 -050080static fastboot::FastBootDriver* fb = nullptr;
Anatol Pomazauc8ba5362011-12-15 17:50:18 -080081
David Anderson1d887432018-08-27 16:47:32 -070082static constexpr char kStatusFormat[] = "%-50s ";
83
Aaron Wisnerdb511202018-06-26 15:38:35 -050084void fb_init(fastboot::FastBootDriver& fbi) {
85 fb = &fbi;
86 auto cb = [](std::string& info) { fprintf(stderr, "(bootloader) %s\n", info.c_str()); };
87 fb->SetInfoCallback(cb);
88}
Colin Cross80f2d032012-05-24 18:24:53 -070089
David Anderson1d887432018-08-27 16:47:32 -070090void fb_reinit(Transport* transport) {
91 fb->set_transport(transport);
92}
93
Aaron Wisnerdb511202018-06-26 15:38:35 -050094const std::string fb_get_error() {
95 return fb->Error();
96}
97
98bool fb_getvar(const std::string& key, std::string* value) {
99 return !fb->GetVar(key, value);
Colin Cross80f2d032012-05-24 18:24:53 -0700100}
101
Elliott Hughes5620d222018-03-28 08:20:00 -0700102static int cb_default(Action& a, int status, const char* resp) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800103 if (status) {
104 fprintf(stderr,"FAILED (%s)\n", resp);
105 } else {
Daniel Sandlercb6e22b2010-02-25 14:05:33 -0500106 double split = now();
Elliott Hughes5620d222018-03-28 08:20:00 -0700107 fprintf(stderr, "OKAY [%7.3fs]\n", (split - a.start));
108 a.start = split;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800109 }
110 return status;
111}
112
Elliott Hughes5620d222018-03-28 08:20:00 -0700113static Action& queue_action(Op op, const std::string& cmd) {
114 std::unique_ptr<Action> a{new Action(op, cmd)};
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800115 a->func = cb_default;
Daniel Sandlercb6e22b2010-02-25 14:05:33 -0500116
Elliott Hughes5620d222018-03-28 08:20:00 -0700117 action_list.push_back(std::move(a));
118 return *action_list.back();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800119}
120
Elliott Hughes5620d222018-03-28 08:20:00 -0700121void fb_set_active(const std::string& slot) {
Jerry Zhang769a9c12018-05-15 17:02:50 -0700122 Action& a = queue_action(OP_COMMAND, FB_CMD_SET_ACTIVE ":" + slot);
Elliott Hughesf238d872018-03-29 14:46:29 -0700123 a.msg = "Setting current slot to '" + slot + "'";
Daniel Rosenbergb7bd4ae2015-09-14 21:05:41 -0700124}
125
Elliott Hughes5620d222018-03-28 08:20:00 -0700126void fb_queue_erase(const std::string& partition) {
Jerry Zhang769a9c12018-05-15 17:02:50 -0700127 Action& a = queue_action(OP_COMMAND, FB_CMD_ERASE ":" + partition);
Elliott Hughesf238d872018-03-29 14:46:29 -0700128 a.msg = "Erasing '" + partition + "'";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800129}
130
Elliott Hughes5620d222018-03-28 08:20:00 -0700131void fb_queue_flash_fd(const std::string& partition, int fd, uint32_t sz) {
132 Action& a = queue_action(OP_DOWNLOAD_FD, "");
133 a.fd = fd;
134 a.size = sz;
Elliott Hughesf238d872018-03-29 14:46:29 -0700135 a.msg = android::base::StringPrintf("Sending '%s' (%u KB)", partition.c_str(), sz / 1024);
Chris Fries0ea946c2017-04-12 10:25:57 -0500136
Jerry Zhang769a9c12018-05-15 17:02:50 -0700137 Action& b = queue_action(OP_COMMAND, FB_CMD_FLASH ":" + partition);
Elliott Hughesf238d872018-03-29 14:46:29 -0700138 b.msg = "Writing '" + partition + "'";
Chris Fries0ea946c2017-04-12 10:25:57 -0500139}
140
Elliott Hughes5620d222018-03-28 08:20:00 -0700141void fb_queue_flash(const std::string& partition, void* data, uint32_t sz) {
142 Action& a = queue_action(OP_DOWNLOAD, "");
143 a.data = data;
144 a.size = sz;
Elliott Hughesf238d872018-03-29 14:46:29 -0700145 a.msg = android::base::StringPrintf("Sending '%s' (%u KB)", partition.c_str(), sz / 1024);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800146
Jerry Zhang769a9c12018-05-15 17:02:50 -0700147 Action& b = queue_action(OP_COMMAND, FB_CMD_FLASH ":" + partition);
Elliott Hughesf238d872018-03-29 14:46:29 -0700148 b.msg = "Writing '" + partition + "'";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800149}
150
Elliott Hughes5620d222018-03-28 08:20:00 -0700151void fb_queue_flash_sparse(const std::string& partition, struct sparse_file* s, uint32_t sz,
152 size_t current, size_t total) {
153 Action& a = queue_action(OP_DOWNLOAD_SPARSE, "");
154 a.data = s;
155 a.size = 0;
Elliott Hughesf238d872018-03-29 14:46:29 -0700156 a.msg = android::base::StringPrintf("Sending sparse '%s' %zu/%zu (%u KB)", partition.c_str(),
Elliott Hughes5620d222018-03-28 08:20:00 -0700157 current, total, sz / 1024);
Colin Crossf8387882012-05-24 17:18:41 -0700158
Jerry Zhang769a9c12018-05-15 17:02:50 -0700159 Action& b = queue_action(OP_COMMAND, FB_CMD_FLASH ":" + partition);
Elliott Hughesf238d872018-03-29 14:46:29 -0700160 b.msg = android::base::StringPrintf("Writing sparse '%s' %zu/%zu", partition.c_str(), current,
161 total);
Colin Crossf8387882012-05-24 17:18:41 -0700162}
163
David Anderson0d4277d2018-07-31 13:27:37 -0700164void fb_queue_create_partition(const std::string& partition, const std::string& size) {
165 Action& a = queue_action(OP_COMMAND, FB_CMD_CREATE_PARTITION ":" + partition + ":" + size);
166 a.msg = "Creating '" + partition + "'";
167}
168
169void fb_queue_delete_partition(const std::string& partition) {
170 Action& a = queue_action(OP_COMMAND, FB_CMD_DELETE_PARTITION ":" + partition);
171 a.msg = "Deleting '" + partition + "'";
172}
173
174void fb_queue_resize_partition(const std::string& partition, const std::string& size) {
175 Action& a = queue_action(OP_COMMAND, FB_CMD_RESIZE_PARTITION ":" + partition + ":" + size);
176 a.msg = "Resizing '" + partition + "'";
177}
178
Elliott Hughesb3748de2015-06-23 20:27:58 -0700179static int match(const char* str, const char** value, unsigned count) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800180 unsigned n;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800181
182 for (n = 0; n < count; n++) {
183 const char *val = value[n];
184 int len = strlen(val);
185 int match;
186
187 if ((len > 1) && (val[len-1] == '*')) {
188 len--;
189 match = !strncmp(val, str, len);
190 } else {
191 match = !strcmp(val, str);
192 }
193
194 if (match) return 1;
195 }
196
197 return 0;
198}
199
Elliott Hughes5620d222018-03-28 08:20:00 -0700200static int cb_check(Action& a, int status, const char* resp, int invert) {
201 const char** value = reinterpret_cast<const char**>(a.data);
202 unsigned count = a.size;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800203 unsigned n;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800204
205 if (status) {
206 fprintf(stderr,"FAILED (%s)\n", resp);
207 return status;
208 }
209
Elliott Hughes5620d222018-03-28 08:20:00 -0700210 if (!a.product.empty()) {
211 if (a.product != cur_product) {
Wink Savilleb98762f2011-04-04 17:54:59 -0700212 double split = now();
Elliott Hughes5620d222018-03-28 08:20:00 -0700213 fprintf(stderr, "IGNORE, product is %s required only for %s [%7.3fs]\n", cur_product,
214 a.product.c_str(), (split - a.start));
215 a.start = split;
Wink Savilleb98762f2011-04-04 17:54:59 -0700216 return 0;
217 }
218 }
219
Elliott Hughes5620d222018-03-28 08:20:00 -0700220 int yes = match(resp, value, count);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800221 if (invert) yes = !yes;
222
223 if (yes) {
Daniel Sandlercb6e22b2010-02-25 14:05:33 -0500224 double split = now();
Elliott Hughes5620d222018-03-28 08:20:00 -0700225 fprintf(stderr, "OKAY [%7.3fs]\n", (split - a.start));
226 a.start = split;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800227 return 0;
228 }
229
Elliott Hughes5620d222018-03-28 08:20:00 -0700230 fprintf(stderr, "FAILED\n\n");
231 fprintf(stderr, "Device %s is '%s'.\n", a.cmd.c_str() + 7, resp);
232 fprintf(stderr, "Update %s '%s'", invert ? "rejects" : "requires", value[0]);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800233 for (n = 1; n < count; n++) {
Elliott Hughes5620d222018-03-28 08:20:00 -0700234 fprintf(stderr, " or '%s'", value[n]);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800235 }
Elliott Hughes5620d222018-03-28 08:20:00 -0700236 fprintf(stderr, ".\n\n");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800237 return -1;
238}
239
Elliott Hughes5620d222018-03-28 08:20:00 -0700240static int cb_require(Action& a, int status, const char* resp) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800241 return cb_check(a, status, resp, 0);
242}
243
Elliott Hughes5620d222018-03-28 08:20:00 -0700244static int cb_reject(Action& a, int status, const char* resp) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800245 return cb_check(a, status, resp, 1);
246}
247
Elliott Hughes5620d222018-03-28 08:20:00 -0700248void fb_queue_require(const std::string& product, const std::string& var, bool invert,
249 size_t nvalues, const char** values) {
Jerry Zhang769a9c12018-05-15 17:02:50 -0700250 Action& a = queue_action(OP_QUERY, FB_CMD_GETVAR ":" + var);
Elliott Hughes5620d222018-03-28 08:20:00 -0700251 a.product = product;
252 a.data = values;
253 a.size = nvalues;
254 a.msg = "Checking " + var;
255 a.func = invert ? cb_reject : cb_require;
256 if (a.data == nullptr) die("out of memory");
Elliott Hughesd6365a72017-05-08 18:04:49 -0700257}
258
Elliott Hughes5620d222018-03-28 08:20:00 -0700259static int cb_display(Action& a, int status, const char* resp) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800260 if (status) {
Elliott Hughes5620d222018-03-28 08:20:00 -0700261 fprintf(stderr, "%s FAILED (%s)\n", a.cmd.c_str(), resp);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800262 return status;
263 }
Elliott Hughes5620d222018-03-28 08:20:00 -0700264 fprintf(stderr, "%s: %s\n", static_cast<const char*>(a.data), resp);
265 free(static_cast<char*>(a.data));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800266 return 0;
267}
268
Elliott Hughes5620d222018-03-28 08:20:00 -0700269void fb_queue_display(const std::string& label, const std::string& var) {
Jerry Zhang769a9c12018-05-15 17:02:50 -0700270 Action& a = queue_action(OP_QUERY, FB_CMD_GETVAR ":" + var);
Elliott Hughes5620d222018-03-28 08:20:00 -0700271 a.data = xstrdup(label.c_str());
272 a.func = cb_display;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800273}
274
Elliott Hughes5620d222018-03-28 08:20:00 -0700275static int cb_save(Action& a, int status, const char* resp) {
Wink Savilleb98762f2011-04-04 17:54:59 -0700276 if (status) {
Elliott Hughes5620d222018-03-28 08:20:00 -0700277 fprintf(stderr, "%s FAILED (%s)\n", a.cmd.c_str(), resp);
Wink Savilleb98762f2011-04-04 17:54:59 -0700278 return status;
279 }
Elliott Hughes5620d222018-03-28 08:20:00 -0700280 strncpy(reinterpret_cast<char*>(a.data), resp, a.size);
Wink Savilleb98762f2011-04-04 17:54:59 -0700281 return 0;
282}
283
Elliott Hughes5620d222018-03-28 08:20:00 -0700284void fb_queue_query_save(const std::string& var, char* dest, uint32_t dest_size) {
Jerry Zhang769a9c12018-05-15 17:02:50 -0700285 Action& a = queue_action(OP_QUERY, FB_CMD_GETVAR ":" + var);
Elliott Hughes5620d222018-03-28 08:20:00 -0700286 a.data = dest;
287 a.size = dest_size;
288 a.func = cb_save;
Wink Savilleb98762f2011-04-04 17:54:59 -0700289}
290
Elliott Hughes5620d222018-03-28 08:20:00 -0700291static int cb_do_nothing(Action&, int, const char*) {
292 fprintf(stderr, "\n");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800293 return 0;
294}
295
Elliott Hughes5620d222018-03-28 08:20:00 -0700296void fb_queue_reboot() {
Jerry Zhang769a9c12018-05-15 17:02:50 -0700297 Action& a = queue_action(OP_COMMAND, FB_CMD_REBOOT);
Elliott Hughes5620d222018-03-28 08:20:00 -0700298 a.func = cb_do_nothing;
Elliott Hughesf238d872018-03-29 14:46:29 -0700299 a.msg = "Rebooting";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800300}
301
Elliott Hughes5620d222018-03-28 08:20:00 -0700302void fb_queue_command(const std::string& cmd, const std::string& msg) {
303 Action& a = queue_action(OP_COMMAND, cmd);
304 a.msg = msg;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800305}
306
Elliott Hughes5620d222018-03-28 08:20:00 -0700307void fb_queue_download(const std::string& name, void* data, uint32_t size) {
308 Action& a = queue_action(OP_DOWNLOAD, "");
309 a.data = data;
310 a.size = size;
311 a.msg = "Downloading '" + name + "'";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800312}
313
Elliott Hughes5620d222018-03-28 08:20:00 -0700314void fb_queue_download_fd(const std::string& name, int fd, uint32_t sz) {
315 Action& a = queue_action(OP_DOWNLOAD_FD, "");
316 a.fd = fd;
317 a.size = sz;
Elliott Hughesf238d872018-03-29 14:46:29 -0700318 a.msg = android::base::StringPrintf("Sending '%s' (%u KB)", name.c_str(), sz / 1024);
Jocelyn Bohr98cc2832017-01-26 19:20:53 -0800319}
320
Elliott Hughes5620d222018-03-28 08:20:00 -0700321void fb_queue_upload(const std::string& outfile) {
322 Action& a = queue_action(OP_UPLOAD, "");
323 a.data = xstrdup(outfile.c_str());
324 a.msg = "Uploading '" + outfile + "'";
Jocelyn Bohr91fefad2017-01-27 14:17:56 -0800325}
326
Elliott Hughes5620d222018-03-28 08:20:00 -0700327void fb_queue_notice(const std::string& notice) {
328 Action& a = queue_action(OP_NOTICE, "");
329 a.msg = notice;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800330}
331
Elliott Hughes5620d222018-03-28 08:20:00 -0700332void fb_queue_wait_for_disconnect() {
Mark Wachsler157b0012013-10-02 09:35:38 -0400333 queue_action(OP_WAIT_FOR_DISCONNECT, "");
334}
335
Aaron Wisnerdb511202018-06-26 15:38:35 -0500336int64_t fb_execute_queue() {
Chris Fries6a999712017-04-04 09:52:47 -0500337 int64_t status = 0;
Elliott Hughes5620d222018-03-28 08:20:00 -0700338 for (auto& a : action_list) {
Daniel Sandlercb6e22b2010-02-25 14:05:33 -0500339 a->start = now();
Elliott Hughes5620d222018-03-28 08:20:00 -0700340 if (!a->msg.empty()) {
David Anderson1d887432018-08-27 16:47:32 -0700341 fprintf(stderr, kStatusFormat, a->msg.c_str());
Elliott Hughes855cdf82018-04-02 14:24:03 -0700342 verbose("\n");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800343 }
344 if (a->op == OP_DOWNLOAD) {
Aaron Wisnerdb511202018-06-26 15:38:35 -0500345 char* cbuf = static_cast<char*>(a->data);
346 status = fb->Download(cbuf, a->size);
Elliott Hughes5620d222018-03-28 08:20:00 -0700347 status = a->func(*a, status, status ? fb_get_error().c_str() : "");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800348 if (status) break;
Chris Fries0ea946c2017-04-12 10:25:57 -0500349 } else if (a->op == OP_DOWNLOAD_FD) {
Aaron Wisnerdb511202018-06-26 15:38:35 -0500350 status = fb->Download(a->fd, a->size);
Elliott Hughes5620d222018-03-28 08:20:00 -0700351 status = a->func(*a, status, status ? fb_get_error().c_str() : "");
Chris Fries0ea946c2017-04-12 10:25:57 -0500352 if (status) break;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800353 } else if (a->op == OP_COMMAND) {
Aaron Wisnerdb511202018-06-26 15:38:35 -0500354 status = fb->RawCommand(a->cmd);
Elliott Hughes5620d222018-03-28 08:20:00 -0700355 status = a->func(*a, status, status ? fb_get_error().c_str() : "");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800356 if (status) break;
357 } else if (a->op == OP_QUERY) {
Aaron Wisnerdb511202018-06-26 15:38:35 -0500358 std::string resp;
359 status = fb->RawCommand(a->cmd, &resp);
360 status = a->func(*a, status, status ? fb_get_error().c_str() : resp.c_str());
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800361 if (status) break;
362 } else if (a->op == OP_NOTICE) {
Elliott Hughes5620d222018-03-28 08:20:00 -0700363 // We already showed the notice because it's in `Action::msg`.
Elliott Hughesf238d872018-03-29 14:46:29 -0700364 fprintf(stderr, "\n");
Colin Crossf8387882012-05-24 17:18:41 -0700365 } else if (a->op == OP_DOWNLOAD_SPARSE) {
Aaron Wisnerdb511202018-06-26 15:38:35 -0500366 status = fb->Download(reinterpret_cast<sparse_file*>(a->data));
Elliott Hughes5620d222018-03-28 08:20:00 -0700367 status = a->func(*a, status, status ? fb_get_error().c_str() : "");
Colin Crossf8387882012-05-24 17:18:41 -0700368 if (status) break;
Mark Wachsler157b0012013-10-02 09:35:38 -0400369 } else if (a->op == OP_WAIT_FOR_DISCONNECT) {
Aaron Wisnerdb511202018-06-26 15:38:35 -0500370 fb->WaitForDisconnect();
Jocelyn Bohr91fefad2017-01-27 14:17:56 -0800371 } else if (a->op == OP_UPLOAD) {
Aaron Wisnerdb511202018-06-26 15:38:35 -0500372 status = fb->Upload(reinterpret_cast<const char*>(a->data));
Elliott Hughes5620d222018-03-28 08:20:00 -0700373 status = a->func(*a, status, status ? fb_get_error().c_str() : "");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800374 } else {
Elliott Hughes5620d222018-03-28 08:20:00 -0700375 die("unknown action: %d", a->op);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800376 }
377 }
Elliott Hughes5620d222018-03-28 08:20:00 -0700378 action_list.clear();
Brian Carlstromeb31c0b2010-04-23 12:38:51 -0700379 return status;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800380}
David Anderson1d887432018-08-27 16:47:32 -0700381
382bool fb_reboot_to_userspace() {
383 // First ensure that the queue is flushed.
384 fb_execute_queue();
385
386 fprintf(stderr, kStatusFormat, "Rebooting to userspace fastboot");
387 verbose("\n");
388
389 if (fb->RebootTo("fastboot") != fastboot::RetCode::SUCCESS) {
390 fprintf(stderr, "FAILED (%s)\n", fb->Error().c_str());
391 return false;
392 }
393 fprintf(stderr, "OKAY\n");
394
395 fb->set_transport(nullptr);
396 return true;
397}