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 #define TAGVER_LEN 4 /* Length of Tag Version */
40 #define TAGLAYOUT_LEN 4 /* Length of FlashLayoutVer */
41 #define SIG1_LEN 20 /* Company Signature 1 Length */
42 #define SIG2_LEN 14 /* Company Signature 2 Length */
43 #define BOARDID_LEN 16 /* Length of BoardId */
44 #define ENDIANFLAG_LEN 2 /* Endian Flag Length */
45 #define CHIPID_LEN 6 /* Chip Id Length */
46 #define IMAGE_LEN 10 /* Length of Length Field */
47 #define ADDRESS_LEN 12 /* Length of Address field */
48 #define DUALFLAG_LEN 2 /* Dual Image flag Length */
49 #define INACTIVEFLAG_LEN 2 /* Inactie Flag Length */
50 #define RSASIG_LEN 20 /* Length of RSA Signature in tag */
51 #define TAGINFO1_LEN 30 /* Length of vendor information field1 in tag */
52 #define FLASHLAYOUTVER_LEN 4 /* Length of Flash Layout Version String tag */
53 #define TAGINFO2_LEN 16 /* Length of vendor information field2 in tag */
54 #define ALTTAGINFO_LEN 54 /* Alternate length for vendor information; Pirelli */
57 #define IMAGETAG_CRC_START 0xFFFFFFFF
59 #define PIRELLI_BOARDS { \
64 * The broadcom firmware assumes the rootfs starts the image,
65 * therefore uses the rootfs start (flash_image_address)
66 * to determine where to flash the image. Since we have the kernel first
67 * we have to give it the kernel address, but the crc uses the length
68 * associated with this address (root_length), which is added to the kernel
69 * length (kernel_length) to determine the length of image to flash and thus
70 * needs to be rootfs + deadcode (jffs2 EOF marker)
74 /* 0-3: Version of the image tag */
75 char tag_version
[TAGVER_LEN
];
76 /* 4-23: Company Line 1 */
78 /* 24-37: Company Line 2 */
80 /* 38-43: Chip this image is for */
81 char chip_id
[CHIPID_LEN
];
82 /* 44-59: Board name */
83 char board_id
[BOARDID_LEN
];
84 /* 60-61: Map endianness -- 1 BE 0 LE */
85 char big_endian
[ENDIANFLAG_LEN
];
86 /* 62-71: Total length of image */
87 char total_length
[IMAGE_LEN
];
88 /* 72-83: Address in memory of CFE */
89 char cfe__address
[ADDRESS_LEN
];
90 /* 84-93: Size of CFE */
91 char cfe_length
[IMAGE_LEN
];
92 /* 94-105: Address in memory of image start
93 * (kernel for OpenWRT, rootfs for stock firmware)
95 char flash_image_start
[ADDRESS_LEN
];
96 /* 106-115: Size of rootfs */
97 char root_length
[IMAGE_LEN
];
98 /* 116-127: Address in memory of kernel */
99 char kernel_address
[ADDRESS_LEN
];
100 /* 128-137: Size of kernel */
101 char kernel_length
[IMAGE_LEN
];
102 /* 138-139: Unused at the moment */
103 char dual_image
[DUALFLAG_LEN
];
104 /* 140-141: Unused at the moment */
105 char inactive_flag
[INACTIVEFLAG_LEN
];
106 /* 142-161: RSA Signature (not used; some vendors may use this) */
107 char rsa_signature
[RSASIG_LEN
];
108 /* 162-191: Compilation and related information (not used in OpenWrt) */
109 char information1
[TAGINFO1_LEN
];
110 /* 192-195: Version flash layout */
111 char flash_layout_ver
[FLASHLAYOUTVER_LEN
];
112 /* 196-199: kernel+rootfs CRC32 */
114 /* 200-215: Unused except on Alice Gate where is is information */
115 char information2
[TAGINFO2_LEN
];
116 /* 216-219: CRC32 of image less imagetag (kernel for Alice Gate) */
118 /* 220-223: CRC32 of rootfs partition */
120 /* 224-227: CRC32 of kernel partition */
122 /* 228-231: Image sequence number */
123 char image_sequence
[4];
124 /* 222-235: Openwrt: real rootfs length */
125 __u32 real_rootfs_length
;
126 /* 236-239: CRC32 of header excluding last 20 bytes */
128 /* 240-255: Unused at present */
131 ssize_t
pread(int fd
, void *buf
, size_t count
, off_t offset
);
132 ssize_t
pwrite(int fd
, const void *buf
, size_t count
, off_t offset
);
134 #define CRC_START 0xFFFFFFFF
136 static uint32_t strntoul(char *str
, char **endptr
, int base
, size_t len
) {
140 newstr
= calloc(len
+ 1, sizeof(char));
142 strncpy(newstr
, str
, len
);
143 res
= strtoul(newstr
, endptr
, base
);
149 uint32_t compute_crc32(uint32_t crc
, off_t start
, size_t compute_len
, int fd
)
151 uint8_t readbuf
[1024];
153 off_t offset
= start
;
155 /* Read a buffer's worth of bytes */
156 while (fd
&& (compute_len
>= sizeof(readbuf
))) {
157 res
= pread(fd
, readbuf
, sizeof(readbuf
), offset
);
158 crc
= crc32(crc
, readbuf
, res
);
159 compute_len
= compute_len
- res
;
163 /* Less than buffer-size bytes remains, read compute_len bytes */
164 if (fd
&& (compute_len
> 0)) {
165 res
= pread(fd
, readbuf
, compute_len
, offset
);
166 crc
= crc32(crc
, readbuf
, res
);
173 trx_fixup(int fd
, const char *name
)
175 struct mtd_info_user mtdInfo
;
181 uint32_t cfelen
, imagelen
, imagestart
, rootfslen
;
182 uint32_t imagecrc
, rootfscrc
, headercrc
;
184 cfelen
= imagelen
= imagestart
= imagecrc
= rootfscrc
= headercrc
= rootfslen
= 0;
187 if (ioctl(fd
, MEMGETINFO
, &mtdInfo
) < 0) {
188 fprintf(stderr
, "Failed to get mtd info\n");
193 if (mtdInfo
.size
<= 0) {
194 fprintf(stderr
, "Invalid MTD device size\n");
198 bfd
= mtd_open(name
, true);
199 ptr
= mmap(NULL
, len
, PROT_READ
|PROT_WRITE
, MAP_SHARED
, bfd
, 0);
200 if (!ptr
|| (ptr
== (void *) -1)) {
205 tag
= (struct bcm_tag
*) (ptr
);
207 cfelen
= strntoul(&tag
->cfe_length
[0], NULL
, 10, IMAGE_LEN
);
209 fprintf(stderr
, "Non-zero CFE length. This is currently unsupported.\n");
213 headercrc
= compute_crc32(CRC_START
, offset
, offsetof(struct bcm_tag
, header_crc
), fd
);
214 if (headercrc
!= *(uint32_t *)(&tag
->header_crc
)) {
215 fprintf(stderr
, "Tag verify failed. This may not be a valid image.\n");
219 sprintf(&tag
->root_length
[0], "%u", 0);
220 strncpy(&tag
->total_length
[0], &tag
->kernel_length
[0], IMAGE_LEN
);
222 imagestart
= sizeof(tag
);
223 memcpy(&tag
->image_crc
, &tag
->kernel_crc
, sizeof(uint32_t));
224 memcpy(&tag
->fskernel_crc
, &tag
->kernel_crc
, sizeof(uint32_t));
225 rootfscrc
= CRC_START
;
226 memcpy(&tag
->rootfs_crc
, &rootfscrc
, sizeof(uint32_t));
227 headercrc
= crc32(CRC_START
, tag
, offsetof(struct bcm_tag
, header_crc
));
228 memcpy(&tag
->header_crc
, &headercrc
, sizeof(uint32_t));
230 msync(ptr
, sizeof(struct bcm_tag
), MS_SYNC
|MS_INVALIDATE
);
238 fprintf(stderr
, "Error fixing up imagetag header\n");
244 trx_check(int imagefd
, const char *mtd
, char *buf
, int *len
)
246 struct bcm_tag
*tag
= (const struct bcm_tag
*) buf
;
251 if (strcmp(mtd
, "linux") != 0)
254 *len
= read(imagefd
, buf
, sizeof(struct bcm_tag
));
255 if (*len
< sizeof(struct bcm_tag
)) {
256 fprintf(stdout
, "Could not get image header, file too small (%d bytes)\n", *len
);
259 headerCRC
= crc32buf(buf
, offsetof(struct bcm_tag
, header_crc
));
260 if (*(uint32_t *)(&tag
->header_crc
) != headerCRC
) {
263 fprintf(stderr
, "Bad header CRC got %08x, calculated %08x\n",
264 *(uint32_t *)(&tag
->header_crc
), headerCRC
);
265 fprintf(stderr
, "This is not the correct file format; refusing to flash.\n"
266 "Please specify the correct file or use -f to force.\n");
271 /* check if image fits to mtd device */
272 fd
= mtd_check_open(mtd
);
274 fprintf(stderr
, "Could not open mtd device: %s\n", mtd
);
278 imageLen
= strntoul(&tag
->total_length
[0], NULL
, 10, IMAGE_LEN
);
280 if(mtdsize
< imageLen
) {
281 fprintf(stderr
, "Image too big for partition: %s\n", mtd
);
291 mtd_fixtrx(const char *mtd
, size_t offset
)
298 uint32_t cfelen
, imagelen
, imagestart
, rootfslen
;
299 uint32_t imagecrc
, rootfscrc
, headercrc
;
300 cfelen
= imagelen
= imagestart
= imagecrc
= rootfscrc
= headercrc
= rootfslen
= 0;
303 fprintf(stderr
, "Trying to fix trx header in %s at 0x%x...\n", mtd
, offset
);
305 block_offset
= offset
& ~(erasesize
- 1);
306 offset
-= block_offset
;
308 fd
= mtd_check_open(mtd
);
310 fprintf(stderr
, "Could not open mtd device: %s\n", mtd
);
314 if (block_offset
+ erasesize
> mtdsize
) {
315 fprintf(stderr
, "Offset too large, device size 0x%x\n", mtdsize
);
319 buf
= malloc(erasesize
);
325 res
= pread(fd
, buf
, erasesize
, block_offset
);
326 if (res
!= erasesize
) {
331 tag
= (struct bcm_tag
*) (buf
+ offset
);
333 cfelen
= strntoul(tag
->cfe_length
, NULL
, 10, IMAGE_LEN
);
335 fprintf(stderr
, "Non-zero CFE length. This is currently unsupported.\n");
340 fprintf(stderr
, "Verifying we actually have an imagetag.\n");
343 headercrc
= compute_crc32(CRC_START
, offset
, offsetof(struct bcm_tag
, header_crc
), fd
);
344 if (headercrc
!= *(uint32_t *)(&tag
->header_crc
)) {
345 fprintf(stderr
, "Tag verify failed. This may not be a valid image.\n");
350 fprintf(stderr
, "Checking current fixed status.\n");
353 rootfslen
= strntoul(&tag
->root_length
[0], NULL
, 10, IMAGE_LEN
);
354 if (rootfslen
== 0) {
356 fprintf(stderr
, "Header already fixed, exiting\n");
362 fprintf(stderr
, "Setting root length to 0.\n");
365 sprintf(&tag
->root_length
[0], "%u", 0);
366 strncpy(&tag
->total_length
[0], &tag
->kernel_length
[0], IMAGE_LEN
);
369 fprintf(stderr
, "Recalculating CRCs.\n");
372 imagestart
= sizeof(tag
);
373 memcpy(&tag
->image_crc
, &tag
->kernel_crc
, sizeof(uint32_t));
374 memcpy(&tag
->fskernel_crc
, &tag
->kernel_crc
, sizeof(uint32_t));
375 rootfscrc
= CRC_START
;
376 memcpy(&tag
->rootfs_crc
, &rootfscrc
, sizeof(uint32_t));
377 headercrc
= crc32(CRC_START
, tag
, offsetof(struct bcm_tag
, header_crc
));
378 memcpy(&tag
->header_crc
, &headercrc
, sizeof(uint32_t));
381 fprintf(stderr
, "Erasing imagetag block\n");
384 if (mtd_erase_block(fd
, block_offset
)) {
385 fprintf(stderr
, "Can't erase block at 0x%x (%s)\n", block_offset
, strerror(errno
));
390 fprintf(stderr
, "New image crc32: 0x%x, rewriting block\n",
391 *(uint32_t *)(&tag
->image_crc
));
392 fprintf(stderr
, "New header crc32: 0x%x, rewriting block\n", headercrc
);
395 if (pwrite(fd
, buf
, erasesize
, block_offset
) != erasesize
) {
396 fprintf(stderr
, "Error writing block (%s)\n", strerror(errno
));
401 fprintf(stderr
, "Done.\n");