1/* 2 * Copyright (C) 2009 Gabor Juhos <juhosg@openwrt.org> 3 * 4 * This program is free software; you can redistribute it and/or modify it 5 * under the terms of the GNU General Public License version 2 as published 6 * by the Free Software Foundation. 7 * 8 */ 9 10#include <stdio.h> 11#include <stdlib.h> 12#include <stdint.h> 13#include <string.h> 14#include <unistd.h> /* for unlink() */ 15#include <libgen.h> 16#include <getopt.h> /* for getopt() */ 17#include <stdarg.h> 18#include <errno.h> 19#include <sys/stat.h> 20 21#define DNI_HDR_LEN 128 22 23/* 24 * Globals 25 */ 26static char *ifname; 27static char *progname; 28static char *ofname; 29static char *version = "1.00.00"; 30static char *region ="NA"; 31 32static char *board_id; 33static char *hw_id; 34/* 35 * Message macros 36 */ 37#define ERR(fmt, ...) do { \ 38 fflush(0); \ 39 fprintf(stderr, "[%s] *** error: " fmt "\n", \ 40 progname, ## __VA_ARGS__ ); \ 41} while (0) 42 43#define ERRS(fmt, ...) do { \ 44 int save = errno; \ 45 fflush(0); \ 46 fprintf(stderr, "[%s] *** error: " fmt "\n", \ 47 progname, ## __VA_ARGS__, strerror(save)); \ 48} while (0) 49 50void usage(int status) 51{ 52 FILE *stream = (status != EXIT_SUCCESS) ? stderr : stdout; 53 struct board_info *board; 54 55 fprintf(stream, "Usage: %s [OPTIONS...]\n", progname); 56 fprintf(stream, 57"\n" 58"Options:\n" 59" -B <board> create image for the board specified with <board>\n" 60" -H <hw_id> set image hardware id to <hw_id>\n" 61" -i <file> read input from the file <file>\n" 62" -o <file> write output to the file <file>\n" 63" -v <version> set image version to <version>\n" 64" -r <region> set image region to <region>\n" 65" -h show this screen\n" 66 ); 67 68 exit(status); 69} 70 71int main(int argc, char *argv[]) 72{ 73 int res = EXIT_FAILURE; 74 int buflen; 75 int err; 76 struct stat st; 77 char *buf; 78 int i; 79 uint8_t csum; 80 81 FILE *outfile, *infile; 82 83 progname = basename(argv[0]); 84 85 while ( 1 ) { 86 int c; 87 88 c = getopt(argc, argv, "B:H:i:o:v:r:h"); 89 if (c == -1) 90 break; 91 92 switch (c) { 93 case 'B': 94 board_id = optarg; 95 break; 96 case 'H': 97 hw_id = optarg; 98 break; 99 case 'i': 100 ifname = optarg; 101 break; 102 case 'o': 103 ofname = optarg; 104 break; 105 case 'v': 106 version = optarg; 107 break; 108 case 'r': 109 region = optarg; 110 break; 111 case 'h': 112 usage(EXIT_SUCCESS); 113 break; 114 default: 115 usage(EXIT_FAILURE); 116 break; 117 } 118 } 119 120 if (board_id == NULL) { 121 ERR("no board specified"); 122 goto err; 123 } 124 125 if (hw_id == NULL) { 126 ERR("no hardware specified"); 127 goto err; 128 } 129 130 if (ifname == NULL) { 131 ERR("no input file specified"); 132 goto err; 133 } 134 135 if (ofname == NULL) { 136 ERR("no output file specified"); 137 goto err; 138 } 139 140 err = stat(ifname, &st); 141 if (err){ 142 ERRS("stat failed on %s", ifname); 143 goto err; 144 } 145 146 buflen = st.st_size + DNI_HDR_LEN + 1; 147 buf = malloc(buflen); 148 if (!buf) { 149 ERR("no memory for buffer\n"); 150 goto err; 151 } 152 153 memset(buf, 0, DNI_HDR_LEN); 154 snprintf(buf, DNI_HDR_LEN, "device:%s\nversion:%s\nregion:%s\nhd_id:%s\n", 155 board_id, version, region, hw_id); 156 157 infile = fopen(ifname, "r"); 158 if (infile == NULL) { 159 ERRS("could not open \"%s\" for reading", ifname); 160 goto err_free; 161 } 162 163 errno = 0; 164 fread(buf + DNI_HDR_LEN, st.st_size, 1, infile); 165 if (errno != 0) { 166 ERRS("unable to read from file %s", ifname); 167 goto err_close_in; 168 } 169 170 csum = 0; 171 for (i = 0; i < (st.st_size + DNI_HDR_LEN); i++) 172 csum += buf[i]; 173 174 csum = 0xff - csum; 175 buf[st.st_size + DNI_HDR_LEN] = csum; 176 177 outfile = fopen(ofname, "w"); 178 if (outfile == NULL) { 179 ERRS("could not open \"%s\" for writing", ofname); 180 goto err_close_in; 181 } 182 183 errno = 0; 184 fwrite(buf, buflen, 1, outfile); 185 if (errno) { 186 ERRS("unable to write to file %s", ofname); 187 goto err_close_out; 188 } 189 190 res = EXIT_SUCCESS; 191 192 out_flush: 193 fflush(outfile); 194 195 err_close_out: 196 fclose(outfile); 197 if (res != EXIT_SUCCESS) { 198 unlink(ofname); 199 } 200 201 err_close_in: 202 fclose(infile); 203 204 err_free: 205 free(buf); 206 207 err: 208 return res; 209} 210