Merge "Remove fastbootd."

This commit is contained in:
Dan Albert 2015-01-29 22:48:19 +00:00 committed by Gerrit Code Review
commit d170bb035d
35 changed files with 0 additions and 4986 deletions

View file

@ -1,83 +0,0 @@
# 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 \
commands/boot.c \
commands/flash.c \
commands/partitions.c \
commands/virtual_partitions.c \
fastbootd.c \
protocol.c \
network_discovery.c \
socket_client.c \
secure.c \
transport.c \
transport_socket.c \
trigger.c \
usb_linux_client.c \
utils.c \
LOCAL_MODULE := fastbootd
LOCAL_MODULE_TAGS := optional
LOCAL_CFLAGS := -Wall -Werror -Wno-unused-parameter -Wno-deprecated-declarations -DFLASH_CERT
LOCAL_STATIC_LIBRARIES := \
libc \
libcrypto_static \
libcutils \
libmdnssd \
libsparse_static \
libz
LOCAL_HAL_STATIC_LIBRARIES := libvendortrigger
LOCAL_FORCE_STATIC_EXECUTABLE := true
include $(BUILD_EXECUTABLE)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := \
commands/partitions.c \
other/gptedit.c \
utils.c
LOCAL_MODULE := gptedit
LOCAL_MODULE_TAGS := optional
LOCAL_CFLAGS := -Wall -Werror -Wno-unused-parameter
LOCAL_STATIC_LIBRARIES := \
libsparse_static \
libc \
libcutils \
libz
LOCAL_FORCE_STATIC_EXECUTABLE := true
include $(BUILD_EXECUTABLE)
# vendor trigger HAL
include $(CLEAR_VARS)
LOCAL_CFLAGS := -Wall -Werror
LOCAL_MODULE := libvendortrigger.default
LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES := vendor_trigger_default.c
LOCAL_STATIC_LIBRARIES := libcutils
include $(BUILD_STATIC_LIBRARY)

View file

@ -1,97 +0,0 @@
/*
* 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

View file

@ -1,409 +0,0 @@
/*
* 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 <inttypes.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <unistd.h>
#include <sys/reboot.h>
#include <fcntl.h>
#include "bootimg.h"
#include "commands/boot.h"
#include "commands/flash.h"
#include "commands/partitions.h"
#include "commands/virtual_partitions.h"
#include "debug.h"
#include "protocol.h"
#include "trigger.h"
#include "utils.h"
#define ATAGS_LOCATION "/proc/atags"
static void cmd_boot(struct protocol_handle *phandle, const char *arg)
{
int sz, atags_sz, new_atags_sz;
int rv;
unsigned kernel_actual;
unsigned ramdisk_actual;
unsigned second_actual;
void *kernel_ptr;
void *ramdisk_ptr;
void *second_ptr;
struct boot_img_hdr *hdr;
char *ptr = NULL;
char *atags_ptr = NULL;
char *new_atags = NULL;
int data_fd = 0;
D(DEBUG, "cmd_boot %s\n", arg);
if (phandle->download_fd < 0) {
fastboot_fail(phandle, "no kernel file");
return;
}
atags_ptr = read_atags(ATAGS_LOCATION, &atags_sz);
if (atags_ptr == NULL) {
fastboot_fail(phandle, "atags read error");
goto error;
}
// TODO: With cms we can also verify partition name included as
// cms signed attribute
if (flash_validate_certificate(phandle->download_fd, &data_fd) != 1) {
fastboot_fail(phandle, "Access forbiden you need the certificate");
return;
}
sz = get_file_size(data_fd);
ptr = (char *) mmap(NULL, sz, PROT_READ,
MAP_POPULATE | MAP_PRIVATE, data_fd, 0);
hdr = (struct boot_img_hdr *) ptr;
if (ptr == MAP_FAILED) {
fastboot_fail(phandle, "internal fastbootd error");
goto error;
}
if ((size_t) sz < sizeof(*hdr)) {
fastboot_fail(phandle, "invalid bootimage header");
goto error;
}
kernel_actual = ROUND_TO_PAGE(hdr->kernel_size, hdr->page_size);
ramdisk_actual = ROUND_TO_PAGE(hdr->ramdisk_size, hdr->page_size);
second_actual = ROUND_TO_PAGE(hdr->second_size, hdr->page_size);
new_atags = (char *) create_atags((unsigned *) atags_ptr, atags_sz, hdr, &new_atags_sz);
if (new_atags == NULL) {
fastboot_fail(phandle, "atags generate error");
goto error;
}
if (new_atags_sz > 0x4000) {
fastboot_fail(phandle, "atags file to large");
goto error;
}
if ((int) (hdr->page_size + kernel_actual + ramdisk_actual) < sz) {
fastboot_fail(phandle, "incomplete bootimage");
goto error;
}
kernel_ptr = (void *)((uintptr_t) ptr + hdr->page_size);
ramdisk_ptr = (void *)((uintptr_t) kernel_ptr + kernel_actual);
second_ptr = (void *)((uintptr_t) ramdisk_ptr + ramdisk_actual);
D(INFO, "preparing to boot");
// Prepares boot physical address. Addresses from header are ignored
rv = prepare_boot_linux(hdr->kernel_addr, kernel_ptr, kernel_actual,
hdr->ramdisk_addr, ramdisk_ptr, ramdisk_actual,
hdr->second_addr, second_ptr, second_actual,
hdr->tags_addr, new_atags, ROUND_TO_PAGE(new_atags_sz, hdr->page_size));
if (rv < 0) {
fastboot_fail(phandle, "kexec prepare failed");
goto error;
}
fastboot_okay(phandle, "");
free(atags_ptr);
munmap(ptr, sz);
free(new_atags);
close(data_fd);
D(INFO, "Kexec going to reboot");
reboot(LINUX_REBOOT_CMD_KEXEC);
fastboot_fail(phandle, "reboot error");
return;
error:
if (atags_ptr != NULL)
free(atags_ptr);
if (ptr != NULL)
munmap(ptr, sz);
}
static void cmd_erase(struct protocol_handle *phandle, const char *arg)
{
int partition_fd;
char path[PATH_MAX];
D(DEBUG, "cmd_erase %s\n", arg);
if (flash_find_entry(arg, path, PATH_MAX)) {
fastboot_fail(phandle, "partition table doesn't exist");
return;
}
if (!path[0]) {
fastboot_fail(phandle, "Couldn't find partition");
return;
}
partition_fd = flash_get_partiton(path);
if (partition_fd < 0) {
fastboot_fail(phandle, "partiton file does not exists");
}
if (flash_erase(partition_fd)) {
fastboot_fail(phandle, "failed to erase partition");
flash_close(partition_fd);
return;
}
if (flash_close(partition_fd) < 0) {
D(ERR, "could not close device %s", strerror(errno));
fastboot_fail(phandle, "failed to erase partition");
return;
}
fastboot_okay(phandle, "");
}
static int GPT_header_location() {
const char *location_str = fastboot_getvar("gpt_sector");
char *str;
int location;
if (!strcmp("", location_str)) {
D(INFO, "GPT location not specified using second sector");
return 1;
}
else {
location = strtoul(location_str, &str, 10);
D(INFO, "GPT location specified as %d", location);
if (*str != '\0')
return -1;
return location - 1;
}
}
static void cmd_gpt_layout(struct protocol_handle *phandle, const char *arg) {
struct GPT_entry_table *oldtable;
int location;
struct GPT_content content;
const char *device;
device = fastboot_getvar("blockdev");
if (!strcmp(device, "")) {
fastboot_fail(phandle, "blockdev not defined in config file");
return;
}
//TODO: add same verification as in cmd_flash
if (phandle->download_fd < 0) {
fastboot_fail(phandle, "no layout file");
return;
}
location = GPT_header_location();
oldtable = GPT_get_device(device, location);
GPT_default_content(&content, oldtable);
if (oldtable == NULL)
D(WARN, "Could not get old gpt table");
else
GPT_release_device(oldtable);
if (!GPT_parse_file(phandle->download_fd, &content)) {
fastboot_fail(phandle, "Could not parse partition config file");
return;
}
if (trigger_gpt_layout(&content)) {
fastboot_fail(phandle, "Vendor forbids this opperation");
GPT_release_content(&content);
return;
}
if (!GPT_write_content(device, &content)) {
fastboot_fail(phandle, "Unable to write gpt file");
GPT_release_content(&content);
return;
}
GPT_release_content(&content);
fastboot_okay(phandle, "");
}
static void cmd_flash(struct protocol_handle *phandle, const char *arg)
{
int partition;
uint64_t sz;
char data[BOOT_MAGIC_SIZE];
char path[PATH_MAX];
ssize_t header_sz = 0;
int data_fd = 0;
D(DEBUG, "cmd_flash %s\n", arg);
if (try_handle_virtual_partition(phandle, arg)) {
return;
}
if (phandle->download_fd < 0) {
fastboot_fail(phandle, "no kernel file");
return;
}
if (flash_find_entry(arg, path, PATH_MAX)) {
fastboot_fail(phandle, "partition table doesn't exist");
return;
}
if (flash_validate_certificate(phandle->download_fd, &data_fd) != 1) {
fastboot_fail(phandle, "Access forbiden you need certificate");
return;
}
// TODO: Maybe its goot idea to check whether the partition is bootable
if (!strcmp(arg, "boot") || !strcmp(arg, "recovery")) {
if (read_data_once(data_fd, data, BOOT_MAGIC_SIZE) < BOOT_MAGIC_SIZE) {
fastboot_fail(phandle, "incoming data read error, cannot read boot header");
return;
}
if (memcmp((void *)data, BOOT_MAGIC, BOOT_MAGIC_SIZE)) {
fastboot_fail(phandle, "image is not a boot image");
return;
}
}
partition = flash_get_partiton(path);
sz = get_file_size64(data_fd);
sz -= header_sz;
if (sz > get_file_size64(partition)) {
flash_close(partition);
D(WARN, "size of file too large");
fastboot_fail(phandle, "size of file too large");
return;
}
D(INFO, "writing %"PRId64" bytes to '%s'\n", sz, arg);
if (flash_write(partition, phandle->download_fd, sz, header_sz)) {
fastboot_fail(phandle, "flash write failure");
return;
}
D(INFO, "partition '%s' updated\n", arg);
flash_close(partition);
close(data_fd);
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) {
fastboot_fail(phandle, "download failed");
return;
}
fastboot_okay(phandle, "");
}
static void cmd_oem(struct protocol_handle *phandle, const char *arg) {
const char *response = "";
//TODO: Maybe it should get download descriptor also
if (trigger_oem_cmd(arg, &response))
fastboot_fail(phandle, response);
else
fastboot_okay(phandle, response);
}
void commands_init()
{
virtual_partition_register("partition-table", cmd_gpt_layout);
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_register("oem", cmd_oem);
//fastboot_publish("version", "0.5");
//fastboot_publish("product", "swordfish");
//fastboot_publish("kernel", "lk");
}

View file

@ -1,255 +0,0 @@
/*
* 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 <sys/syscall.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <malloc.h>
#include <unistd.h>
#include "boot.h"
#include "debug.h"
#include "utils.h"
#include "bootimg.h"
#define KEXEC_ARM_ATAGS_OFFSET 0x1000
#define KEXEC_ARM_ZIMAGE_OFFSET 0x8000
#define MEMORY_SIZE 0x0800000
#define START_ADDRESS 0x44000000
#define KERNEL_START (START_ADDRESS + KEXEC_ARM_ZIMAGE_OFFSET)
#define ATAG_NONE_TYPE 0x00000000
#define ATAG_CORE_TYPE 0x54410001
#define ATAG_RAMDISK_TYPE 0x54410004
#define ATAG_INITRD2_TYPE 0x54420005
#define ATAG_CMDLINE_TYPE 0x54410009
#define MAX_ATAG_SIZE 0x4000
struct atag_info {
unsigned size;
unsigned type;
};
struct atag_initrd2 {
unsigned start;
unsigned size;
};
struct atag_cmdline {
char cmdline[0];
};
struct atag {
struct atag_info info;
union {
struct atag_initrd2 initrd2;
struct atag_cmdline cmdline;
} data;
};
long kexec_load(unsigned int entry, unsigned long nr_segments,
struct kexec_segment *segment, unsigned long flags) {
return syscall(__NR_kexec_load, entry, nr_segments, segment, flags);
}
/*
* Prepares arguments for kexec
* Kernel address is not set into kernel_phys
* Ramdisk is set to position relative to kernel
*/
int prepare_boot_linux(uintptr_t kernel_phys, void *kernel_addr, int kernel_size,
uintptr_t ramdisk_phys, void *ramdisk_addr, int ramdisk_size,
uintptr_t second_phys, void *second_addr, int second_size,
uintptr_t atags_phys, void *atags_addr, int atags_size) {
struct kexec_segment segment[4];
int segment_count = 2;
unsigned entry = START_ADDRESS + KEXEC_ARM_ZIMAGE_OFFSET;
int rv;
int page_size = getpagesize();
segment[0].buf = kernel_addr;
segment[0].bufsz = kernel_size;
segment[0].mem = (void *) KERNEL_START;
segment[0].memsz = ROUND_TO_PAGE(kernel_size, page_size);
if (kernel_size > MEMORY_SIZE - KEXEC_ARM_ZIMAGE_OFFSET) {
D(INFO, "Kernel image too big");
return -1;
}
segment[1].buf = atags_addr;
segment[1].bufsz = atags_size;
segment[1].mem = (void *) (START_ADDRESS + KEXEC_ARM_ATAGS_OFFSET);
segment[1].memsz = ROUND_TO_PAGE(atags_size, page_size);
D(INFO, "Ramdisk size is %d", ramdisk_size);
if (ramdisk_size != 0) {
segment[segment_count].buf = ramdisk_addr;
segment[segment_count].bufsz = ramdisk_size;
segment[segment_count].mem = (void *) (KERNEL_START + ramdisk_phys - kernel_phys);
segment[segment_count].memsz = ROUND_TO_PAGE(ramdisk_phys, page_size);
++segment_count;
}
D(INFO, "Ramdisk size is %d", ramdisk_size);
if (second_size != 0) {
segment[segment_count].buf = second_addr;
segment[segment_count].bufsz = second_size;
segment[segment_count].mem = (void *) (KERNEL_START + second_phys - kernel_phys);
segment[segment_count].memsz = ROUND_TO_PAGE(second_size, page_size);
entry = second_phys;
++segment_count;
}
rv = kexec_load(entry, segment_count, segment, KEXEC_ARCH_DEFAULT);
if (rv != 0) {
D(INFO, "Kexec_load returned non-zero exit code: %s\n", strerror(errno));
return -1;
}
return 1;
}
unsigned *create_atags(unsigned *atags_position, int atag_size, const struct boot_img_hdr *hdr, int *size) {
struct atag *current_tag = (struct atag *) atags_position;
unsigned *current_tag_raw = atags_position;
unsigned *new_atags = malloc(ROUND_TO_PAGE(atag_size + BOOT_ARGS_SIZE * sizeof(char),
hdr->page_size));
//This pointer will point into the beggining of buffer free space
unsigned *natags_raw_buff = new_atags;
int new_atags_size = 0;
int current_size;
int cmdl_length;
// copy tags from current atag file
while (current_tag->info.type != ATAG_NONE_TYPE) {
switch (current_tag->info.type) {
case ATAG_CMDLINE_TYPE:
case ATAG_RAMDISK_TYPE:
case ATAG_INITRD2_TYPE: break;
default:
memcpy((void *)natags_raw_buff, (void *)current_tag_raw, current_tag->info.size * sizeof(unsigned));
natags_raw_buff += current_tag->info.size;
new_atags_size += current_tag->info.size;
}
current_tag_raw += current_tag->info.size;
current_tag = (struct atag *) current_tag_raw;
if (current_tag_raw >= atags_position + atag_size) {
D(ERR, "Critical error in atags");
return NULL;
}
}
// set INITRD2 tag
if (hdr->ramdisk_size > 0) {
current_size = (sizeof(struct atag_info) + sizeof(struct atag_initrd2)) / sizeof(unsigned);
*((struct atag *) natags_raw_buff) = (struct atag) {
.info = {
.size = current_size,
.type = ATAG_INITRD2_TYPE
},
.data = {
.initrd2 = (struct atag_initrd2) {
.start = hdr->ramdisk_addr,
.size = hdr->ramdisk_size
}
}
};
new_atags_size += current_size;
natags_raw_buff += current_size;
}
// set ATAG_CMDLINE
cmdl_length = strnlen((char *) hdr->cmdline, BOOT_ARGS_SIZE - 1);
current_size = sizeof(struct atag_info) + (1 + cmdl_length);
current_size = (current_size + sizeof(unsigned) - 1) / sizeof(unsigned);
*((struct atag *) natags_raw_buff) = (struct atag) {
.info = {
.size = current_size,
.type = ATAG_CMDLINE_TYPE
},
};
//copy cmdline and ensure that there is null character
memcpy(((struct atag *) natags_raw_buff)->data.cmdline.cmdline,
(char *) hdr->cmdline, cmdl_length);
((struct atag *) natags_raw_buff)->data.cmdline.cmdline[cmdl_length] = '\0';
new_atags_size += current_size;
natags_raw_buff += current_size;
// set ATAG_NONE
*((struct atag *) natags_raw_buff) = (struct atag) {
.info = {
.size = 0,
.type = ATAG_NONE_TYPE
},
};
new_atags_size += sizeof(struct atag_info) / sizeof(unsigned);
natags_raw_buff += sizeof(struct atag_info) / sizeof(unsigned);
*size = new_atags_size * sizeof(unsigned);
return new_atags;
}
char *read_atags(const char * path, int *atags_sz) {
int afd = -1;
char *atags_ptr = NULL;
afd = open(path, O_RDONLY);
if (afd < 0) {
D(ERR, "wrong atags file");
return 0;
}
atags_ptr = (char *) malloc(MAX_ATAG_SIZE);
if (atags_ptr == NULL) {
D(ERR, "insufficient memory");
return 0;
}
*atags_sz = read(afd, atags_ptr, MAX_ATAG_SIZE);
close(afd);
return atags_ptr;
}

