Fastbootd: socket and network transport
Change-Id: I395e5361d0484bd11421225c152f9aec00305f11
This commit is contained in:
parent
00f4e93730
commit
2a656c332b
9 changed files with 396 additions and 53 deletions
|
@ -30,7 +30,9 @@ LOCAL_SRC_FILES := \
|
|||
commands/virtual_partitions.c \
|
||||
fastbootd.c \
|
||||
protocol.c \
|
||||
socket_client.c \
|
||||
transport.c \
|
||||
transport_socket.c \
|
||||
trigger.c \
|
||||
usb_linux_client.c \
|
||||
utils.c
|
||||
|
|
|
@ -16,32 +16,69 @@
|
|||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <cutils/klog.h>
|
||||
#include <getopt.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include "trigger.h"
|
||||
#include "socket_client.h"
|
||||
|
||||
unsigned int debug_level = DEBUG;
|
||||
|
||||
void commands_init();
|
||||
void usb_init();
|
||||
void config_init();
|
||||
int transport_socket_init();
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int socket_client = 0;
|
||||
int c;
|
||||
|
||||
klog_init();
|
||||
klog_set_level(6);
|
||||
|
||||
const struct option longopts[] = {
|
||||
{"socket", no_argument, 0, 'S'},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
while (1) {
|
||||
c = getopt_long(argc, argv, "S", longopts, NULL);
|
||||
/* Alphabetical cases */
|
||||
if (c < 0)
|
||||
break;
|
||||
switch (c) {
|
||||
case 'S':
|
||||
socket_client = 1;
|
||||
break;
|
||||
case '?':
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
|
||||
klog_init();
|
||||
klog_set_level(6);
|
||||
|
||||
config_init();
|
||||
load_trigger();
|
||||
commands_init();
|
||||
usb_init();
|
||||
while (1) {
|
||||
sleep(1);
|
||||
if (socket_client) {
|
||||
run_socket_client();
|
||||
}
|
||||
else {
|
||||
config_init();
|
||||
load_trigger();
|
||||
commands_init();
|
||||
usb_init();
|
||||
if (!transport_socket_init())
|
||||
exit(1);
|
||||
while (1) {
|
||||
sleep(1);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
94
fastbootd/socket_client.c
Normal file
94
fastbootd/socket_client.c
Normal file
|
@ -0,0 +1,94 @@
|
|||
/*
|
||||
* Copyright (c) 2009-2013, Google Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Google, Inc. nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <cutils/sockets.h>
|
||||
#include <poll.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
#define BUFFER_SIZE 256
|
||||
|
||||
#define STDIN_FD 0
|
||||
#define STDOUT_FD 1
|
||||
#define STDERR_FD 2
|
||||
|
||||
void run_socket_client() {
|
||||
int fd;
|
||||
char buffer[BUFFER_SIZE];
|
||||
int n;
|
||||
struct pollfd fds[2];
|
||||
|
||||
fd = socket_local_client("fastbootd",
|
||||
ANDROID_SOCKET_NAMESPACE_RESERVED,
|
||||
SOCK_STREAM);
|
||||
|
||||
if (fd < 0) {
|
||||
fprintf(stderr, "ERROR: Unable to open fastbootd socket\n");
|
||||
return;
|
||||
}
|
||||
|
||||
fds[0].fd = STDIN_FD;
|
||||
fds[0].events = POLLIN;
|
||||
fds[1].fd = fd;
|
||||
fds[1].events = POLLIN;
|
||||
|
||||
while(true) {
|
||||
if (poll(fds, 2, -1) <= 0) {
|
||||
fprintf(stderr, "ERROR: socket error");
|
||||
return;
|
||||
}
|
||||
|
||||
if (fds[0].revents & POLLIN) {
|
||||
if ((n = read(STDIN_FD, buffer, BUFFER_SIZE)) < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (bulk_write(fd, buffer, n) < 0) {
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
if (fds[1].revents & POLLIN) {
|
||||
if ((n = read(fd, buffer, BUFFER_SIZE)) < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (bulk_write(STDOUT_FD, buffer, n) < 0) {
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
error:
|
||||
fprintf(stderr, "Transport error\n");
|
||||
}
|
37
fastbootd/socket_client.h
Normal file
37
fastbootd/socket_client.h
Normal file
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Copyright (c) 2009-2013, Google Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Google, Inc. nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _FASTBOOTD_SOCKET_CLIENT_H
|
||||
#define _FASTBOOTD_SOCKET_CLIENT_H
|
||||
|
||||
void run_socket_client();
|
||||
|
||||
#endif
|
|
@ -99,6 +99,7 @@ static void *transport_data_thread(void *arg)
|
|||
}
|
||||
if (ret > 0) {
|
||||
buffer[ret] = 0;
|
||||
//TODO: multiple threads
|
||||
protocol_handle_command(phandle, buffer);
|
||||
}
|
||||
}
|
||||
|
|
155
fastbootd/transport_socket.c
Normal file
155
fastbootd/transport_socket.c
Normal file
|
@ -0,0 +1,155 @@
|
|||
/*
|
||||
* Copyright (c) 2009-2013, Google Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Google, Inc. nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <unistd.h>
|
||||
#include <cutils/sockets.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include "transport.h"
|
||||
#include "utils.h"
|
||||
|
||||
|
||||
#define container_of(ptr, type, member) \
|
||||
((type*)((char*)(ptr) - offsetof(type, member)))
|
||||
|
||||
#define SOCKET_WORKING 0
|
||||
#define SOCKET_STOPPED -1
|
||||
|
||||
|
||||
struct socket_transport {
|
||||
struct transport transport;
|
||||
|
||||
int fd;
|
||||
};
|
||||
|
||||
struct socket_handle {
|
||||
struct transport_handle handle;
|
||||
|
||||
int fd;
|
||||
};
|
||||
|
||||
void socket_close(struct transport_handle *thandle)
|
||||
{
|
||||
struct socket_handle * handle = container_of(thandle, struct socket_handle, handle);
|
||||
close(handle->fd);
|
||||
}
|
||||
|
||||
struct transport_handle *socket_connect(struct transport *transport)
|
||||
{
|
||||
struct socket_handle *handle = calloc(sizeof(struct socket_handle), 1);
|
||||
struct socket_transport *socket_transport = container_of(transport, struct socket_transport, transport);
|
||||
struct sockaddr addr;
|
||||
socklen_t alen = sizeof(addr);
|
||||
|
||||
handle->fd = accept(socket_transport->fd, &addr, &alen);
|
||||
|
||||
if (handle->fd < 0) {
|
||||
D(WARN, "socket connect error");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
D(DEBUG, "[ socket_thread - registering device ]");
|
||||
return &handle->handle;
|
||||
}
|
||||
|
||||
ssize_t socket_write(struct transport_handle *thandle, const void *data, size_t len)
|
||||
{
|
||||
ssize_t ret;
|
||||
struct socket_handle *handle = container_of(thandle, struct socket_handle, handle);
|
||||
|
||||
D(DEBUG, "about to write (fd=%d, len=%d)", handle->fd, len);
|
||||
ret = bulk_write(handle->fd, data, len);
|
||||
if (ret < 0) {
|
||||
D(ERR, "ERROR: fd = %d, ret = %zd", handle->fd, ret);
|
||||
return -1;
|
||||
}
|
||||
D(DEBUG, "[ socket_write done fd=%d ]", handle->fd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ssize_t socket_read(struct transport_handle *thandle, void *data, size_t len)
|
||||
{
|
||||
ssize_t ret;
|
||||
struct socket_handle *handle = container_of(thandle, struct socket_handle, handle);
|
||||
|
||||
D(DEBUG, "about to read (fd=%d, len=%d)", handle->fd, len);
|
||||
ret = bulk_read(handle->fd, data, len);
|
||||
if (ret < 0) {
|
||||
D(ERR, "ERROR: fd = %d, ret = %zd", handle->fd, ret);
|
||||
return -1;
|
||||
}
|
||||
D(DEBUG, "[ socket_read done fd=%d ret=%zd]", handle->fd, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int listen_socket_init(struct socket_transport *socket_transport)
|
||||
{
|
||||
int s = android_get_control_socket("fastbootd");
|
||||
|
||||
if (s < 0) {
|
||||
D(WARN, "android_get_control_socket(fastbootd): %s\n", strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (listen(s, 4) < 0) {
|
||||
D(WARN, "listen(control socket): %s\n", strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
|
||||
socket_transport->fd = s;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int transport_socket_init()
|
||||
{
|
||||
struct socket_transport *socket_transport = malloc(sizeof(struct socket_transport));
|
||||
|
||||
socket_transport->transport.connect = socket_connect;
|
||||
socket_transport->transport.close = socket_close;
|
||||
socket_transport->transport.read = socket_read;
|
||||
socket_transport->transport.write = socket_write;
|
||||
// TODO: create sshd key pair if necessary
|
||||
|
||||
if (!listen_socket_init(socket_transport)) {
|
||||
D(ERR, "socket transport init failed");
|
||||
free(socket_transport);
|
||||
return 0;
|
||||
}
|
||||
|
||||
transport_register(&socket_transport->transport);
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -30,6 +30,7 @@
|
|||
|
||||
#include "debug.h"
|
||||
#include "transport.h"
|
||||
#include "utils.h"
|
||||
|
||||
#define TRACE_TAG TRACE_USB
|
||||
|
||||
|
@ -50,8 +51,6 @@
|
|||
#define USB_FFS_FASTBOOT_OUT USB_FFS_FASTBOOT_EP(ep1)
|
||||
#define USB_FFS_FASTBOOT_IN USB_FFS_FASTBOOT_EP(ep2)
|
||||
|
||||
#define READ_BUF_SIZE (16*1024)
|
||||
|
||||
#define container_of(ptr, type, member) \
|
||||
((type*)((char*)(ptr) - offsetof(type, member)))
|
||||
|
||||
|
@ -212,26 +211,6 @@ err:
|
|||
return -1;
|
||||
}
|
||||
|
||||
static ssize_t bulk_write(int bulk_in, const char *buf, size_t length)
|
||||
{
|
||||
size_t count = 0;
|
||||
ssize_t ret;
|
||||
|
||||
do {
|
||||
ret = TEMP_FAILURE_RETRY(write(bulk_in, buf + count, length - count));
|
||||
if (ret < 0) {
|
||||
D(WARN, "[ bulk_read failed fd=%d length=%d errno=%d %s ]",
|
||||
bulk_in, length, errno, strerror(errno));
|
||||
return -1;
|
||||
} else {
|
||||
count += ret;
|
||||
}
|
||||
} while (count < length);
|
||||
|
||||
D(VERBOSE, "[ bulk_write done fd=%d ]", bulk_in);
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t usb_write(struct transport_handle *thandle, const void *data, size_t len)
|
||||
{
|
||||
ssize_t ret;
|
||||
|
@ -248,30 +227,6 @@ static ssize_t usb_write(struct transport_handle *thandle, const void *data, siz
|
|||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t bulk_read(int bulk_out, char *buf, size_t length)
|
||||
{
|
||||
ssize_t ret;
|
||||
size_t n = 0;
|
||||
|
||||
while (n < length) {
|
||||
size_t to_read = (length - n > READ_BUF_SIZE) ? READ_BUF_SIZE : length - n;
|
||||
ret = TEMP_FAILURE_RETRY(read(bulk_out, buf + n, to_read));
|
||||
if (ret < 0) {
|
||||
D(WARN, "[ bulk_read failed fd=%d length=%d errno=%d %s ]",
|
||||
bulk_out, length, errno, strerror(errno));
|
||||
return ret;
|
||||
}
|
||||
n += ret;
|
||||
if (ret < (ssize_t)to_read) {
|
||||
D(VERBOSE, "bulk_read short read, ret=%zd to_read=%u n=%u length=%u",
|
||||
ret, to_read, n, length);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
ssize_t usb_read(struct transport_handle *thandle, void *data, size_t len)
|
||||
{
|
||||
ssize_t ret;
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include <stdio.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <linux/fs.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "utils.h"
|
||||
#include "debug.h"
|
||||
|
@ -46,6 +47,7 @@
|
|||
#define BLKSECDISCARD _IO(0x12,125)
|
||||
#endif
|
||||
|
||||
#define READ_BUF_SIZE (16*1024)
|
||||
|
||||
int get_stream_size(FILE *stream) {
|
||||
int size;
|
||||
|
@ -145,3 +147,60 @@ int wipe_block_device(int fd, int64_t len)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int create_temp_file() {
|
||||
char tempname[] = "/dev/fastboot_data_XXXXXX";
|
||||
int fd;
|
||||
|
||||
fd = mkstemp(tempname);
|
||||
if (fd < 0)
|
||||
return -1;
|
||||
|
||||
unlink(tempname);
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
ssize_t bulk_write(int bulk_in, const char *buf, size_t length)
|
||||
{
|
||||
size_t count = 0;
|
||||
ssize_t ret;
|
||||
|
||||
do {
|
||||
ret = TEMP_FAILURE_RETRY(write(bulk_in, buf + count, length - count));
|
||||
if (ret < 0) {
|
||||
D(WARN, "[ bulk_write failed fd=%d length=%d errno=%d %s ]",
|
||||
bulk_in, length, errno, strerror(errno));
|
||||
return -1;
|
||||
} else {
|
||||
count += ret;
|
||||
}
|
||||
} while (count < length);
|
||||
|
||||
D(VERBOSE, "[ bulk_write done fd=%d ]", bulk_in);
|
||||
return count;
|
||||
}
|
||||
|
||||
ssize_t bulk_read(int bulk_out, char *buf, size_t length)
|
||||
{
|
||||
ssize_t ret;
|
||||
size_t n = 0;
|
||||
|
||||
while (n < length) {
|
||||
size_t to_read = (length - n > READ_BUF_SIZE) ? READ_BUF_SIZE : length - n;
|
||||
ret = TEMP_FAILURE_RETRY(read(bulk_out, buf + n, to_read));
|
||||
if (ret < 0) {
|
||||
D(WARN, "[ bulk_read failed fd=%d length=%d errno=%d %s ]",
|
||||
bulk_out, length, errno, strerror(errno));
|
||||
return ret;
|
||||
}
|
||||
n += ret;
|
||||
if (ret < (ssize_t)to_read) {
|
||||
D(VERBOSE, "bulk_read short read, ret=%zd to_read=%u n=%u length=%u",
|
||||
ret, to_read, n, length);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
|
|
|
@ -42,6 +42,9 @@ uint64_t get_file_size64(int fd);
|
|||
uint64_t get_file_size(int fd);
|
||||
uint64_t get_block_device_size(int fd);
|
||||
int wipe_block_device(int fd, int64_t len);
|
||||
int create_temp_file();
|
||||
ssize_t bulk_read(int bulk_out, char *buf, size_t length);
|
||||
ssize_t bulk_write(int bulk_in, const char *buf, size_t length);
|
||||
|
||||
#define ROUND_TO_PAGE(address,pagesize) ((address + pagesize - 1) & (~(pagesize - 1)))
|
||||
|
||||
|
|
Loading…
Reference in a new issue