4 * Copyright (C) 2005 Mike Baker
5 * Copyright (C) 2008 Felix Fietkau <nbd@openwrt.org>
6 * Copyrigth (C) 2010 Daniel Dickinson <openwrt@cshore.neomailbox.net>
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
33 #include <sys/ioctl.h>
34 #include <mtd/mtd-user.h>
39 ssize_t
pread(int fd
, void *buf
, size_t count
, off_t offset
);
40 ssize_t
pwrite(int fd
, const void *buf
, size_t count
, off_t offset
);
42 #define CRC_START 0xFFFFFFFF
44 static uint32_t strntoul(char *str
, char **endptr
, int base
, size_t len
) {
48 newstr
= calloc(len
+ 1, sizeof(char));
50 strncpy(newstr
, str
, len
);
51 res
= strtoul(newstr
, endptr
, base
);
57 uint32_t compute_crc32(uint32_t crc
, off_t start
, size_t compute_len
, int fd
)
59 uint8_t readbuf
[1024];
63 /* Read a buffer's worth of bytes */
64 while (fd
&& (compute_len
>= sizeof(readbuf
))) {
65 res
= pread(fd
, readbuf
, sizeof(readbuf
), offset
);
66 crc
= crc32(crc
, readbuf
, res
);
67 compute_len
= compute_len
- res
;
71 /* Less than buffer-size bytes remains, read compute_len bytes */
72 if (fd
&& (compute_len
> 0)) {
73 res
= pread(fd
, readbuf
, compute_len
, offset
);
74 crc
= crc32(crc
, readbuf
, res
);
81 trx_fixup(int fd
, const char *name
)
83 struct mtd_info_user mtdInfo
;
89 uint32_t cfelen
, imagelen
, imagestart
, rootfslen
;
90 uint32_t imagecrc
, rootfscrc
, headercrc
;
92 cfelen
= imagelen
= imagestart
= imagecrc
= rootfscrc
= headercrc
= rootfslen
= 0;
95 if (ioctl(fd
, MEMGETINFO
, &mtdInfo
) < 0) {
96 fprintf(stderr
, "Failed to get mtd info\n");
101 if (mtdInfo
.size
<= 0) {
102 fprintf(stderr
, "Invalid MTD device size\n");
106 bfd
= mtd_open(name
, true);
107 ptr
= mmap(NULL
, len
, PROT_READ
|PROT_WRITE
, MAP_SHARED
, bfd
, 0);
108 if (!ptr
|| (ptr
== (void *) -1)) {
113 tag
= (struct bcm_tag
*) (ptr
);
115 cfelen
= strntoul(&tag
->cfeLength
[0], NULL
, 10, IMAGE_LEN
);
117 fprintf(stderr
, "Non-zero CFE length. This is currently unsupported.\n");
121 headercrc
= compute_crc32(CRC_START
, offset
, offsetof(struct bcm_tag
, headerCRC
), fd
);
122 if (headercrc
!= *(uint32_t *)(&tag
->headerCRC
[0])) {
123 fprintf(stderr
, "Tag verify failed. This may not be a valid image.\n");
127 sprintf(&tag
->flashRootLength
[0], "%lu", 0);
128 strncpy(&tag
->totalLength
[0], &tag
->kernelLength
[0], IMAGE_LEN
);
130 imagestart
= sizeof(tag
);
131 memcpy(&tag
->imageCRC
[0], &tag
->kernelCRC
[0], CRC_LEN
);
132 memcpy(&tag
->fskernelCRC
[0], &tag
->kernelCRC
[0], CRC_LEN
);
133 rootfscrc
= CRC_START
;
134 memcpy(&tag
->rootfsCRC
[0], &rootfscrc
, sizeof(uint32_t));
135 headercrc
= crc32(CRC_START
, tag
, offsetof(struct bcm_tag
, headerCRC
));
136 memcpy(&tag
->headerCRC
[0], &headercrc
, sizeof(uint32_t));
138 msync(ptr
, sizeof(struct bcm_tag
), MS_SYNC
|MS_INVALIDATE
);
146 fprintf(stderr
, "Error fixing up imagetag header\n");
152 trx_check(int imagefd
, const char *mtd
, char *buf
, int *len
)
154 struct bcm_tag
*tag
= (const struct bcm_tag
*) buf
;
159 if (strcmp(mtd
, "linux") != 0)
162 *len
= read(imagefd
, buf
, sizeof(struct bcm_tag
));
163 if (*len
< sizeof(struct bcm_tag
)) {
164 fprintf(stdout
, "Could not get image header, file too small (%d bytes)\n", *len
);
167 headerCRC
= crc32buf(buf
, offsetof(struct bcm_tag
, headerCRC
));
168 if (*(uint32_t *)(&tag
->headerCRC
[0]) != headerCRC
) {
171 fprintf(stderr
, "Bad header CRC got %08lx, calculated %08lx\n",
172 *(uint32_t *)(&tag
->headerCRC
[0]), headerCRC
);
173 fprintf(stderr
, "This is not the correct file format; refusing to flash.\n"
174 "Please specify the correct file or use -f to force.\n");
179 /* check if image fits to mtd device */
180 fd
= mtd_check_open(mtd
);
182 fprintf(stderr
, "Could not open mtd device: %s\n", mtd
);
186 imageLen
= strntoul(&tag
->totalLength
[0], NULL
, 10, IMAGE_LEN
);
188 if(mtdsize
< imageLen
) {
189 fprintf(stderr
, "Image too big for partition: %s\n", mtd
);
199 mtd_fixtrx(const char *mtd
, size_t offset
)
206 uint32_t cfelen
, imagelen
, imagestart
, rootfslen
;
207 uint32_t imagecrc
, rootfscrc
, headercrc
;
208 cfelen
= imagelen
= imagestart
= imagecrc
= rootfscrc
= headercrc
= rootfslen
= 0;
211 fprintf(stderr
, "Trying to fix trx header in %s at 0x%x...\n", mtd
, offset
);
213 block_offset
= offset
& ~(erasesize
- 1);
214 offset
-= block_offset
;
216 fd
= mtd_check_open(mtd
);
218 fprintf(stderr
, "Could not open mtd device: %s\n", mtd
);
222 if (block_offset
+ erasesize
> mtdsize
) {
223 fprintf(stderr
, "Offset too large, device size 0x%x\n", mtdsize
);
227 buf
= malloc(erasesize
);
233 res
= pread(fd
, buf
, erasesize
, block_offset
);
234 if (res
!= erasesize
) {
239 tag
= (struct bcm_tag
*) (buf
+ offset
);
241 cfelen
= strntoul(&tag
->cfeLength
[0], NULL
, 10, IMAGE_LEN
);
243 fprintf(stderr
, "Non-zero CFE length. This is currently unsupported.\n");
248 fprintf(stderr
, "Verifying we actually have an imagetag.\n");
251 headercrc
= compute_crc32(CRC_START
, offset
, offsetof(struct bcm_tag
, headerCRC
), fd
);
252 if (headercrc
!= *(uint32_t *)(&tag
->headerCRC
[0])) {
253 fprintf(stderr
, "Tag verify failed. This may not be a valid image.\n");
258 fprintf(stderr
, "Checking current fixed status.\n");
261 rootfslen
= strntoul(&tag
->flashRootLength
[0], NULL
, 10, IMAGE_LEN
);
262 if (rootfslen
== 0) {
264 fprintf(stderr
, "Header already fixed, exiting\n");
270 fprintf(stderr
, "Setting root length to 0.\n");
273 sprintf(&tag
->flashRootLength
[0], "%lu", 0);
274 strncpy(&tag
->totalLength
[0], &tag
->kernelLength
[0], IMAGE_LEN
);
277 fprintf(stderr
, "Recalculating CRCs.\n");
280 imagestart
= sizeof(tag
);
281 memcpy(&tag
->imageCRC
[0], &tag
->kernelCRC
[0], CRC_LEN
);
282 memcpy(&tag
->fskernelCRC
[0], &tag
->kernelCRC
[0], CRC_LEN
);
283 rootfscrc
= CRC_START
;
284 memcpy(&tag
->rootfsCRC
[0], &rootfscrc
, sizeof(uint32_t));
285 headercrc
= crc32(CRC_START
, tag
, offsetof(struct bcm_tag
, headerCRC
));
286 memcpy(&tag
->headerCRC
[0], &headercrc
, sizeof(uint32_t));
289 fprintf(stderr
, "Erasing imagetag block\n");
292 if (mtd_erase_block(fd
, block_offset
)) {
293 fprintf(stderr
, "Can't erase block at 0x%x (%s)\n", block_offset
, strerror(errno
));
298 fprintf(stderr
, "New image crc32: 0x%x, rewriting block\n",
299 *(uint32_t *)(&tag
->imageCRC
[0]));
300 fprintf(stderr
, "New header crc32: 0x%x, rewriting block\n", headercrc
);
303 if (pwrite(fd
, buf
, erasesize
, block_offset
) != erasesize
) {
304 fprintf(stderr
, "Error writing block (%s)\n", strerror(errno
));
309 fprintf(stderr
, "Done.\n");
This page took 0.072011 seconds and 5 git commands to generate.