View file

@ -1,50 +0,0 @@
/*
* 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 __FASTBOOT_BOOT_H
#define __FASTBOOT_BOOT_H
#include <sys/cdefs.h>
#include <linux/kexec.h>
#include "bootimg.h"
#define KEXEC_TYPE_DEFAULT 0
#define KEXEC_TYPE_CRASH 1
int prepare_boot_linux(uintptr_t, void *, int, uintptr_t, void *, int,
uintptr_t, void *, int, uintptr_t, void *, int);
unsigned *create_atags(unsigned *, int, const struct boot_img_hdr *, int *);
long kexec_load(unsigned int, unsigned long, struct kexec_segment *, unsigned long);
char *read_atags(const char *, int *);
#endif /* _SYS_KEXEC_H */

View file

@ -1,162 +0,0 @@
/*
* 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 <sys/stat.h>
#include <fcntl.h>
#include <inttypes.h>
#include <sys/mman.h>
#include "flash.h"
#include "protocol.h"
#include "debug.h"
#include "utils.h"
#include "commands/partitions.h"
#ifdef FLASH_CERT
#include "secure.h"
#endif
#define ALLOWED_CHARS "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-."
#define BUFFER_SIZE 1024 * 1024
#define MIN(a, b) (a > b ? b : a)
int flash_find_entry(const char *name, char *out, size_t outlen)
{
//TODO: Assumption: All the partitions has they unique name
const char *path = fastboot_getvar("device-directory");
size_t length;
if (strcmp(path, "") == 0) {
D(ERR, "device-directory: not defined in config file");
return -1;
}
length = strspn(name, ALLOWED_CHARS);
if (length != strlen(name)) {
D(ERR, "Not allowed char in name: %c", name[length]);
return -1;
}
if (snprintf(out, outlen, "%s%s", path, name) >= (int) outlen) {
D(ERR, "Too long path to partition file");
return -1;
}
if (access(out, F_OK ) == -1) {
D(ERR, "could not find partition file %s", name);
return -1;
}
return 0;
}
int flash_erase(int fd)
{
int64_t size;
size = get_block_device_size(fd);
D(DEBUG, "erase %"PRId64" data from %d\n", size, fd);
return wipe_block_device(fd, size);
}
int flash_write(int partition_fd, int data_fd, ssize_t size, ssize_t skip)
{
ssize_t written = 0;
struct GPT_mapping input;
struct GPT_mapping output;
while (written < size) {
int current_size = MIN(size - written, BUFFER_SIZE);
if (gpt_mmap(&input, written + skip, current_size, data_fd)) {
D(ERR, "Error in writing data, unable to map data file %zd at %zd size %d", size, skip, current_size);
return -1;
}
if (gpt_mmap(&output, written, current_size, partition_fd)) {
D(ERR, "Error in writing data, unable to map output partition");
return -1;
}
memcpy(output.ptr, input.ptr, current_size);
gpt_unmap(&input);
gpt_unmap(&output);
written += current_size;
}
return 0;
}
#ifdef FLASH_CERT
int flash_validate_certificate(int signed_fd, int *data_fd) {
int ret = 0;
const char *cert_path;
X509_STORE *store = NULL;
CMS_ContentInfo *content_info;
BIO *content;
cert_path = fastboot_getvar("certificate-path");
if (!strcmp(cert_path, "")) {
D(ERR, "could not find cert-key value in config file");
goto finish;
}
store = cert_store_from_path(cert_path);
if (store == NULL) {
D(ERR, "unable to create certification store");
goto finish;
}
if (cert_read(signed_fd, &content_info, &content)) {
D(ERR, "reading data failed");
goto finish;
}
ret = cert_verify(content, content_info, store, data_fd);
cert_release(content, content_info);
return ret;
finish:
if (store != NULL)
cert_release_store(store);
return ret;
}
#else
int flash_validate_certificate(int signed_fd, int *data_fd) {
return 1;
}
#endif

View file

@ -1,71 +0,0 @@
/*
* 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_ERASE_H
#define _FASTBOOTD_ERASE_H
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include "debug.h"
int flash_find_entry(const char *, char *, size_t);
int flash_erase(int fd);
static inline int flash_get_partiton(const char *path) {
return open(path, O_RDWR);
}
static inline int flash_close(int fd) {
return close(fd);
}
int flash_write(int partition, int data, ssize_t size, ssize_t skip);
static inline ssize_t read_data_once(int fd, char *buffer, ssize_t size) {
ssize_t readcount = 0;
ssize_t len;
while ((len = TEMP_FAILURE_RETRY(read(fd, (void *) &buffer[readcount], size - readcount))) > 0) {
readcount += len;
}
if (len < 0) {
D(ERR, "Read error:%s", strerror(errno));
return len;
}
return readcount;
}
int flash_validate_certificate(int signed_fd, int *data_fd);
#endif

View file

@ -1,775 +0,0 @@
/*
* 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 <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <endian.h>
#include <zlib.h>
#include <linux/hdreg.h>
#include <sys/ioctl.h>
#include <stdlib.h>
#include <string.h>
#include <cutils/config_utils.h>
#include <inttypes.h>
#include "partitions.h"
#include "debug.h"
#include "utils.h"
#include "protocol.h"
#define BLKRRPART _IO(0x12,95) /* re-read partition table */
#define BLKSSZGET _IO(0x12,104)
#define DIV_ROUND_UP(x, y) (((x) + (y) - 1)/(y))
#define ALIGN(x, y) ((y) * DIV_ROUND_UP((x), (y)))
#define ALIGN_DOWN(x, y) ((y) * ((x) / (y)))
const uint8_t partition_type_uuid[16] = {
0xa2, 0xa0, 0xd0, 0xeb, 0xe5, 0xb9, 0x33, 0x44,
0x87, 0xc0, 0x68, 0xb6, 0xb7, 0x26, 0x99, 0xc7,
};
//TODO: There is assumption that we are using little endian
static void GPT_entry_clear(struct GPT_entry_raw *entry)
{
memset(entry, 0, sizeof(*entry));
}
/*
* returns mapped location to choosen area
* mapped_ptr is pointer to whole area mapped (it can be bigger then requested)
*/
int gpt_mmap(struct GPT_mapping *mapping, uint64_t location, int size, int fd)
{
unsigned int location_diff = location & ~PAGE_MASK;
mapping->size = ALIGN(size + location_diff, PAGE_SIZE);
uint64_t sz = get_file_size64(fd);
if (sz < size + location) {
D(ERR, "the location of mapping area is outside of the device size %" PRId64, sz);
return 1;
}
location = ALIGN_DOWN(location, PAGE_SIZE);
mapping->map_ptr = mmap64(NULL, mapping->size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, location);
if (mapping->map_ptr == MAP_FAILED) {
mapping->ptr = MAP_FAILED;
D(ERR, "map failed: %s", strerror(errno));
return 1;
}
mapping->ptr = (void *)((char *) mapping->map_ptr + location_diff);
return 0;
}
void gpt_unmap(struct GPT_mapping *mapping) {
munmap(mapping->map_ptr, mapping->size);
}
#define LBA_ADDR(table, value) ((uint64_t) (table)->sector_size * (value))
int GPT_map_from_content(struct GPT_entry_table *table, const struct GPT_content *content)
{
// Mapping header
if (gpt_mmap(&table->header_map, LBA_ADDR(table, content->header.current_lba),
table->sector_size, table->fd)) {
D(ERR, "unable to map header:%s\n", strerror(errno));
goto error_header;
}
table->header = (struct GPT_header *) table->header_map.ptr;
table->partition_table_size = ROUND_UP(content->header.entries_count * sizeof(*table->entries),
table->sector_size);
// Mapping entry table
if (gpt_mmap(&table->entries_map, LBA_ADDR(table, content->header.entries_lba),
table->partition_table_size, table->fd)) {
D(ERR, "unable to map entries");
goto error_signature;
}
table->entries = (struct GPT_entry_raw *) table->entries_map.ptr;
// Mapping secondary header
if (gpt_mmap(&table->sec_header_map, LBA_ADDR(table, content->header.backup_lba),
table->sector_size, table->fd)) {
D(ERR, "unable to map backup gpt header");
goto error_sec_header;
}
// Mapping secondary entries table
if (gpt_mmap(&table->sec_entries_map,
LBA_ADDR(table, content->header.backup_lba) - table->partition_table_size,
table->partition_table_size, table->fd)) {
D(ERR, "unable to map secondary gpt table");
goto error_sec_entries;
}
table->second_header = (struct GPT_header *) table->sec_header_map.ptr;
table->second_entries = (struct GPT_entry_raw *) table->sec_entries_map.ptr;
table->second_valid = strcmp("EFI PART", (char *) table->second_header->signature) == 0;
return 0;
error_sec_entries:
gpt_unmap(&table->sec_header_map);
error_sec_header:
gpt_unmap(&table->entries_map);
error_signature:
gpt_unmap(&table->header_map);
error_header:
return 1;
}
int GPT_map(struct GPT_entry_table *table, unsigned header_lba)
{
struct GPT_content content;
struct GPT_mapping mapping;
struct GPT_header *header;
if (gpt_mmap(&mapping, LBA_ADDR(table, header_lba), table->sector_size, table->fd)) {
D(ERR, "unable to map header: %s", strerror(errno));
goto error_header;
}
header = (struct GPT_header *) mapping.ptr;
if (strcmp("EFI PART", (char *) header->signature)) {
D(ERR, "GPT entry not valid");
goto error_signature;
}
content.header = *header;
gpt_unmap(&mapping);
return GPT_map_from_content(table, &content);
error_signature:
gpt_unmap(&table->header_map);
error_header:
return 1;
}
struct GPT_entry_table* GPT_get_device(const char *path, unsigned header_lba)
{
struct GPT_entry_table *table;
size_t sector_bytes;
table = (struct GPT_entry_table *) malloc(sizeof(*table));
table->fd = open(path, O_RDWR);
if (table->fd < 0) {
D(ERR, "unable to open file %s:%s\n", path, strerror(errno));
return NULL;
}
if (!ioctl(table->fd, BLKSSZGET, &sector_bytes)) {
table->sector_size = (unsigned) sector_bytes;
D(INFO, "Got sector size %d", table->sector_size);
} else {
D(WARN, "unable to get sector size, assuming 512");
table->sector_size = 512;
}
if (GPT_map(table, header_lba)) {
D(ERR, "Could not map gpt");
return NULL;
}
return table;
}
static struct GPT_entry_table* GPT_get_from_content(const char *path, const struct GPT_content *content)
{
struct GPT_entry_table *table;
size_t sector_bytes;
table = (struct GPT_entry_table *) malloc(sizeof(*table));
table->fd = open(path, O_RDWR);
if (table->fd < 0) {
D(ERR, "unable to open file %s:%s\n", path, strerror(errno));
return NULL;
}
if (!ioctl(table->fd, BLKSSZGET, &sector_bytes)) {
table->sector_size = (unsigned) sector_bytes;
D(INFO, "Got sector size %d", table->sector_size);
} else {
D(WARN, "unable to get sector size %s, assuming 512", strerror(errno));
table->sector_size = 512;
}
if (GPT_map_from_content(table, content)) {
D(ERR, "Could not map gpt");
return NULL;
}
return table;
}
void GPT_release_device(struct GPT_entry_table *table)
{
gpt_unmap(&table->header_map);
gpt_unmap(&table->entries_map);
gpt_unmap(&table->sec_header_map);
gpt_unmap(&table->sec_entries_map);
close(table->fd);
free(table);
}
static int GPT_check_overlap(struct GPT_entry_table *table, struct GPT_entry_raw *entry);
static int GPT_check_overlap_except(struct GPT_entry_table *table,
struct GPT_entry_raw *entry,
struct GPT_entry_raw *exclude);
void GPT_edit_entry(struct GPT_entry_table *table,
struct GPT_entry_raw *old_entry,
struct GPT_entry_raw *new_entry)
{
struct GPT_entry_raw *current_entry = GPT_get_pointer(table, old_entry);
if (GPT_check_overlap_except(table, new_entry, current_entry)) {
D(ERR, "Couldn't add overlaping partition");
return;
}
if (current_entry == NULL) {
D(ERR, "Couldn't find entry");
return;
}
*current_entry = *new_entry;
}
int GPT_delete_entry(struct GPT_entry_table *table, struct GPT_entry_raw *entry)
{
struct GPT_entry_raw *raw = GPT_get_pointer(table, entry);
if (raw == NULL) {
D(ERR, "could not find entry");
return 1;
}
D(DEBUG, "Deleting gpt entry '%s'\n", raw->partition_guid);
// Entry in the middle of table may become empty
GPT_entry_clear(raw);
return 0;
}
void GPT_add_entry(struct GPT_entry_table *table, struct GPT_entry_raw *entry)
{
unsigned i;
int inserted = 0;
if (GPT_check_overlap(table, entry)) {
D(ERR, "Couldn't add overlaping partition");
return;
}
if (GPT_get_pointer(table, entry) != NULL) {
D(WARN, "Add entry fault, this entry already exists");
return;
}
struct GPT_entry_raw *entries = table->entries;
for (i = 0; i < table->header->entries_count; ++i) {
if (!entries[i].type_guid[0]) {
inserted = 1;
D(DEBUG, "inserting");
memcpy(&entries[i], entry, sizeof(entries[i]));
break;
}
}
if (!inserted) {
D(ERR, "Unable to find empty partion entry");
}
}
struct GPT_entry_raw *GPT_get_pointer_by_UTFname(struct GPT_entry_table *table, const uint16_t *name);
struct GPT_entry_raw *GPT_get_pointer(struct GPT_entry_table *table, struct GPT_entry_raw *entry)
{
if (entry->partition_guid[0] != 0)
return GPT_get_pointer_by_guid(table, (const char *) entry->partition_guid);
else if (entry->name[0] != 0)
return GPT_get_pointer_by_UTFname(table, entry->name);
D(WARN, "Name or guid needed to find entry");
return NULL;
}
struct GPT_entry_raw *GPT_get_pointer_by_guid(struct GPT_entry_table *table, const char *name)
{
int current = (int) table->header->entries_count;
for (current = current - 1; current >= 0; --current) {
if (strncmp((char *) name,
(char *) table->entries[current].partition_guid, 16) == 0) {
return &table->entries[current];
}
}
return NULL;
}
int strncmp_UTF16_char(const uint16_t *s1, const char *s2, size_t n)
{
if (n == 0)
return (0);
do {
if (((*s1) & 127) != *s2++)
return (((unsigned char) ((*s1) & 127)) - *(unsigned char *)--s2);
if (*s1++ == 0)
break;
} while (--n != 0);
return (0);
}
int strncmp_UTF16(const uint16_t *s1, const uint16_t *s2, size_t n)
{
if (n == 0)
return (0);
do {
if ((*s1) != *s2++)
return (*s1 - *--s2);
if (*s1++ == 0)
break;
} while (--n != 0);
return (0);
}
struct GPT_entry_raw *GPT_get_pointer_by_name(struct GPT_entry_table *table, const char *name)
{
int count = (int) table->header->entries_count;
int current;
for (current = 0; current < count; ++current) {
if (strncmp_UTF16_char(table->entries[current].name,
(char *) name, 16) == 0) {
return &table->entries[current];
}
}
return NULL;
}
struct GPT_entry_raw *GPT_get_pointer_by_UTFname(struct GPT_entry_table *table, const uint16_t *name)
{
int count = (int) table->header->entries_count;
int current;
for (current = 0; current < count; ++current) {
if (strncmp_UTF16(table->entries[current].name,
name, GPT_NAMELEN) == 0) {
return &table->entries[current];
}
}
return NULL;
}
void GPT_sync(struct GPT_entry_table *table)
{
uint32_t crc;
//calculate crc32
crc = crc32(0, Z_NULL, 0);
crc = crc32(crc, (void*) table->entries, table->header->entries_count * sizeof(*table->entries));
table->header->partition_array_checksum = crc;
table->header->header_checksum = 0;
crc = crc32(0, Z_NULL, 0);
crc = crc32(crc, (void*) table->header, table->header->header_size);
table->header->header_checksum = crc;
//sync secondary partion
if (table->second_valid) {
memcpy((void *)table->second_entries, (void *) table->entries, table->partition_table_size);
memcpy((void *)table->second_header, (void *)table->header, sizeof(*table->header));
}
if(!ioctl(table->fd, BLKRRPART, NULL)) {
D(WARN, "Unable to force kernel to refresh partition table");
}
}
void GPT_to_UTF16(uint16_t *to, const char *from, int n)
{
int i;
for (i = 0; i < (n - 1) && (to[i] = from[i]) != '\0'; ++i);
to[i] = '\0';
}
void GPT_from_UTF16(char *to, const uint16_t *from, int n)
{
int i;
for (i = 0; i < (n - 1) && (to[i] = from[i] & 127) != '\0'; ++i);
to[i] = '\0';
}
static int GPT_check_overlap_except(struct GPT_entry_table *table,
struct GPT_entry_raw *entry,
struct GPT_entry_raw *exclude) {
int current = (int) table->header->entries_count;
int dontcheck;
struct GPT_entry_raw *current_entry;
if (entry->last_lba < entry->first_lba) {
D(WARN, "Start address have to be less than end address");
return 1;
}
for (current = current - 1; current >= 0; --current) {
current_entry = &table->entries[current];
dontcheck = strncmp((char *) entry->partition_guid,
(char *) current_entry->partition_guid , 16) == 0;
dontcheck |= current_entry->type_guid[0] == 0;
dontcheck |= current_entry == exclude;
if (!dontcheck && ((entry->last_lba >= current_entry->first_lba &&
entry->first_lba < current_entry->last_lba ))) {
return 1;
}
}
return 0;
}
static int GPT_check_overlap(struct GPT_entry_table *table, struct GPT_entry_raw *entry)
{
return GPT_check_overlap_except(table, entry, NULL);
}
static char *get_key_value(char *ptr, char **key, char **value)
{
*key = ptr;
ptr = strchr(ptr, '=');
if (ptr == NULL)
return NULL;
*ptr++ = '\0';
*value = ptr;
ptr = strchr(ptr, ';');
if (ptr == NULL)
ptr = *value + strlen(*value);
else
*ptr = '\0';
*key = strip(*key);
*value = strip(*value);
return ptr;
}
//TODO: little endian?
static int add_key_value(const char *key, const char *value, struct GPT_entry_raw *entry)
{
char *endptr;
if (!strcmp(key, "type")) {
strncpy((char *) entry->type_guid, value, 16);
entry->type_guid[15] = 0;
}
else if (!strcmp(key, "guid")) {
strncpy((char *) entry->partition_guid, value, 16);
entry->type_guid[15] = 0;
}
else if (!strcmp(key, "firstlba")) {
entry->first_lba = strtoul(value, &endptr, 10);
if (*endptr != '\0') goto error;
}
else if (!strcmp(key, "lastlba")) {
entry->last_lba = strtoul(value, &endptr, 10);
if (*endptr != '\0') goto error;
}
else if (!strcmp(key, "flags")) {
entry->flags = strtoul(value, &endptr, 16);
if (*endptr != '\0') goto error;
}
else if (!strcmp(key, "name")) {
GPT_to_UTF16(entry->name, value, GPT_NAMELEN);
}
else {
goto error;
}
return 0;
error:
D(ERR, "Could not find key or parse value: %s,%s", key, value);
return 1;
}
int GPT_parse_entry(char *string, struct GPT_entry_raw *entry)
{
char *ptr = string;
char *key = NULL;
char *value = NULL;
while ((ptr = get_key_value(ptr, &key, &value)) != NULL) {
if (add_key_value(key, value, entry)) {
D(WARN, "key or value not valid: %s %s", key, value);
return 1;
}
}
return 0;
}
void entry_set_guid(int n, uint8_t *guid)
{
int fd;
fd = open("/dev/urandom", O_RDONLY);
read(fd, guid, 16);
close(fd);
//rfc4122
guid[8] = (guid[8] & 0x3F) | 0x80;
guid[7] = (guid[7] & 0x0F) | 0x40;
}
void GPT_default_content(struct GPT_content *content, struct GPT_entry_table *table)
{
if (table != NULL) {
memcpy(&content->header, table->header, sizeof(content->header));
content->header.header_size = sizeof(content->header);
content->header.entry_size = sizeof(struct GPT_entry_raw);
}
else {
D(WARN, "Could not locate old gpt table, using default values");
memset(&content->header, 0, sizeof(content->header) / sizeof(int));
content->header = (struct GPT_header) {
.revision = 0x10000,
.header_size = sizeof(content->header),
.header_checksum = 0,
.reserved_zeros = 0,
.current_lba = 1,
.backup_lba = 1,
.entry_size = sizeof(struct GPT_entry_raw),
.partition_array_checksum = 0
};
strncpy((char *)content->header.signature, "EFI PART", 8);
strncpy((char *)content->header.disk_guid, "ANDROID MMC DISK", 16);
}
}
static int get_config_uint64(cnode *node, uint64_t *ptr, const char *name)
{
const char *tmp;
uint64_t val;
char *endptr;
if ((tmp = config_str(node, name, NULL))) {
val = strtoull(tmp, &endptr, 10);
if (*endptr != '\0') {
D(WARN, "Value for %s is not a number: %s", name, tmp);
return 1;
}
*ptr = val;
return 0;
}
return 1;
}
static int get_config_string(cnode *node, char *ptr, int max_len, const char *name)
{
size_t begin, end;
const char *value = config_str(node, name, NULL);
if (!value)
return -1;
begin = strcspn(value, "\"") + 1;
end = strcspn(&value[begin], "\"");
if ((int) end > max_len) {
D(WARN, "Identifier \"%s\" too long", value);
return -1;
}
strncpy(ptr, &value[begin], end);
if((int) end < max_len)
ptr[end] = 0;
return 0;
}
static void GPT_parse_header(cnode *node, struct GPT_content *content)
{
get_config_uint64(node, &content->header.current_lba, "header_lba");
get_config_uint64(node, &content->header.backup_lba, "backup_lba");
get_config_uint64(node, &content->header.first_usable_lba, "first_lba");
get_config_uint64(node, &content->header.last_usable_lba, "last_lba");
get_config_uint64(node, &content->header.entries_lba, "entries_lba");
get_config_string(node, (char *) content->header.disk_guid, 16, "guid");
}
static int GPT_parse_partitions(cnode *node, struct GPT_content *content)
{
cnode *current;
int i;
uint64_t partition_size;
struct GPT_entry_raw *entry;
for (i = 0, current = node->first_child; current; current = current->next, ++i) {
entry = &content->entries[i];
entry_set_guid(i, content->entries[i].partition_guid);
memcpy(&content->entries[i].type_guid, partition_type_uuid, 16);
if (get_config_uint64(current, &entry->first_lba, "first_lba")) {
D(ERR, "first_lba not specified");
return 1;
}
if (get_config_uint64(current, &partition_size, "partition_size")) {
D(ERR, "partition_size not specified");
return 1;
}
if (config_str(current, "system", NULL)) {
entry->flags |= GPT_FLAG_SYSTEM;
}
if (config_str(current, "bootable", NULL)) {
entry->flags |= GPT_FLAG_BOOTABLE;
}
if (config_str(current, "readonly", NULL)) {
entry->flags |= GPT_FLAG_READONLY;
}
if (config_str(current, "automount", NULL)) {
entry->flags |= GPT_FLAG_DOAUTOMOUNT;
}
get_config_uint64(current, &content->entries[i].flags, "flags");
content->entries[i].last_lba = content->entries[i].first_lba + partition_size - 1;
GPT_to_UTF16(content->entries[i].name, current->name, 16);
}
return 0;
}
static inline int cnode_count(cnode *node)
{
int i;
cnode *current;
for (i = 0, current = node->first_child; current; current = current->next, ++i)
;
return i;
}
static int GPT_parse_cnode(cnode *root, struct GPT_content *content)
{
cnode *partnode;
if (!(partnode = config_find(root, "partitions"))) {
D(ERR, "Could not find partition table");
return 0;
}
GPT_parse_header(root, content);
content->header.entries_count = cnode_count(partnode);
content->entries = malloc(content->header.entries_count * sizeof(struct GPT_entry_raw));
if (GPT_parse_partitions(partnode, content)) {
D(ERR, "Could not parse partitions");
return 0;
}
return 1;
}
int GPT_parse_file(int fd, struct GPT_content *content)
{
char *data;
int size;
int ret;
cnode *root = config_node("", "");
size = get_file_size(fd);
data = (char *) mmap(NULL, size + 1, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
if (data == NULL) {
if (size == 0)
D(ERR, "config file empty");
else
D(ERR, "Out of memory");
return 0;
}
data[size - 1] = 0;
config_load(root, data);
if (root->first_child == NULL) {
D(ERR, "Could not read config file");
return 0;
}
ret = GPT_parse_cnode(root, content);
munmap(data, size);
return ret;
}
void GPT_release_content(struct GPT_content *content)
{
free(content->entries);
}
int GPT_write_content(const char *device, struct GPT_content *content)
{
struct GPT_entry_table *maptable;
maptable = GPT_get_from_content(device, content);
if (maptable == NULL) {
D(ERR, "could not map device");
return 0;
}
memcpy(maptable->header, &content->header, sizeof(*maptable->header));
memcpy(maptable->entries, content->entries,
content->header.entries_count * sizeof(*maptable->entries));
GPT_sync(maptable);
GPT_release_device(maptable);
return 1;
}

View file

@ -1,140 +0,0 @@
/*
* 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_PATITIONS_
#define __FASTBOOTD_PATITIONS_
#include <stdint.h>
#define GPT_ENTRIES 128
#define GPT_NAMELEN 36
#define GPT_FLAG_SYSTEM (1ULL << 0)
#define GPT_FLAG_BOOTABLE (1ULL << 2)
#define GPT_FLAG_READONLY (1ULL << 60)
#define GPT_FLAG_DOAUTOMOUNT (1ULL << 63)
// it should be passed in little endian order
struct GPT_entry_raw {
uint8_t type_guid[16];
uint8_t partition_guid[16];
uint64_t first_lba; // little endian
uint64_t last_lba;
uint64_t flags;
uint16_t name[GPT_NAMELEN]; // UTF-16 LE
};
struct GPT_mapping {
void *map_ptr;
void *ptr;
unsigned size;
};
struct GPT_entry_table {
int fd;
struct GPT_mapping header_map;
struct GPT_mapping entries_map;
struct GPT_mapping sec_header_map;
struct GPT_mapping sec_entries_map;
struct GPT_header *header;
struct GPT_entry_raw *entries;
struct GPT_header *second_header;
struct GPT_entry_raw *second_entries;
unsigned sector_size;
unsigned partition_table_size;
int second_valid;
};
struct GPT_header {
uint8_t signature[8];
uint32_t revision;
uint32_t header_size;
uint32_t header_checksum;
uint32_t reserved_zeros;
uint64_t current_lba;
uint64_t backup_lba;
uint64_t first_usable_lba;
uint64_t last_usable_lba;
uint8_t disk_guid[16];
uint64_t entries_lba;
uint32_t entries_count;
uint32_t entry_size;
uint32_t partition_array_checksum;
// the rest should be filled with zeros
} __attribute__((packed));
struct GPT_content {
struct GPT_header header;
struct GPT_entry_raw *entries;
};
struct GPT_entry_table* GPT_get_device(const char *, unsigned lba);
void GPT_release_device(struct GPT_entry_table *);
void GPT_edit_entry(struct GPT_entry_table *table,
struct GPT_entry_raw *old_entry,
struct GPT_entry_raw *new_entry);
int GPT_delete_entry(struct GPT_entry_table *table, struct GPT_entry_raw *entry);
void GPT_add_entry(struct GPT_entry_table *table, struct GPT_entry_raw *entry);
struct GPT_entry_raw *GPT_get_pointer(struct GPT_entry_table *table, struct GPT_entry_raw *entry);
struct GPT_entry_raw *GPT_get_pointer_by_guid(struct GPT_entry_table *, const char *);
struct GPT_entry_raw *GPT_get_pointer_by_name(struct GPT_entry_table *, const char *);
//Use after every edit operation
void GPT_sync();
void GPT_to_UTF16(uint16_t *, const char *, int );
void GPT_from_UTF16(char *, const uint16_t *, int);
int GPT_parse_entry(char *string, struct GPT_entry_raw *entry);
void GPT_default_content(struct GPT_content *content, struct GPT_entry_table *table);
void GPT_release_content(struct GPT_content *content);
int GPT_parse_file(int fd, struct GPT_content *content);
int GPT_write_content(const char *device, struct GPT_content *content);
int gpt_mmap(struct GPT_mapping *mapping, uint64_t location, int size, int fd);
void gpt_unmap(struct GPT_mapping *mapping);
#endif

View file

@ -1,69 +0,0 @@
/*
* 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 "commands/virtual_partitions.h"
#include <malloc.h>
#include <string.h>
#include "debug.h"
static struct virtual_partition *partitions = NULL;
int try_handle_virtual_partition(struct protocol_handle *handle, const char *arg)
{
struct virtual_partition *current;
for (current = partitions; current != NULL; current = current->next) {
if (!strcmp(current->name, arg)) {
current->handler(handle, arg);
}
}
return 0;
}
void virtual_partition_register(
const char * name,
void (*handler)(struct protocol_handle *phandle, const char *arg))
{
struct virtual_partition *new;
new = malloc(sizeof(*new));
if (new) {
new->name = name;
new->handler = handler;
new->next = partitions;
partitions = new;
}
else {
D(ERR, "Out of memory");
}
}

View file

@ -1,49 +0,0 @@
/*
* 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_VIRTUAL_PARTITIONS_H
#define FASTBOOTD_VIRTUAL_PARTITIONS_H
#include "protocol.h"
struct virtual_partition {
struct virtual_partition *next;
const char *name;
void (*handler)(struct protocol_handle *phandle, const char *arg);
};
int try_handle_virtual_partition(struct protocol_handle *handle, const char *arg);
void virtual_partition_register(
const char * name,
void (*handler)(struct protocol_handle *phandle, const char *arg));
#endif

View file

@ -1,147 +0,0 @@
/*
* Copyright (c) 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 <errno.h>
#include <fcntl.h>
#include <malloc.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include "protocol.h"
#include "utils.h"
#include "debug.h"
// TODO: change config path
#define CONFIG_PATH "/data/fastboot.cfg"
static int config_parse_line(char *line)
{
char *c;
char *key;
char *value;
c = strchr(line, '#');
if (c)
*c = '\0';
if (strspn(line, " \t") == strlen(line))
return 0;
c = strchr(line, '=');
if (c == NULL)
return -1;
key = line;
*c = '\0';
value = c + 1;
key = strip(key);
value = strip(value);
key = strdup(key);
value = strdup(value);
fastboot_publish(key, value);
return 0;
}
static void config_parse(char *buffer)
{
char *saveptr;
char *str = buffer;
char *line = buffer;
int c;
int ret;
for (c = 1; line != NULL; c++) {
line = strtok_r(str, "\r\n", &saveptr);
if (line != NULL) {
D(VERBOSE, "'%s'", line);
ret = config_parse_line(line);
if (ret < 0) {
D(WARN, "error parsing " CONFIG_PATH " line %d", c);
}
}
str = NULL;
}
}
void config_init()
{
int fd;
off_t len;
ssize_t ret;
size_t count = 0;
char *buffer;
fd = open(CONFIG_PATH, O_RDONLY);
if (fd < 0) {
D(ERR, "failed to open " CONFIG_PATH);
return;
}
len = lseek(fd, 0, SEEK_END);
if (len < 0) {
D(ERR, "failed to seek to end of " CONFIG_PATH);
return;
}
lseek(fd, 0, SEEK_SET);
buffer = malloc(len + 1);
if (buffer == NULL) {
D(ERR, "failed to allocate %ld bytes", len);
return;
}
while (count < (size_t)len) {
ret = read(fd, buffer + count, len - count);
if (ret < 0 && errno != EINTR) {
D(ERR, "failed to read " CONFIG_PATH ": %d %s", errno, strerror(errno));
return;
}
if (ret == 0) {
D(ERR, "early EOF reading " CONFIG_PATH);
return;
}
count += ret;
}
buffer[len] = '\0';
config_parse(buffer);
free(buffer);
}

View file

@ -1,42 +0,0 @@
/*
* Copyright (C) 2013 The Android Open Source Project
*
* 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.
*/
#ifndef _FASTBOOTD_DEBUG_H_
#define _FASTBOOTD_DEBUG_H_
#include <stdio.h>
#include <cutils/klog.h>
#define ERR 0
#define WARN 1
#define INFO 2
#define VERBOSE 3
#define DEBUG 4
extern unsigned int debug_level;
//#define DLOG(fmt, ...) printf(fmt, ##__VA_ARGS__)
#define DLOG(fmt, ...) KLOG_INFO("fastbootd", fmt, ##__VA_ARGS__)
#define D(level, fmt, ...) \
do { \
if (debug_level == level || debug_level > level) { \
DLOG("%s:%d " fmt "\n", __BASE_FILE__, __LINE__, ##__VA_ARGS__); \
} \
} while (0)
#endif

View file

@ -1,100 +0,0 @@
/*
* Copyright (C) 2013 The Android Open Source Project
*
* 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.
*/
#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"
#include "secure.h"
unsigned int debug_level = DEBUG;
void commands_init();
void usb_init();
void config_init();
int transport_socket_init();
int network_discovery_init();
void ssh_server_start();
int main(int argc, char **argv)
{
int socket_client = 0;
int c;
int network = 1;
klog_init();
klog_set_level(6);
const struct option longopts[] = {
{"socket", no_argument, 0, 'S'},
{"nonetwork", no_argument, 0, 'n'},
{0, 0, 0, 0}
};
while (1) {
c = getopt_long(argc, argv, "Sn", longopts, NULL);
/* Alphabetical cases */
if (c < 0)
break;
switch (c) {
case 'S':
socket_client = 1;
break;
case 'n':
network = 0;
break;
case '?':
return 1;
default:
return 0;
}
}
(void)argc;
(void)argv;
klog_init();
klog_set_level(6);
if (socket_client) {
//TODO: Shouldn't we change current tty into raw mode?
run_socket_client();
}
else {
cert_init_crypto();
config_init();
load_trigger();
commands_init();
usb_init();
if (network) {
if (!transport_socket_init())
exit(1);
ssh_server_start();
network_discovery_init();
}
while (1) {
sleep(1);
}
}
return 0;
}

View file

@ -1,118 +0,0 @@
/*
* 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 <string.h>
#include <dns_sd.h>
#include <cutils/properties.h>
#include <unistd.h>
#include "debug.h"
#include "network_discovery.h"
#include "utils.h"
#define MDNS_SERVICE_NAME "mdnsd"
#define MDNS_SERVICE_STATUS "init.svc.mdnsd"
#define FASTBOOTD_TYPE "_fastbootd._tcp"
#define FASTBOOTD_DOMAIN "local."
#define FASTBOOTD_NAME "fastbootd"
static void reg_reply(DNSServiceRef sdref, const DNSServiceFlags flags, DNSServiceErrorType errorCode,
const char *name, const char *regtype, const char *domain, void *context)
{
(void)sdref; // Unused
(void)flags; // Unused
(void)context; // Unused
if (errorCode == kDNSServiceErr_ServiceNotRunning) {
fprintf(stderr, "Error code %d\n", errorCode);
}
printf("Got a reply for service %s.%s%s: ", name, regtype, domain);
if (errorCode == kDNSServiceErr_NoError)
{
if (flags & kDNSServiceFlagsAdd)
printf("Name now registered and active\n");
else
printf("Name registration removed\n");
if (errorCode == kDNSServiceErr_NameConflict)
printf("Name in use, please choose another\n");
else
printf("Error %d\n", errorCode);
if (!(flags & kDNSServiceFlagsMoreComing)) fflush(stdout);
}
}
static int register_service() {
DNSServiceRef sdref = NULL;
const char *domain = FASTBOOTD_DOMAIN;
const char *type = FASTBOOTD_TYPE;
const char *host = NULL;
char name[PROP_VALUE_MAX];
uint16_t port = 22;
int flags = 0;
DNSServiceErrorType result;
property_get("ro.serialno", name, "");
if (!strcmp(name, "")) {
D(ERR, "No property serialno");
return -1;
}
result = DNSServiceRegister(&sdref, flags, kDNSServiceInterfaceIndexAny,
name, type, domain, host, port,
0, NULL, reg_reply, NULL);
if (result != kDNSServiceErr_NoError) {
D(ERR, "Unable to register service");
return -1;
}
return 0;
}
int network_discovery_init()
{
D(INFO, "Starting discovery");
if (service_start(MDNS_SERVICE_NAME)) {
D(ERR, "Unable to start discovery");
return -1;
}
if (register_service()) {
D(ERR, "Unable to register service");
return -1;
}
return 0;
}

View file

@ -1,37 +0,0 @@
/*
* 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_NETWORK_DISCOVERY_H
#define _FASTBOOTD_NETWORK_DISCOVERY_H
int network_discovery_init();
#endif

View file

@ -1,304 +0,0 @@
/*
* 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 <getopt.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <cutils/klog.h>
#include "commands/partitions.h"
#include "debug.h"
unsigned int debug_level = DEBUG;
//TODO: add tool to generate config file
void usage() {
fprintf(stderr,
"usage: test_gpt [ <option> ] <file>\n"
"\n"
"options:\n"
" -p print partitions\n"
" -c print config file\n"
" -a adds new partition\n"
" -d deletes partition (-o needed)\n"
"\n"
" -n name@startlba,endlba new partition detail\n"
" -o old partition name\n"
" -t type guid\n"
" -g partition guid\n"
" -l gpt_location specyfies gpt secto\n"
);
}
void printGPT(struct GPT_entry_table *table);
void addGPT(struct GPT_entry_table *table, const char *arg, const char *guid, const char *tguid);
void deleteGPT(struct GPT_entry_table *table, const char *name);
void configPrintGPT(struct GPT_entry_table *table);
int main(int argc, char *argv[]) {
int print_cmd = 0;
int config_cmd = 0;
int add_cmd = 0;
int del_cmd = 0;
int sync_cmd = 0;
int c;
const char *new_partition = NULL;
const char *old_partition = NULL;
const char *type_guid = NULL;
const char *partition_guid = NULL;
unsigned gpt_location = 1;
klog_init();
klog_set_level(6);
const struct option longopts[] = {
{"print", no_argument, 0, 'p'},
{"config-print", no_argument, 0, 'c'},
{"add", no_argument, 0, 'a'},
{"del", no_argument, 0, 'd'},
{"new", required_argument, 0, 'n'},
{"old", required_argument, 0, 'o'},
{"type", required_argument, 0, 't'},
{"sync", required_argument, 0, 's'},
{"guid", required_argument, 0, 'g'},
{"location", required_argument, 0, 'l'},
{0, 0, 0, 0}
};
while (1) {
c = getopt_long(argc, argv, "pcadt:g:n:o:sl:", longopts, NULL);
/* Alphabetical cases */
if (c < 0)
break;
switch (c) {
case 'p':
print_cmd = 1;
break;
case 'c':
config_cmd = 1;
break;
case 'a':
add_cmd = 1;
break;
case 'd':
del_cmd = 1;
break;
case 'n':
new_partition = optarg;
break;
case 'o':
old_partition = optarg;
break;
case 't':
type_guid = optarg;
case 'g':
partition_guid = optarg;
break;
case 's':
sync_cmd = 1;
break;
case 'l':
gpt_location = strtoul(optarg, NULL, 10);
fprintf(stderr, "Got offset as %d", gpt_location);
break;
case '?':
return 1;
default:
abort();
}
}
argc -= optind;
argv += optind;
if (argc < 1) {
usage();
return 1;
}
const char *path = argv[0];
struct GPT_entry_table *table = GPT_get_device(path, gpt_location);
if (table == NULL) {
fprintf(stderr, "unable to get GPT table from %s\n", path);
return 1;
}
if (add_cmd)
addGPT(table, new_partition, partition_guid, type_guid);
if (del_cmd)
deleteGPT(table, old_partition);
if (print_cmd)
printGPT(table);
if (config_cmd)
configPrintGPT(table);
if (sync_cmd)
GPT_sync(table);
GPT_release_device(table);
return 0;
}
void printGPT(struct GPT_entry_table *table) {
struct GPT_entry_raw *entry = table->entries;
unsigned n, m;
char name[GPT_NAMELEN + 1];
printf("ptn start block end block name\n");
printf("---- ------------- -------------\n");
for (n = 0; n < table->header->entries_count; n++, entry++) {
if (entry->type_guid[0] == 0)
continue;
for (m = 0; m < GPT_NAMELEN; m++) {
name[m] = entry->name[m] & 127;
}
name[m] = 0;
printf("#%03d %13"PRId64" %13"PRId64" %s\n",
n + 1, entry->first_lba, entry->last_lba, name);
}
}
void configPrintGPT(struct GPT_entry_table *table) {
struct GPT_entry_raw *entry = table->entries;
unsigned n, m;
char name[GPT_NAMELEN + 1];
char temp_guid[17];
temp_guid[16] = 0;
printf("header_lba %"PRId64"\n", table->header->current_lba);
printf("backup_lba %"PRId64"\n", table->header->backup_lba);
printf("first_lba %"PRId64"\n", table->header->first_usable_lba);
printf("last_lba %"PRId64"\n", table->header->last_usable_lba);
printf("entries_lba %"PRId64"\n", table->header->entries_lba);
snprintf(temp_guid, 17, "%s", table->header->disk_guid);
printf("guid \"%s\"", temp_guid);
printf("\npartitions {\n");
for (n = 0; n < table->header->entries_count; n++, entry++) {
uint64_t size = entry->last_lba - entry->first_lba + 1;
if (entry->type_guid[0] == 0)
continue;
for (m = 0; m < GPT_NAMELEN; m++) {
name[m] = entry->name[m] & 127;
}
name[m] = 0;
printf(" %s {\n", name);
snprintf(temp_guid, 17, "%s", entry->partition_guid);
printf(" guid \"%s\"\n", temp_guid);
printf(" first_lba %"PRId64"\n", entry->first_lba);
printf(" partition_size %"PRId64"\n", size);
if (entry->flags & GPT_FLAG_SYSTEM)
printf(" system\n");
if (entry->flags & GPT_FLAG_BOOTABLE)
printf(" bootable\n");
if (entry->flags & GPT_FLAG_READONLY)
printf(" readonly\n");
if (entry->flags & GPT_FLAG_DOAUTOMOUNT)
printf(" automount\n");
printf(" }\n\n");
}
printf("}\n");
}
void addGPT(struct GPT_entry_table *table, const char *str , const char *guid, const char *tguid) {
char *c, *c2;
char *arg = malloc(strlen(str));
char *name = arg;
unsigned start, end;
strcpy(arg, str);
if (guid == NULL || tguid == NULL) {
fprintf(stderr, "Type guid and partion guid needed");
free(arg);
return;
}
c = strchr(arg, '@');
if (c == NULL) {
fprintf(stderr, "Wrong entry format");
free(arg);
return;
}
*c++ = '\0';
c2 = strchr(c, ',');
if (c2 == NULL) {
fprintf(stderr, "Wrong entry format");
free(arg);
return;
}
start = strtoul(c, NULL, 10);
*c2++ = '\0';
end = strtoul(c2, NULL, 10);
struct GPT_entry_raw data;
strncpy((char *)data.partition_guid, guid, 15);
data.partition_guid[15] = '\0';
strncpy((char *)data.type_guid, tguid, 15);
data.type_guid[15] = '\0';
GPT_to_UTF16(data.name, name, GPT_NAMELEN);
data.first_lba = start;
data.last_lba = end;
fprintf(stderr, "Adding (%d,%d) %s as, [%s, %s]", start, end, name, (char *) data.type_guid, (char *) data.partition_guid);
GPT_add_entry(table, &data);
free(arg);
}
void deleteGPT(struct GPT_entry_table *table, const char *name) {
struct GPT_entry_raw *entry;
if (name == NULL) {
fprintf(stderr, "Need partition name");
return;
}
entry = GPT_get_pointer_by_name(table, name);
if (!entry) {
fprintf(stderr, "Unable to find partition: %s", name);
return;
}
GPT_delete_entry(table, entry);
}

