Merge "fastboot: remove command queue"
This commit is contained in:
commit
04ccbfd62c
7 changed files with 170 additions and 303 deletions
|
|
@ -44,43 +44,10 @@
|
|||
#include "constants.h"
|
||||
#include "transport.h"
|
||||
|
||||
enum Op {
|
||||
OP_DOWNLOAD,
|
||||
OP_COMMAND,
|
||||
OP_QUERY,
|
||||
OP_NOTICE,
|
||||
OP_DOWNLOAD_SPARSE,
|
||||
OP_WAIT_FOR_DISCONNECT,
|
||||
OP_DOWNLOAD_FD,
|
||||
OP_UPLOAD,
|
||||
};
|
||||
using android::base::StringPrintf;
|
||||
|
||||
struct Action {
|
||||
Action(Op op, const std::string& cmd) : op(op), cmd(cmd) {}
|
||||
|
||||
Op op;
|
||||
std::string cmd;
|
||||
std::string msg;
|
||||
|
||||
std::string product;
|
||||
|
||||
void* data = nullptr;
|
||||
// The protocol only supports 32-bit sizes, so you'll have to break
|
||||
// anything larger into multiple chunks.
|
||||
uint32_t size = 0;
|
||||
|
||||
int fd = -1;
|
||||
|
||||
int (*func)(Action& a, int status, const char* resp) = nullptr;
|
||||
|
||||
double start = -1;
|
||||
};
|
||||
|
||||
static std::vector<std::unique_ptr<Action>> action_list;
|
||||
static fastboot::FastBootDriver* fb = nullptr;
|
||||
|
||||
static constexpr char kStatusFormat[] = "%-50s ";
|
||||
|
||||
void fb_init(fastboot::FastBootDriver& fbi) {
|
||||
fb = &fbi;
|
||||
auto cb = [](std::string& info) { fprintf(stderr, "(bootloader) %s\n", info.c_str()); };
|
||||
|
|
@ -101,81 +68,72 @@ bool fb_getvar(const std::string& key, std::string* value) {
|
|||
return !fb->GetVar(key, value);
|
||||
}
|
||||
|
||||
static int cb_default(Action& a, int status, const char* resp) {
|
||||
static void HandleResult(double start, int status) {
|
||||
if (status) {
|
||||
fprintf(stderr,"FAILED (%s)\n", resp);
|
||||
fprintf(stderr, "FAILED (%s)\n", fb->Error().c_str());
|
||||
die("Command failed");
|
||||
} else {
|
||||
double split = now();
|
||||
fprintf(stderr, "OKAY [%7.3fs]\n", (split - a.start));
|
||||
a.start = split;
|
||||
fprintf(stderr, "OKAY [%7.3fs]\n", (split - start));
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
static Action& queue_action(Op op, const std::string& cmd) {
|
||||
std::unique_ptr<Action> a{new Action(op, cmd)};
|
||||
a->func = cb_default;
|
||||
|
||||
action_list.push_back(std::move(a));
|
||||
return *action_list.back();
|
||||
}
|
||||
#define RUN_COMMAND(command) \
|
||||
{ \
|
||||
double start = now(); \
|
||||
auto status = (command); \
|
||||
HandleResult(start, status); \
|
||||
}
|
||||
|
||||
void fb_set_active(const std::string& slot) {
|
||||
Action& a = queue_action(OP_COMMAND, FB_CMD_SET_ACTIVE ":" + slot);
|
||||
a.msg = "Setting current slot to '" + slot + "'";
|
||||
Status("Setting current slot to '" + slot + "'");
|
||||
RUN_COMMAND(fb->SetActive(slot));
|
||||
}
|
||||
|
||||
void fb_queue_erase(const std::string& partition) {
|
||||
Action& a = queue_action(OP_COMMAND, FB_CMD_ERASE ":" + partition);
|
||||
a.msg = "Erasing '" + partition + "'";
|
||||
void fb_erase(const std::string& partition) {
|
||||
Status("Erasing '" + partition + "'");
|
||||
RUN_COMMAND(fb->Erase(partition));
|
||||
}
|
||||
|
||||
void fb_queue_flash_fd(const std::string& partition, int fd, uint32_t sz) {
|
||||
Action& a = queue_action(OP_DOWNLOAD_FD, "");
|
||||
a.fd = fd;
|
||||
a.size = sz;
|
||||
a.msg = android::base::StringPrintf("Sending '%s' (%u KB)", partition.c_str(), sz / 1024);
|
||||
void fb_flash_fd(const std::string& partition, int fd, uint32_t sz) {
|
||||
Status(StringPrintf("Sending '%s' (%u KB)", partition.c_str(), sz / 1024));
|
||||
RUN_COMMAND(fb->Download(fd, sz));
|
||||
|
||||
Action& b = queue_action(OP_COMMAND, FB_CMD_FLASH ":" + partition);
|
||||
b.msg = "Writing '" + partition + "'";
|
||||
Status("Writing '" + partition + "'");
|
||||
RUN_COMMAND(fb->Flash(partition));
|
||||
}
|
||||
|
||||
void fb_queue_flash(const std::string& partition, void* data, uint32_t sz) {
|
||||
Action& a = queue_action(OP_DOWNLOAD, "");
|
||||
a.data = data;
|
||||
a.size = sz;
|
||||
a.msg = android::base::StringPrintf("Sending '%s' (%u KB)", partition.c_str(), sz / 1024);
|
||||
void fb_flash(const std::string& partition, void* data, uint32_t sz) {
|
||||
Status(StringPrintf("Sending '%s' (%u KB)", partition.c_str(), sz / 1024));
|
||||
RUN_COMMAND(fb->Download(static_cast<char*>(data), sz));
|
||||
|
||||
Action& b = queue_action(OP_COMMAND, FB_CMD_FLASH ":" + partition);
|
||||
b.msg = "Writing '" + partition + "'";
|
||||
Status("Writing '" + partition + "'");
|
||||
RUN_COMMAND(fb->Flash(partition));
|
||||
}
|
||||
|
||||
void fb_queue_flash_sparse(const std::string& partition, struct sparse_file* s, uint32_t sz,
|
||||
size_t current, size_t total) {
|
||||
Action& a = queue_action(OP_DOWNLOAD_SPARSE, "");
|
||||
a.data = s;
|
||||
a.size = 0;
|
||||
a.msg = android::base::StringPrintf("Sending sparse '%s' %zu/%zu (%u KB)", partition.c_str(),
|
||||
current, total, sz / 1024);
|
||||
void fb_flash_sparse(const std::string& partition, struct sparse_file* s, uint32_t sz,
|
||||
size_t current, size_t total) {
|
||||
Status(StringPrintf("Sending sparse '%s' %zu/%zu (%u KB)", partition.c_str(), current, total,
|
||||
sz / 1024));
|
||||
RUN_COMMAND(fb->Download(s));
|
||||
|
||||
Action& b = queue_action(OP_COMMAND, FB_CMD_FLASH ":" + partition);
|
||||
b.msg = android::base::StringPrintf("Writing sparse '%s' %zu/%zu", partition.c_str(), current,
|
||||
total);
|
||||
Status(StringPrintf("Writing sparse '%s' %zu/%zu", partition.c_str(), current, total));
|
||||
RUN_COMMAND(fb->Flash(partition));
|
||||
}
|
||||
|
||||
void fb_queue_create_partition(const std::string& partition, const std::string& size) {
|
||||
Action& a = queue_action(OP_COMMAND, FB_CMD_CREATE_PARTITION ":" + partition + ":" + size);
|
||||
a.msg = "Creating '" + partition + "'";
|
||||
void fb_create_partition(const std::string& partition, const std::string& size) {
|
||||
Status("Creating '" + partition + "'");
|
||||
RUN_COMMAND(fb->RawCommand(FB_CMD_CREATE_PARTITION ":" + partition + ":" + size));
|
||||
}
|
||||
|
||||
void fb_queue_delete_partition(const std::string& partition) {
|
||||
Action& a = queue_action(OP_COMMAND, FB_CMD_DELETE_PARTITION ":" + partition);
|
||||
a.msg = "Deleting '" + partition + "'";
|
||||
void fb_delete_partition(const std::string& partition) {
|
||||
Status("Deleting '" + partition + "'");
|
||||
RUN_COMMAND(fb->RawCommand(FB_CMD_DELETE_PARTITION ":" + partition));
|
||||
}
|
||||
|
||||
void fb_queue_resize_partition(const std::string& partition, const std::string& size) {
|
||||
Action& a = queue_action(OP_COMMAND, FB_CMD_RESIZE_PARTITION ":" + partition + ":" + size);
|
||||
a.msg = "Resizing '" + partition + "'";
|
||||
void fb_resize_partition(const std::string& partition, const std::string& size) {
|
||||
Status("Resizing '" + partition + "'");
|
||||
RUN_COMMAND(fb->RawCommand(FB_CMD_RESIZE_PARTITION ":" + partition + ":" + size));
|
||||
}
|
||||
|
||||
static int match(const char* str, const char** value, unsigned count) {
|
||||
|
|
@ -199,193 +157,108 @@ static int match(const char* str, const char** value, unsigned count) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int cb_check(Action& a, int status, const char* resp, int invert) {
|
||||
const char** value = reinterpret_cast<const char**>(a.data);
|
||||
unsigned count = a.size;
|
||||
unsigned n;
|
||||
void fb_require(const std::string& product, const std::string& var, bool invert, size_t count,
|
||||
const char** values) {
|
||||
Status("Checking '" + var + "'");
|
||||
|
||||
double start = now();
|
||||
|
||||
std::string var_value;
|
||||
auto status = fb->GetVar(var, &var_value);
|
||||
|
||||
if (status) {
|
||||
fprintf(stderr,"FAILED (%s)\n", resp);
|
||||
return status;
|
||||
fprintf(stderr, "getvar:%s FAILED (%s)\n", var.c_str(), fb->Error().c_str());
|
||||
die("requirements not met!");
|
||||
}
|
||||
|
||||
if (!a.product.empty()) {
|
||||
if (a.product != cur_product) {
|
||||
if (!product.empty()) {
|
||||
if (product != cur_product) {
|
||||
double split = now();
|
||||
fprintf(stderr, "IGNORE, product is %s required only for %s [%7.3fs]\n", cur_product,
|
||||
a.product.c_str(), (split - a.start));
|
||||
a.start = split;
|
||||
return 0;
|
||||
product.c_str(), (split - start));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
int yes = match(resp, value, count);
|
||||
int yes = match(var_value.c_str(), values, count);
|
||||
if (invert) yes = !yes;
|
||||
|
||||
if (yes) {
|
||||
double split = now();
|
||||
fprintf(stderr, "OKAY [%7.3fs]\n", (split - a.start));
|
||||
a.start = split;
|
||||
return 0;
|
||||
fprintf(stderr, "OKAY [%7.3fs]\n", (split - start));
|
||||
return;
|
||||
}
|
||||
|
||||
fprintf(stderr, "FAILED\n\n");
|
||||
fprintf(stderr, "Device %s is '%s'.\n", a.cmd.c_str() + 7, resp);
|
||||
fprintf(stderr, "Update %s '%s'", invert ? "rejects" : "requires", value[0]);
|
||||
for (n = 1; n < count; n++) {
|
||||
fprintf(stderr, " or '%s'", value[n]);
|
||||
fprintf(stderr, "Device %s is '%s'.\n", var.c_str(), var_value.c_str());
|
||||
fprintf(stderr, "Update %s '%s'", invert ? "rejects" : "requires", values[0]);
|
||||
for (size_t n = 1; n < count; n++) {
|
||||
fprintf(stderr, " or '%s'", values[n]);
|
||||
}
|
||||
fprintf(stderr, ".\n\n");
|
||||
return -1;
|
||||
die("requirements not met!");
|
||||
}
|
||||
|
||||
static int cb_require(Action& a, int status, const char* resp) {
|
||||
return cb_check(a, status, resp, 0);
|
||||
}
|
||||
void fb_display(const std::string& label, const std::string& var) {
|
||||
std::string value;
|
||||
auto status = fb->GetVar(var, &value);
|
||||
|
||||
static int cb_reject(Action& a, int status, const char* resp) {
|
||||
return cb_check(a, status, resp, 1);
|
||||
}
|
||||
|
||||
void fb_queue_require(const std::string& product, const std::string& var, bool invert,
|
||||
size_t nvalues, const char** values) {
|
||||
Action& a = queue_action(OP_QUERY, FB_CMD_GETVAR ":" + var);
|
||||
a.product = product;
|
||||
a.data = values;
|
||||
a.size = nvalues;
|
||||
a.msg = "Checking " + var;
|
||||
a.func = invert ? cb_reject : cb_require;
|
||||
if (a.data == nullptr) die("out of memory");
|
||||
}
|
||||
|
||||
static int cb_display(Action& a, int status, const char* resp) {
|
||||
if (status) {
|
||||
fprintf(stderr, "%s FAILED (%s)\n", a.cmd.c_str(), resp);
|
||||
return status;
|
||||
fprintf(stderr, "getvar:%s FAILED (%s)\n", var.c_str(), fb->Error().c_str());
|
||||
return;
|
||||
}
|
||||
fprintf(stderr, "%s: %s\n", static_cast<const char*>(a.data), resp);
|
||||
free(static_cast<char*>(a.data));
|
||||
return 0;
|
||||
fprintf(stderr, "%s: %s\n", label.c_str(), value.c_str());
|
||||
}
|
||||
|
||||
void fb_queue_display(const std::string& label, const std::string& var) {
|
||||
Action& a = queue_action(OP_QUERY, FB_CMD_GETVAR ":" + var);
|
||||
a.data = xstrdup(label.c_str());
|
||||
a.func = cb_display;
|
||||
}
|
||||
void fb_query_save(const std::string& var, char* dest, uint32_t dest_size) {
|
||||
std::string value;
|
||||
auto status = fb->GetVar(var, &value);
|
||||
|
||||
static int cb_save(Action& a, int status, const char* resp) {
|
||||
if (status) {
|
||||
fprintf(stderr, "%s FAILED (%s)\n", a.cmd.c_str(), resp);
|
||||
return status;
|
||||
fprintf(stderr, "getvar:%s FAILED (%s)\n", var.c_str(), fb->Error().c_str());
|
||||
return;
|
||||
}
|
||||
strncpy(reinterpret_cast<char*>(a.data), resp, a.size);
|
||||
return 0;
|
||||
|
||||
strncpy(dest, value.c_str(), dest_size);
|
||||
}
|
||||
|
||||
void fb_queue_query_save(const std::string& var, char* dest, uint32_t dest_size) {
|
||||
Action& a = queue_action(OP_QUERY, FB_CMD_GETVAR ":" + var);
|
||||
a.data = dest;
|
||||
a.size = dest_size;
|
||||
a.func = cb_save;
|
||||
}
|
||||
|
||||
static int cb_do_nothing(Action&, int, const char*) {
|
||||
void fb_reboot() {
|
||||
fprintf(stderr, "Rebooting");
|
||||
fb->Reboot();
|
||||
fprintf(stderr, "\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
void fb_queue_reboot() {
|
||||
Action& a = queue_action(OP_COMMAND, FB_CMD_REBOOT);
|
||||
a.func = cb_do_nothing;
|
||||
a.msg = "Rebooting";
|
||||
void fb_command(const std::string& cmd, const std::string& msg) {
|
||||
Status(msg);
|
||||
RUN_COMMAND(fb->RawCommand(cmd));
|
||||
}
|
||||
|
||||
void fb_queue_command(const std::string& cmd, const std::string& msg) {
|
||||
Action& a = queue_action(OP_COMMAND, cmd);
|
||||
a.msg = msg;
|
||||
void fb_download(const std::string& name, void* data, uint32_t size) {
|
||||
Status("Downloading '" + name + "'");
|
||||
RUN_COMMAND(fb->Download(static_cast<char*>(data), size));
|
||||
}
|
||||
|
||||
void fb_queue_download(const std::string& name, void* data, uint32_t size) {
|
||||
Action& a = queue_action(OP_DOWNLOAD, "");
|
||||
a.data = data;
|
||||
a.size = size;
|
||||
a.msg = "Downloading '" + name + "'";
|
||||
void fb_download_fd(const std::string& name, int fd, uint32_t sz) {
|
||||
Status(StringPrintf("Sending '%s' (%u KB)", name.c_str(), sz / 1024));
|
||||
RUN_COMMAND(fb->Download(fd, sz));
|
||||
}
|
||||
|
||||
void fb_queue_download_fd(const std::string& name, int fd, uint32_t sz) {
|
||||
Action& a = queue_action(OP_DOWNLOAD_FD, "");
|
||||
a.fd = fd;
|
||||
a.size = sz;
|
||||
a.msg = android::base::StringPrintf("Sending '%s' (%u KB)", name.c_str(), sz / 1024);
|
||||
void fb_upload(const std::string& outfile) {
|
||||
Status("Uploading '" + outfile + "'");
|
||||
RUN_COMMAND(fb->Upload(outfile));
|
||||
}
|
||||
|
||||
void fb_queue_upload(const std::string& outfile) {
|
||||
Action& a = queue_action(OP_UPLOAD, "");
|
||||
a.data = xstrdup(outfile.c_str());
|
||||
a.msg = "Uploading '" + outfile + "'";
|
||||
void fb_notice(const std::string& notice) {
|
||||
Status(notice);
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
void fb_queue_notice(const std::string& notice) {
|
||||
Action& a = queue_action(OP_NOTICE, "");
|
||||
a.msg = notice;
|
||||
}
|
||||
|
||||
void fb_queue_wait_for_disconnect() {
|
||||
queue_action(OP_WAIT_FOR_DISCONNECT, "");
|
||||
}
|
||||
|
||||
int64_t fb_execute_queue() {
|
||||
int64_t status = 0;
|
||||
for (auto& a : action_list) {
|
||||
a->start = now();
|
||||
if (!a->msg.empty()) {
|
||||
fprintf(stderr, kStatusFormat, a->msg.c_str());
|
||||
verbose("\n");
|
||||
}
|
||||
if (a->op == OP_DOWNLOAD) {
|
||||
char* cbuf = static_cast<char*>(a->data);
|
||||
status = fb->Download(cbuf, a->size);
|
||||
status = a->func(*a, status, status ? fb_get_error().c_str() : "");
|
||||
if (status) break;
|
||||
} else if (a->op == OP_DOWNLOAD_FD) {
|
||||
status = fb->Download(a->fd, a->size);
|
||||
status = a->func(*a, status, status ? fb_get_error().c_str() : "");
|
||||
if (status) break;
|
||||
} else if (a->op == OP_COMMAND) {
|
||||
status = fb->RawCommand(a->cmd);
|
||||
status = a->func(*a, status, status ? fb_get_error().c_str() : "");
|
||||
if (status) break;
|
||||
} else if (a->op == OP_QUERY) {
|
||||
std::string resp;
|
||||
status = fb->RawCommand(a->cmd, &resp);
|
||||
status = a->func(*a, status, status ? fb_get_error().c_str() : resp.c_str());
|
||||
if (status) break;
|
||||
} else if (a->op == OP_NOTICE) {
|
||||
// We already showed the notice because it's in `Action::msg`.
|
||||
fprintf(stderr, "\n");
|
||||
} else if (a->op == OP_DOWNLOAD_SPARSE) {
|
||||
status = fb->Download(reinterpret_cast<sparse_file*>(a->data));
|
||||
status = a->func(*a, status, status ? fb_get_error().c_str() : "");
|
||||
if (status) break;
|
||||
} else if (a->op == OP_WAIT_FOR_DISCONNECT) {
|
||||
fb->WaitForDisconnect();
|
||||
} else if (a->op == OP_UPLOAD) {
|
||||
status = fb->Upload(reinterpret_cast<const char*>(a->data));
|
||||
status = a->func(*a, status, status ? fb_get_error().c_str() : "");
|
||||
} else {
|
||||
die("unknown action: %d", a->op);
|
||||
}
|
||||
}
|
||||
action_list.clear();
|
||||
return status;
|
||||
void fb_wait_for_disconnect() {
|
||||
fb->WaitForDisconnect();
|
||||
}
|
||||
|
||||
bool fb_reboot_to_userspace() {
|
||||
// First ensure that the queue is flushed.
|
||||
fb_execute_queue();
|
||||
|
||||
fprintf(stderr, kStatusFormat, "Rebooting to userspace fastboot");
|
||||
Status("Rebooting to userspace fastboot");
|
||||
verbose("\n");
|
||||
|
||||
if (fb->RebootTo("fastboot") != fastboot::RetCode::SUCCESS) {
|
||||
|
|
|
|||
|
|
@ -44,36 +44,29 @@ struct sparse_file;
|
|||
|
||||
const std::string fb_get_error();
|
||||
|
||||
//#define FB_COMMAND_SZ (fastboot::FB_COMMAND_SZ)
|
||||
//#define FB_RESPONSE_SZ (fastboot::FB_RESPONSE_SZ)
|
||||
|
||||
/* engine.c - high level command queue engine */
|
||||
|
||||
void fb_init(fastboot::FastBootDriver& fbi);
|
||||
void fb_reinit(Transport* transport);
|
||||
|
||||
bool fb_getvar(const std::string& key, std::string* value);
|
||||
void fb_queue_flash(const std::string& partition, void* data, uint32_t sz);
|
||||
void fb_queue_flash_fd(const std::string& partition, int fd, uint32_t sz);
|
||||
void fb_queue_flash_sparse(const std::string& partition, struct sparse_file* s, uint32_t sz,
|
||||
size_t current, size_t total);
|
||||
void fb_queue_erase(const std::string& partition);
|
||||
void fb_queue_format(const std::string& partition, int skip_if_not_supported, int32_t max_chunk_sz);
|
||||
void fb_queue_require(const std::string& prod, const std::string& var, bool invert, size_t nvalues,
|
||||
const char** values);
|
||||
void fb_queue_display(const std::string& label, const std::string& var);
|
||||
void fb_queue_query_save(const std::string& var, char* dest, uint32_t dest_size);
|
||||
void fb_queue_reboot(void);
|
||||
void fb_queue_command(const std::string& cmd, const std::string& msg);
|
||||
void fb_queue_download(const std::string& name, void* data, uint32_t size);
|
||||
void fb_queue_download_fd(const std::string& name, int fd, uint32_t sz);
|
||||
void fb_queue_upload(const std::string& outfile);
|
||||
void fb_queue_notice(const std::string& notice);
|
||||
void fb_queue_wait_for_disconnect(void);
|
||||
void fb_queue_create_partition(const std::string& partition, const std::string& size);
|
||||
void fb_queue_delete_partition(const std::string& partition);
|
||||
void fb_queue_resize_partition(const std::string& partition, const std::string& size);
|
||||
int64_t fb_execute_queue();
|
||||
void fb_flash(const std::string& partition, void* data, uint32_t sz);
|
||||
void fb_flash_fd(const std::string& partition, int fd, uint32_t sz);
|
||||
void fb_flash_sparse(const std::string& partition, struct sparse_file* s, uint32_t sz,
|
||||
size_t current, size_t total);
|
||||
void fb_erase(const std::string& partition);
|
||||
void fb_require(const std::string& prod, const std::string& var, bool invert, size_t nvalues,
|
||||
const char** values);
|
||||
void fb_display(const std::string& label, const std::string& var);
|
||||
void fb_query_save(const std::string& var, char* dest, uint32_t dest_size);
|
||||
void fb_reboot();
|
||||
void fb_command(const std::string& cmd, const std::string& msg);
|
||||
void fb_download(const std::string& name, void* data, uint32_t size);
|
||||
void fb_download_fd(const std::string& name, int fd, uint32_t sz);
|
||||
void fb_upload(const std::string& outfile);
|
||||
void fb_notice(const std::string& notice);
|
||||
void fb_wait_for_disconnect(void);
|
||||
void fb_create_partition(const std::string& partition, const std::string& size);
|
||||
void fb_delete_partition(const std::string& partition);
|
||||
void fb_resize_partition(const std::string& partition, const std::string& size);
|
||||
void fb_set_active(const std::string& slot);
|
||||
bool fb_reboot_to_userspace();
|
||||
|
||||
|
|
|
|||
|
|
@ -688,7 +688,7 @@ static void check_requirement(char* line) {
|
|||
out[i] = xstrdup(strip(val[i]));
|
||||
}
|
||||
|
||||
fb_queue_require(product, var, invert, count, out);
|
||||
fb_require(product, var, invert, count, out);
|
||||
}
|
||||
|
||||
static void check_requirements(char* data, int64_t sz) {
|
||||
|
|
@ -702,15 +702,14 @@ static void check_requirements(char* data, int64_t sz) {
|
|||
s++;
|
||||
}
|
||||
}
|
||||
if (fb_execute_queue()) die("requirements not met!");
|
||||
}
|
||||
|
||||
static void queue_info_dump() {
|
||||
fb_queue_notice("--------------------------------------------");
|
||||
fb_queue_display("Bootloader Version...", "version-bootloader");
|
||||
fb_queue_display("Baseband Version.....", "version-baseband");
|
||||
fb_queue_display("Serial Number........", "serialno");
|
||||
fb_queue_notice("--------------------------------------------");
|
||||
static void dump_info() {
|
||||
fb_notice("--------------------------------------------");
|
||||
fb_display("Bootloader Version...", "version-bootloader");
|
||||
fb_display("Baseband Version.....", "version-baseband");
|
||||
fb_display("Serial Number........", "serialno");
|
||||
fb_notice("--------------------------------------------");
|
||||
}
|
||||
|
||||
static struct sparse_file** load_sparse_files(int fd, int64_t max_size) {
|
||||
|
|
@ -883,12 +882,12 @@ static void flash_buf(const std::string& partition, struct fastboot_buffer *buf)
|
|||
|
||||
for (size_t i = 0; i < sparse_files.size(); ++i) {
|
||||
const auto& pair = sparse_files[i];
|
||||
fb_queue_flash_sparse(partition, pair.first, pair.second, i + 1, sparse_files.size());
|
||||
fb_flash_sparse(partition, pair.first, pair.second, i + 1, sparse_files.size());
|
||||
}
|
||||
break;
|
||||
}
|
||||
case FB_BUFFER_FD:
|
||||
fb_queue_flash_fd(partition, buf->fd, buf->sz);
|
||||
fb_flash_fd(partition, buf->fd, buf->sz);
|
||||
break;
|
||||
default:
|
||||
die("unknown buffer type: %d", buf->type);
|
||||
|
|
@ -1145,7 +1144,7 @@ void FlashAllTool::Flash() {
|
|||
for (const auto& [image, slot] : os_images_) {
|
||||
auto resize_partition = [](const std::string& partition) -> void {
|
||||
if (is_logical(partition)) {
|
||||
fb_queue_resize_partition(partition, "0");
|
||||
fb_resize_partition(partition, "0");
|
||||
}
|
||||
};
|
||||
do_for_partitions(image->part_name, slot, resize_partition, false);
|
||||
|
|
@ -1223,12 +1222,12 @@ void FlashAllTool::FlashImage(const Image& image, const std::string& slot, fastb
|
|||
int64_t sz;
|
||||
void* data = source_.ReadFile(image.sig_name, &sz);
|
||||
if (data) {
|
||||
fb_queue_download("signature", data, sz);
|
||||
fb_queue_command("signature", "installing signature");
|
||||
fb_download("signature", data, sz);
|
||||
fb_command("signature", "installing signature");
|
||||
}
|
||||
|
||||
if (is_logical(partition_name)) {
|
||||
fb_queue_resize_partition(partition_name, std::to_string(buf->image_size));
|
||||
fb_resize_partition(partition_name, std::to_string(buf->image_size));
|
||||
}
|
||||
flash_buf(partition_name.c_str(), buf);
|
||||
};
|
||||
|
|
@ -1247,17 +1246,13 @@ void FlashAllTool::UpdateSuperPartition() {
|
|||
if (!is_userspace_fastboot()) {
|
||||
reboot_to_userspace_fastboot();
|
||||
}
|
||||
fb_queue_download_fd("super", fd, get_file_size(fd));
|
||||
fb_download_fd("super", fd, get_file_size(fd));
|
||||
|
||||
std::string command = "update-super:super";
|
||||
if (wipe_) {
|
||||
command += ":wipe";
|
||||
}
|
||||
fb_queue_command(command, "Updating super partition");
|
||||
|
||||
// We need these commands to have finished before proceeding, since
|
||||
// otherwise "getvar is-logical" may not return a correct answer below.
|
||||
fb_execute_queue();
|
||||
fb_command(command, "Updating super partition");
|
||||
}
|
||||
|
||||
class ZipImageSource final : public ImageSource {
|
||||
|
|
@ -1279,9 +1274,9 @@ int ZipImageSource::OpenFile(const std::string& name) const {
|
|||
}
|
||||
|
||||
static void do_update(const char* filename, const std::string& slot_override, bool skip_secondary) {
|
||||
queue_info_dump();
|
||||
dump_info();
|
||||
|
||||
fb_queue_query_save("product", cur_product, sizeof(cur_product));
|
||||
fb_query_save("product", cur_product, sizeof(cur_product));
|
||||
|
||||
ZipArchiveHandle zip;
|
||||
int error = OpenArchive(filename, &zip);
|
||||
|
|
@ -1316,9 +1311,9 @@ int LocalImageSource::OpenFile(const std::string& name) const {
|
|||
|
||||
static void do_flashall(const std::string& slot_override, bool skip_secondary, bool wipe) {
|
||||
std::string fname;
|
||||
queue_info_dump();
|
||||
dump_info();
|
||||
|
||||
fb_queue_query_save("product", cur_product, sizeof(cur_product));
|
||||
fb_query_save("product", cur_product, sizeof(cur_product));
|
||||
|
||||
FlashAllTool tool(LocalImageSource(), slot_override, skip_secondary, wipe);
|
||||
tool.Flash();
|
||||
|
|
@ -1338,7 +1333,7 @@ static void do_oem_command(const std::string& cmd, std::vector<std::string>* arg
|
|||
while (!args->empty()) {
|
||||
command += " " + next_arg(args);
|
||||
}
|
||||
fb_queue_command(command, "");
|
||||
fb_command(command, "");
|
||||
}
|
||||
|
||||
static std::string fb_fix_numeric_var(std::string var) {
|
||||
|
|
@ -1641,7 +1636,7 @@ int FastBootTool::Main(int argc, char* argv[]) {
|
|||
|
||||
if (command == "getvar") {
|
||||
std::string variable = next_arg(&args);
|
||||
fb_queue_display(variable, variable);
|
||||
fb_display(variable, variable);
|
||||
} else if (command == "erase") {
|
||||
std::string partition = next_arg(&args);
|
||||
auto erase = [&](const std::string& partition) {
|
||||
|
|
@ -1653,7 +1648,7 @@ int FastBootTool::Main(int argc, char* argv[]) {
|
|||
partition_type.c_str());
|
||||
}
|
||||
|
||||
fb_queue_erase(partition);
|
||||
fb_erase(partition);
|
||||
};
|
||||
do_for_partitions(partition, slot_override, erase, true);
|
||||
} else if (android::base::StartsWith(command, "format")) {
|
||||
|
|
@ -1681,8 +1676,8 @@ int FastBootTool::Main(int argc, char* argv[]) {
|
|||
data = load_file(filename.c_str(), &sz);
|
||||
if (data == nullptr) die("could not load '%s': %s", filename.c_str(), strerror(errno));
|
||||
if (sz != 256) die("signature must be 256 bytes (got %" PRId64 ")", sz);
|
||||
fb_queue_download("signature", data, sz);
|
||||
fb_queue_command("signature", "installing signature");
|
||||
fb_download("signature", data, sz);
|
||||
fb_command("signature", "installing signature");
|
||||
} else if (command == "reboot") {
|
||||
wants_reboot = true;
|
||||
|
||||
|
|
@ -1710,7 +1705,7 @@ int FastBootTool::Main(int argc, char* argv[]) {
|
|||
} else if (command == "reboot-fastboot") {
|
||||
wants_reboot_fastboot = true;
|
||||
} else if (command == "continue") {
|
||||
fb_queue_command("continue", "resuming boot");
|
||||
fb_command("continue", "resuming boot");
|
||||
} else if (command == "boot") {
|
||||
std::string kernel = next_arg(&args);
|
||||
std::string ramdisk;
|
||||
|
|
@ -1719,8 +1714,8 @@ int FastBootTool::Main(int argc, char* argv[]) {
|
|||
if (!args.empty()) second_stage = next_arg(&args);
|
||||
|
||||
data = load_bootable_image(kernel, ramdisk, second_stage, &sz);
|
||||
fb_queue_download("boot.img", data, sz);
|
||||
fb_queue_command("boot", "booting");
|
||||
fb_download("boot.img", data, sz);
|
||||
fb_command("boot", "booting");
|
||||
} else if (command == "flash") {
|
||||
std::string pname = next_arg(&args);
|
||||
|
||||
|
|
@ -1746,7 +1741,7 @@ int FastBootTool::Main(int argc, char* argv[]) {
|
|||
|
||||
data = load_bootable_image(kernel, ramdisk, second_stage, &sz);
|
||||
auto flashraw = [&](const std::string& partition) {
|
||||
fb_queue_flash(partition, data, sz);
|
||||
fb_flash(partition, data, sz);
|
||||
};
|
||||
do_for_partitions(partition, slot_override, flashraw, true);
|
||||
} else if (command == "flashall") {
|
||||
|
|
@ -1778,10 +1773,10 @@ int FastBootTool::Main(int argc, char* argv[]) {
|
|||
if (!load_buf(filename.c_str(), &buf) || buf.type != FB_BUFFER_FD) {
|
||||
die("cannot load '%s'", filename.c_str());
|
||||
}
|
||||
fb_queue_download_fd(filename, buf.fd, buf.sz);
|
||||
fb_download_fd(filename, buf.fd, buf.sz);
|
||||
} else if (command == "get_staged") {
|
||||
std::string filename = next_arg(&args);
|
||||
fb_queue_upload(filename);
|
||||
fb_upload(filename);
|
||||
} else if (command == "oem") {
|
||||
do_oem_command("oem", &args);
|
||||
} else if (command == "flashing") {
|
||||
|
|
@ -1798,14 +1793,14 @@ int FastBootTool::Main(int argc, char* argv[]) {
|
|||
} else if (command == "create-logical-partition") {
|
||||
std::string partition = next_arg(&args);
|
||||
std::string size = next_arg(&args);
|
||||
fb_queue_create_partition(partition, size);
|
||||
fb_create_partition(partition, size);
|
||||
} else if (command == "delete-logical-partition") {
|
||||
std::string partition = next_arg(&args);
|
||||
fb_queue_delete_partition(partition);
|
||||
fb_delete_partition(partition);
|
||||
} else if (command == "resize-logical-partition") {
|
||||
std::string partition = next_arg(&args);
|
||||
std::string size = next_arg(&args);
|
||||
fb_queue_resize_partition(partition, size);
|
||||
fb_resize_partition(partition, size);
|
||||
} else {
|
||||
syntax_error("unknown command %s", command.c_str());
|
||||
}
|
||||
|
|
@ -1817,7 +1812,7 @@ int FastBootTool::Main(int argc, char* argv[]) {
|
|||
std::string partition_type;
|
||||
if (!fb_getvar(std::string{"partition-type:"} + partition, &partition_type)) continue;
|
||||
if (partition_type.empty()) continue;
|
||||
fb_queue_erase(partition);
|
||||
fb_erase(partition);
|
||||
if (partition == "userdata" && set_fbe_marker) {
|
||||
fprintf(stderr, "setting FBE marker on initial userdata...\n");
|
||||
std::string initial_userdata_dir = create_fbemarker_tmpdir();
|
||||
|
|
@ -1832,26 +1827,25 @@ int FastBootTool::Main(int argc, char* argv[]) {
|
|||
fb_set_active(next_active);
|
||||
}
|
||||
if (wants_reboot && !skip_reboot) {
|
||||
fb_queue_reboot();
|
||||
fb_queue_wait_for_disconnect();
|
||||
fb_reboot();
|
||||
fb_wait_for_disconnect();
|
||||
} else if (wants_reboot_bootloader) {
|
||||
fb_queue_command("reboot-bootloader", "rebooting into bootloader");
|
||||
fb_queue_wait_for_disconnect();
|
||||
fb_command("reboot-bootloader", "rebooting into bootloader");
|
||||
fb_wait_for_disconnect();
|
||||
} else if (wants_reboot_recovery) {
|
||||
fb_queue_command("reboot-recovery", "rebooting into recovery");
|
||||
fb_queue_wait_for_disconnect();
|
||||
fb_command("reboot-recovery", "rebooting into recovery");
|
||||
fb_wait_for_disconnect();
|
||||
} else if (wants_reboot_fastboot) {
|
||||
fb_queue_command("reboot-fastboot", "rebooting into fastboot");
|
||||
fb_queue_wait_for_disconnect();
|
||||
fb_command("reboot-fastboot", "rebooting into fastboot");
|
||||
fb_wait_for_disconnect();
|
||||
}
|
||||
|
||||
int status = fb_execute_queue() ? EXIT_FAILURE : EXIT_SUCCESS;
|
||||
fprintf(stderr, "Finished. Total time: %.3fs\n", (now() - start));
|
||||
|
||||
if (Transport* old_transport = fb.set_transport(nullptr)) {
|
||||
delete old_transport;
|
||||
}
|
||||
return status;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void FastBootTool::ParseOsPatchLevel(boot_img_hdr_v1* hdr, const char* arg) {
|
||||
|
|
|
|||
|
|
@ -97,9 +97,9 @@ RetCode FastBootDriver::RebootTo(std::string target, std::string* response,
|
|||
return RawCommand("reboot-" + target, response, info);
|
||||
}
|
||||
|
||||
RetCode FastBootDriver::SetActive(const std::string& part, std::string* response,
|
||||
RetCode FastBootDriver::SetActive(const std::string& slot, std::string* response,
|
||||
std::vector<std::string>* info) {
|
||||
return RawCommand(Commands::SET_ACTIVE + part, response, info);
|
||||
return RawCommand(Commands::SET_ACTIVE + slot, response, info);
|
||||
}
|
||||
|
||||
RetCode FastBootDriver::FlashPartition(const std::string& part, const std::vector<char>& data) {
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ class FastBootDriver {
|
|||
RetCode Reboot(std::string* response = nullptr, std::vector<std::string>* info = nullptr);
|
||||
RetCode RebootTo(std::string target, std::string* response = nullptr,
|
||||
std::vector<std::string>* info = nullptr);
|
||||
RetCode SetActive(const std::string& part, std::string* response = nullptr,
|
||||
RetCode SetActive(const std::string& slot, std::string* response = nullptr,
|
||||
std::vector<std::string>* info = nullptr);
|
||||
RetCode Upload(const std::string& outfile, std::string* response = nullptr,
|
||||
std::vector<std::string>* info = nullptr);
|
||||
|
|
|
|||
|
|
@ -70,6 +70,11 @@ void verbose(const char* fmt, ...) {
|
|||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
void Status(const std::string& message) {
|
||||
static constexpr char kStatusFormat[] = "%-50s ";
|
||||
fprintf(stderr, kStatusFormat, message.c_str());
|
||||
}
|
||||
|
||||
char* xstrdup(const char* s) {
|
||||
char* result = strdup(s);
|
||||
if (!result) die("out of memory");
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@ double now();
|
|||
char* xstrdup(const char*);
|
||||
void set_verbose();
|
||||
|
||||
void Status(const std::string& message);
|
||||
|
||||
// These printf-like functions are implemented in terms of vsnprintf, so they
|
||||
// use the same attribute for compile-time format string checking.
|
||||
void die(const char* fmt, ...) __attribute__((__noreturn__))
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue