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>
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_check(int imagefd
, const char *mtd
, char *buf
, int *len
)
83 struct bcm_tag
*tag
= (const struct bcm_tag
*) buf
;
88 if (strcmp(mtd
, "linux") != 0)
91 *len
= read(imagefd
, buf
, sizeof(struct bcm_tag
));
92 if (*len
< sizeof(struct bcm_tag
)) {
93 fprintf(stdout
, "Could not get image header, file too small (%d bytes)\n", *len
);
96 headerCRC
= crc32buf(buf
, offsetof(struct bcm_tag
, headerCRC
));
97 if (*(uint32_t *)(&tag
->headerCRC
[0]) != headerCRC
) {
100 fprintf(stderr
, "Bad header CRC got %08lx, calculated %08lx\n",
101 *(uint32_t *)(&tag
->headerCRC
[0]), headerCRC
);
102 fprintf(stderr
, "This is not the correct file format; refusing to flash.\n"
103 "Please specify the correct file or use -f to force.\n");
108 /* check if image fits to mtd device */
109 fd
= mtd_check_open(mtd
);
111 fprintf(stderr
, "Could not open mtd device: %s\n", mtd
);
115 imageLen
= strntoul(&tag
->totalLength
[0], NULL
, 10, IMAGE_LEN
);
117 if(mtdsize
< imageLen
) {
118 fprintf(stderr
, "Image too big for partition: %s\n", mtd
);
128 mtd_fixtrx(const char *mtd
, size_t offset
)
135 uint32_t cfelen
, imagelen
, imagestart
, rootfslen
;
136 uint32_t imagecrc
, rootfscrc
, headercrc
;
137 cfelen
= imagelen
= imagestart
= imagecrc
= rootfscrc
= headercrc
= rootfslen
= 0;
140 fprintf(stderr
, "Trying to fix trx header in %s at 0x%x...\n", mtd
, offset
);
142 block_offset
= offset
& ~(erasesize
- 1);
143 offset
-= block_offset
;
145 fd
= mtd_check_open(mtd
);
147 fprintf(stderr
, "Could not open mtd device: %s\n", mtd
);
151 if (block_offset
+ erasesize
> mtdsize
) {
152 fprintf(stderr
, "Offset too large, device size 0x%x\n", mtdsize
);
156 buf
= malloc(erasesize
);
162 res
= pread(fd
, buf
, erasesize
, block_offset
);
163 if (res
!= erasesize
) {
168 tag
= (struct bcm_tag
*) (buf
+ offset
);
170 cfelen
= strntoul(&tag
->cfeLength
[0], NULL
, 10, IMAGE_LEN
);
172 fprintf(stderr
, "Non-zero CFE length. This is currently unsupported.\n");
177 fprintf(stderr
, "Verifying we actually have an imagetag.\n");
180 headercrc
= compute_crc32(CRC_START
, offset
, offsetof(struct bcm_tag
, headerCRC
), fd
);
181 if (headercrc
!= *(uint32_t *)(&tag
->headerCRC
[0])) {
182 fprintf(stderr
, "Tag verify failed. This may not be a valid image.\n");
187 fprintf(stderr
, "Checking current fixed status.\n");
190 rootfslen
= strntoul(&tag
->rootLength
[0], NULL
, 10, IMAGE_LEN
);
191 if (rootfslen
== 0) {
193 fprintf(stderr
, "Header already fixed, exiting\n");
199 fprintf(stderr
, "Setting root length to 0.\n");
202 sprintf(&tag
->rootLength
[0], "%lu", 0);
203 strncpy(&tag
->totalLength
[0], &tag
->kernelLength
[0], IMAGE_LEN
);
206 fprintf(stderr
, "Recalculating CRCs.\n");
209 imagestart
= sizeof(tag
);
210 memcpy(&tag
->imageCRC
[0], &tag
->kernelCRC
[0], CRC_LEN
);
211 memcpy(&tag
->fskernelCRC
[0], &tag
->kernelCRC
[0], CRC_LEN
);
212 rootfscrc
= CRC_START
;
213 memcpy(&tag
->rootfsCRC
[0], &rootfscrc
, sizeof(uint32_t));
214 headercrc
= crc32(CRC_START
, tag
, offsetof(struct bcm_tag
, headerCRC
));
215 memcpy(&tag
->headerCRC
[0], &headercrc
, sizeof(uint32_t));
218 fprintf(stderr
, "Erasing imagetag block\n");
221 if (mtd_erase_block(fd
, block_offset
)) {
222 fprintf(stderr
, "Can't erase block at 0x%x (%s)\n", block_offset
, strerror(errno
));
227 fprintf(stderr
, "New image crc32: 0x%x, rewriting block\n",
228 *(uint32_t *)(&tag
->imageCRC
[0]));
229 fprintf(stderr
, "New header crc32: 0x%x, rewriting block\n", headercrc
);
232 if (pwrite(fd
, buf
, erasesize
, block_offset
) != erasesize
) {
233 fprintf(stderr
, "Error writing block (%s)\n", strerror(errno
));
238 fprintf(stderr
, "Done.\n");
This page took 0.070714 seconds and 5 git commands to generate.