Loading fastboot/Android.mk +1 −1 Original line number Original line Diff line number Diff line Loading @@ -51,7 +51,7 @@ LOCAL_CFLAGS_darwin := -Wno-unused-parameter LOCAL_SRC_FILES_windows := usb_windows.cpp LOCAL_SRC_FILES_windows := usb_windows.cpp LOCAL_STATIC_LIBRARIES_windows := AdbWinApi LOCAL_STATIC_LIBRARIES_windows := AdbWinApi LOCAL_REQUIRED_MODULES_windows := AdbWinApi LOCAL_REQUIRED_MODULES_windows := AdbWinApi AdbWinUsbApi LOCAL_LDLIBS_windows := -lws2_32 LOCAL_LDLIBS_windows := -lws2_32 LOCAL_C_INCLUDES_windows := development/host/windows/usb/api LOCAL_C_INCLUDES_windows := development/host/windows/usb/api Loading fastboot/engine.cpp +25 −6 Original line number Original line Diff line number Diff line Loading @@ -44,6 +44,7 @@ #define OP_NOTICE 4 #define OP_NOTICE 4 #define OP_DOWNLOAD_SPARSE 5 #define OP_DOWNLOAD_SPARSE 5 #define OP_WAIT_FOR_DISCONNECT 6 #define OP_WAIT_FOR_DISCONNECT 6 #define OP_DOWNLOAD_FD 7 typedef struct Action Action; typedef struct Action Action; Loading @@ -56,6 +57,7 @@ struct Action { char cmd[CMD_SIZE]; char cmd[CMD_SIZE]; const char* prod; const char* prod; void* data; void* data; int fd; // The protocol only supports 32-bit sizes, so you'll have to break // The protocol only supports 32-bit sizes, so you'll have to break // anything larger into chunks. // anything larger into chunks. Loading Loading @@ -142,7 +144,20 @@ void fb_queue_erase(const char *ptn) a->msg = mkmsg("erasing '%s'", ptn); a->msg = mkmsg("erasing '%s'", ptn); } } void fb_queue_flash(const char *ptn, void *data, unsigned sz) void fb_queue_flash_fd(const char *ptn, 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)", ptn, sz / 1024); a = queue_action(OP_COMMAND, "flash:%s", ptn); a->msg = mkmsg("writing '%s'", ptn); } void fb_queue_flash(const char *ptn, void *data, uint32_t sz) { { Action *a; Action *a; Loading @@ -155,7 +170,7 @@ void fb_queue_flash(const char *ptn, void *data, unsigned sz) a->msg = mkmsg("writing '%s'", ptn); a->msg = mkmsg("writing '%s'", ptn); } } void fb_queue_flash_sparse(const char* ptn, struct sparse_file* s, unsigned sz, size_t current, void fb_queue_flash_sparse(const char* ptn, struct sparse_file* s, uint32_t sz, size_t current, size_t total) { size_t total) { Action *a; Action *a; Loading Loading @@ -282,7 +297,7 @@ static int cb_save(Action* a, int status, const char* resp) { return 0; return 0; } } void fb_queue_query_save(const char *var, char *dest, unsigned dest_size) void fb_queue_query_save(const char *var, char *dest, uint32_t dest_size) { { Action *a; Action *a; a = queue_action(OP_QUERY, "getvar:%s", var); a = queue_action(OP_QUERY, "getvar:%s", var); Loading @@ -309,7 +324,7 @@ void fb_queue_command(const char *cmd, const char *msg) a->msg = msg; a->msg = msg; } } void fb_queue_download(const char *name, void *data, unsigned size) void fb_queue_download(const char *name, void *data, uint32_t size) { { Action *a = queue_action(OP_DOWNLOAD, ""); Action *a = queue_action(OP_DOWNLOAD, ""); a->data = data; a->data = data; Loading @@ -328,11 +343,11 @@ void fb_queue_wait_for_disconnect(void) queue_action(OP_WAIT_FOR_DISCONNECT, ""); queue_action(OP_WAIT_FOR_DISCONNECT, ""); } } int fb_execute_queue(Transport* transport) int64_t fb_execute_queue(Transport* transport) { { Action *a; Action *a; char resp[FB_RESPONSE_SZ+1]; char resp[FB_RESPONSE_SZ+1]; int status = 0; int64_t status = 0; a = action_list; a = action_list; if (!a) if (!a) Loading @@ -351,6 +366,10 @@ int fb_execute_queue(Transport* transport) status = fb_download_data(transport, a->data, a->size); status = fb_download_data(transport, a->data, a->size); status = a->func(a, status, status ? fb_get_error().c_str() : ""); status = a->func(a, status, status ? fb_get_error().c_str() : ""); if (status) break; if (status) break; } else if (a->op == OP_DOWNLOAD_FD) { status = fb_download_data_fd(transport, a->fd, a->size); status = a->func(a, status, status ? fb_get_error().c_str() : ""); if (status) break; } else if (a->op == OP_COMMAND) { } else if (a->op == OP_COMMAND) { status = fb_command(transport, a->cmd); status = fb_command(transport, a->cmd); status = a->func(a, status, status ? fb_get_error().c_str() : ""); status = a->func(a, status, status ? fb_get_error().c_str() : ""); Loading fastboot/fastboot.cpp +28 −11 Original line number Original line Diff line number Diff line Loading @@ -55,6 +55,7 @@ #include <android-base/parsenetaddress.h> #include <android-base/parsenetaddress.h> #include <android-base/stringprintf.h> #include <android-base/stringprintf.h> #include <android-base/strings.h> #include <android-base/strings.h> #include <android-base/unique_fd.h> #include <sparse/sparse.h> #include <sparse/sparse.h> #include <ziparchive/zip_archive.h> #include <ziparchive/zip_archive.h> Loading @@ -67,6 +68,8 @@ #include "udp.h" #include "udp.h" #include "usb.h" #include "usb.h" using android::base::unique_fd; #ifndef O_BINARY #ifndef O_BINARY #define O_BINARY 0 #define O_BINARY 0 #endif #endif Loading @@ -78,6 +81,10 @@ static const char* product = nullptr; static const char* cmdline = nullptr; static const char* cmdline = nullptr; static unsigned short vendor_id = 0; static unsigned short vendor_id = 0; static int long_listing = 0; static int long_listing = 0; // Don't resparse files in too-big chunks. // libsparse will support INT_MAX, but this results in large allocations, so // let's keep it at 1GB to avoid memory pressure on the host. static constexpr int64_t RESPARSE_LIMIT = 1 * 1024 * 1024 * 1024; static int64_t sparse_limit = -1; static int64_t sparse_limit = -1; static int64_t target_sparse_limit = -1; static int64_t target_sparse_limit = -1; Loading @@ -91,7 +98,7 @@ static unsigned tags_offset = 0x00000100; static const std::string convert_fbe_marker_filename("convert_fbe"); static const std::string convert_fbe_marker_filename("convert_fbe"); enum fb_buffer_type { enum fb_buffer_type { FB_BUFFER, FB_BUFFER_FD, FB_BUFFER_SPARSE, FB_BUFFER_SPARSE, }; }; Loading @@ -99,6 +106,7 @@ struct fastboot_buffer { enum fb_buffer_type type; enum fb_buffer_type type; void* data; void* data; int64_t sz; int64_t sz; int fd; }; }; static struct { static struct { Loading Loading @@ -789,7 +797,7 @@ static int64_t get_sparse_limit(Transport* transport, int64_t size) { } } if (size > limit) { if (size > limit) { return limit; return std::min(limit, RESPARSE_LIMIT); } } return 0; return 0; Loading Loading @@ -822,10 +830,9 @@ static bool load_buf_fd(Transport* transport, int fd, struct fastboot_buffer* bu buf->type = FB_BUFFER_SPARSE; buf->type = FB_BUFFER_SPARSE; buf->data = s; buf->data = s; } else { } else { void* data = load_fd(fd, &sz); buf->type = FB_BUFFER_FD; if (data == nullptr) return -1; buf->data = nullptr; buf->type = FB_BUFFER; buf->fd = fd; buf->data = data; buf->sz = sz; buf->sz = sz; } } Loading @@ -833,11 +840,22 @@ static bool load_buf_fd(Transport* transport, int fd, struct fastboot_buffer* bu } } static bool load_buf(Transport* transport, const char* fname, struct fastboot_buffer* buf) { static bool load_buf(Transport* transport, const char* fname, struct fastboot_buffer* buf) { int fd = open(fname, O_RDONLY | O_BINARY); unique_fd fd(TEMP_FAILURE_RETRY(open(fname, O_RDONLY | O_BINARY))); if (fd == -1) { if (fd == -1) { return false; return false; } } return load_buf_fd(transport, fd, buf); struct stat s; if (fstat(fd, &s)) { return false; } if (!S_ISREG(s.st_mode)) { errno = S_ISDIR(s.st_mode) ? EISDIR : EINVAL; return false; } return load_buf_fd(transport, fd.release(), buf); } } static void flash_buf(const char *pname, struct fastboot_buffer *buf) static void flash_buf(const char *pname, struct fastboot_buffer *buf) Loading @@ -860,9 +878,8 @@ static void flash_buf(const char *pname, struct fastboot_buffer *buf) } } break; break; } } case FB_BUFFER_FD: case FB_BUFFER: fb_queue_flash_fd(pname, buf->fd, buf->sz); fb_queue_flash(pname, buf->data, buf->sz); break; break; default: default: die("unknown buffer type: %d", buf->type); die("unknown buffer type: %d", buf->type); Loading fastboot/fastboot.h +4 −2 Original line number Original line Diff line number Diff line Loading @@ -41,7 +41,8 @@ struct sparse_file; /* protocol.c - fastboot protocol */ /* protocol.c - fastboot protocol */ int fb_command(Transport* transport, const char* cmd); int fb_command(Transport* transport, const char* cmd); int fb_command_response(Transport* transport, const char* cmd, char* response); int fb_command_response(Transport* transport, const char* cmd, char* response); int fb_download_data(Transport* transport, const void* data, uint32_t size); 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); int fb_download_data_sparse(Transport* transport, struct sparse_file* s); const std::string fb_get_error(); const std::string fb_get_error(); Loading @@ -51,6 +52,7 @@ const std::string fb_get_error(); /* engine.c - high level command queue engine */ /* engine.c - high level command queue engine */ bool fb_getvar(Transport* transport, const std::string& key, std::string* value); bool fb_getvar(Transport* transport, const std::string& key, std::string* value); void fb_queue_flash(const char *ptn, void *data, uint32_t sz); void fb_queue_flash(const char *ptn, void *data, uint32_t sz); void fb_queue_flash_fd(const char *ptn, int fd, uint32_t sz); void fb_queue_flash_sparse(const char* ptn, struct sparse_file* s, uint32_t sz, size_t current, void fb_queue_flash_sparse(const char* ptn, struct sparse_file* s, uint32_t sz, size_t current, size_t total); size_t total); void fb_queue_erase(const char *ptn); void fb_queue_erase(const char *ptn); Loading @@ -64,7 +66,7 @@ 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(const char *name, void *data, uint32_t size); void fb_queue_notice(const char *notice); void fb_queue_notice(const char *notice); void fb_queue_wait_for_disconnect(void); void fb_queue_wait_for_disconnect(void); int fb_execute_queue(Transport* transport); int64_t fb_execute_queue(Transport* transport); void fb_set_active(const char *slot); void fb_set_active(const char *slot); /* util stuff */ /* util stuff */ Loading fastboot/protocol.cpp +54 −16 Original line number Original line Diff line number Diff line Loading @@ -38,6 +38,7 @@ #include <android-base/stringprintf.h> #include <android-base/stringprintf.h> #include <sparse/sparse.h> #include <sparse/sparse.h> #include <utils/FileMap.h> #include "fastboot.h" #include "fastboot.h" #include "transport.h" #include "transport.h" Loading @@ -48,7 +49,7 @@ const std::string fb_get_error() { return g_error; return g_error; } } static int check_response(Transport* transport, uint32_t size, char* response) { static int64_t check_response(Transport* transport, uint32_t size, char* response) { char status[65]; char status[65]; while (true) { while (true) { Loading Loading @@ -105,7 +106,7 @@ static int check_response(Transport* transport, uint32_t size, char* response) { return -1; return -1; } } static int _command_start(Transport* transport, const char* cmd, uint32_t size, char* response) { static int64_t _command_start(Transport* transport, const char* cmd, uint32_t size, char* response) { size_t cmdsize = strlen(cmd); size_t cmdsize = strlen(cmd); if (cmdsize > 64) { if (cmdsize > 64) { g_error = android::base::StringPrintf("command too large (%zu)", cmdsize); g_error = android::base::StringPrintf("command too large (%zu)", cmdsize); Loading @@ -125,14 +126,14 @@ static int _command_start(Transport* transport, const char* cmd, uint32_t size, return check_response(transport, size, response); return check_response(transport, size, response); } } static int _command_data(Transport* transport, const void* data, uint32_t size) { static int64_t _command_data(Transport* transport, const void* data, uint32_t size) { int r = transport->Write(data, size); int64_t r = transport->Write(data, size); if (r < 0) { if (r < 0) { g_error = android::base::StringPrintf("data transfer failure (%s)", strerror(errno)); g_error = android::base::StringPrintf("data transfer failure (%s)", strerror(errno)); transport->Close(); transport->Close(); return -1; return -1; } } if (r != ((int) size)) { if (r != static_cast<int64_t>(size)) { g_error = "data transfer failure (short transfer)"; g_error = "data transfer failure (short transfer)"; transport->Close(); transport->Close(); return -1; return -1; Loading @@ -140,17 +141,17 @@ static int _command_data(Transport* transport, const void* data, uint32_t size) return r; return r; } } static int _command_end(Transport* transport) { static int64_t _command_end(Transport* transport) { return check_response(transport, 0, 0) < 0 ? -1 : 0; return check_response(transport, 0, 0) < 0 ? -1 : 0; } } static int _command_send(Transport* transport, const char* cmd, const void* data, uint32_t size, static int64_t _command_send(Transport* transport, const char* cmd, const void* data, uint32_t size, char* response) { char* response) { if (size == 0) { if (size == 0) { return -1; return -1; } } int r = _command_start(transport, cmd, size, response); int64_t r = _command_start(transport, cmd, size, response); if (r < 0) { if (r < 0) { return -1; return -1; } } Loading @@ -168,6 +169,39 @@ static int _command_send(Transport* transport, const char* cmd, const void* data return size; return size; } } static int64_t _command_send_fd(Transport* transport, const char* cmd, int fd, uint32_t size, char* response) { static constexpr uint32_t MAX_MAP_SIZE = 512 * 1024 * 1024; off64_t offset = 0; uint32_t remaining = size; if (_command_start(transport, cmd, size, response) < 0) { return -1; } while (remaining) { android::FileMap filemap; size_t len = std::min(remaining, MAX_MAP_SIZE); if (!filemap.create(NULL, fd, offset, len, true)) { return -1; } if (_command_data(transport, filemap.getDataPtr(), len) < 0) { return -1; } remaining -= len; offset += len; } if (_command_end(transport) < 0) { return -1; } return size; } static int _command_send_no_data(Transport* transport, const char* cmd, char* response) { static int _command_send_no_data(Transport* transport, const char* cmd, char* response) { return _command_start(transport, cmd, 0, response); return _command_start(transport, cmd, 0, response); } } Loading @@ -180,10 +214,14 @@ int fb_command_response(Transport* transport, const char* cmd, char* response) { return _command_send_no_data(transport, cmd, response); return _command_send_no_data(transport, cmd, response); } } int fb_download_data(Transport* transport, const void* data, uint32_t size) { int64_t fb_download_data(Transport* transport, const void* data, uint32_t size) { char cmd[64]; std::string cmd(android::base::StringPrintf("download:%08x", size)); snprintf(cmd, sizeof(cmd), "download:%08x", size); return _command_send(transport, cmd.c_str(), data, size, 0) < 0 ? -1 : 0; return _command_send(transport, cmd, data, size, 0) < 0 ? -1 : 0; } int64_t fb_download_data_fd(Transport* transport, int fd, uint32_t size) { std::string cmd(android::base::StringPrintf("download:%08x", size)); return _command_send_fd(transport, cmd.c_str(), fd, size, 0) < 0 ? -1 : 0; } } #define TRANSPORT_BUF_SIZE 1024 #define TRANSPORT_BUF_SIZE 1024 Loading Loading @@ -242,7 +280,8 @@ static int fb_download_data_sparse_write(void *priv, const void *data, int len) static int fb_download_data_sparse_flush(Transport* transport) { static int fb_download_data_sparse_flush(Transport* transport) { if (transport_buf_len > 0) { if (transport_buf_len > 0) { if (_command_data(transport, transport_buf, transport_buf_len) != transport_buf_len) { int64_t r = _command_data(transport, transport_buf, transport_buf_len); if (r != static_cast<int64_t>(transport_buf_len)) { return -1; return -1; } } transport_buf_len = 0; transport_buf_len = 0; Loading @@ -256,9 +295,8 @@ int fb_download_data_sparse(Transport* transport, struct sparse_file* s) { return -1; return -1; } } char cmd[64]; std::string cmd(android::base::StringPrintf("download:%08x", size)); snprintf(cmd, sizeof(cmd), "download:%08x", size); int r = _command_start(transport, cmd.c_str(), size, 0); int r = _command_start(transport, cmd, size, 0); if (r < 0) { if (r < 0) { return -1; return -1; } } Loading Loading
fastboot/Android.mk +1 −1 Original line number Original line Diff line number Diff line Loading @@ -51,7 +51,7 @@ LOCAL_CFLAGS_darwin := -Wno-unused-parameter LOCAL_SRC_FILES_windows := usb_windows.cpp LOCAL_SRC_FILES_windows := usb_windows.cpp LOCAL_STATIC_LIBRARIES_windows := AdbWinApi LOCAL_STATIC_LIBRARIES_windows := AdbWinApi LOCAL_REQUIRED_MODULES_windows := AdbWinApi LOCAL_REQUIRED_MODULES_windows := AdbWinApi AdbWinUsbApi LOCAL_LDLIBS_windows := -lws2_32 LOCAL_LDLIBS_windows := -lws2_32 LOCAL_C_INCLUDES_windows := development/host/windows/usb/api LOCAL_C_INCLUDES_windows := development/host/windows/usb/api Loading
fastboot/engine.cpp +25 −6 Original line number Original line Diff line number Diff line Loading @@ -44,6 +44,7 @@ #define OP_NOTICE 4 #define OP_NOTICE 4 #define OP_DOWNLOAD_SPARSE 5 #define OP_DOWNLOAD_SPARSE 5 #define OP_WAIT_FOR_DISCONNECT 6 #define OP_WAIT_FOR_DISCONNECT 6 #define OP_DOWNLOAD_FD 7 typedef struct Action Action; typedef struct Action Action; Loading @@ -56,6 +57,7 @@ struct Action { char cmd[CMD_SIZE]; char cmd[CMD_SIZE]; const char* prod; const char* prod; void* data; void* data; int fd; // The protocol only supports 32-bit sizes, so you'll have to break // The protocol only supports 32-bit sizes, so you'll have to break // anything larger into chunks. // anything larger into chunks. Loading Loading @@ -142,7 +144,20 @@ void fb_queue_erase(const char *ptn) a->msg = mkmsg("erasing '%s'", ptn); a->msg = mkmsg("erasing '%s'", ptn); } } void fb_queue_flash(const char *ptn, void *data, unsigned sz) void fb_queue_flash_fd(const char *ptn, 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)", ptn, sz / 1024); a = queue_action(OP_COMMAND, "flash:%s", ptn); a->msg = mkmsg("writing '%s'", ptn); } void fb_queue_flash(const char *ptn, void *data, uint32_t sz) { { Action *a; Action *a; Loading @@ -155,7 +170,7 @@ void fb_queue_flash(const char *ptn, void *data, unsigned sz) a->msg = mkmsg("writing '%s'", ptn); a->msg = mkmsg("writing '%s'", ptn); } } void fb_queue_flash_sparse(const char* ptn, struct sparse_file* s, unsigned sz, size_t current, void fb_queue_flash_sparse(const char* ptn, struct sparse_file* s, uint32_t sz, size_t current, size_t total) { size_t total) { Action *a; Action *a; Loading Loading @@ -282,7 +297,7 @@ static int cb_save(Action* a, int status, const char* resp) { return 0; return 0; } } void fb_queue_query_save(const char *var, char *dest, unsigned dest_size) void fb_queue_query_save(const char *var, char *dest, uint32_t dest_size) { { Action *a; Action *a; a = queue_action(OP_QUERY, "getvar:%s", var); a = queue_action(OP_QUERY, "getvar:%s", var); Loading @@ -309,7 +324,7 @@ void fb_queue_command(const char *cmd, const char *msg) a->msg = msg; a->msg = msg; } } void fb_queue_download(const char *name, void *data, unsigned size) void fb_queue_download(const char *name, void *data, uint32_t size) { { Action *a = queue_action(OP_DOWNLOAD, ""); Action *a = queue_action(OP_DOWNLOAD, ""); a->data = data; a->data = data; Loading @@ -328,11 +343,11 @@ void fb_queue_wait_for_disconnect(void) queue_action(OP_WAIT_FOR_DISCONNECT, ""); queue_action(OP_WAIT_FOR_DISCONNECT, ""); } } int fb_execute_queue(Transport* transport) int64_t fb_execute_queue(Transport* transport) { { Action *a; Action *a; char resp[FB_RESPONSE_SZ+1]; char resp[FB_RESPONSE_SZ+1]; int status = 0; int64_t status = 0; a = action_list; a = action_list; if (!a) if (!a) Loading @@ -351,6 +366,10 @@ int fb_execute_queue(Transport* transport) status = fb_download_data(transport, a->data, a->size); status = fb_download_data(transport, a->data, a->size); status = a->func(a, status, status ? fb_get_error().c_str() : ""); status = a->func(a, status, status ? fb_get_error().c_str() : ""); if (status) break; if (status) break; } else if (a->op == OP_DOWNLOAD_FD) { status = fb_download_data_fd(transport, a->fd, a->size); status = a->func(a, status, status ? fb_get_error().c_str() : ""); if (status) break; } else if (a->op == OP_COMMAND) { } else if (a->op == OP_COMMAND) { status = fb_command(transport, a->cmd); status = fb_command(transport, a->cmd); status = a->func(a, status, status ? fb_get_error().c_str() : ""); status = a->func(a, status, status ? fb_get_error().c_str() : ""); Loading
fastboot/fastboot.cpp +28 −11 Original line number Original line Diff line number Diff line Loading @@ -55,6 +55,7 @@ #include <android-base/parsenetaddress.h> #include <android-base/parsenetaddress.h> #include <android-base/stringprintf.h> #include <android-base/stringprintf.h> #include <android-base/strings.h> #include <android-base/strings.h> #include <android-base/unique_fd.h> #include <sparse/sparse.h> #include <sparse/sparse.h> #include <ziparchive/zip_archive.h> #include <ziparchive/zip_archive.h> Loading @@ -67,6 +68,8 @@ #include "udp.h" #include "udp.h" #include "usb.h" #include "usb.h" using android::base::unique_fd; #ifndef O_BINARY #ifndef O_BINARY #define O_BINARY 0 #define O_BINARY 0 #endif #endif Loading @@ -78,6 +81,10 @@ static const char* product = nullptr; static const char* cmdline = nullptr; static const char* cmdline = nullptr; static unsigned short vendor_id = 0; static unsigned short vendor_id = 0; static int long_listing = 0; static int long_listing = 0; // Don't resparse files in too-big chunks. // libsparse will support INT_MAX, but this results in large allocations, so // let's keep it at 1GB to avoid memory pressure on the host. static constexpr int64_t RESPARSE_LIMIT = 1 * 1024 * 1024 * 1024; static int64_t sparse_limit = -1; static int64_t sparse_limit = -1; static int64_t target_sparse_limit = -1; static int64_t target_sparse_limit = -1; Loading @@ -91,7 +98,7 @@ static unsigned tags_offset = 0x00000100; static const std::string convert_fbe_marker_filename("convert_fbe"); static const std::string convert_fbe_marker_filename("convert_fbe"); enum fb_buffer_type { enum fb_buffer_type { FB_BUFFER, FB_BUFFER_FD, FB_BUFFER_SPARSE, FB_BUFFER_SPARSE, }; }; Loading @@ -99,6 +106,7 @@ struct fastboot_buffer { enum fb_buffer_type type; enum fb_buffer_type type; void* data; void* data; int64_t sz; int64_t sz; int fd; }; }; static struct { static struct { Loading Loading @@ -789,7 +797,7 @@ static int64_t get_sparse_limit(Transport* transport, int64_t size) { } } if (size > limit) { if (size > limit) { return limit; return std::min(limit, RESPARSE_LIMIT); } } return 0; return 0; Loading Loading @@ -822,10 +830,9 @@ static bool load_buf_fd(Transport* transport, int fd, struct fastboot_buffer* bu buf->type = FB_BUFFER_SPARSE; buf->type = FB_BUFFER_SPARSE; buf->data = s; buf->data = s; } else { } else { void* data = load_fd(fd, &sz); buf->type = FB_BUFFER_FD; if (data == nullptr) return -1; buf->data = nullptr; buf->type = FB_BUFFER; buf->fd = fd; buf->data = data; buf->sz = sz; buf->sz = sz; } } Loading @@ -833,11 +840,22 @@ static bool load_buf_fd(Transport* transport, int fd, struct fastboot_buffer* bu } } static bool load_buf(Transport* transport, const char* fname, struct fastboot_buffer* buf) { static bool load_buf(Transport* transport, const char* fname, struct fastboot_buffer* buf) { int fd = open(fname, O_RDONLY | O_BINARY); unique_fd fd(TEMP_FAILURE_RETRY(open(fname, O_RDONLY | O_BINARY))); if (fd == -1) { if (fd == -1) { return false; return false; } } return load_buf_fd(transport, fd, buf); struct stat s; if (fstat(fd, &s)) { return false; } if (!S_ISREG(s.st_mode)) { errno = S_ISDIR(s.st_mode) ? EISDIR : EINVAL; return false; } return load_buf_fd(transport, fd.release(), buf); } } static void flash_buf(const char *pname, struct fastboot_buffer *buf) static void flash_buf(const char *pname, struct fastboot_buffer *buf) Loading @@ -860,9 +878,8 @@ static void flash_buf(const char *pname, struct fastboot_buffer *buf) } } break; break; } } case FB_BUFFER_FD: case FB_BUFFER: fb_queue_flash_fd(pname, buf->fd, buf->sz); fb_queue_flash(pname, buf->data, buf->sz); break; break; default: default: die("unknown buffer type: %d", buf->type); die("unknown buffer type: %d", buf->type); Loading
fastboot/fastboot.h +4 −2 Original line number Original line Diff line number Diff line Loading @@ -41,7 +41,8 @@ struct sparse_file; /* protocol.c - fastboot protocol */ /* protocol.c - fastboot protocol */ int fb_command(Transport* transport, const char* cmd); int fb_command(Transport* transport, const char* cmd); int fb_command_response(Transport* transport, const char* cmd, char* response); int fb_command_response(Transport* transport, const char* cmd, char* response); int fb_download_data(Transport* transport, const void* data, uint32_t size); 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); int fb_download_data_sparse(Transport* transport, struct sparse_file* s); const std::string fb_get_error(); const std::string fb_get_error(); Loading @@ -51,6 +52,7 @@ const std::string fb_get_error(); /* engine.c - high level command queue engine */ /* engine.c - high level command queue engine */ bool fb_getvar(Transport* transport, const std::string& key, std::string* value); bool fb_getvar(Transport* transport, const std::string& key, std::string* value); void fb_queue_flash(const char *ptn, void *data, uint32_t sz); void fb_queue_flash(const char *ptn, void *data, uint32_t sz); void fb_queue_flash_fd(const char *ptn, int fd, uint32_t sz); void fb_queue_flash_sparse(const char* ptn, struct sparse_file* s, uint32_t sz, size_t current, void fb_queue_flash_sparse(const char* ptn, struct sparse_file* s, uint32_t sz, size_t current, size_t total); size_t total); void fb_queue_erase(const char *ptn); void fb_queue_erase(const char *ptn); Loading @@ -64,7 +66,7 @@ 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(const char *name, void *data, uint32_t size); void fb_queue_notice(const char *notice); void fb_queue_notice(const char *notice); void fb_queue_wait_for_disconnect(void); void fb_queue_wait_for_disconnect(void); int fb_execute_queue(Transport* transport); int64_t fb_execute_queue(Transport* transport); void fb_set_active(const char *slot); void fb_set_active(const char *slot); /* util stuff */ /* util stuff */ Loading
fastboot/protocol.cpp +54 −16 Original line number Original line Diff line number Diff line Loading @@ -38,6 +38,7 @@ #include <android-base/stringprintf.h> #include <android-base/stringprintf.h> #include <sparse/sparse.h> #include <sparse/sparse.h> #include <utils/FileMap.h> #include "fastboot.h" #include "fastboot.h" #include "transport.h" #include "transport.h" Loading @@ -48,7 +49,7 @@ const std::string fb_get_error() { return g_error; return g_error; } } static int check_response(Transport* transport, uint32_t size, char* response) { static int64_t check_response(Transport* transport, uint32_t size, char* response) { char status[65]; char status[65]; while (true) { while (true) { Loading Loading @@ -105,7 +106,7 @@ static int check_response(Transport* transport, uint32_t size, char* response) { return -1; return -1; } } static int _command_start(Transport* transport, const char* cmd, uint32_t size, char* response) { static int64_t _command_start(Transport* transport, const char* cmd, uint32_t size, char* response) { size_t cmdsize = strlen(cmd); size_t cmdsize = strlen(cmd); if (cmdsize > 64) { if (cmdsize > 64) { g_error = android::base::StringPrintf("command too large (%zu)", cmdsize); g_error = android::base::StringPrintf("command too large (%zu)", cmdsize); Loading @@ -125,14 +126,14 @@ static int _command_start(Transport* transport, const char* cmd, uint32_t size, return check_response(transport, size, response); return check_response(transport, size, response); } } static int _command_data(Transport* transport, const void* data, uint32_t size) { static int64_t _command_data(Transport* transport, const void* data, uint32_t size) { int r = transport->Write(data, size); int64_t r = transport->Write(data, size); if (r < 0) { if (r < 0) { g_error = android::base::StringPrintf("data transfer failure (%s)", strerror(errno)); g_error = android::base::StringPrintf("data transfer failure (%s)", strerror(errno)); transport->Close(); transport->Close(); return -1; return -1; } } if (r != ((int) size)) { if (r != static_cast<int64_t>(size)) { g_error = "data transfer failure (short transfer)"; g_error = "data transfer failure (short transfer)"; transport->Close(); transport->Close(); return -1; return -1; Loading @@ -140,17 +141,17 @@ static int _command_data(Transport* transport, const void* data, uint32_t size) return r; return r; } } static int _command_end(Transport* transport) { static int64_t _command_end(Transport* transport) { return check_response(transport, 0, 0) < 0 ? -1 : 0; return check_response(transport, 0, 0) < 0 ? -1 : 0; } } static int _command_send(Transport* transport, const char* cmd, const void* data, uint32_t size, static int64_t _command_send(Transport* transport, const char* cmd, const void* data, uint32_t size, char* response) { char* response) { if (size == 0) { if (size == 0) { return -1; return -1; } } int r = _command_start(transport, cmd, size, response); int64_t r = _command_start(transport, cmd, size, response); if (r < 0) { if (r < 0) { return -1; return -1; } } Loading @@ -168,6 +169,39 @@ static int _command_send(Transport* transport, const char* cmd, const void* data return size; return size; } } static int64_t _command_send_fd(Transport* transport, const char* cmd, int fd, uint32_t size, char* response) { static constexpr uint32_t MAX_MAP_SIZE = 512 * 1024 * 1024; off64_t offset = 0; uint32_t remaining = size; if (_command_start(transport, cmd, size, response) < 0) { return -1; } while (remaining) { android::FileMap filemap; size_t len = std::min(remaining, MAX_MAP_SIZE); if (!filemap.create(NULL, fd, offset, len, true)) { return -1; } if (_command_data(transport, filemap.getDataPtr(), len) < 0) { return -1; } remaining -= len; offset += len; } if (_command_end(transport) < 0) { return -1; } return size; } static int _command_send_no_data(Transport* transport, const char* cmd, char* response) { static int _command_send_no_data(Transport* transport, const char* cmd, char* response) { return _command_start(transport, cmd, 0, response); return _command_start(transport, cmd, 0, response); } } Loading @@ -180,10 +214,14 @@ int fb_command_response(Transport* transport, const char* cmd, char* response) { return _command_send_no_data(transport, cmd, response); return _command_send_no_data(transport, cmd, response); } } int fb_download_data(Transport* transport, const void* data, uint32_t size) { int64_t fb_download_data(Transport* transport, const void* data, uint32_t size) { char cmd[64]; std::string cmd(android::base::StringPrintf("download:%08x", size)); snprintf(cmd, sizeof(cmd), "download:%08x", size); return _command_send(transport, cmd.c_str(), data, size, 0) < 0 ? -1 : 0; return _command_send(transport, cmd, data, size, 0) < 0 ? -1 : 0; } int64_t fb_download_data_fd(Transport* transport, int fd, uint32_t size) { std::string cmd(android::base::StringPrintf("download:%08x", size)); return _command_send_fd(transport, cmd.c_str(), fd, size, 0) < 0 ? -1 : 0; } } #define TRANSPORT_BUF_SIZE 1024 #define TRANSPORT_BUF_SIZE 1024 Loading Loading @@ -242,7 +280,8 @@ static int fb_download_data_sparse_write(void *priv, const void *data, int len) static int fb_download_data_sparse_flush(Transport* transport) { static int fb_download_data_sparse_flush(Transport* transport) { if (transport_buf_len > 0) { if (transport_buf_len > 0) { if (_command_data(transport, transport_buf, transport_buf_len) != transport_buf_len) { int64_t r = _command_data(transport, transport_buf, transport_buf_len); if (r != static_cast<int64_t>(transport_buf_len)) { return -1; return -1; } } transport_buf_len = 0; transport_buf_len = 0; Loading @@ -256,9 +295,8 @@ int fb_download_data_sparse(Transport* transport, struct sparse_file* s) { return -1; return -1; } } char cmd[64]; std::string cmd(android::base::StringPrintf("download:%08x", size)); snprintf(cmd, sizeof(cmd), "download:%08x", size); int r = _command_start(transport, cmd.c_str(), size, 0); int r = _command_start(transport, cmd, size, 0); if (r < 0) { if (r < 0) { return -1; return -1; } } Loading