blob: 0ac57afc58dfaa78b0d5a8b0632e5e460fa55475 [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
Tom Cherry11f12092018-08-29 21:36:28 -070047using android::base::StringPrintf;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080048
Aaron Wisnerdb511202018-06-26 15:38:35 -050049static fastboot::FastBootDriver* fb = nullptr;
Anatol Pomazauc8ba5362011-12-15 17:50:18 -080050
Aaron Wisnerdb511202018-06-26 15:38:35 -050051void fb_init(fastboot::FastBootDriver& fbi) {
52 fb = &fbi;
53 auto cb = [](std::string& info) { fprintf(stderr, "(bootloader) %s\n", info.c_str()); };
54 fb->SetInfoCallback(cb);
55}
Colin Cross80f2d032012-05-24 18:24:53 -070056
David Anderson1d887432018-08-27 16:47:32 -070057void fb_reinit(Transport* transport) {
David Anderson03de6452018-09-04 14:32:54 -070058 if (Transport* old_transport = fb->set_transport(transport)) {
59 delete old_transport;
60 }
David Anderson1d887432018-08-27 16:47:32 -070061}
62
Aaron Wisnerdb511202018-06-26 15:38:35 -050063const std::string fb_get_error() {
64 return fb->Error();
65}
66
67bool fb_getvar(const std::string& key, std::string* value) {
68 return !fb->GetVar(key, value);
Colin Cross80f2d032012-05-24 18:24:53 -070069}
70
Tom Cherry11f12092018-08-29 21:36:28 -070071static void HandleResult(double start, int status) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080072 if (status) {
Tom Cherry11f12092018-08-29 21:36:28 -070073 fprintf(stderr, "FAILED (%s)\n", fb->Error().c_str());
74 die("Command failed");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080075 } else {
Daniel Sandlercb6e22b2010-02-25 14:05:33 -050076 double split = now();
Tom Cherry11f12092018-08-29 21:36:28 -070077 fprintf(stderr, "OKAY [%7.3fs]\n", (split - start));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080078 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080079}
80
Tom Cherry11f12092018-08-29 21:36:28 -070081#define RUN_COMMAND(command) \
82 { \
83 double start = now(); \
84 auto status = (command); \
85 HandleResult(start, status); \
86 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080087
Elliott Hughes5620d222018-03-28 08:20:00 -070088void fb_set_active(const std::string& slot) {
Tom Cherry11f12092018-08-29 21:36:28 -070089 Status("Setting current slot to '" + slot + "'");
90 RUN_COMMAND(fb->SetActive(slot));
Daniel Rosenbergb7bd4ae2015-09-14 21:05:41 -070091}
92
Tom Cherry11f12092018-08-29 21:36:28 -070093void fb_erase(const std::string& partition) {
94 Status("Erasing '" + partition + "'");
95 RUN_COMMAND(fb->Erase(partition));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080096}
97
Tom Cherry11f12092018-08-29 21:36:28 -070098void fb_flash_fd(const std::string& partition, int fd, uint32_t sz) {
99 Status(StringPrintf("Sending '%s' (%u KB)", partition.c_str(), sz / 1024));
100 RUN_COMMAND(fb->Download(fd, sz));
Chris Fries0ea946c2017-04-12 10:25:57 -0500101
Tom Cherry11f12092018-08-29 21:36:28 -0700102 Status("Writing '" + partition + "'");
103 RUN_COMMAND(fb->Flash(partition));
Chris Fries0ea946c2017-04-12 10:25:57 -0500104}
105
Tom Cherry11f12092018-08-29 21:36:28 -0700106void fb_flash(const std::string& partition, void* data, uint32_t sz) {
107 Status(StringPrintf("Sending '%s' (%u KB)", partition.c_str(), sz / 1024));
108 RUN_COMMAND(fb->Download(static_cast<char*>(data), sz));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800109
Tom Cherry11f12092018-08-29 21:36:28 -0700110 Status("Writing '" + partition + "'");
111 RUN_COMMAND(fb->Flash(partition));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800112}
113
Tom Cherry11f12092018-08-29 21:36:28 -0700114void fb_flash_sparse(const std::string& partition, struct sparse_file* s, uint32_t sz,
115 size_t current, size_t total) {
116 Status(StringPrintf("Sending sparse '%s' %zu/%zu (%u KB)", partition.c_str(), current, total,
117 sz / 1024));
118 RUN_COMMAND(fb->Download(s));
Colin Crossf8387882012-05-24 17:18:41 -0700119
Tom Cherry11f12092018-08-29 21:36:28 -0700120 Status(StringPrintf("Writing sparse '%s' %zu/%zu", partition.c_str(), current, total));
121 RUN_COMMAND(fb->Flash(partition));
Colin Crossf8387882012-05-24 17:18:41 -0700122}
123
Tom Cherry11f12092018-08-29 21:36:28 -0700124void fb_create_partition(const std::string& partition, const std::string& size) {
125 Status("Creating '" + partition + "'");
126 RUN_COMMAND(fb->RawCommand(FB_CMD_CREATE_PARTITION ":" + partition + ":" + size));
David Anderson0d4277d2018-07-31 13:27:37 -0700127}
128
Tom Cherry11f12092018-08-29 21:36:28 -0700129void fb_delete_partition(const std::string& partition) {
130 Status("Deleting '" + partition + "'");
131 RUN_COMMAND(fb->RawCommand(FB_CMD_DELETE_PARTITION ":" + partition));
David Anderson0d4277d2018-07-31 13:27:37 -0700132}
133
Tom Cherry11f12092018-08-29 21:36:28 -0700134void fb_resize_partition(const std::string& partition, const std::string& size) {
135 Status("Resizing '" + partition + "'");
136 RUN_COMMAND(fb->RawCommand(FB_CMD_RESIZE_PARTITION ":" + partition + ":" + size));
David Anderson0d4277d2018-07-31 13:27:37 -0700137}
138
Elliott Hughesb3748de2015-06-23 20:27:58 -0700139static int match(const char* str, const char** value, unsigned count) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800140 unsigned n;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800141
142 for (n = 0; n < count; n++) {
143 const char *val = value[n];
144 int len = strlen(val);
145 int match;
146
147 if ((len > 1) && (val[len-1] == '*')) {
148 len--;
149 match = !strncmp(val, str, len);
150 } else {
151 match = !strcmp(val, str);
152 }
153
154 if (match) return 1;
155 }
156
157 return 0;
158}
159
Tom Cherry11f12092018-08-29 21:36:28 -0700160void fb_require(const std::string& product, const std::string& var, bool invert, size_t count,
161 const char** values) {
162 Status("Checking '" + var + "'");
163
164 double start = now();
165
166 std::string var_value;
167 auto status = fb->GetVar(var, &var_value);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800168
169 if (status) {
Tom Cherry11f12092018-08-29 21:36:28 -0700170 fprintf(stderr, "getvar:%s FAILED (%s)\n", var.c_str(), fb->Error().c_str());
171 die("requirements not met!");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800172 }
173
Tom Cherry11f12092018-08-29 21:36:28 -0700174 if (!product.empty()) {
175 if (product != cur_product) {
Wink Savilleb98762f2011-04-04 17:54:59 -0700176 double split = now();
Elliott Hughes5620d222018-03-28 08:20:00 -0700177 fprintf(stderr, "IGNORE, product is %s required only for %s [%7.3fs]\n", cur_product,
Tom Cherry11f12092018-08-29 21:36:28 -0700178 product.c_str(), (split - start));
179 return;
Wink Savilleb98762f2011-04-04 17:54:59 -0700180 }
181 }
182
Tom Cherry11f12092018-08-29 21:36:28 -0700183 int yes = match(var_value.c_str(), values, count);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800184 if (invert) yes = !yes;
185
186 if (yes) {
Daniel Sandlercb6e22b2010-02-25 14:05:33 -0500187 double split = now();
Tom Cherry11f12092018-08-29 21:36:28 -0700188 fprintf(stderr, "OKAY [%7.3fs]\n", (split - start));
189 return;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800190 }
191
Elliott Hughes5620d222018-03-28 08:20:00 -0700192 fprintf(stderr, "FAILED\n\n");
Tom Cherry11f12092018-08-29 21:36:28 -0700193 fprintf(stderr, "Device %s is '%s'.\n", var.c_str(), var_value.c_str());
194 fprintf(stderr, "Update %s '%s'", invert ? "rejects" : "requires", values[0]);
195 for (size_t n = 1; n < count; n++) {
196 fprintf(stderr, " or '%s'", values[n]);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800197 }
Elliott Hughes5620d222018-03-28 08:20:00 -0700198 fprintf(stderr, ".\n\n");
Tom Cherry11f12092018-08-29 21:36:28 -0700199 die("requirements not met!");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800200}
201
Tom Cherry11f12092018-08-29 21:36:28 -0700202void fb_display(const std::string& label, const std::string& var) {
203 std::string value;
204 auto status = fb->GetVar(var, &value);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800205
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800206 if (status) {
Tom Cherry11f12092018-08-29 21:36:28 -0700207 fprintf(stderr, "getvar:%s FAILED (%s)\n", var.c_str(), fb->Error().c_str());
208 return;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800209 }
Tom Cherry11f12092018-08-29 21:36:28 -0700210 fprintf(stderr, "%s: %s\n", label.c_str(), value.c_str());
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800211}
212
Tom Cherry11f12092018-08-29 21:36:28 -0700213void fb_query_save(const std::string& var, char* dest, uint32_t dest_size) {
214 std::string value;
215 auto status = fb->GetVar(var, &value);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800216
Wink Savilleb98762f2011-04-04 17:54:59 -0700217 if (status) {
Tom Cherry11f12092018-08-29 21:36:28 -0700218 fprintf(stderr, "getvar:%s FAILED (%s)\n", var.c_str(), fb->Error().c_str());
219 return;
Wink Savilleb98762f2011-04-04 17:54:59 -0700220 }
Tom Cherry11f12092018-08-29 21:36:28 -0700221
222 strncpy(dest, value.c_str(), dest_size);
Wink Savilleb98762f2011-04-04 17:54:59 -0700223}
224
Tom Cherry11f12092018-08-29 21:36:28 -0700225void fb_reboot() {
226 fprintf(stderr, "Rebooting");
227 fb->Reboot();
Elliott Hughes5620d222018-03-28 08:20:00 -0700228 fprintf(stderr, "\n");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800229}
230
Tom Cherry11f12092018-08-29 21:36:28 -0700231void fb_command(const std::string& cmd, const std::string& msg) {
232 Status(msg);
233 RUN_COMMAND(fb->RawCommand(cmd));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800234}
235
Tom Cherry11f12092018-08-29 21:36:28 -0700236void fb_download(const std::string& name, void* data, uint32_t size) {
237 Status("Downloading '" + name + "'");
238 RUN_COMMAND(fb->Download(static_cast<char*>(data), size));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800239}
240
Tom Cherry11f12092018-08-29 21:36:28 -0700241void fb_download_fd(const std::string& name, int fd, uint32_t sz) {
242 Status(StringPrintf("Sending '%s' (%u KB)", name.c_str(), sz / 1024));
243 RUN_COMMAND(fb->Download(fd, sz));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800244}
245
Tom Cherry11f12092018-08-29 21:36:28 -0700246void fb_upload(const std::string& outfile) {
247 Status("Uploading '" + outfile + "'");
248 RUN_COMMAND(fb->Upload(outfile));
Jocelyn Bohr98cc2832017-01-26 19:20:53 -0800249}
250
Tom Cherry11f12092018-08-29 21:36:28 -0700251void fb_notice(const std::string& notice) {
252 Status(notice);
253 fprintf(stderr, "\n");
Jocelyn Bohr91fefad2017-01-27 14:17:56 -0800254}
255
Tom Cherry11f12092018-08-29 21:36:28 -0700256void fb_wait_for_disconnect() {
257 fb->WaitForDisconnect();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800258}
David Anderson1d887432018-08-27 16:47:32 -0700259
260bool fb_reboot_to_userspace() {
Tom Cherry11f12092018-08-29 21:36:28 -0700261 Status("Rebooting to userspace fastboot");
David Anderson1d887432018-08-27 16:47:32 -0700262 verbose("\n");
263
264 if (fb->RebootTo("fastboot") != fastboot::RetCode::SUCCESS) {
265 fprintf(stderr, "FAILED (%s)\n", fb->Error().c_str());
266 return false;
267 }
268 fprintf(stderr, "OKAY\n");
269
David Anderson03de6452018-09-04 14:32:54 -0700270 fb_reinit(nullptr);
David Anderson1d887432018-08-27 16:47:32 -0700271 return true;
272}