View file

@ -1,60 +0,0 @@
header_lba 1
backup_lba 101
first_lba 43
last_lba 100
entries_lba 2
partitions {
#You can generate this as output from gptedit -c
SOS {
first_lba 28672
partition_size 16384
}
DTB {
first_lba 45056
partition_size 8192
}
LNX {
first_lba 53248
partition_size 16384
}
APP {
first_lba 69632
partition_size 1048576
}
CAC {
first_lba 1118208
partition_size 1572864
}
MSC {
first_lba 2691072
partition_size 4096
}
USP {
first_lba 2695168
partition_size 65536
}
MDA {
first_lba 2760704
partition_size 4096
}
FCT {
first_lba 2764800
partition_size 32768
}
UDA {
first_lba 2797568
partition_size 27975680
}
}

View file

@ -1,181 +0,0 @@
package signtool;
import java.io.*;
import java.util.Properties;
import java.util.ArrayList;
import javax.mail.internet.*;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.activation.MailcapCommandMap;
import javax.activation.CommandMap;
import java.security.PrivateKey;
import java.security.Security;
import java.security.KeyFactory;
import java.security.KeyStore;
import java.security.NoSuchAlgorithmException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.InvalidKeySpecException;
import java.security.cert.X509Certificate;
import java.security.cert.CertificateFactory;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateEncodingException;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder;
import org.bouncycastle.cms.jcajce.JcaSignerInfoGeneratorBuilder;
import org.bouncycastle.operator.ContentSigner;
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
import org.bouncycastle.cms.CMSProcessableByteArray;
import org.bouncycastle.cms.CMSSignedGenerator;
import org.bouncycastle.cms.CMSSignedDataGenerator;
import org.bouncycastle.cms.CMSSignedGenerator;
import org.bouncycastle.cms.CMSProcessable;
import org.bouncycastle.cms.CMSSignedData;
import org.bouncycastle.cms.CMSTypedData;
import org.bouncycastle.cert.jcajce.JcaCertStore;
import org.bouncycastle.util.Store;
import org.bouncycastle.asn1.ASN1InputStream;
import org.bouncycastle.asn1.DEROutputStream;
import org.bouncycastle.asn1.ASN1Object;
public class SignImg {
/* It reads private key in pkcs#8 formate
* Conversion:
* openssl pkcs8 -topk8 -nocrypt -outform DER < inkey.pem > outkey.pk8
*/
private static PrivateKey getPrivateKey(String path) throws IOException, FileNotFoundException, NoSuchAlgorithmException, InvalidKeySpecException {
File file = new File(path);
FileInputStream fis = new FileInputStream(file);
byte[] data = new byte[(int)file.length()];
fis.read(data);
fis.close();
PKCS8EncodedKeySpec kspec = new PKCS8EncodedKeySpec(data);
KeyFactory kf = KeyFactory.getInstance("RSA");
PrivateKey privateKey = kf.generatePrivate(kspec);
return privateKey;
}
private static MimeBodyPart getContent(String path) throws IOException, FileNotFoundException, MessagingException {
MimeBodyPart body = new MimeBodyPart();
File file = new File(path);
FileInputStream fis = new FileInputStream(file);
byte[] data = new byte[(int)file.length()];
fis.read(data);
fis.close();
body.setContent(data, "application/octet-stream");
return body;
}
private static CMSProcessableByteArray getCMSContent(String path) throws IOException, FileNotFoundException, MessagingException {
File file = new File(path);
FileInputStream fis = new FileInputStream(file);
byte[] data = new byte[(int)file.length()];
fis.read(data);
fis.close();
CMSProcessableByteArray cms = new CMSProcessableByteArray(data);
return cms;
}
private static X509Certificate readCert(String path) throws IOException, FileNotFoundException, CertificateException {
File file = new File(path);
FileInputStream is = new FileInputStream(file);
CertificateFactory cf = CertificateFactory.getInstance("X.509");
Certificate cert = cf.generateCertificate(is);
is.close();
return (X509Certificate) cert;
}
private static void save(MimeBodyPart content, String path) throws IOException, FileNotFoundException, MessagingException {
File file = new File(path);
FileOutputStream os = new FileOutputStream(file);
content.writeTo(os);
os.close();
}
private static Store certToStore(X509Certificate certificate) throws CertificateEncodingException {
ArrayList<X509Certificate> certList = new ArrayList<X509Certificate>();
certList.add(certificate);
return new JcaCertStore(certList);
}
public static void setDefaultMailcap()
{
MailcapCommandMap _mailcap =
(MailcapCommandMap)CommandMap.getDefaultCommandMap();
_mailcap.addMailcap("application/pkcs7-signature;; x-java-content-handler=org.bouncycastle.mail.smime.handlers.pkcs7_signature");
_mailcap.addMailcap("application/pkcs7-mime;; x-java-content-handler=org.bouncycastle.mail.smime.handlers.pkcs7_mime");
_mailcap.addMailcap("application/x-pkcs7-signature;; x-java-content-handler=org.bouncycastle.mail.smime.handlers.x_pkcs7_signature");
_mailcap.addMailcap("application/x-pkcs7-mime;; x-java-content-handler=org.bouncycastle.mail.smime.handlers.x_pkcs7_mime");
_mailcap.addMailcap("multipart/signed;; x-java-content-handler=org.bouncycastle.mail.smime.handlers.multipart_signed");
CommandMap.setDefaultCommandMap(_mailcap);
}
public static void main(String[] args) {
try {
if (args.length < 4) {
System.out.println("Usage: signimg data private_key certificate output");
return;
}
System.out.println("Signing the image");
setDefaultMailcap();
Security.addProvider(new BouncyCastleProvider());
PrivateKey key = getPrivateKey(args[1]);
System.out.println("File read sucessfully");
CMSSignedDataGenerator generator = new CMSSignedDataGenerator();
CMSTypedData body = getCMSContent(args[0]);
System.out.println("Content read sucessfully");
X509Certificate cert = (X509Certificate) readCert(args[2]);
System.out.println("Certificate read sucessfully");
ContentSigner sha256Signer = new JcaContentSignerBuilder("SHA256withRSA").setProvider("BC").build(key);
Store certs = certToStore(cert);
generator.addCertificates(certs);
generator.addSignerInfoGenerator(
new JcaSignerInfoGeneratorBuilder(
new JcaDigestCalculatorProviderBuilder().setProvider("BC").build())
.build(sha256Signer, cert));
CMSSignedData signed = generator.generate(body, true);
System.out.println("Signed");
Properties props = System.getProperties();
Session session = Session.getDefaultInstance(props, null);
File file = new File(args[3]);
FileOutputStream os = new FileOutputStream(file);
ASN1InputStream asn1 = new ASN1InputStream(signed.getEncoded());
ByteArrayOutputStream out = new ByteArrayOutputStream();
DEROutputStream dOut = new DEROutputStream(os);
dOut.writeObject(ASN1Object.fromByteArray(signed.getEncoded()));
}
catch (Exception ex) {
System.out.println("Exception during programm execution: " + ex.getMessage());
}
}
}

