summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSzymon Starzycki <sstar@google.com>2013-09-05 14:26:28 -0700
committerColin Cross <ccross@android.com>2013-12-04 15:00:52 -0800
commit2a656c332b792c84fa6e96d8b40e2c8c0fe94ef9 (patch)
tree01dd953573860354316663eea20f563fc7e4130b
parent00f4e937300b09342983614e792668c269cd7fde (diff)
downloadsystem_core-2a656c332b792c84fa6e96d8b40e2c8c0fe94ef9.zip
system_core-2a656c332b792c84fa6e96d8b40e2c8c0fe94ef9.tar.gz
system_core-2a656c332b792c84fa6e96d8b40e2c8c0fe94ef9.tar.bz2
Fastbootd: socket and network transport
Change-Id: I395e5361d0484bd11421225c152f9aec00305f11
-rw-r--r--fastbootd/Android.mk2
-rw-r--r--fastbootd/fastbootd.c51
-rw-r--r--fastbootd/socket_client.c94
-rw-r--r--fastbootd/socket_client.h37
-rw-r--r--fastbootd/transport.c1
-rw-r--r--fastbootd/transport_socket.c155
-rw-r--r--fastbootd/usb_linux_client.c47
-rw-r--r--fastbootd/utils.c59
-rw-r--r--fastbootd/utils.h3
9 files changed, 396 insertions, 53 deletions
diff --git a/fastbootd/Android.mk b/fastbootd/Android.mk
index f7c67a9..063e308 100644
--- a/fastbootd/Android.mk
+++ b/fastbootd/Android.mk
@@ -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
diff --git a/fastbootd/fastbootd.c b/fastbootd/fastbootd.c
index 90b9ef9..264b6f5 100644
--- a/fastbootd/fastbootd.c
+++ b/fastbootd/fastbootd.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;
}
diff --git a/fastbootd/socket_client.c b/fastbootd/socket_client.c
new file mode 100644
index 0000000..da636db
--- /dev/null
+++ b/fastbootd/socket_client.c
@@ -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");
+}
diff --git a/fastbootd/socket_client.h b/fastbootd/socket_client.h
new file mode 100644
index 0000000..4481ff2
--- /dev/null
+++ b/fastbootd/socket_client.h
@@ -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
diff --git a/fastbootd/transport.c b/fastbootd/transport.c
index 01a5a8a..19a705c 100644
--- a/fastbootd/transport.c
+++ b/fastbootd/transport.c
@@ -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);
}
}
diff --git a/fastbootd/transport_socket.c b/fastbootd/transport_socket.c
new file mode 100644
index 0000000..801b8d6
--- /dev/null
+++ b/fastbootd/transport_socket.c
@@ -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;
+}
+
diff --git a/fastbootd/usb_linux_client.c b/fastbootd/usb_linux_client.c
index 111cf35..7a8e46f 100644
--- a/fastbootd/usb_linux_client.c
+++ b/fastbootd/usb_linux_client.c
@@ -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;
diff --git a/fastbootd/utils.c b/fastbootd/utils.c
index 16e1c09..cac5509 100644
--- a/fastbootd/utils.c
+++ b/fastbootd/utils.c
@@ -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;
+}
+
diff --git a/fastbootd/utils.h b/fastbootd/utils.h
index a553a25..c714786 100644
--- a/fastbootd/utils.h
+++ b/fastbootd/utils.h
@@ -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)))