1a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross/* 2a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross * Copyright (c) 2009-2013, Google Inc. 3a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross * All rights reserved. 4a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross * 5a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross * Redistribution and use in source and binary forms, with or without 6a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross * modification, are permitted provided that the following conditions 7a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross * are met: 8a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross * * Redistributions of source code must retain the above copyright 9a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross * notice, this list of conditions and the following disclaimer. 10a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross * * Redistributions in binary form must reproduce the above copyright 11a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross * notice, this list of conditions and the following disclaimer in 12a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross * the documentation and/or other materials provided with the 13a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross * distribution. 14a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross * * Neither the name of Google, Inc. nor the names of its contributors 15a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross * may be used to endorse or promote products derived from this 16a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross * software without specific prior written permission. 17a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross * 18a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 21a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 22a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 23a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 24a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 25a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 26a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 28a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross * SUCH DAMAGE. 30a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross */ 31a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross 32a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross#include <stddef.h> 33a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross#include <stdio.h> 34a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross#include <stdlib.h> 35a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross#include <string.h> 36a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross 37a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross#include "debug.h" 38a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross#include "protocol.h" 39a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross#include "transport.h" 40a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross 41a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross#define STATE_OFFLINE 0 42a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross#define STATE_COMMAND 1 43a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross#define STATE_COMPLETE 2 44a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross#define STATE_ERROR 3 45a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross 46a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Crossstruct fastboot_cmd { 47a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross struct fastboot_cmd *next; 48a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross const char *prefix; 49a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross unsigned prefix_len; 50a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross void (*execute)(struct protocol_handle *phandle, const char *arg); 51a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross}; 52a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross 53a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Crossstruct fastboot_var { 54a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross struct fastboot_var *next; 55a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross const char *name; 56a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross const char *value; 57a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross}; 58a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross 59a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Crossstatic struct fastboot_cmd *cmdlist; 60a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross 61a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Crossvoid fastboot_register(const char *prefix, 62a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross void (*phandle)(struct protocol_handle *phandle, const char *arg)) 63a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross{ 64a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross struct fastboot_cmd *cmd; 65a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross cmd = malloc(sizeof(*cmd)); 66a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross if (cmd) { 67a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross cmd->prefix = prefix; 68a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross cmd->prefix_len = strlen(prefix); 69a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross cmd->execute = phandle; 70a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross cmd->next = cmdlist; 71a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross cmdlist = cmd; 72a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross } 73a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross} 74a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross 75a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Crossstatic struct fastboot_var *varlist; 76a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross 77a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Crossvoid fastboot_publish(const char *name, const char *value) 78a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross{ 79a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross struct fastboot_var *var; 80a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross var = malloc(sizeof(*var)); 81a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross if (var) { 82a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross var->name = name; 83a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross var->value = value; 84a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross var->next = varlist; 85a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross varlist = var; 86a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross } 87a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross} 88a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross 89a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Crossconst char *fastboot_getvar(const char *name) 90a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross{ 91a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross struct fastboot_var *var; 92a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross 93a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross for (var = varlist; var; var = var->next) { 94a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross if (!strcmp(var->name, name)) { 95a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross return var->value; 96a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross } 97a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross } 98a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross 99a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross return ""; 100a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross} 101a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross 102a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Crossint protocol_handle_download(struct protocol_handle *phandle, size_t len) 103a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross{ 104a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross return transport_handle_download(phandle->transport_handle, len); 105a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross} 106a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross 107a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Crossstatic ssize_t protocol_handle_write(struct protocol_handle *phandle, 108a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross char *buffer, size_t len) 109a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross{ 110a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross return transport_handle_write(phandle->transport_handle, buffer, len); 111a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross} 112a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross 113a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Crossstatic void fastboot_ack(struct protocol_handle *phandle, const char *code, 114a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross const char *reason) 115a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross{ 116a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross char response[64]; 117a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross 118a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross if (phandle->state != STATE_COMMAND) 119a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross return; 120a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross 121a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross if (reason == 0) 122a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross reason = ""; 123a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross 124a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross snprintf(response, 64, "%s%s", code, reason); 125a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross phandle->state = STATE_COMPLETE; 126a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross 127a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross protocol_handle_write(phandle, response, strlen(response)); 128a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross} 129a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross 130a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Crossvoid fastboot_fail(struct protocol_handle *phandle, const char *reason) 131a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross{ 132a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross fastboot_ack(phandle, "FAIL", reason); 133a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross} 134a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross 135a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Crossvoid fastboot_okay(struct protocol_handle *phandle, const char *info) 136a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross{ 137a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross fastboot_ack(phandle, "OKAY", info); 138a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross} 139a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross 140a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Crossvoid fastboot_data(struct protocol_handle *phandle, size_t len) 141a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross{ 142a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross char response[64]; 143a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross ssize_t ret; 144a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross 145a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross snprintf(response, 64, "DATA%08x", len); 146a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross ret = protocol_handle_write(phandle, response, strlen(response)); 147a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross if (ret < 0) 148a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross return; 149a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross} 150a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross 151a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Crossvoid protocol_handle_command(struct protocol_handle *phandle, char *buffer) 152a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross{ 153a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross D(INFO,"fastboot: %s\n", buffer); 154a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross 155a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross struct fastboot_cmd *cmd; 156a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross 157a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross for (cmd = cmdlist; cmd; cmd = cmd->next) { 158a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross if (memcmp(buffer, cmd->prefix, cmd->prefix_len)) 159a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross continue; 160a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross phandle->state = STATE_COMMAND; 161a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross cmd->execute(phandle, buffer + cmd->prefix_len); 162a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross if (phandle->state == STATE_COMMAND) 163a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross fastboot_fail(phandle, "unknown reason"); 164a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross return; 165a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross } 166a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross 167a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross fastboot_fail(phandle, "unknown command"); 168a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross} 169a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross 170a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Crossstruct protocol_handle *create_protocol_handle(struct transport_handle *thandle) 171a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross{ 172a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross struct protocol_handle *phandle; 173a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross 174a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross phandle = calloc(sizeof(struct protocol_handle), 1); 175a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross 176a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross phandle->transport_handle = thandle; 177a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross phandle->state = STATE_OFFLINE; 178a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross phandle->download_fd = -1; 179a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross 180a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross pthread_mutex_init(&phandle->lock, NULL); 181a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross 182a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross return phandle; 183a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross} 184a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross 185a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Crossint protocol_get_download(struct protocol_handle *phandle) 186a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross{ 187a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross int fd; 188a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross 189a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross pthread_mutex_lock(&phandle->lock); 190a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross fd = phandle->download_fd; 191a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross phandle->download_fd = -1; 192a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross pthread_mutex_unlock(&phandle->lock); 193a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross 194a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross return fd; 195a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross} 196