View file

@ -1,195 +0,0 @@
/*
* 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 <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "debug.h"
#include "protocol.h"
#include "transport.h"
#define STATE_OFFLINE 0
#define STATE_COMMAND 1
#define STATE_COMPLETE 2
#define STATE_ERROR 3
struct fastboot_cmd {
struct fastboot_cmd *next;
const char *prefix;
unsigned prefix_len;
void (*execute)(struct protocol_handle *phandle, const char *arg);
};
struct fastboot_var {
struct fastboot_var *next;
const char *name;
const char *value;
};
static struct fastboot_cmd *cmdlist;
void fastboot_register(const char *prefix,
void (*phandle)(struct protocol_handle *phandle, const char *arg))
{
struct fastboot_cmd *cmd;
cmd = malloc(sizeof(*cmd));
if (cmd) {
cmd->prefix = prefix;
cmd->prefix_len = strlen(prefix);
cmd->execute = phandle;
cmd->next = cmdlist;
cmdlist = cmd;
}
}
static struct fastboot_var *varlist;
void fastboot_publish(const char *name, const char *value)
{
struct fastboot_var *var;
var = malloc(sizeof(*var));
if (var) {
var->name = name;
var->value = value;
var->next = varlist;
varlist = var;
}
}
const char *fastboot_getvar(const char *name)
{
struct fastboot_var *var;
for (var = varlist; var; var = var->next) {
if (!strcmp(var->name, name)) {
return var->value;
}
}
return "";
}
int protocol_handle_download(struct protocol_handle *phandle, size_t len)
{
return transport_handle_download(phandle->transport_handle, len);
}
static ssize_t protocol_handle_write(struct protocol_handle *phandle,
char *buffer, size_t len)
{
return transport_handle_write(phandle->transport_handle, buffer, len);
}
static void fastboot_ack(struct protocol_handle *phandle, const char *code,
const char *reason)
{
char response[64];
if (phandle->state != STATE_COMMAND)
return;
if (reason == 0)
reason = "";
snprintf(response, 64, "%s%s", code, reason);
phandle->state = STATE_COMPLETE;
protocol_handle_write(phandle, response, strlen(response));
}
void fastboot_fail(struct protocol_handle *phandle, const char *reason)
{
fastboot_ack(phandle, "FAIL", reason);
}
void fastboot_okay(struct protocol_handle *phandle, const char *info)
{
fastboot_ack(phandle, "OKAY", info);
}
void fastboot_data(struct protocol_handle *phandle, size_t len)
{
char response[64];
ssize_t ret;
snprintf(response, 64, "DATA%08zx", len);
ret = protocol_handle_write(phandle, response, strlen(response));
if (ret < 0)
return;
}
void protocol_handle_command(struct protocol_handle *phandle, char *buffer)
{
D(INFO,"fastboot: %s\n", buffer);
struct fastboot_cmd *cmd;
for (cmd = cmdlist; cmd; cmd = cmd->next) {
if (memcmp(buffer, cmd->prefix, cmd->prefix_len))
continue;
phandle->state = STATE_COMMAND;
cmd->execute(phandle, buffer + cmd->prefix_len);
if (phandle->state == STATE_COMMAND)
fastboot_fail(phandle, "unknown reason");
return;
}
fastboot_fail(phandle, "unknown command");
}
struct protocol_handle *create_protocol_handle(struct transport_handle *thandle)
{
struct protocol_handle *phandle;
phandle = calloc(sizeof(struct protocol_handle), 1);
phandle->transport_handle = thandle;
phandle->state = STATE_OFFLINE;
phandle->download_fd = -1;
pthread_mutex_init(&phandle->lock, NULL);
return phandle;
}
int protocol_get_download(struct protocol_handle *phandle)
{
int fd;
pthread_mutex_lock(&phandle->lock);
fd = phandle->download_fd;
phandle->download_fd = -1;
pthread_mutex_unlock(&phandle->lock);
return fd;
}

View file

@ -1,61 +0,0 @@
/*
* Copyright (c) 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_PROTOCOL_H_
#define _FASTBOOTD_PROTOCOL_H_
#include <pthread.h>
#include <stddef.h>
struct protocol_handle {
struct transport_handle *transport_handle;
unsigned int state;
int download_fd;
pthread_mutex_t lock;
};
void fastboot_register(const char *prefix,
void (*handle)(struct protocol_handle *handle, const char *arg));
void fastboot_publish(const char *name, const char *value);
const char *fastboot_getvar(const char *name);
struct protocol_handle *create_protocol_handle(struct transport_handle *t);
void protocol_handle_command(struct protocol_handle *handle, char *buffer);
int protocol_handle_download(struct protocol_handle *phandle, size_t len);
int protocol_get_download(struct protocol_handle *phandle);
void fastboot_fail(struct protocol_handle *handle, const char *reason);
void fastboot_okay(struct protocol_handle *handle, const char *reason);
void fastboot_data(struct protocol_handle *handle, size_t len);
#endif

View file

@ -1,169 +0,0 @@
/*
* 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 <openssl/pem.h>
#include <openssl/engine.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#include <openssl/pem.h>
#include <openssl/cms.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include "secure.h"
#include "debug.h"
#include "utils.h"
void cert_init_crypto() {
CRYPTO_malloc_init();
ERR_load_crypto_strings();
OpenSSL_add_all_algorithms();
ENGINE_load_builtin_engines();
}
X509_STORE *cert_store_from_path(const char *path) {
X509_STORE *store;
struct stat st;
X509_LOOKUP *lookup;
if (stat(path, &st)) {
D(ERR, "Unable to stat cert path");
goto error;
}
if (!(store = X509_STORE_new())) {
goto error;
}
if (S_ISDIR(st.st_mode)) {
lookup = X509_STORE_add_lookup(store,X509_LOOKUP_hash_dir());
if (lookup == NULL)
goto error;
if (!X509_LOOKUP_add_dir(lookup, path, X509_FILETYPE_PEM)) {
D(ERR, "Error loading cert directory %s", path);
goto error;
}
}
else if(S_ISREG(st.st_mode)) {
lookup = X509_STORE_add_lookup(store,X509_LOOKUP_file());
if (lookup == NULL)
goto error;
if (!X509_LOOKUP_load_file(lookup, path, X509_FILETYPE_PEM)) {
D(ERR, "Error loading cert directory %s", path);
goto error;
}
}
else {
D(ERR, "cert path is not directory or regular file");
goto error;
}
return store;
error:
return NULL;
}
int cert_read(int fd, CMS_ContentInfo **content, BIO **output) {
BIO *input;
*output = NULL;
input = BIO_new_fd(fd, BIO_NOCLOSE);
if (input == NULL) {
D(ERR, "Unable to open input");
goto error;
}
//TODO:
// read with d2i_CMS_bio to support DER
// with java or just encode data with base64
*content = SMIME_read_CMS(input, output);
if (*content == NULL) {
unsigned long err = ERR_peek_last_error();
D(ERR, "Unable to parse input file: %s", ERR_lib_error_string(err));
goto error_read;
}
BIO_free(input);
return 0;
error_read:
BIO_free(input);
error:
return 1;
}
int cert_verify(BIO *content, CMS_ContentInfo *content_info, X509_STORE *store, int *out_fd) {
BIO *output_temp;
int ret;
*out_fd = create_temp_file();
if (*out_fd < 0) {
D(ERR, "unable to create temporary file");
return -1;
}
output_temp = BIO_new_fd(*out_fd, BIO_NOCLOSE);
if (output_temp == NULL) {
D(ERR, "unable to create temporary bio");
close(*out_fd);
return -1;
}
ret = CMS_verify(content_info, NULL ,store, content, output_temp, 0);
if (ret == 0) {
char buf[256];
unsigned long err = ERR_peek_last_error();
D(ERR, "Verification failed with reason: %s, %s", ERR_lib_error_string(err), ERR_error_string(err, buf));
D(ERR, "Data used: content %p", content);
}
ERR_clear_error();
ERR_remove_state(0);
BIO_free(output_temp);
return ret;
}
void cert_release(BIO *content, CMS_ContentInfo *info) {
BIO_free(content);
CMS_ContentInfo_free(info);
}

View file

@ -1,53 +0,0 @@
/*
* 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_SECURE_H
#define _FASTBOOTD_SECURE_H
#include <openssl/ssl.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#include <openssl/pem.h>
#include <openssl/cms.h>
void cert_init_crypto();
X509_STORE *cert_store_from_path(const char*stream);
static inline void cert_release_store(X509_STORE *store) {
X509_STORE_free(store);
}
int cert_read(int fd, CMS_ContentInfo **content, BIO **output);
int cert_verify(BIO *content, CMS_ContentInfo *content_info, X509_STORE *store, int *out_fd);
void cert_release(BIO *content, CMS_ContentInfo *info);
#endif

View file

@ -1,94 +0,0 @@
/*
* 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");
}

View file

@ -1,37 +0,0 @@
/*
* 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

View file

@ -1,152 +0,0 @@
/*
* Copyright (C) 2013 The Android Open Source Project
*
* 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.
*/
#include <errno.h>
#include <pthread.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/mman.h>
#include "debug.h"
#include "protocol.h"
#include "transport.h"
#define COMMAND_BUF_SIZE 64
ssize_t transport_handle_write(struct transport_handle *thandle, char *buffer, size_t len)
{
return thandle->transport->write(thandle, buffer, len);
}
void transport_handle_close(struct transport_handle *thandle)
{
thandle->transport->close(thandle);
}
int transport_handle_download(struct transport_handle *thandle, size_t len)
{
ssize_t ret;
size_t n = 0;
int fd;
// TODO: move out of /dev
char tempname[] = "/dev/fastboot_download_XXXXXX";
char *buffer;
fd = mkstemp(tempname);
if (fd < 0)
return -1;
unlink(tempname);
ftruncate(fd, len);
buffer = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (buffer == MAP_FAILED) {
D(ERR, "mmap(%zu) failed: %d %s", len, errno, strerror(errno));
goto err;
}
while (n < len) {
ret = thandle->transport->read(thandle, buffer + n, len - n);
if (ret <= 0) {
D(WARN, "transport read failed, ret=%zd %s", ret, strerror(-ret));
break;
}
n += ret;
}
munmap(buffer, len);
if (n != len)
goto err;
return fd;
err:
close(fd);
transport_handle_close(thandle);
return -1;
}
static void *transport_data_thread(void *arg)
{
struct transport_handle *thandle = arg;
struct protocol_handle *phandle = create_protocol_handle(thandle);
while (!thandle->stopped) {
int ret;
char buffer[COMMAND_BUF_SIZE + 1];
D(VERBOSE, "transport_data_thread\n");
ret = thandle->transport->read(thandle, buffer, COMMAND_BUF_SIZE);
if (ret <= 0) {
D(DEBUG, "ret = %d\n", ret);
break;
}
if (ret > 0) {
buffer[ret] = 0;
//TODO: multiple threads
protocol_handle_command(phandle, buffer);
}
}
transport_handle_close(thandle);
free(thandle);
return NULL;
}
static void *transport_connect_thread(void *arg)
{
struct transport *transport = arg;
while (!transport->stopped) {
struct transport_handle *thandle;
pthread_t thread;
pthread_attr_t attr;
D(VERBOSE, "transport_connect_thread\n");
thandle = transport->connect(transport);
if (thandle == NULL) {
D(ERR, "transport connect failed\n");
sleep(1);
continue;
}
thandle->transport = transport;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
pthread_create(&thread, &attr, transport_data_thread, thandle);
sleep(1);
}
return NULL;
}
void transport_register(struct transport *transport)
{
pthread_t thread;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
pthread_create(&thread, &attr, transport_connect_thread, transport);
}

View file

@ -1,41 +0,0 @@
/*
* Copyright (C) 2013 The Android Open Source Project
*
* 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.
*/
#ifndef _FASTBOOTD_TRANSPORT_H_
#define _FASTBOOTD_TRANSPORT_H_
#include <stdbool.h>
struct transport_handle {
struct transport *transport;
bool stopped;
};
struct transport {
void (*init)();
void (*close)(struct transport_handle *thandle);
ssize_t (*read)(struct transport_handle *thandle, void *data, size_t len);
ssize_t (*write)(struct transport_handle *thandle, const void *data, size_t len);
struct transport_handle *(*connect)(struct transport *transport);
bool stopped;
};
void transport_register(struct transport *transport);
ssize_t transport_handle_write(struct transport_handle *handle, char *buffer, size_t len);
int transport_handle_download(struct transport_handle *handle, size_t len);
#endif

View file

@ -1,154 +0,0 @@
/*
* 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=%zu)", 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=%zu)", 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;
if (!listen_socket_init(socket_transport)) {
D(ERR, "socket transport init failed");
free(socket_transport);
return 0;
}
transport_register(&socket_transport->transport);
return 1;
}

View file

@ -1,57 +0,0 @@
/*
* 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 <dlfcn.h>
#include <hardware/hardware.h>
#include "debug.h"
#include "trigger.h"
#include "protocol.h"
#include "vendor_trigger.h"
static const int version = 1;
int load_trigger() {
int libversion;
if (trigger_init() != 0) {
D(ERR, "libvendortrigger failed to initialize");
return 1;
}
if (trigger_check_version(version, &libversion)) {
D(ERR, "Library report incompability");
return 1;
}
D(INFO, "libvendortrigger loaded");
return 0;
}

View file

@ -1,40 +0,0 @@
/*
* 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_TRIGGER_H_
#define __FASTBOOTD_TRIGGER_H_
#include "commands/partitions.h"
#include "vendor_trigger.h"
int load_trigger();
#endif

View file

@ -1,339 +0,0 @@
/*
* Copyright (C) 2007 The Android Open Source Project
*
* 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.
*/
#include <endian.h>
#include <errno.h>
#include <fcntl.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <linux/usb/ch9.h>
#include <linux/usb/functionfs.h>
#include "debug.h"
#include "transport.h"
#include "utils.h"
#define TRACE_TAG TRACE_USB
#define MAX_PACKET_SIZE_FS 64
#define MAX_PACKET_SIZE_HS 512
#define cpu_to_le16(x) htole16(x)
#define cpu_to_le32(x) htole32(x)
#define FASTBOOT_CLASS 0xff
#define FASTBOOT_SUBCLASS 0x42
#define FASTBOOT_PROTOCOL 0x3
#define USB_FFS_FASTBOOT_PATH "/dev/usb-ffs/adb/"
#define USB_FFS_FASTBOOT_EP(x) USB_FFS_FASTBOOT_PATH#x
#define USB_FFS_FASTBOOT_EP0 USB_FFS_FASTBOOT_EP(ep0)
#define USB_FFS_FASTBOOT_OUT USB_FFS_FASTBOOT_EP(ep1)
#define USB_FFS_FASTBOOT_IN USB_FFS_FASTBOOT_EP(ep2)
#define container_of(ptr, type, member) \
((type*)((char*)(ptr) - offsetof(type, member)))
struct usb_transport {
struct transport transport;
pthread_cond_t notify;
pthread_mutex_t lock;
int control;
int bulk_out; /* "out" from the host's perspective => source for fastbootd */
int bulk_in; /* "in" from the host's perspective => sink for fastbootd */
};
struct usb_handle {
struct transport_handle handle;
};
struct func_desc {
struct usb_interface_descriptor intf;
struct usb_endpoint_descriptor_no_audio source;
struct usb_endpoint_descriptor_no_audio sink;
} __attribute__((packed));
struct desc_v1 {
struct usb_functionfs_descs_head_v1 {
__le32 magic;
__le32 length;
__le32 fs_count;
__le32 hs_count;
} __attribute__((packed)) header;
struct func_desc fs_descs, hs_descs;
} __attribute__((packed));
struct desc_v2 {
struct usb_functionfs_descs_head_v2 header;
// The rest of the structure depends on the flags in the header.
__le32 fs_count;
__le32 hs_count;
struct func_desc fs_descs, hs_descs;
} __attribute__((packed));
struct func_desc fs_descriptors = {
.intf = {
.bLength = sizeof(fs_descriptors.intf),
.bDescriptorType = USB_DT_INTERFACE,
.bInterfaceNumber = 0,
.bNumEndpoints = 2,
.bInterfaceClass = FASTBOOT_CLASS,
.bInterfaceSubClass = FASTBOOT_SUBCLASS,
.bInterfaceProtocol = FASTBOOT_PROTOCOL,
.iInterface = 1, /* first string from the provided table */
},
.source = {
.bLength = sizeof(fs_descriptors.source),
.bDescriptorType = USB_DT_ENDPOINT,
.bEndpointAddress = 1 | USB_DIR_OUT,
.bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = MAX_PACKET_SIZE_FS,
},
.sink = {
.bLength = sizeof(fs_descriptors.sink),
.bDescriptorType = USB_DT_ENDPOINT,
.bEndpointAddress = 2 | USB_DIR_IN,
.bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = MAX_PACKET_SIZE_FS,
},
};
struct func_desc hs_descriptors = {
.intf = {
.bLength = sizeof(hs_descriptors.intf),
.bDescriptorType = USB_DT_INTERFACE,
.bInterfaceNumber = 0,
.bNumEndpoints = 2,
.bInterfaceClass = FASTBOOT_CLASS,
.bInterfaceSubClass = FASTBOOT_SUBCLASS,
.bInterfaceProtocol = FASTBOOT_PROTOCOL,
.iInterface = 1, /* first string from the provided table */
},
.source = {
.bLength = sizeof(hs_descriptors.source),
.bDescriptorType = USB_DT_ENDPOINT,
.bEndpointAddress = 1 | USB_DIR_OUT,
.bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = MAX_PACKET_SIZE_HS,
},
.sink = {
.bLength = sizeof(hs_descriptors.sink),
.bDescriptorType = USB_DT_ENDPOINT,
.bEndpointAddress = 2 | USB_DIR_IN,
.bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = MAX_PACKET_SIZE_HS,
},
};
#define STR_INTERFACE_ "Fastboot Interface"
static const struct {
struct usb_functionfs_strings_head header;
struct {
__le16 code;
const char str1[sizeof(STR_INTERFACE_)];
} __attribute__((packed)) lang0;
} __attribute__((packed)) strings = {
.header = {
.magic = cpu_to_le32(FUNCTIONFS_STRINGS_MAGIC),
.length = cpu_to_le32(sizeof(strings)),
.str_count = cpu_to_le32(1),
.lang_count = cpu_to_le32(1),
},
.lang0 = {
cpu_to_le16(0x0409), /* en-us */
STR_INTERFACE_,
},
};
static int init_functionfs(struct usb_transport *usb_transport)
{
ssize_t ret;
struct desc_v1 v1_descriptor;
struct desc_v2 v2_descriptor;
v2_descriptor.header.magic = cpu_to_le32(FUNCTIONFS_DESCRIPTORS_MAGIC_V2);
v2_descriptor.header.length = cpu_to_le32(sizeof(v2_descriptor));
v2_descriptor.header.flags = FUNCTIONFS_HAS_FS_DESC | FUNCTIONFS_HAS_HS_DESC;
v2_descriptor.fs_count = 3;
v2_descriptor.hs_count = 3;
v2_descriptor.fs_descs = fs_descriptors;
v2_descriptor.hs_descs = hs_descriptors;
D(VERBOSE, "OPENING %s", USB_FFS_FASTBOOT_EP0);
usb_transport->control = open(USB_FFS_FASTBOOT_EP0, O_RDWR);
if (usb_transport->control < 0) {
D(ERR, "[ %s: cannot open control endpoint: errno=%d]", USB_FFS_FASTBOOT_EP0, errno);
goto err;
}
ret = write(usb_transport->control, &v2_descriptor, sizeof(v2_descriptor));
if (ret < 0) {
v1_descriptor.header.magic = cpu_to_le32(FUNCTIONFS_DESCRIPTORS_MAGIC);
v1_descriptor.header.length = cpu_to_le32(sizeof(v1_descriptor));
v1_descriptor.header.fs_count = 3;
v1_descriptor.header.hs_count = 3;
v1_descriptor.fs_descs = fs_descriptors;
v1_descriptor.hs_descs = hs_descriptors;
D(ERR, "[ %s: Switching to V1_descriptor format errno=%d ]\n", USB_FFS_FASTBOOT_EP0, errno);
ret = write(usb_transport->control, &v1_descriptor, sizeof(v1_descriptor));
if (ret < 0) {
D(ERR, "[ %s: write descriptors failed: errno=%d ]", USB_FFS_FASTBOOT_EP0, errno);
goto err;
}
}
ret = write(usb_transport->control, &strings, sizeof(strings));
if (ret < 0) {
D(ERR, "[ %s: writing strings failed: errno=%d]", USB_FFS_FASTBOOT_EP0, errno);
goto err;
}
usb_transport->bulk_out = open(USB_FFS_FASTBOOT_OUT, O_RDWR);
if (usb_transport->bulk_out < 0) {
D(ERR, "[ %s: cannot open bulk-out ep: errno=%d ]", USB_FFS_FASTBOOT_OUT, errno);
goto err;
}
usb_transport->bulk_in = open(USB_FFS_FASTBOOT_IN, O_RDWR);
if (usb_transport->bulk_in < 0) {
D(ERR, "[ %s: cannot open bulk-in ep: errno=%d ]", USB_FFS_FASTBOOT_IN, errno);
goto err;
}
return 0;
err:
if (usb_transport->bulk_in > 0) {
close(usb_transport->bulk_in);
usb_transport->bulk_in = -1;
}
if (usb_transport->bulk_out > 0) {
close(usb_transport->bulk_out);
usb_transport->bulk_out = -1;
}
if (usb_transport->control > 0) {
close(usb_transport->control);
usb_transport->control = -1;
}
return -1;
}
static ssize_t usb_write(struct transport_handle *thandle, const void *data, size_t len)
{
ssize_t ret;
struct transport *t = thandle->transport;
struct usb_transport *usb_transport = container_of(t, struct usb_transport, transport);
D(DEBUG, "about to write (fd=%d, len=%zu)", usb_transport->bulk_in, len);
ret = bulk_write(usb_transport->bulk_in, data, len);
if (ret < 0) {
D(ERR, "ERROR: fd = %d, ret = %zd", usb_transport->bulk_in, ret);
return -1;
}
D(DEBUG, "[ usb_write done fd=%d ]", usb_transport->bulk_in);
return ret;
}
ssize_t usb_read(struct transport_handle *thandle, void *data, size_t len)
{
ssize_t ret;
struct transport *t = thandle->transport;
struct usb_transport *usb_transport = container_of(t, struct usb_transport, transport);
D(DEBUG, "about to read (fd=%d, len=%zu)", usb_transport->bulk_out, len);
ret = bulk_read(usb_transport->bulk_out, data, len);
if (ret < 0) {
D(ERR, "ERROR: fd = %d, ret = %zd", usb_transport->bulk_out, ret);
return -1;
}
D(DEBUG, "[ usb_read done fd=%d ret=%zd]", usb_transport->bulk_out, ret);
return ret;
}
void usb_close(struct transport_handle *thandle)
{
int err;
struct transport *t = thandle->transport;
struct usb_transport *usb_transport = container_of(t, struct usb_transport, transport);
err = ioctl(usb_transport->bulk_in, FUNCTIONFS_CLEAR_HALT);
if (err < 0)
D(WARN, "[ kick: source (fd=%d) clear halt failed (%d) ]", usb_transport->bulk_in, errno);
err = ioctl(usb_transport->bulk_out, FUNCTIONFS_CLEAR_HALT);
if (err < 0)
D(WARN, "[ kick: sink (fd=%d) clear halt failed (%d) ]", usb_transport->bulk_out, errno);
pthread_mutex_lock(&usb_transport->lock);
close(usb_transport->control);
close(usb_transport->bulk_out);
close(usb_transport->bulk_in);
usb_transport->control = usb_transport->bulk_out = usb_transport->bulk_in = -1;
pthread_cond_signal(&usb_transport->notify);
pthread_mutex_unlock(&usb_transport->lock);
}
struct transport_handle *usb_connect(struct transport *transport)
{
int ret;
struct usb_handle *usb_handle = calloc(sizeof(struct usb_handle), 1);
struct usb_transport *usb_transport = container_of(transport, struct usb_transport, transport);
pthread_mutex_lock(&usb_transport->lock);
while (usb_transport->control != -1)
pthread_cond_wait(&usb_transport->notify, &usb_transport->lock);
pthread_mutex_unlock(&usb_transport->lock);
ret = init_functionfs(usb_transport);
if (ret < 0) {
D(ERR, "usb connect: failed to initialize usb transport");
return NULL;
}
D(DEBUG, "[ usb_thread - registering device ]");
return &usb_handle->handle;
}
void usb_init()
{
struct usb_transport *usb_transport = calloc(1, sizeof(struct usb_transport));
usb_transport->transport.connect = usb_connect;
usb_transport->transport.close = usb_close;
usb_transport->transport.read = usb_read;
usb_transport->transport.write = usb_write;
usb_transport->control = -1;
usb_transport->bulk_out = -1;
usb_transport->bulk_out = -1;
pthread_cond_init(&usb_transport->notify, NULL);
pthread_mutex_init(&usb_transport->lock, NULL);
transport_register(&usb_transport->transport);
}

View file

@ -1,262 +0,0 @@
/*
* 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 <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/ioctl.h>
#include <linux/fs.h>
#include <stdlib.h>
#include <string.h>
#include <cutils/properties.h>
#include "utils.h"
#include "debug.h"
#ifndef BLKDISCARD
#define BLKDISCARD _IO(0x12,119)
#endif
#ifndef BLKSECDISCARD
#define BLKSECDISCARD _IO(0x12,125)
#endif
#define READ_BUF_SIZE (16*1024)
int get_stream_size(FILE *stream) {
int size;
fseek(stream, 0, SEEK_END);
size = ftell(stream);
fseek(stream, 0, SEEK_SET);
return size;
}
uint64_t get_block_device_size(int fd)
{
uint64_t size = 0;
int ret;
ret = ioctl(fd, BLKGETSIZE64, &size);
if (ret)
return 0;
return size;
}
uint64_t get_file_size(int fd)
{
struct stat buf;
int ret;
int64_t computed_size;
ret = fstat(fd, &buf);
if (ret)
return 0;
if (S_ISREG(buf.st_mode))
computed_size = buf.st_size;
else if (S_ISBLK(buf.st_mode))
computed_size = get_block_device_size(fd);
else
computed_size = 0;
return computed_size;
}
uint64_t get_file_size64(int fd)
{
struct stat64 buf;
int ret;
uint64_t computed_size;
ret = fstat64(fd, &buf);
if (ret)
return 0;
if (S_ISREG(buf.st_mode))
computed_size = buf.st_size;
else if (S_ISBLK(buf.st_mode))
computed_size = get_block_device_size(fd);
else
computed_size = 0;
return computed_size;
}
char *strip(char *str)
{
int n;
n = strspn(str, " \t");
str += n;
n = strcspn(str, " \t");
str[n] = '\0';
return str;
}
int wipe_block_device(int fd, int64_t len)
{
uint64_t range[2];
int ret;
range[0] = 0;
range[1] = len;
ret = ioctl(fd, BLKSECDISCARD, &range);
if (ret < 0) {
range[0] = 0;
range[1] = len;
ret = ioctl(fd, BLKDISCARD, &range);
if (ret < 0) {
D(WARN, "Discard failed\n");
return 1;
} else {
D(WARN, "Wipe via secure discard failed, used discard instead\n");
return 0;
}
}
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=%zu 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=%zu 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=%zu n=%zu length=%zu",
ret, to_read, n, length);
break;
}
}
return n;
}
#define NAP_TIME 200 // 200 ms between polls
static int wait_for_property(const char *name, const char *desired_value, int maxwait)
{
char value[PROPERTY_VALUE_MAX] = {'\0'};
int maxnaps = (maxwait * 1000) / NAP_TIME;
if (maxnaps < 1) {
maxnaps = 1;
}
while (maxnaps-- > 0) {
usleep(NAP_TIME * 1000);
if (property_get(name, value, NULL)) {
if (desired_value == NULL || strcmp(value, desired_value) == 0) {
return 0;
}
}
}
return -1; /* failure */
}
int service_start(const char *service_name)
{
int result = 0;
char property_value[PROPERTY_VALUE_MAX];
property_get(service_name, property_value, "");
if (strcmp("running", property_value) != 0) {
D(INFO, "Starting %s", service_name);
property_set("ctl.start", service_name);
if (wait_for_property(service_name, "running", 5))
result = -1;
}
return result;
}
int service_stop(const char *service_name)
{
int result = 0;
D(INFO, "Stopping MDNSD");
property_set("ctl.stop", service_name);
if (wait_for_property(service_name, "stopped", 5))
result = -1;
return result;
}
int ssh_server_start()
{
return service_start("sshd");
}

