Skip to content

Commit

Permalink
fastbootd: userspace implementation of the fastboot device-side protocol
Browse files Browse the repository at this point in the history
Initial commit of fastbootd.  A few commands work, but not
fully functional yet.

Change-Id: I589dee7b327b4460e94b4434aaf9bcf780faa839
  • Loading branch information
colincross committed Jul 24, 2013
1 parent fb32808 commit a3d386e
Show file tree
Hide file tree
Showing 11 changed files with 1,388 additions and 0 deletions.
38 changes: 38 additions & 0 deletions fastbootd/Android.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Copyright (C) 2013 Google Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)

LOCAL_SRC_FILES := \
config.c \
commands.c \
fastbootd.c \
protocol.c \
transport.c \
usb_linux_client.c

LOCAL_MODULE := fastbootd
LOCAL_MODULE_TAGS := optional
LOCAL_CFLAGS := -Wall -Werror -Wno-unused-parameter

LOCAL_STATIC_LIBRARIES := \
libsparse_static \
libc \
libcutils

LOCAL_FORCE_STATIC_EXECUTABLE := true

include $(BUILD_EXECUTABLE)
97 changes: 97 additions & 0 deletions fastbootd/bootimg.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
/*
* Copyright (C) 2008 The Android Open Source Project
* 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.
*
* 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 _BOOT_IMAGE_H_
#define _BOOT_IMAGE_H_

typedef struct boot_img_hdr boot_img_hdr;

#define BOOT_MAGIC "ANDROID!"
#define BOOT_MAGIC_SIZE 8
#define BOOT_NAME_SIZE 16
#define BOOT_ARGS_SIZE 512

struct boot_img_hdr
{
unsigned char magic[BOOT_MAGIC_SIZE];

unsigned kernel_size; /* size in bytes */
unsigned kernel_addr; /* physical load addr */

unsigned ramdisk_size; /* size in bytes */
unsigned ramdisk_addr; /* physical load addr */

unsigned second_size; /* size in bytes */
unsigned second_addr; /* physical load addr */

unsigned tags_addr; /* physical addr for kernel tags */
unsigned page_size; /* flash page size we assume */
unsigned unused[2]; /* future expansion: should be 0 */

unsigned char name[BOOT_NAME_SIZE]; /* asciiz product name */

unsigned char cmdline[BOOT_ARGS_SIZE];

unsigned id[8]; /* timestamp / checksum / sha1 / etc */
};

/*
** +-----------------+
** | boot header | 1 page
** +-----------------+
** | kernel | n pages
** +-----------------+
** | ramdisk | m pages
** +-----------------+
** | second stage | o pages
** +-----------------+
**
** n = (kernel_size + page_size - 1) / page_size
** m = (ramdisk_size + page_size - 1) / page_size
** o = (second_size + page_size - 1) / page_size
**
** 0. all entities are page_size aligned in flash
** 1. kernel and ramdisk are required (size != 0)
** 2. second is optional (second_size == 0 -> no second)
** 3. load each element (kernel, ramdisk, second) at
** the specified physical address (kernel_addr, etc)
** 4. prepare tags at tag_addr. kernel_args[] is
** appended to the kernel commandline in the tags.
** 5. r0 = 0, r1 = MACHINE_TYPE, r2 = tags_addr
** 6. if second_size != 0: jump to second_addr
** else: jump to kernel_addr
*/

boot_img_hdr *mkbootimg(void *kernel, unsigned kernel_size,
void *ramdisk, unsigned ramdisk_size,
void *second, unsigned second_size,
unsigned page_size,
unsigned *bootimg_size);

void bootimg_set_cmdline(boot_img_hdr *hdr, const char *cmdline);
#endif
206 changes: 206 additions & 0 deletions fastbootd/commands.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
/*
* 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 <unistd.h>
#include <sys/types.h>

#include "bootimg.h"
#include "debug.h"
#include "protocol.h"

static void cmd_boot(struct protocol_handle *phandle, const char *arg)
{
#if 0
unsigned kernel_actual;
unsigned ramdisk_actual;
static struct boot_img_hdr hdr;
char *ptr = ((char*) data);

if (sz < sizeof(hdr)) {
fastboot_fail(phandle, "invalid bootimage header");
return;
}

memcpy(&hdr, data, sizeof(hdr));

/* ensure commandline is terminated */
hdr.cmdline[BOOT_ARGS_SIZE-1] = 0;

