Root/qiboot/tools/mkudfu.c

1/*
2 * USB DFU file trailer tool
3 * (C) Copyright by OpenMoko, Inc.
4 * Author: Harald Welte <laforge@openmoko.org>
5 *
6 * based on mkimage.c, copyright information as follows:
7 *
8 * (C) Copyright 2000-2004
9 * DENX Software Engineering
10 * Wolfgang Denk, wd@denx.de
11 * All rights reserved.
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License as
15 * published by the Free Software Foundation; either version 2 of
16 * the License, or (at your option) any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
26 * MA 02111-1307 USA
27 */
28
29#include <errno.h>
30#include <fcntl.h>
31#include <stdio.h>
32#include <stdlib.h>
33#include <string.h>
34#ifndef __WIN32__
35#include <netinet/in.h> /* for host / network byte order conversions */
36#endif
37#include <sys/mman.h>
38#include <sys/stat.h>
39#include <time.h>
40#include <unistd.h>
41
42#if defined(__BEOS__) || defined(__NetBSD__) || defined(__APPLE__)
43#include <inttypes.h>
44#endif
45
46#ifdef __WIN32__
47typedef unsigned int __u32;
48
49#define SWAP_LONG(x) \
50    ((__u32)( \
51        (((__u32)(x) & (__u32)0x000000ffUL) << 24) | \
52        (((__u32)(x) & (__u32)0x0000ff00UL) << 8) | \
53        (((__u32)(x) & (__u32)0x00ff0000UL) >> 8) | \
54        (((__u32)(x) & (__u32)0xff000000UL) >> 24) ))
55typedef unsigned char uint8_t;
56typedef unsigned short uint16_t;
57typedef unsigned int uint32_t;
58
59#define ntohl(a) SWAP_LONG(a)
60#define htonl(a) SWAP_LONG(a)
61#endif /* __WIN32__ */
62
63#ifndef O_BINARY /* should be define'd on __WIN32__ */
64#define O_BINARY 0
65#endif
66
67#include "usb_dfu_trailer.h"
68
69extern int errno;
70
71#ifndef MAP_FAILED
72#define MAP_FAILED (-1)
73#endif
74
75static char *cmdname;
76
77static char *datafile;
78static char *imagefile;
79
80
81static void usage()
82{
83    fprintf (stderr, "%s - create / display u-boot DFU trailer\n", cmdname);
84    fprintf (stderr, "Usage: %s -l image\n"
85             " -l ==> list image header information\n"
86             " %s -v VID -p PID -r REV -d data_file image\n",
87        cmdname, cmdname);
88    fprintf (stderr, " -v ==> set vendor ID to 'VID'\n"
89             " -p ==> set product ID system to 'PID'\n"
90             " -r ==> set hardware revision to 'REV'\n"
91             " -d ==> use 'data_file' as input file\n"
92        );
93    exit (EXIT_FAILURE);
94}
95
96static void print_trailer(struct uboot_dfu_trailer *trailer)
97{
98    printf("===> DFU Trailer information:\n");
99    printf("Trailer Vers.: %d\n", trailer->version);
100    printf("Trailer Length: %d\n", trailer->length);
101    printf("VendorID: 0x%04x\n", trailer->vendor);
102    printf("ProductID: 0x%04x\n", trailer->product);
103    printf("HW Revision: 0x%04x\n", trailer->revision);
104}
105
106static void copy_file (int ifd, const char *datafile, int pad)
107{
108    int dfd;
109    struct stat sbuf;
110    unsigned char *ptr;
111    int tail;
112    int zero = 0;
113    int offset = 0;
114    int size;
115
116    if ((dfd = open(datafile, O_RDONLY|O_BINARY)) < 0) {
117        fprintf (stderr, "%s: Can't open %s: %s\n",
118            cmdname, datafile, strerror(errno));
119        exit (EXIT_FAILURE);
120    }
121
122    if (fstat(dfd, &sbuf) < 0) {
123        fprintf (stderr, "%s: Can't stat %s: %s\n",
124            cmdname, datafile, strerror(errno));
125        exit (EXIT_FAILURE);
126    }
127
128    ptr = (unsigned char *)mmap(0, sbuf.st_size,
129                    PROT_READ, MAP_SHARED, dfd, 0);
130    if (ptr == (unsigned char *)MAP_FAILED) {
131        fprintf (stderr, "%s: Can't read %s: %s\n",
132            cmdname, datafile, strerror(errno));
133        exit (EXIT_FAILURE);
134    }
135
136    size = sbuf.st_size - offset;
137    if (write(ifd, ptr + offset, size) != size) {
138        fprintf (stderr, "%s: Write error on %s: %s\n",
139            cmdname, imagefile, strerror(errno));
140        exit (EXIT_FAILURE);
141    }
142
143    if (pad && ((tail = size % 4) != 0)) {
144
145        if (write(ifd, (char *)&zero, 4-tail) != 4-tail) {
146            fprintf (stderr, "%s: Write error on %s: %s\n",
147                cmdname, imagefile, strerror(errno));
148            exit (EXIT_FAILURE);
149        }
150    }
151
152    (void) munmap((void *)ptr, sbuf.st_size);
153    (void) close (dfd);
154}
155
156
157int main(int argc, char **argv)
158{
159    int ifd;
160    int lflag = 0;
161    struct stat sbuf;
162    u_int16_t opt_vendor, opt_product, opt_revision;
163    struct uboot_dfu_trailer _hdr, _mirror, *hdr = &_hdr;
164
165    opt_vendor = opt_product = opt_revision = 0;
166
167    cmdname = *argv;
168
169    while (--argc > 0 && **++argv == '-') {
170        while (*++*argv) {
171            switch (**argv) {
172            case 'l':
173                lflag = 1;
174                break;
175            case 'v':
176                if (--argc <= 0)
177                    usage ();
178                opt_vendor = strtoul(*++argv, NULL, 16);
179                goto NXTARG;
180            case 'p':
181                if (--argc <= 0)
182                    usage ();
183                opt_product = strtoul(*++argv, NULL, 16);
184                goto NXTARG;
185            case 'r':
186                if (--argc <= 0)
187                    usage ();
188                opt_revision = strtoul(*++argv, NULL, 16);
189                goto NXTARG;
190            case 'd':
191                if (--argc <= 0)
192                    usage ();
193                datafile = *++argv;
194                goto NXTARG;
195            case 'h':
196                usage();
197                break;
198            default:
199                usage();
200            }
201        }
202NXTARG: ;
203    }
204
205    if (argc != 1)
206        usage();
207
208    imagefile = *argv;
209
210    if (lflag)
211        ifd = open(imagefile, O_RDONLY|O_BINARY);
212    else
213        ifd = open(imagefile, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, 0666);
214
215    if (ifd < 0) {
216        fprintf (stderr, "%s: Can't open %s: %s\n",
217            cmdname, imagefile, strerror(errno));
218        exit (EXIT_FAILURE);
219    }
220
221    if (lflag) {
222        unsigned char *ptr;
223        /* list header information of existing image */
224        if (fstat(ifd, &sbuf) < 0) {
225            fprintf (stderr, "%s: Can't stat %s: %s\n",
226                cmdname, imagefile, strerror(errno));
227            exit (EXIT_FAILURE);
228        }
229
230        if ((unsigned)sbuf.st_size < sizeof(struct uboot_dfu_trailer)) {
231            fprintf (stderr,
232                "%s: Bad size: \"%s\" is no valid image\n",
233                cmdname, imagefile);
234            exit (EXIT_FAILURE);
235        }
236
237        ptr = (unsigned char *)mmap(0, sbuf.st_size,
238                        PROT_READ, MAP_SHARED, ifd, 0);
239        if ((caddr_t)ptr == (caddr_t)-1) {
240            fprintf (stderr, "%s: Can't read %s: %s\n",
241                cmdname, imagefile, strerror(errno));
242            exit (EXIT_FAILURE);
243        }
244
245        dfu_trailer_mirror(hdr, ptr+sbuf.st_size);
246
247        if (hdr->magic != UBOOT_DFU_TRAILER_MAGIC) {
248            fprintf (stderr,
249                "%s: Bad Magic Number: \"%s\" is no valid image\n",
250                cmdname, imagefile);
251            exit (EXIT_FAILURE);
252        }
253
254        /* for multi-file images we need the data part, too */
255        print_trailer(hdr);
256
257        (void) munmap((void *)ptr, sbuf.st_size);
258        (void) close (ifd);
259
260        exit (EXIT_SUCCESS);
261    }
262
263    /* if we're not listing: */
264
265    copy_file (ifd, datafile, 0);
266
267    memset (hdr, 0, sizeof(struct uboot_dfu_trailer));
268
269    /* Build new header */
270    hdr->version = UBOOT_DFU_TRAILER_V1;
271    hdr->magic = UBOOT_DFU_TRAILER_MAGIC;
272    hdr->length = sizeof(struct uboot_dfu_trailer);
273    hdr->vendor = opt_vendor;
274    hdr->product = opt_product;
275    hdr->revision = opt_revision;
276
277    print_trailer(hdr);
278    dfu_trailer_mirror(&_mirror, (unsigned char *)hdr+sizeof(*hdr));
279
280    if (write(ifd, &_mirror, sizeof(struct uboot_dfu_trailer))
281                    != sizeof(struct uboot_dfu_trailer)) {
282        fprintf (stderr, "%s: Write error on %s: %s\n",
283            cmdname, imagefile, strerror(errno));
284        exit (EXIT_FAILURE);
285    }
286
287    /* We're a bit of paranoid */
288#if defined(_POSIX_SYNCHRONIZED_IO) && !defined(__sun__) && !defined(__FreeBSD__)
289    (void) fdatasync (ifd);
290#else
291    (void) fsync (ifd);
292#endif
293
294    if (fstat(ifd, &sbuf) < 0) {
295        fprintf (stderr, "%s: Can't stat %s: %s\n",
296            cmdname, imagefile, strerror(errno));
297        exit (EXIT_FAILURE);
298    }
299
300    /* We're a bit of paranoid */
301#if defined(_POSIX_SYNCHRONIZED_IO) && !defined(__sun__) && !defined(__FreeBSD__)
302    (void) fdatasync (ifd);
303#else
304    (void) fsync (ifd);
305#endif
306
307    if (close(ifd)) {
308        fprintf (stderr, "%s: Write error on %s: %s\n",
309            cmdname, imagefile, strerror(errno));
310        exit (EXIT_FAILURE);
311    }
312
313    exit (EXIT_SUCCESS);
314}
315

Archive Download this file



interactive