Merge changes I5b1a1ce0,I483a18f9
am: 9349b72a67
Change-Id: Ia2a70526d7fd97a45d62f896f6e3888c9df3e982
This commit is contained in:
commit
4cd2da28ff
|
@ -126,6 +126,16 @@ The various currently defined commands are:
|
|||
space in RAM or "FAIL" if not. The size of
|
||||
the download is remembered.
|
||||
|
||||
upload Read data from memory which was staged by the last
|
||||
command, e.g. an oem command. The client will reply
|
||||
with "DATA%08x" if it is ready to send %08x bytes of
|
||||
data. If no data was staged in the last command,
|
||||
the client must reply with "FAIL". After the client
|
||||
successfully sends %08x bytes, the client shall send
|
||||
a single packet starting with "OKAY". Clients
|
||||
should not support "upload" unless it supports an
|
||||
oem command that requires "upload" capabilities.
|
||||
|
||||
verify:%08x Send a digital signature to verify the downloaded
|
||||
data. Required if the bootloader is "secure"
|
||||
otherwise "flash" and "boot" will be ignored.
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
#define OP_DOWNLOAD_SPARSE 5
|
||||
#define OP_WAIT_FOR_DISCONNECT 6
|
||||
#define OP_DOWNLOAD_FD 7
|
||||
#define OP_UPLOAD 8
|
||||
|
||||
typedef struct Action Action;
|
||||
|
||||
|
@ -332,6 +333,22 @@ void fb_queue_download(const char *name, void *data, uint32_t size)
|
|||
a->msg = mkmsg("downloading '%s'", name);
|
||||
}
|
||||
|
||||
void fb_queue_download_fd(const char *name, int fd, uint32_t sz)
|
||||
{
|
||||
Action *a;
|
||||
a = queue_action(OP_DOWNLOAD_FD, "");
|
||||
a->fd = fd;
|
||||
a->size = sz;
|
||||
a->msg = mkmsg("sending '%s' (%d KB)", name, sz / 1024);
|
||||
}
|
||||
|
||||
void fb_queue_upload(char *outfile)
|
||||
{
|
||||
Action *a = queue_action(OP_UPLOAD, "");
|
||||
a->data = outfile;
|
||||
a->msg = mkmsg("uploading '%s'", outfile);
|
||||
}
|
||||
|
||||
void fb_queue_notice(const char *notice)
|
||||
{
|
||||
Action *a = queue_action(OP_NOTICE, "");
|
||||
|
@ -386,6 +403,9 @@ int64_t fb_execute_queue(Transport* transport)
|
|||
if (status) break;
|
||||
} else if (a->op == OP_WAIT_FOR_DISCONNECT) {
|
||||
transport->WaitForDisconnect();
|
||||
} else if (a->op == OP_UPLOAD) {
|
||||
status = fb_upload_data(transport, reinterpret_cast<char*>(a->data));
|
||||
status = a->func(a, status, status ? fb_get_error().c_str() : "");
|
||||
} else {
|
||||
die("bogus action");
|
||||
}
|
||||
|
|
|
@ -371,6 +371,13 @@ static void usage() {
|
|||
" continue Continue with autoboot.\n"
|
||||
" reboot [bootloader|emergency] Reboot device [into bootloader or emergency mode].\n"
|
||||
" reboot-bootloader Reboot device into bootloader.\n"
|
||||
" oem <parameter1> ... <parameterN> Executes oem specific command.\n"
|
||||
" stage <infile> Sends contents of <infile> to stage for\n"
|
||||
" the next command. Supported only on\n"
|
||||
" Android Things devices.\n"
|
||||
" get_staged <outfile> Receives data to <outfile> staged by the\n"
|
||||
" last command. Supported only on Android\n"
|
||||
" Things devices.\n"
|
||||
" help Show this help message.\n"
|
||||
"\n"
|
||||
"options:\n"
|
||||
|
@ -1823,6 +1830,20 @@ int main(int argc, char **argv)
|
|||
}
|
||||
fb_set_active(slot.c_str());
|
||||
skip(2);
|
||||
} else if(!strcmp(*argv, "stage")) {
|
||||
require(2);
|
||||
std::string infile(argv[1]);
|
||||
skip(2);
|
||||
struct fastboot_buffer buf;
|
||||
if (!load_buf(transport, infile.c_str(), &buf) || buf.type != FB_BUFFER_FD) {
|
||||
die("cannot load '%s'", infile.c_str());
|
||||
}
|
||||
fb_queue_download_fd(infile.c_str(), buf.fd, buf.sz);
|
||||
} else if(!strcmp(*argv, "get_staged")) {
|
||||
require(2);
|
||||
char *outfile = argv[1];
|
||||
skip(2);
|
||||
fb_queue_upload(outfile);
|
||||
} else if(!strcmp(*argv, "oem")) {
|
||||
argc = do_oem_command(argc, argv);
|
||||
} else if(!strcmp(*argv, "flashing")) {
|
||||
|
|
|
@ -44,6 +44,7 @@ int fb_command_response(Transport* transport, const char* cmd, char* response);
|
|||
int64_t fb_download_data(Transport* transport, const void* data, uint32_t size);
|
||||
int64_t fb_download_data_fd(Transport* transport, int fd, uint32_t size);
|
||||
int fb_download_data_sparse(Transport* transport, struct sparse_file* s);
|
||||
int64_t fb_upload_data(Transport* transport, const char* outfile);
|
||||
const std::string fb_get_error();
|
||||
|
||||
#define FB_COMMAND_SZ 64
|
||||
|
@ -64,6 +65,8 @@ void fb_queue_query_save(const char *var, char *dest, uint32_t dest_size);
|
|||
void fb_queue_reboot(void);
|
||||
void fb_queue_command(const char *cmd, const char *msg);
|
||||
void fb_queue_download(const char *name, void *data, uint32_t size);
|
||||
void fb_queue_download_fd(const char *name, int fd, uint32_t sz);
|
||||
void fb_queue_upload(char *outfile);
|
||||
void fb_queue_notice(const char *notice);
|
||||
void fb_queue_wait_for_disconnect(void);
|
||||
int64_t fb_execute_queue(Transport* transport);
|
||||
|
|
|
@ -29,14 +29,18 @@
|
|||
#define round_down(a, b) \
|
||||
({ typeof(a) _a = (a); typeof(b) _b = (b); _a - (_a % _b); })
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
#include <android-base/file.h>
|
||||
#include <android-base/stringprintf.h>
|
||||
#include <android-base/unique_fd.h>
|
||||
#include <sparse/sparse.h>
|
||||
#include <utils/FileMap.h>
|
||||
|
||||
|
@ -45,6 +49,9 @@
|
|||
|
||||
static std::string g_error;
|
||||
|
||||
using android::base::unique_fd;
|
||||
using android::base::WriteStringToFile;
|
||||
|
||||
const std::string fb_get_error() {
|
||||
return g_error;
|
||||
}
|
||||
|
@ -126,15 +133,30 @@ static int64_t _command_start(Transport* transport, const char* cmd, uint32_t si
|
|||
return check_response(transport, size, response);
|
||||
}
|
||||
|
||||
static int64_t _command_data(Transport* transport, const void* data, uint32_t size) {
|
||||
static int64_t _command_write_data(Transport* transport, const void* data, uint32_t size) {
|
||||
int64_t r = transport->Write(data, size);
|
||||
if (r < 0) {
|
||||
g_error = android::base::StringPrintf("data transfer failure (%s)", strerror(errno));
|
||||
g_error = android::base::StringPrintf("data write failure (%s)", strerror(errno));
|
||||
transport->Close();
|
||||
return -1;
|
||||
}
|
||||
if (r != static_cast<int64_t>(size)) {
|
||||
g_error = "data transfer failure (short transfer)";
|
||||
g_error = "data write failure (short transfer)";
|
||||
transport->Close();
|
||||
return -1;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
static int64_t _command_read_data(Transport* transport, void* data, uint32_t size) {
|
||||
int64_t r = transport->Read(data, size);
|
||||
if (r < 0) {
|
||||
g_error = android::base::StringPrintf("data read failure (%s)", strerror(errno));
|
||||
transport->Close();
|
||||
return -1;
|
||||
}
|
||||
if (r != (static_cast<int64_t>(size))) {
|
||||
g_error = "data read failure (short transfer)";
|
||||
transport->Close();
|
||||
return -1;
|
||||
}
|
||||
|
@ -155,8 +177,7 @@ static int64_t _command_send(Transport* transport, const char* cmd, const void*
|
|||
if (r < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
r = _command_data(transport, data, size);
|
||||
r = _command_write_data(transport, data, size);
|
||||
if (r < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
@ -187,7 +208,7 @@ static int64_t _command_send_fd(Transport* transport, const char* cmd, int fd, u
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (_command_data(transport, filemap.getDataPtr(), len) < 0) {
|
||||
if (_command_write_data(transport, filemap.getDataPtr(), len) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -224,6 +245,28 @@ int64_t fb_download_data_fd(Transport* transport, int fd, uint32_t size) {
|
|||
return _command_send_fd(transport, cmd.c_str(), fd, size, 0) < 0 ? -1 : 0;
|
||||
}
|
||||
|
||||
int64_t fb_upload_data(Transport* transport, const char* outfile) {
|
||||
// positive return value is the upload size sent by the device
|
||||
int64_t r = _command_start(transport, "upload", std::numeric_limits<int32_t>::max(), nullptr);
|
||||
if (r <= 0) {
|
||||
g_error = android::base::StringPrintf("command start failed (%s)", strerror(errno));
|
||||
return r;
|
||||
}
|
||||
|
||||
std::string data;
|
||||
data.resize(r);
|
||||
if ((r = _command_read_data(transport, &data[0], data.size())) == -1) {
|
||||
return r;
|
||||
}
|
||||
|
||||
if (!WriteStringToFile(data, outfile, true)) {
|
||||
g_error = android::base::StringPrintf("write to '%s' failed", outfile);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return _command_end(transport);
|
||||
}
|
||||
|
||||
#define TRANSPORT_BUF_SIZE 1024
|
||||
static char transport_buf[TRANSPORT_BUF_SIZE];
|
||||
static int transport_buf_len;
|
||||
|
@ -245,7 +288,7 @@ static int fb_download_data_sparse_write(void *priv, const void *data, int len)
|
|||
}
|
||||
|
||||
if (transport_buf_len == TRANSPORT_BUF_SIZE) {
|
||||
r = _command_data(transport, transport_buf, TRANSPORT_BUF_SIZE);
|
||||
r = _command_write_data(transport, transport_buf, TRANSPORT_BUF_SIZE);
|
||||
if (r != TRANSPORT_BUF_SIZE) {
|
||||
return -1;
|
||||
}
|
||||
|
@ -258,7 +301,7 @@ static int fb_download_data_sparse_write(void *priv, const void *data, int len)
|
|||
return -1;
|
||||
}
|
||||
to_write = round_down(len, TRANSPORT_BUF_SIZE);
|
||||
r = _command_data(transport, ptr, to_write);
|
||||
r = _command_write_data(transport, ptr, to_write);
|
||||
if (r != to_write) {
|
||||
return -1;
|
||||
}
|
||||
|
@ -280,7 +323,7 @@ static int fb_download_data_sparse_write(void *priv, const void *data, int len)
|
|||
|
||||
static int fb_download_data_sparse_flush(Transport* transport) {
|
||||
if (transport_buf_len > 0) {
|
||||
int64_t r = _command_data(transport, transport_buf, transport_buf_len);
|
||||
int64_t r = _command_write_data(transport, transport_buf, transport_buf_len);
|
||||
if (r != static_cast<int64_t>(transport_buf_len)) {
|
||||
return -1;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue