Merge "Remove fastbootd."
This commit is contained in:
commit
d170bb035d
35 changed files with 0 additions and 4986 deletions
|
@ -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)
|
|
@ -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
|
|
@ -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");
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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 */
|
||||
|
|
@ -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
|
|
@ -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
|
||||
|
|
@ -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, §or_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, §or_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;
|
||||
}
|
||||
|
|
@ -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
|
|
@ -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");
|
||||
}
|
||||
}
|
|
@ -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
|
|
@ -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);
|
||||
}
|
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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
|
|
@ -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");
|
||||
}
|
|
@ -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
|
|
@ -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);
|
||||
}
|
|
@ -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
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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");
|
||||
}
|
|
@ -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
|
|
@ -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
|
|
@ -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;
|
||||
}
|
Loading…
Reference in a new issue