kernel_actual = ROUND_TO_PAGE(hdr.kernel_size);
ramdisk_actual = ROUND_TO_PAGE(hdr.ramdisk_size);

if (2048 + kernel_actual + ramdisk_actual < sz) {
fastboot_fail(phandle, "incomplete bootimage");
return;
}

/*memmove((void*) KERNEL_ADDR, ptr + 2048, hdr.kernel_size);
memmove((void*) RAMDISK_ADDR, ptr + 2048 + kernel_actual, hdr.ramdisk_size);*/

fastboot_okay(phandle, "");
udc_stop();


/*boot_linux((void*) KERNEL_ADDR, (void*) TAGS_ADDR,
(const char*) hdr.cmdline, LINUX_MACHTYPE,
(void*) RAMDISK_ADDR, hdr.ramdisk_size);*/
#endif
}

static void cmd_erase(struct protocol_handle *phandle, const char *arg)
{
#if 0
struct ptentry *ptn;
struct ptable *ptable;

ptable = flash_get_ptable();
if (ptable == NULL) {
fastboot_fail(phandle, "partition table doesn't exist");
return;
}

ptn = ptable_find(ptable, arg);
if (ptn == NULL) {
fastboot_fail(phandle, "unknown partition name");
return;
}

if (flash_erase(ptn)) {
fastboot_fail(phandle, "failed to erase partition");
return;
}
fastboot_okay(phandle, "");
#endif
}

static void cmd_flash(struct protocol_handle *phandle, const char *arg)
{
#if 0
struct ptentry *ptn;
struct ptable *ptable;
unsigned extra = 0;

ptable = flash_get_ptable();
if (ptable == NULL) {
fastboot_fail(phandle, "partition table doesn't exist");
return;
}

ptn = ptable_find(ptable, arg);
if (ptn == NULL) {
fastboot_fail(phandle, "unknown partition name");
return;
}

if (!strcmp(ptn->name, "boot") || !strcmp(ptn->name, "recovery")) {
if (memcmp((void *)data, BOOT_MAGIC, BOOT_MAGIC_SIZE)) {
fastboot_fail(phandle, "image is not a boot image");
return;
}
}

if (!strcmp(ptn->name, "system") || !strcmp(ptn->name, "userdata"))
extra = 64;
else
sz = ROUND_TO_PAGE(sz);

D(INFO, "writing %d bytes to '%s'\n", sz, ptn->name);
if (flash_write(ptn, extra, data, sz)) {
fastboot_fail(phandle, "flash write failure");
return;
}
D(INFO, "partition '%s' updated\n", ptn->name);
#endif
fastboot_okay(phandle, "");
}

static void cmd_continue(struct protocol_handle *phandle, const char *arg)
{
fastboot_okay(phandle, "");
#if 0
udc_stop();

boot_linux_from_flash();
#endif
}

static void cmd_getvar(struct protocol_handle *phandle, const char *arg)
{
const char *value;
D(DEBUG, "cmd_getvar %s\n", arg);

value = fastboot_getvar(arg);

fastboot_okay(phandle, value);
}

static void cmd_download(struct protocol_handle *phandle, const char *arg)
{
unsigned len = strtoul(arg, NULL, 16);
int old_fd;

if (len > 256 * 1024 * 1024) {
fastboot_fail(phandle, "data too large");
return;
}

fastboot_data(phandle, len);

old_fd = protocol_get_download(phandle);
if (old_fd >= 0) {
off_t len = lseek(old_fd, 0, SEEK_END);
D(INFO, "disposing of unused fd %d, size %ld", old_fd, len);
close(old_fd);
}

phandle->download_fd = protocol_handle_download(phandle, len);
if (phandle->download_fd < 0) {
//handle->state = STATE_ERROR;
fastboot_fail(phandle, "download failed");
return;
}

fastboot_okay(phandle, "");
}

void commands_init()
{
fastboot_register("boot", cmd_boot);
fastboot_register("erase:", cmd_erase);
fastboot_register("flash:", cmd_flash);
fastboot_register("continue", cmd_continue);
fastboot_register("getvar:", cmd_getvar);
fastboot_register("download:", cmd_download);
//fastboot_publish("version", "0.5");
//fastboot_publish("product", "swordfish");
//fastboot_publish("kernel", "lk");
}
Loading

0 comments on commit a3d386e

Please sign in to comment.