1/* 2 * bt3cfw.c 3 * 4 * Copyright (c) 2001 Maksim Yevmenkin <m_evmenkin@yahoo.com> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 * 28 * $Id: bt3cfw.c,v 1.2 2003/05/21 22:40:29 max Exp $ 29 * $FreeBSD$ 30 */ 31 32#include <sys/types.h> 33#include <errno.h> 34#include <netgraph.h> 35#include <netgraph/bluetooth/include/ng_bt3c.h> 36#include <stdarg.h> 37#include <stdio.h> 38#include <stdlib.h> 39#include <string.h> 40#include <syslog.h> 41#include <unistd.h> 42 43#define BT3CFW_IDENT "bt3cfw" 44#define BT3CFW_MAX_FIRMWARE_SIZE 0xffff 45 46/* Convert hex ASCII to int4 */ 47static int 48hexa2int4(const char *a) 49{ 50 if ('0' <= *a && *a <= '9') 51 return (*a - '0'); 52 53 if ('A' <= *a && *a <= 'F') 54 return (*a - 'A' + 0xa); 55 56 if ('a' <= *a && *a <= 'f') 57 return (*a - 'a' + 0xa); 58 59 syslog(LOG_ERR, "Invalid hex character: '%c' (%#x)", *a, *a); 60 exit(255); 61} 62 63/* Convert hex ASCII to int8 */ 64static int 65hexa2int8(const char *a) 66{ 67 return ((hexa2int4(a) << 4) | hexa2int4(a + 1)); 68} 69 70/* Convert hex ASCII to int16 */ 71static int 72hexa2int16(const char *a) 73{ 74 return ((hexa2int8(a) << 8) | hexa2int8(a + 2)); 75} 76 77/* Convert hex ASCII to int32 */ 78static int 79hexa2int32(const char *a) 80{ 81 return ((hexa2int16(a) << 16) | hexa2int16(a + 4)); 82} 83 84/* Display usage() and exit */ 85static void 86usage(void) 87{ 88 syslog(LOG_ERR, "Usage: %s -f FirmwareFile -n NodeName", BT3CFW_IDENT); 89 exit(255); 90} 91 92/* Main */ 93int 94main(int argc, char *argv[]) 95{ 96 FILE *firmware_file = NULL; 97 char buffer[80], path[NG_PATHSIZ], 98 *firmware_filename = NULL; 99 uint8_t *firmware = NULL; 100 int firmware_size, opt, cs, ds; 101 102 memset(path, 0, sizeof(path)); 103 openlog(BT3CFW_IDENT, LOG_NDELAY|LOG_PID|LOG_PERROR, LOG_USER); 104 105 while ((opt = getopt(argc, argv, "f:hn:")) != -1) { 106 switch (opt) { 107 case 'f': 108 firmware_filename = optarg; 109 break; 110 111 case 'n': 112 snprintf(path, sizeof(path), "%s:", optarg); 113 break; 114 115 case 'h': 116 default: 117 usage(); 118 /* NOT REACHED */ 119 } 120 } 121 122 if (firmware_filename == NULL || path[0] == 0) 123 usage(); 124 /* NOT REACHED */ 125 126 firmware = (uint8_t *) calloc(BT3CFW_MAX_FIRMWARE_SIZE, 127 sizeof(uint8_t)); 128 if (firmware == NULL) { 129 syslog(LOG_ERR, "Could not allocate firmware buffer"); 130 exit(255); 131 } 132 133 if ((firmware_file = fopen(firmware_filename, "r")) == NULL) { 134 syslog(LOG_ERR, "Could not open BT3C firmware file %s. %s (%d)", 135 firmware_filename, strerror(errno), errno); 136 exit(255); 137 } 138 139 firmware_size = 0; 140 141 while (fgets(buffer, sizeof(buffer), firmware_file)) { 142 int i, size, address, cs, fcs; 143 144 size = hexa2int8(buffer + 2); 145 address = hexa2int32(buffer + 4); 146 fcs = hexa2int8(buffer + 2 + size * 2); 147 148 if (buffer[1] == '3') { 149 ng_bt3c_firmware_block_ep *block = NULL; 150 uint16_t *data = NULL; 151 152 block = (ng_bt3c_firmware_block_ep *) 153 (firmware + firmware_size); 154 155 firmware_size += sizeof(*block); 156 if (firmware_size >= BT3CFW_MAX_FIRMWARE_SIZE) { 157 syslog(LOG_ERR, "Could not add new firmware " \ 158 "block. Firmware file %s is " \ 159 "too big, firmware_size=%d", 160 firmware_filename, 161 firmware_size); 162 exit(255); 163 } 164 165 block->block_address = address; 166 block->block_size = (size - 4) / 2; 167 block->block_alignment = (block->block_size * 2) % 3; 168 if (block->block_alignment != 0) 169 block->block_alignment = 3 - block->block_alignment; 170 171 firmware_size += (block->block_size * 2); 172 firmware_size += block->block_alignment; 173 if (firmware_size >= BT3CFW_MAX_FIRMWARE_SIZE) { 174 syslog(LOG_ERR, "Could not add new firmware " \ 175 "data. Firmware file %s is " \ 176 "too big, firmware_size=%d", 177 firmware_filename, 178 firmware_size); 179 exit(255); 180 } 181 182 /* First part of the cheksum: size and address */ 183 cs = 0; 184 for (i = 0; i < 5; i++) 185 cs += hexa2int8(buffer + 2 + i * 2); 186 187 /* Data + second part of the cheksum: data */ 188 data = (uint16_t *)(block + 1); 189 for (i = 0; i < block->block_size; i++) { 190 data[i] = hexa2int16(buffer + (i * 4) + 12); 191 cs += (((data[i] & 0xff00) >> 8) & 0xff); 192 cs += (data[i] & 0x00ff); 193 } 194 } else 195 for (cs = 0, i = 0; i < size; i++) 196 cs += hexa2int8(buffer + 2 + i * 2); 197 198 if (((cs + fcs) & 0xff) != 0xff) { 199 syslog(LOG_ERR, "Invalid firmware file %s. Checksum " \ 200 "error, cs=%#x, fcs=%#x, checksum=%#x", 201 firmware_filename, (cs & 0xff), fcs, 202 ((cs + fcs) & 0xff)); 203 exit(255); 204 } 205 } 206 207 /* Send firmware to the card */ 208 if (NgMkSockNode(NULL, &cs, &ds) < 0) { 209 syslog(LOG_ERR, "Could not create Netgraph socket. %s (%d)", 210 strerror(errno), errno); 211 exit(255); 212 } 213 214 if (NgSendMsg(cs, path, NGM_BT3C_COOKIE, 215 NGM_BT3C_NODE_DOWNLOAD_FIRMWARE, 216 (void const *) firmware, firmware_size) < 0) { 217 syslog(LOG_ERR, "Could not send Netgraph message. %s (%d)", 218 strerror(errno), errno); 219 exit(255); 220 } 221 222 free(firmware); 223 firmware = NULL; 224 fclose(firmware_file); 225 226 return (0); 227} 228 229