View file

@ -1,56 +0,0 @@
/*
* 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 _FASTBOOT_UTILS_H
#define _FASTBOOT_UTILS_H
#include <stdio.h>
int get_stream_size(FILE *);
char *strip(char *str);
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);
int service_start(const char *service_name);
int service_stop(const char *service_name);
int ssh_server_start();
#define ROUND_TO_PAGE(address,pagesize) ((address + pagesize - 1) & (~(pagesize - 1)))
#define ROUND_UP(number,size) (((number + size - 1) / size) * size)
#endif

View file

@ -1,69 +0,0 @@
/*
* 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 __VENDOR_TRIGGER_H_
#define __VENDOR_TRIGGER_H_
__BEGIN_DECLS
struct GPT_entry_raw;
struct GPT_content;
/*
* Implemented in libvendortrigger to handle platform-specific behavior.
*/
/*
* trigger_init() is called once at startup time before calling any other method
*
* returns 0 on success and nonzero on error
*/
int trigger_init(void);
/*
* This function runs once after trigger_init completes.
*
* version is number parameter indicating version on the fastbootd side
* libversion is version indicateing version of the library version
*
* returns 0 if it can cooperate with the current version and 1 in opposite
*/
int trigger_check_version(const int version, int *libversion);
/*
* Return value -1 forbid the action from the vendor site and sets errno
*/
int trigger_gpt_layout(struct GPT_content *);
int trigger_oem_cmd(const char *arg, const char **response);
__END_DECLS
#endif

View file

@ -1,58 +0,0 @@
/*
* 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 <cutils/klog.h>
#include <vendor_trigger.h>
static const int version = 1;
int trigger_init(void) {
klog_init();
klog_set_level(7);
return 0;
}
int trigger_check_version(const int fastboot_version, int *libversion) {
KLOG_DEBUG("fastbootd", "%s: %d (%d)", __func__, fastboot_version, version);
*libversion = version;
return !(fastboot_version == version);
}
int trigger_gpt_layout(struct GPT_content *table) {
KLOG_DEBUG("fastbootd", "%s: %p", __func__, table);
return 0;
}
int trigger_oem_cmd(const char *arg, const char **response __unused) {
KLOG_DEBUG("fastbootd", "%s: %s", __func__, arg);
return 0;
}