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 = ""; 31static char *hd_id; 32 33static char *board_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 ": %s\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" -i <file> read input from the file <file>\n" 61" -o <file> write output to the file <file>\n" 62" -v <version> set image version to <version>\n" 63" -r <region> set image region to <region>\n" 64" -H <hd_id> set image hardware id to <hd_id>\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 pos, rem, 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:i:o:v:r:H:h"); 89 if (c == -1) 90 break; 91 92 switch (c) { 93 case 'B': 94 board_id = optarg; 95 break; 96 case 'i': 97 ifname = optarg; 98 break; 99 case 'o': 100 ofname = optarg; 101 break; 102 case 'v': 103 version = optarg; 104 break; 105 case 'r': 106 region = optarg; 107 break; 108 case 'H': 109 hd_id = 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 (ifname == NULL) { 126 ERR("no input file specified"); 127 goto err; 128 } 129 130 if (ofname == NULL) { 131 ERR("no output file specified"); 132 goto err; 133 } 134 135 err = stat(ifname, &st); 136 if (err){ 137 ERRS("stat failed on %s", ifname); 138 goto err; 139 } 140 141 buflen = st.st_size + DNI_HDR_LEN + 1; 142 buf = malloc(buflen); 143 if (!buf) { 144 ERR("no memory for buffer\n"); 145 goto err; 146 } 147 148 memset(buf, 0, DNI_HDR_LEN); 149 pos = snprintf(buf, DNI_HDR_LEN, "device:%s\nversion:V%s\nregion:%s\n", 150 board_id, version, region); 151 rem = DNI_HDR_LEN - pos; 152 if (pos >= 0 && rem > 1 && hd_id) { 153 snprintf(buf + pos, rem, "hd_id:%s\n", hd_id); 154 } 155 156 infile = fopen(ifname, "r"); 157 if (infile == NULL) { 158 ERRS("could not open \"%s\" for reading", ifname); 159 goto err_free; 160 } 161 162 errno = 0; 163 fread(buf + DNI_HDR_LEN, st.st_size, 1, infile); 164 if (errno != 0) { 165 ERRS("unable to read from file %s", ifname); 166 goto err_close_in; 167 } 168 169 csum = 0; 170 for (i = 0; i < (st.st_size + DNI_HDR_LEN); i++) 171 csum += buf[i]; 172 173 csum = 0xff - csum; 174 buf[st.st_size + DNI_HDR_LEN] = csum; 175 176 outfile = fopen(ofname, "w"); 177 if (outfile == NULL) { 178 ERRS("could not open \"%s\" for writing", ofname); 179 goto err_close_in; 180 } 181 182 errno = 0; 183 fwrite(buf, buflen, 1, outfile); 184 if (errno) { 185 ERRS("unable to write to file %s", ofname); 186 goto err_close_out; 187 } 188 189 res = EXIT_SUCCESS; 190 191 out_flush: 192 fflush(outfile); 193 194 err_close_out: 195 fclose(outfile); 196 if (res != EXIT_SUCCESS) { 197 unlink(ofname); 198 } 199 200 err_close_in: 201 fclose(infile); 202 203 err_free: 204 free(buf); 205 206 err: 207 return res; 208} 209