package/mtd: add fixtrx command
[openwrt-10.03/.git] / package / mtd / src / trx.c
1 /*
2  * trx.c
3  *
4  * Copyright (C) 2005 Mike Baker
5  * Copyright (C) 2008 Felix Fietkau <nbd@openwrt.org>
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
20  */
21
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <stddef.h>
25 #include <unistd.h>
26 #include <fcntl.h>
27 #include <sys/mman.h>
28 #include <sys/stat.h>
29 #include <string.h>
30
31 #include <sys/ioctl.h>
32 #include "mtd-api.h"
33 #include "mtd.h"
34 #include "crc32.h"
35
36 #define TRX_MAGIC       0x30524448      /* "HDR0" */
37 struct trx_header {
38         unsigned magic;         /* "HDR0" */
39         unsigned len;           /* Length of file including header */
40         unsigned crc32;         /* 32-bit CRC from flag_version to end of file */
41         unsigned flag_version;  /* 0:15 flags, 16:31 version */
42         unsigned offsets[3];    /* Offsets of partitions from start of header */
43 };
44
45 int
46 trx_fixup(int fd, const char *name)
47 {
48         struct mtd_info_user mtdInfo;
49         unsigned long len;
50         struct trx_header *trx;
51         void *ptr, *scan;
52         int bfd;
53
54         if (ioctl(fd, MEMGETINFO, &mtdInfo) < 0) {
55                 fprintf(stderr, "Failed to get mtd info\n");
56                 goto err;
57         }
58
59         len = mtdInfo.size;
60         if (mtdInfo.size <= 0) {
61                 fprintf(stderr, "Invalid MTD device size\n");
62                 goto err;
63         }
64
65         bfd = mtd_open(name, true);
66         ptr = mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_SHARED, bfd, 0);
67         if (!ptr || (ptr == (void *) -1)) {
68                 perror("mmap");
69                 goto err1;
70         }
71
72         trx = ptr;
73         if (trx->magic != TRX_MAGIC) {
74                 fprintf(stderr, "TRX header not found\n");
75                 goto err;
76         }
77
78         scan = ptr + offsetof(struct trx_header, flag_version);
79         trx->crc32 = crc32buf(scan, trx->len - (scan - ptr));
80         msync(ptr, sizeof(struct trx_header), MS_SYNC|MS_INVALIDATE);
81         munmap(ptr, len);
82         close(bfd);
83         return 0;
84
85 err1:
86         close(bfd);
87 err:
88         fprintf(stderr, "Error fixing up TRX header\n");
89         return -1;
90 }
91
92 int
93 trx_check(int imagefd, const char *mtd, char *buf, int *len)
94 {
95         const struct trx_header *trx = (const struct trx_header *) buf;
96         int fd;
97
98         if (strcmp(mtd, "linux") != 0)
99                 return 1;
100
101         *len = read(imagefd, buf, 32);
102         if (*len < 32) {
103                 fprintf(stdout, "Could not get image header, file too small (%d bytes)\n", *len);
104                 return 0;
105         }
106
107         if (trx->magic != TRX_MAGIC || trx->len < sizeof(struct trx_header)) {
108                 if (quiet < 2) {
109                         fprintf(stderr, "Bad trx header\n");
110                         fprintf(stderr, "This is not the correct file format; refusing to flash.\n"
111                                         "Please specify the correct file or use -f to force.\n");
112                 }
113                 return 0;
114         }
115
116         /* check if image fits to mtd device */
117         fd = mtd_check_open(mtd);
118         if(fd < 0) {
119                 fprintf(stderr, "Could not open mtd device: %s\n", mtd);
120                 exit(1);
121         }
122
123         if(mtdsize < trx->len) {
124                 fprintf(stderr, "Image too big for partition: %s\n", mtd);
125                 close(fd);
126                 return 0;
127         }
128
129         close(fd);
130         return 1;
131 }
132