New upstream release.
Debian Janitor
2 years ago
4 | 4 | * Detect device from asic id |
5 | 5 | |
6 | 6 | disk: |
7 | * Support for flashing mmc images | |
8 | 7 | * Badblock checking |
9 | 8 | |
10 | 9 | fiasco: |
14 | 13 | * Support for Harmattan images |
15 | 14 | |
16 | 15 | local: |
17 | * Support for flashing (on device) | |
18 | 16 | * Write versions |
19 | 17 | * Badblock checking |
20 | 18 |
0 | 0xffff (0.10-1) UNRELEASED; urgency=low | |
1 | ||
2 | * New upstream release. | |
3 | ||
4 | -- Debian Janitor <janitor@jelmer.uk> Sat, 29 Jan 2022 02:53:30 -0000 | |
5 | ||
0 | 6 | 0xffff (0.9-1) unstable; urgency=medium |
1 | 7 | |
2 | 8 | [ Debian Janitor ] |
29 | 29 | For dumping mtd partition is used tool nanddump. Here is example how to dump |
30 | 30 | kernel image without padding to file zImage: |
31 | 31 | |
32 | $ nanddump -o -b -s 0x00000800 -l 0x001FF800 -f zImage /dev/mtd2 | |
32 | $ nanddump --omitoob -s 0x00000800 -l 0x001FF800 -f zImage /dev/mtd2 | |
33 | 33 | |
34 | 34 | Params means: |
35 | -o - "Omit oob data" | |
36 | -b - "Omit bad blocks" | |
35 | --omitoob - "Omit oob data" | |
37 | 36 | -s - "Start address" |
38 | 37 | -l - "Length" |
39 | 38 | -f - "Output file" |
37 | 37 | |
38 | 38 | 1 byte = 0x54 -- signature |
39 | 39 | 1 byte -- number of subsection blocks |
40 | (start of data block) | |
41 | 1 byte -- type of subsection block (data - always 0x2e) | |
42 | 1 byte -- length of subsection block (data - always 25) | |
43 | 3 bytes -- unknown (always 0x01 0x01 0x00) | |
40 | block { | |
41 | 1 byte -- type of subsection block | |
42 | 0x2E - file data | |
43 | 0x2F - partition info | |
44 | 0x31 - version | |
45 | 0x32 - device & hw revisions (size of device is 16, hw revision 8) | |
46 | 0x33 - layout | |
47 | 0x34 - image data part block (one block for one data part) | |
48 | 1 byte -- length of subsection block | |
49 | N bytes -- subsection block data | |
50 | } | |
51 | 1 byte -- checksum of subsection data without signature (0xFF - xorpair) | |
52 | N bytes -- image data | |
53 | ||
54 | ||
55 | FILE DATA BLOCK | |
56 | ||
57 | 1 byte -- asic index (always APE - 0x01) | |
58 | 1 byte -- device type (always NAND - 0x01) | |
59 | 1 byte -- device index (always 0x00) | |
44 | 60 | 2 bytes -- checksum for the image contents (xorpair) (big endian) |
45 | 61 | 12 bytes -- image name type (first byte is FF if is the last image) |
46 | 62 | 4 bytes -- length of image data (big endian) |
63 | 4 bytes -- load address of image data (big endian, unused always zero) | |
64 | ||
65 | ||
66 | PARTITION INFO BLOCK | |
67 | ||
68 | N bytes -- unknown | |
69 | ||
70 | ||
71 | IMAGE DATA PART BLOCK | |
72 | ||
47 | 73 | 4 bytes -- unknown (always 0x00 0x00 0x00 0x00) |
48 | (end of data block) | |
49 | block { | |
50 | 1 byte -- type of subsection block | |
51 | '1' - version | |
52 | '2' - device & hw revisions (size of device is 16, hw revision 8) | |
53 | '3' - layout | |
54 | '4' - unknown | |
55 | '/' - unknown | |
56 | 1 byte -- length of subsection block | |
57 | N bytes -- subsection block data | |
58 | } | |
59 | 1 byte -- unknown (0x00 is accepted, maybe end of subsections?) | |
60 | N bytes -- image data | |
74 | 4 bytes -- offset (big endian) | |
75 | 4 bytes -- unknown (always 0x00 0x00 0x00 0x00) | |
76 | 4 bytes -- size (big endian) | |
77 | N bytes -- partition name (prefix) in layout (may be omitted) | |
78 | ||
79 | ||
80 | LAYOUT DATA BLOCK | |
81 | ||
82 | N bytes of text data, e.g.: | |
83 | ||
84 | mmc { | |
85 | name = "internal"; | |
86 | partition { | |
87 | fs_type = "vfat"; | |
88 | prefix = "mydocs"; | |
89 | no_create = true; | |
90 | } | |
91 | partition { | |
92 | size = 2048; | |
93 | fs_type = "ext3"; | |
94 | prefix = "home"; | |
95 | } | |
96 | partition { | |
97 | size = 768; | |
98 | fs_type = "swap"; | |
99 | } | |
100 | } |
183 | 183 | continue; |
184 | 184 | } |
185 | 185 | |
186 | for ( i = 0; device_first->hwrevs[i] != -1; ++i ) | |
187 | if ( device_first->hwrevs[i] >= 0 && device_first->hwrevs[i] <= 9999 ) | |
188 | ++local; | |
186 | if ( device_first->hwrevs ) { | |
187 | for ( i = 0; device_first->hwrevs[i] != -1; ++i ) | |
188 | if ( device_first->hwrevs[i] >= 0 && device_first->hwrevs[i] <= 9999 ) | |
189 | ++local; | |
190 | } | |
189 | 191 | |
190 | 192 | size += (1+16+(MAX_HWREVS+1)*8)*(local/MAX_HWREVS+1); |
191 | 193 | count += local/MAX_HWREVS; |
214 | 216 | continue; |
215 | 217 | } |
216 | 218 | |
217 | while ( device_first->hwrevs[i+1] != -1 ) { | |
219 | do { | |
218 | 220 | |
219 | 221 | uint8_t len = 0; |
220 | 222 | ret[j] = ++last_ptr; |
227 | 229 | |
228 | 230 | for ( k = 0; k < MAX_HWREVS; ++k ) { |
229 | 231 | |
230 | if ( device_first->hwrevs[i+1] == -1 ) | |
232 | if ( ! device_first->hwrevs || device_first->hwrevs[i+1] == -1 ) | |
231 | 233 | break; |
232 | 234 | |
233 | 235 | ++i; |
245 | 247 | |
246 | 248 | ++j; |
247 | 249 | |
248 | } | |
250 | } while ( device_first->hwrevs && device_first->hwrevs[i+1] != -1 ); | |
249 | 251 | |
250 | 252 | device_first = device_first->next; |
251 | 253 |
117 | 117 | |
118 | 118 | blkdev[len] = 0; |
119 | 119 | |
120 | fd = open(blkdev, (readonly ? O_RDONLY : O_RDWR) | O_EXCL | O_NONBLOCK); | |
120 | fd = open(blkdev, ((simulate || readonly) ? O_RDONLY : O_RDWR) | O_EXCL | O_NONBLOCK); | |
121 | 121 | if ( fd < 0 ) { |
122 | 122 | ERROR_INFO("Cannot open block device %s", blkdev); |
123 | 123 | return -1; |
143 | 143 | ERROR("Block device name is too long"); |
144 | 144 | return -1; |
145 | 145 | } |
146 | fd = open(blkdev, (readonly ? O_RDONLY : O_RDWR) | O_EXCL); | |
146 | fd = open(blkdev, ((simulate || readonly) ? O_RDONLY : O_RDWR) | O_EXCL); | |
147 | 147 | if ( fd < 0 && errno == ENOENT ) { |
148 | 148 | if ( snprintf(blkdev+len, sizeof(blkdev)-len, "%d", partition) >= (int)(sizeof(blkdev)-len) ) { |
149 | 149 | ERROR("Block device name is too long"); |
150 | 150 | return -1; |
151 | 151 | } |
152 | fd = open(blkdev, (readonly ? O_RDONLY : O_RDWR) | O_EXCL); | |
152 | fd = open(blkdev, ((simulate || readonly) ? O_RDONLY : O_RDWR) | O_EXCL); | |
153 | 153 | } |
154 | 154 | if ( fd < 0 && errno == ENOENT ) { |
155 | 155 | blkdev[len] = 0; |
200 | 200 | |
201 | 201 | int disk_dump_dev(int fd, const char * file) { |
202 | 202 | |
203 | int fd2; | |
203 | int fd2 = -1; | |
204 | 204 | int ret; |
205 | 205 | char * path; |
206 | 206 | uint64_t blksize; |
252 | 252 | return -1; |
253 | 253 | } |
254 | 254 | |
255 | fd2 = creat(file, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); | |
256 | ||
257 | if ( fd2 < 0 ) { | |
258 | ERROR_INFO("Cannot create file %s", file); | |
259 | return -1; | |
255 | if ( ! simulate ) { | |
256 | ||
257 | fd2 = creat(file, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); | |
258 | ||
259 | if ( fd2 < 0 ) { | |
260 | ERROR_INFO("Cannot create file %s", file); | |
261 | return -1; | |
262 | } | |
263 | ||
260 | 264 | } |
261 | 265 | |
262 | 266 | sent = 0; |
271 | 275 | break; |
272 | 276 | if ( size < 0 ) { |
273 | 277 | PRINTF_ERROR("Reading from block device failed"); |
274 | close(fd2); | |
275 | return -1; | |
276 | } | |
277 | if ( write(fd2, global_buf, size) != size ) { | |
278 | PRINTF_ERROR("Dumping image failed"); | |
279 | close(fd2); | |
280 | return -1; | |
278 | if ( ! simulate ) | |
279 | close(fd2); | |
280 | return -1; | |
281 | } | |
282 | if ( ! simulate ) { | |
283 | if ( write(fd2, global_buf, size) != size ) { | |
284 | PRINTF_ERROR("Dumping image failed"); | |
285 | close(fd2); | |
286 | return -1; | |
287 | } | |
281 | 288 | } |
282 | 289 | sent += size; |
283 | 290 | printf_progressbar(sent, blksize); |
284 | 291 | } |
285 | 292 | |
286 | close(fd2); | |
293 | if ( ! simulate ) | |
294 | close(fd2); | |
287 | 295 | return 0; |
288 | 296 | |
289 | 297 | } |
290 | 298 | |
291 | int disk_flash_dev(int fd, const char * file) { | |
292 | ||
293 | ERROR("Not implemented yet"); | |
294 | (void)fd; | |
295 | (void)file; | |
296 | return -1; | |
299 | int disk_flash_dev(int fd, struct image * image) { | |
300 | ||
301 | uint64_t blksize; | |
302 | size_t need, sent; | |
303 | ssize_t size; | |
304 | ||
305 | if ( image->type != IMAGE_MMC ) | |
306 | ERROR_RETURN("Only mmc images are supported", -1); | |
307 | ||
308 | printf("Writing image to block device...\n"); | |
309 | ||
310 | #ifdef __linux__ | |
311 | ||
312 | if ( ioctl(fd, BLKGETSIZE64, &blksize) != 0 ) { | |
313 | ERROR_INFO("Cannot get size of block device"); | |
314 | return -1; | |
315 | } | |
316 | ||
317 | #else | |
318 | ||
319 | blksize = lseek(fd, 0, SEEK_END); | |
320 | if ( (off_t)blksize == (off_t)-1 ) { | |
321 | ERROR_INFO("Cannot get size of block device"); | |
322 | return -1; | |
323 | } | |
324 | ||
325 | if ( lseek(fd, 0, SEEK_SET) == (off_t)-1 ) { | |
326 | ERROR_INFO("Cannot seek to begin of block device"); | |
327 | return -1; | |
328 | } | |
329 | ||
330 | #endif | |
331 | ||
332 | if ( blksize == 0 ) | |
333 | ERROR_RETURN("Block device has zero size", -1); | |
334 | ||
335 | if ( image->size > blksize ) | |
336 | ERROR_RETURN("Image is too big", -1); | |
337 | ||
338 | sent = 0; | |
339 | printf_progressbar(0, image->size); | |
340 | ||
341 | while ( sent < image->size ) { | |
342 | need = image->size - sent; | |
343 | if ( need > sizeof(global_buf) ) | |
344 | need = sizeof(global_buf); | |
345 | size = image_read(image, global_buf, need); | |
346 | if ( size == 0 ) { | |
347 | PRINTF_ERROR("Failed to read image"); | |
348 | return -1; | |
349 | } | |
350 | if ( ! simulate ) { | |
351 | if ( write(fd, global_buf, size) != size ) { | |
352 | PRINTF_ERROR("Writing image failed"); | |
353 | return -1; | |
354 | } | |
355 | } | |
356 | sent += size; | |
357 | printf_progressbar(sent, image->size); | |
358 | } | |
359 | ||
360 | return 0; | |
297 | 361 | |
298 | 362 | } |
299 | 363 | |
411 | 475 | maj2 = tmp; |
412 | 476 | } |
413 | 477 | |
414 | /* TODO: change 1 to 0 when disk_flash_dev will be implemented */ | |
415 | ||
416 | 478 | /* RX-51, RM-680 and RM-696 export MyDocs in first usb device and just first partion, so host system see whole device without MBR table */ |
417 | 479 | if ( dev->device == DEVICE_RX_51 || dev->device == DEVICE_RM_680 || dev->device == DEVICE_RM_696 ) |
418 | fd = disk_open_dev(maj1, min1, -1, 1); | |
480 | fd = disk_open_dev(maj1, min1, -1, simulate ? 1 : 0); | |
419 | 481 | /* Other devices can export SD card as first partition and export whole mmc device, so host system will see MBR table */ |
420 | 482 | else if ( maj2 != -1 && min2 != -1 ) |
421 | fd = disk_open_dev(maj2, min2, 1, 1); | |
483 | fd = disk_open_dev(maj2, min2, 1, simulate ? 1 : 0); | |
422 | 484 | else |
423 | fd = disk_open_dev(maj1, min1, 1, 1); | |
485 | fd = disk_open_dev(maj1, min1, 1, simulate ? 1 : 0); | |
424 | 486 | |
425 | 487 | if ( fd < 0 ) |
426 | 488 | return -1; |
453 | 515 | |
454 | 516 | int disk_flash_image(struct usb_device_info * dev, struct image * image) { |
455 | 517 | |
456 | ERROR("Not implemented yet"); | |
457 | (void)dev; | |
458 | (void)image; | |
459 | return -1; | |
518 | int ret; | |
519 | ||
520 | printf("Flash image:\n"); | |
521 | image_print_info(image); | |
522 | ||
523 | ret = disk_flash_dev(dev->data, image); | |
524 | if ( ret == 0 ) | |
525 | printf("Done\n"); | |
526 | ||
527 | return ret; | |
460 | 528 | |
461 | 529 | } |
462 | 530 |
29 | 29 | |
30 | 30 | int disk_open_dev(int maj, int min, int partition, int readonly); |
31 | 31 | int disk_dump_dev(int fd, const char * file); |
32 | int disk_flash_dev(int fd, const char * file); | |
32 | int disk_flash_dev(int fd, struct image * image); | |
33 | 33 | |
34 | 34 | int disk_flash_image(struct usb_device_info * dev, struct image * image); |
35 | 35 | int disk_dump_image(struct usb_device_info * dev, enum image_type image, const char * file); |
33 | 33 | #include "image.h" |
34 | 34 | #include "fiasco.h" |
35 | 35 | |
36 | #define CHECKSUM(checksum, buf, size) do { size_t _i; for ( _i = 0; _i < size; _i++ ) checksum += ((unsigned char *)buf)[_i]; } while (0) | |
36 | 37 | #define FIASCO_READ_ERROR(fiasco, ...) do { ERROR_INFO(__VA_ARGS__); fiasco_free(fiasco); return NULL; } while (0) |
37 | 38 | #define FIASCO_WRITE_ERROR(file, fd, ...) do { ERROR_INFO_STR(file, __VA_ARGS__); if ( fd >= 0 ) close(fd); return -1; } while (0) |
38 | 39 | #define READ_OR_FAIL(fiasco, buf, size) do { if ( read(fiasco->fd, buf, size) != size ) { FIASCO_READ_ERROR(fiasco, "Cannot read %d bytes", size); } } while (0) |
39 | #define READ_OR_RETURN(fiasco, buf, size) do { if ( read(fiasco->fd, buf, size) != size ) return fiasco; } while (0) | |
40 | #define READ_OR_RETURN(fiasco, checksum, buf, size) do { if ( read(fiasco->fd, buf, size) != size ) return fiasco; CHECKSUM(checksum, buf, size); } while (0) | |
40 | 41 | #define WRITE_OR_FAIL_FREE(file, fd, buf, size, var) do { if ( ! simulate ) { if ( write(fd, buf, size) != (ssize_t)size ) { free(var); FIASCO_WRITE_ERROR(file, fd, "Cannot write %d bytes", size); } } } while (0) |
41 | 42 | #define WRITE_OR_FAIL(file, fd, buf, size) WRITE_OR_FAIL_FREE(file, fd, buf, size, NULL) |
42 | 43 | |
64 | 65 | char hwrevs[1024]; |
65 | 66 | char version[257]; |
66 | 67 | char layout[257]; |
68 | uint8_t asicidx; | |
69 | uint8_t devicetype; | |
70 | uint8_t deviceidx; | |
71 | uint8_t checksum; | |
72 | uint32_t address; | |
67 | 73 | uint16_t hash; |
68 | 74 | off_t offset; |
69 | 75 | struct image * image; |
76 | struct image_part * image_part; | |
77 | struct image_part * image_parts; | |
70 | 78 | |
71 | 79 | char hwrev[9]; |
72 | 80 | unsigned char buf[512]; |
119 | 127 | while ( 1 ) { |
120 | 128 | |
121 | 129 | /* If end of file, return fiasco image */ |
122 | READ_OR_RETURN(fiasco, buf, 7); | |
123 | ||
124 | /* Header of next image */ | |
125 | if ( ! ( buf[0] == 0x54 && buf[2] == 0x2E && buf[3] == 0x19 && buf[4] == 0x01 && buf[5] == 0x01 && buf[6] == 0x00 ) ) { | |
130 | checksum = 0x00; | |
131 | READ_OR_RETURN(fiasco, checksum, buf, 1); | |
132 | ||
133 | /* Header of next image (0x54) */ | |
134 | if ( buf[0] != 0x54 ) { | |
126 | 135 | ERROR("Invalid next image header"); |
127 | 136 | return fiasco; |
128 | 137 | } |
129 | 138 | |
130 | count8 = buf[1]; | |
131 | if ( count8 > 0 ) | |
132 | --count8; | |
133 | ||
134 | READ_OR_RETURN(fiasco, &hash, 2); | |
139 | checksum = 0x00; | |
140 | ||
141 | READ_OR_RETURN(fiasco, checksum, &count8, 1); | |
142 | ||
143 | if ( count8 == 0 ) { | |
144 | ERROR("No section in image header"); | |
145 | return fiasco; | |
146 | } | |
147 | ||
148 | READ_OR_RETURN(fiasco, checksum, buf, 2); | |
149 | ||
150 | /* File data section (0x2E) with length of 25 bytes */ | |
151 | if ( buf[0] != 0x2E || buf[1] != 25 ) { | |
152 | ERROR("First section in image header is not file data with length of 25 bytes"); | |
153 | return fiasco; | |
154 | } | |
155 | ||
156 | READ_OR_RETURN(fiasco, checksum, &asicidx, 1); | |
157 | READ_OR_RETURN(fiasco, checksum, &devicetype, 1); | |
158 | READ_OR_RETURN(fiasco, checksum, &deviceidx, 1); | |
159 | ||
160 | READ_OR_RETURN(fiasco, checksum, &hash, 2); | |
135 | 161 | hash = ntohs(hash); |
136 | 162 | |
137 | 163 | memset(type, 0, sizeof(type)); |
138 | READ_OR_RETURN(fiasco, type, 12); | |
164 | READ_OR_RETURN(fiasco, checksum, type, 12); | |
139 | 165 | |
140 | 166 | byte = type[0]; |
141 | 167 | if ( byte == 0xFF ) |
143 | 169 | |
144 | 170 | VERBOSE(" %s\n", type); |
145 | 171 | |
146 | READ_OR_RETURN(fiasco, &length, 4); | |
172 | READ_OR_RETURN(fiasco, checksum, &length, 4); | |
147 | 173 | length = ntohl(length); |
148 | 174 | |
149 | /* unknown */ | |
150 | READ_OR_RETURN(fiasco, buf, 4); | |
175 | /* load address (unused) */ | |
176 | READ_OR_RETURN(fiasco, checksum, &address, 4); | |
177 | ||
178 | /* end of file data section */ | |
179 | --count8; | |
151 | 180 | |
152 | 181 | VERBOSE(" size: %d bytes\n", length); |
153 | VERBOSE(" hash: %#04x\n", hash); | |
182 | VERBOSE(" address: 0x%04x\n", address); | |
183 | VERBOSE(" hash: 0x%04x\n", hash); | |
184 | VERBOSE(" asic idx: %d\n", asicidx); | |
185 | VERBOSE(" device type: %d\n", devicetype); | |
186 | VERBOSE(" device idx: %d\n", deviceidx); | |
154 | 187 | VERBOSE(" subsections: %d\n", count8); |
155 | 188 | |
156 | 189 | memset(device, 0, sizeof(device)); |
157 | 190 | memset(hwrevs, 0, sizeof(hwrevs)); |
158 | 191 | memset(version, 0, sizeof(version)); |
159 | 192 | memset(layout, 0, sizeof(layout)); |
193 | image_part = NULL; | |
194 | image_parts = NULL; | |
160 | 195 | |
161 | 196 | while ( count8 > 0 ) { |
162 | 197 | |
163 | READ_OR_RETURN(fiasco, &byte, 1); | |
164 | READ_OR_RETURN(fiasco, &length8, 1); | |
165 | READ_OR_RETURN(fiasco, buf, length8); | |
198 | READ_OR_RETURN(fiasco, checksum, &byte, 1); | |
199 | READ_OR_RETURN(fiasco, checksum, &length8, 1); | |
200 | READ_OR_RETURN(fiasco, checksum, buf, length8); | |
166 | 201 | |
167 | 202 | VERBOSE(" subinfo\n"); |
168 | 203 | VERBOSE(" length: %d\n", length8); |
206 | 241 | memset(layout, 0, sizeof(layout)); |
207 | 242 | strncpy(layout, (char *)buf, length8); |
208 | 243 | VERBOSE("layout\n"); |
244 | } else if ( byte == '4' ) { | |
245 | VERBOSE("data part\n"); | |
246 | if ( length8 < 16 ) { | |
247 | VERBOSE(" (damaged)\n"); | |
248 | } else { | |
249 | if ( image_parts ) { | |
250 | image_part->next = calloc(1, sizeof(struct image_part)); | |
251 | if ( ! image_part->next ) | |
252 | FIASCO_READ_ERROR(fiasco, "Cannot allocate image"); | |
253 | image_part = image_part->next; | |
254 | } else { | |
255 | image_parts = calloc(1, sizeof(struct image_part)); | |
256 | if ( ! image_parts ) | |
257 | FIASCO_READ_ERROR(fiasco, "Cannot allocate image"); | |
258 | image_part = image_parts; | |
259 | } | |
260 | image_part->offset = ntohl(*(uint32_t *)&buf[4]); | |
261 | image_part->size = ntohl(*(uint32_t *)&buf[12]); | |
262 | if ( length8 > 16 ) { | |
263 | image_part->name = calloc(1, length8-16+1); | |
264 | if ( image_part->name ) | |
265 | memcpy(image_part->name, &buf[16], length8-16); | |
266 | } | |
267 | VERBOSE(" unknown: 0x%02x 0x%02x 0x%02x 0x%02x\n", buf[0], buf[1], buf[2], buf[3]); | |
268 | VERBOSE(" offset: %u bytes\n", image_part->offset); | |
269 | VERBOSE(" unknown: 0x%02x 0x%02x 0x%02x 0x%02x\n", buf[8], buf[9], buf[10], buf[11]); | |
270 | VERBOSE(" size: %u bytes\n", image_part->size); | |
271 | if ( image_part->name ) | |
272 | VERBOSE(" partition name: %s\n", image_part->name); | |
273 | } | |
209 | 274 | } else { |
210 | VERBOSE("unknown ('%c':%#x)\n", byte, byte); | |
275 | int i; | |
276 | VERBOSE("unknown (%#x)\n", byte); | |
277 | VERBOSE(" hexdump:"); | |
278 | for ( i = 0; i < length8; i++ ) VERBOSE(" 0x%02x", buf[i]); | |
279 | VERBOSE("\n"); | |
211 | 280 | } |
212 | 281 | |
213 | 282 | --count8; |
214 | 283 | } |
215 | 284 | |
216 | /* unknown */ | |
217 | READ_OR_RETURN(fiasco, buf, 1); | |
285 | /* checksum */ | |
286 | READ_OR_RETURN(fiasco, checksum, buf, 1); | |
287 | VERBOSE(" subinfo checksum: 0x%02x\n", buf[0]); | |
288 | ||
289 | if ( ! noverify && buf[0] != 0x00 && checksum != 0xFF ) { | |
290 | ERROR("Image header subinfo checksum mishmash (counted 0x%02x, got 0x%02x)", (0xFF - checksum + buf[0]) & 0xFF, buf[0]); | |
291 | return fiasco; | |
292 | } | |
218 | 293 | |
219 | 294 | offset = lseek(fiasco->fd, 0, SEEK_CUR); |
220 | 295 | if ( offset == (off_t)-1 ) |
225 | 300 | VERBOSE(" hwrevs: %s\n", hwrevs); |
226 | 301 | VERBOSE(" data at: %#08x\n", (unsigned int)offset); |
227 | 302 | |
228 | image = image_alloc_from_shared_fd(fiasco->fd, length, offset, hash, type, device, hwrevs, version, layout); | |
303 | image = image_alloc_from_shared_fd(fiasco->fd, length, offset, hash, type, device, hwrevs, version, layout, image_parts); | |
229 | 304 | |
230 | 305 | if ( ! image ) |
231 | 306 | FIASCO_READ_ERROR(fiasco, "Cannot allocate image"); |
273 | 348 | uint32_t length; |
274 | 349 | uint16_t hash; |
275 | 350 | uint8_t length8; |
351 | uint8_t checksum; | |
276 | 352 | char ** device_hwrevs_bufs; |
277 | 353 | const char * str; |
278 | 354 | const char * type; |
279 | 355 | struct image_list * image_list; |
356 | struct image_part * image_part; | |
280 | 357 | struct image * image; |
281 | 358 | unsigned char buf[4096]; |
282 | 359 | |
374 | 451 | /* signature */ |
375 | 452 | WRITE_OR_FAIL_FREE(file, fd, "T", 1, device_hwrevs_bufs); |
376 | 453 | |
454 | checksum = 0x00; | |
455 | ||
377 | 456 | /* number of subsections */ |
378 | length8 = device_count+1; | |
457 | length8 = device_count+2; | |
379 | 458 | if ( image->version ) |
380 | 459 | ++length8; |
381 | 460 | if ( image->layout ) |
382 | 461 | ++length8; |
383 | 462 | WRITE_OR_FAIL_FREE(file, fd, &length8, 1, device_hwrevs_bufs); |
384 | ||
385 | /* unknown */ | |
463 | CHECKSUM(checksum, &length8, 1); | |
464 | ||
465 | /* file data: asic index: APE (0x01), device type: NAND (0x01), device index: 0 */ | |
386 | 466 | WRITE_OR_FAIL_FREE(file, fd, "\x2e\x19\x01\x01\x00", 5, device_hwrevs_bufs); |
467 | CHECKSUM(checksum, "\x2e\x19\x01\x01\x00", 5); | |
387 | 468 | |
388 | 469 | /* checksum */ |
389 | 470 | hash = htons(image->hash); |
390 | 471 | WRITE_OR_FAIL_FREE(file, fd, &hash, 2, device_hwrevs_bufs); |
472 | CHECKSUM(checksum, &hash, 2); | |
391 | 473 | |
392 | 474 | /* image type name */ |
393 | 475 | memset(buf, 0, 12); |
394 | 476 | strncpy((char *)buf, type, 12); |
395 | 477 | WRITE_OR_FAIL_FREE(file, fd, buf, 12, device_hwrevs_bufs); |
478 | CHECKSUM(checksum, buf, 12); | |
396 | 479 | |
397 | 480 | /* image size */ |
398 | 481 | size = htonl(image->size); |
399 | 482 | WRITE_OR_FAIL_FREE(file, fd, &size, 4, device_hwrevs_bufs); |
400 | ||
401 | /* unknown */ | |
483 | CHECKSUM(checksum, &size, 4); | |
484 | ||
485 | /* image load address (unused always zero) */ | |
402 | 486 | WRITE_OR_FAIL_FREE(file, fd, "\x00\x00\x00\x00", 4, device_hwrevs_bufs); |
487 | CHECKSUM(checksum, "\x00\x00\x00\x00", 4); | |
403 | 488 | |
404 | 489 | /* append version subsection */ |
405 | 490 | if ( image->version ) { |
407 | 492 | length8 = strlen(image->version)+1; /* +1 for NULL term */ |
408 | 493 | WRITE_OR_FAIL_FREE(file, fd, &length8, 1, device_hwrevs_bufs); |
409 | 494 | WRITE_OR_FAIL_FREE(file, fd, image->version, length8, device_hwrevs_bufs); |
495 | CHECKSUM(checksum, "1", 1); | |
496 | CHECKSUM(checksum, &length8, 1); | |
497 | CHECKSUM(checksum, image->version, length8); | |
410 | 498 | } |
411 | 499 | |
412 | 500 | /* append device & hwrevs subsection */ |
415 | 503 | length8 = ((uint8_t *)(device_hwrevs_bufs[i]))[0]; |
416 | 504 | WRITE_OR_FAIL_FREE(file, fd, &length8, 1, device_hwrevs_bufs); |
417 | 505 | WRITE_OR_FAIL_FREE(file, fd, device_hwrevs_bufs[i]+1, length8, device_hwrevs_bufs); |
506 | CHECKSUM(checksum, "2", 1); | |
507 | CHECKSUM(checksum, &length8, 1); | |
508 | CHECKSUM(checksum, device_hwrevs_bufs[i]+1, length8); | |
418 | 509 | } |
419 | 510 | free(device_hwrevs_bufs); |
420 | 511 | |
424 | 515 | length8 = strlen(image->layout); |
425 | 516 | WRITE_OR_FAIL(file, fd, &length8, 1); |
426 | 517 | WRITE_OR_FAIL(file, fd, image->layout, length8); |
427 | } | |
428 | ||
429 | /* dummy byte - end of all subsections */ | |
430 | WRITE_OR_FAIL(file, fd, "\x00", 1); | |
518 | CHECKSUM(checksum, "3", 1); | |
519 | CHECKSUM(checksum, &length8, 1); | |
520 | CHECKSUM(checksum, image->layout, length8); | |
521 | } | |
522 | ||
523 | if ( image->parts ) { | |
524 | /* for each image part append subsection */ | |
525 | for ( image_part = image->parts; image_part; image_part = image_part->next ) { | |
526 | WRITE_OR_FAIL(file, fd, "4", 1); /* 4 - image data part */ | |
527 | CHECKSUM(checksum, "4", 1); | |
528 | length = 16 + (image_part->name ? strlen(image_part->name) : 0); | |
529 | length8 = length <= UINT8_MAX ? length : UINT8_MAX; | |
530 | WRITE_OR_FAIL(file, fd, &length8, 1); | |
531 | CHECKSUM(checksum, &length8, 1); | |
532 | WRITE_OR_FAIL(file, fd, "\x00\x00\x00\x00", 4); /* unknown */ | |
533 | CHECKSUM(checksum, "\x00\x00\x00\x00", 4); | |
534 | size = htonl(image_part->offset); | |
535 | WRITE_OR_FAIL(file, fd, &size, 4); | |
536 | CHECKSUM(checksum, &size, 4); | |
537 | WRITE_OR_FAIL(file, fd, "\x00\x00\x00\x00", 4); /* unknown */ | |
538 | CHECKSUM(checksum, "\x00\x00\x00\x00", 4); | |
539 | size = htonl(image_part->size); | |
540 | WRITE_OR_FAIL(file, fd, &size, 4); | |
541 | CHECKSUM(checksum, &size, 4); | |
542 | if ( image_part->name ) { | |
543 | WRITE_OR_FAIL(file, fd, image_part->name, length-16); | |
544 | CHECKSUM(checksum, image_part->name, length-16); | |
545 | } | |
546 | } | |
547 | } else { | |
548 | /* append one image data part subsection */; | |
549 | WRITE_OR_FAIL(file, fd, "4\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 14); | |
550 | CHECKSUM(checksum, "4\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 14); | |
551 | size = htonl(image->size); | |
552 | WRITE_OR_FAIL(file, fd, &size, 4); | |
553 | CHECKSUM(checksum, &size, 4); | |
554 | } | |
555 | ||
556 | /* checksum of header */ | |
557 | checksum = 0xFF - checksum; | |
558 | WRITE_OR_FAIL(file, fd, &checksum, 1); | |
431 | 559 | |
432 | 560 | printf("Writing image data...\n"); |
433 | 561 | |
460 | 588 | char * name; |
461 | 589 | char * layout_name; |
462 | 590 | struct image * image; |
591 | struct image_part * image_part; | |
463 | 592 | struct image_list * image_list; |
464 | uint32_t size; | |
593 | uint32_t offset, size, need, total_size, written; | |
594 | int part_num; | |
465 | 595 | char cwd[256]; |
466 | 596 | unsigned char buf[4096]; |
467 | 597 | |
488 | 618 | while ( image_list ) { |
489 | 619 | |
490 | 620 | fd = -1; |
491 | name = NULL; | |
492 | layout_name = NULL; | |
493 | 621 | |
494 | 622 | image = image_list->image; |
495 | ||
496 | name = image_name_alloc_from_values(image); | |
497 | if ( ! name ) | |
498 | return -1; | |
499 | 623 | |
500 | 624 | printf("\n"); |
501 | 625 | printf("Unpacking image...\n"); |
503 | 627 | |
504 | 628 | if ( image->layout ) { |
505 | 629 | |
506 | layout_name = calloc(1, strlen(name) + sizeof(".layout")-1 + 1); | |
630 | name = image_name_alloc_from_values(image, -1); | |
631 | if ( ! name ) | |
632 | ALLOC_ERROR_RETURN(-1); | |
633 | ||
634 | layout_name = calloc(1, strlen(name) + sizeof("_layout")-1 + 1); | |
507 | 635 | if ( ! layout_name ) { |
508 | 636 | free(name); |
509 | 637 | ALLOC_ERROR_RETURN(-1); |
510 | 638 | } |
511 | 639 | |
512 | sprintf(layout_name, "%s.layout", name); | |
640 | sprintf(layout_name, "%s_layout", name); | |
641 | free(name); | |
513 | 642 | |
514 | 643 | printf(" Layout file: %s\n", layout_name); |
515 | ||
516 | } | |
517 | ||
518 | printf(" Output file: %s\n", name); | |
519 | ||
520 | if ( ! simulate ) { | |
521 | fd = open(name, O_RDWR|O_CREAT|O_TRUNC, 0644); | |
522 | if ( fd < 0 ) { | |
523 | ERROR_INFO("Cannot create output file %s", name); | |
524 | free(name); | |
525 | free(layout_name); | |
526 | return -1; | |
527 | } | |
528 | } | |
529 | ||
530 | image_seek(image, 0); | |
531 | while ( 1 ) { | |
532 | size = image_read(image, buf, sizeof(buf)); | |
533 | if ( size == 0 ) | |
534 | break; | |
535 | if ( ! simulate ) { | |
536 | if ( write(fd, buf, size) != (ssize_t)size ) { | |
537 | ERROR_INFO_STR(name, "Cannot write %d bytes", size); | |
538 | close(fd); | |
539 | free(name); | |
540 | free(layout_name); | |
541 | return -1; | |
542 | } | |
543 | } | |
544 | } | |
545 | ||
546 | free(name); | |
547 | ||
548 | if ( ! simulate ) | |
549 | close(fd); | |
550 | ||
551 | if ( image->layout ) { | |
552 | 644 | |
553 | 645 | if ( ! simulate ) { |
554 | 646 | fd = open(layout_name, O_RDWR|O_CREAT|O_TRUNC, 0644); |
570 | 662 | |
571 | 663 | free(layout_name); |
572 | 664 | |
573 | if ( ! simulate ) | |
665 | if ( ! simulate ) { | |
574 | 666 | close(fd); |
575 | ||
576 | } | |
667 | fd = -1; | |
668 | } | |
669 | ||
670 | } | |
671 | ||
672 | part_num = 0; | |
673 | image_part = image->parts; | |
674 | ||
675 | do { | |
676 | ||
677 | offset = image_part ? image_part->offset : 0; | |
678 | total_size = image_part ? image_part->size : image->size; | |
679 | ||
680 | name = image_name_alloc_from_values(image, image_part ? part_num : -1); | |
681 | if ( ! name ) | |
682 | ALLOC_ERROR_RETURN(-1); | |
683 | ||
684 | if ( image_part && ( part_num > 0 || image_part->next ) ) | |
685 | printf(" Output file part %d: %s\n", part_num+1, name); | |
686 | else | |
687 | printf(" Output file: %s\n", name); | |
688 | ||
689 | if ( ! simulate ) { | |
690 | fd = open(name, O_RDWR|O_CREAT|O_TRUNC, 0644); | |
691 | if ( fd < 0 ) { | |
692 | ERROR_INFO("Cannot create output file %s", name); | |
693 | free(name); | |
694 | return -1; | |
695 | } | |
696 | } | |
697 | ||
698 | written = 0; | |
699 | image_seek(image, offset); | |
700 | while ( written < total_size ) { | |
701 | need = total_size - written; | |
702 | if ( need > sizeof(buf) ) | |
703 | need = sizeof(buf); | |
704 | size = image_read(image, buf, need); | |
705 | if ( size == 0 ) | |
706 | break; | |
707 | if ( ! simulate ) { | |
708 | if ( write(fd, buf, size) != (ssize_t)size ) { | |
709 | ERROR_INFO_STR(name, "Cannot write %d bytes", size); | |
710 | close(fd); | |
711 | free(name); | |
712 | return -1; | |
713 | } | |
714 | } | |
715 | written += size; | |
716 | } | |
717 | ||
718 | free(name); | |
719 | ||
720 | if ( ! simulate ) { | |
721 | close(fd); | |
722 | fd = -1; | |
723 | } | |
724 | ||
725 | if ( image_part ) { | |
726 | image_part = image_part->next; | |
727 | part_num++; | |
728 | } | |
729 | ||
730 | } while ( image_part ); | |
577 | 731 | |
578 | 732 | image_list = image_list->next; |
579 | 733 |
99 | 99 | } |
100 | 100 | |
101 | 101 | /* format: type-device:hwrevs_version */ |
102 | char * image_name_alloc_from_values(struct image * image) { | |
102 | char * image_name_alloc_from_values(struct image * image, int part_num) { | |
103 | 103 | |
104 | 104 | char * name; |
105 | 105 | char * ptr; |
107 | 107 | size_t length; |
108 | 108 | const char * type; |
109 | 109 | const char * device; |
110 | struct image_part * part; | |
111 | int i; | |
110 | 112 | |
111 | 113 | type = image_type_to_string(image->type); |
112 | 114 | |
122 | 124 | hwrevs = hwrevs_alloc_to_string(image->devices->hwrevs); |
123 | 125 | else |
124 | 126 | hwrevs = NULL; |
127 | ||
128 | part = image->parts; | |
129 | ||
130 | if ( part && ( !part->next || part_num < 0 ) ) | |
131 | part = NULL; | |
132 | ||
133 | for ( i = 0; i < part_num && part; i++ ) | |
134 | part = part->next; | |
125 | 135 | |
126 | 136 | length = 1 + strlen(type); |
127 | 137 | |
131 | 141 | length += 1 + strlen(hwrevs); |
132 | 142 | if ( image->version ) |
133 | 143 | length += 1 + strlen(image->version); |
144 | if ( part ) | |
145 | length += 4 + 3; /* 3 <= strlen(part_num) */ | |
146 | if ( part && part->name ) | |
147 | length += 1 + strlen(part->name); | |
134 | 148 | |
135 | 149 | name = calloc(1, length); |
136 | 150 | if ( ! name ) { |
148 | 162 | if ( image->version ) |
149 | 163 | ptr += sprintf(ptr, "_%s", image->version); |
150 | 164 | |
165 | if ( part ) { | |
166 | ptr += sprintf(ptr, "_part%d", part_num+1); | |
167 | if ( part->name ) | |
168 | ptr += sprintf(ptr, "_%s", part->name); | |
169 | } | |
170 | ||
151 | 171 | free(hwrevs); |
152 | 172 | |
153 | 173 | return name; |
154 | 174 | |
155 | 175 | } |
156 | 176 | |
157 | static int image_append(struct image * image, const char * type, const char * device, const char * hwrevs, const char * version, const char * layout) { | |
177 | static int image_append(struct image * image, const char * type, const char * device, const char * hwrevs, const char * version, const char * layout, struct image_part * parts) { | |
158 | 178 | |
159 | 179 | enum image_type detected_type; |
160 | 180 | |
209 | 229 | else |
210 | 230 | image->layout = NULL; |
211 | 231 | |
232 | image->parts = parts; | |
233 | ||
212 | 234 | return 0; |
213 | 235 | |
214 | 236 | } |
243 | 265 | |
244 | 266 | } |
245 | 267 | |
246 | struct image * image_alloc_from_file(const char * file, const char * type, const char * device, const char * hwrevs, const char * version, const char * layout) { | |
268 | struct image * image_alloc_from_file(const char * file, const char * type, const char * device, const char * hwrevs, const char * version, const char * layout, struct image_part * parts) { | |
247 | 269 | |
248 | 270 | int fd; |
249 | 271 | |
253 | 275 | return NULL; |
254 | 276 | } |
255 | 277 | |
256 | return image_alloc_from_fd(fd, file, type, device, hwrevs, version, layout); | |
257 | ||
258 | } | |
259 | ||
260 | struct image * image_alloc_from_fd(int fd, const char * orig_filename, const char * type, const char * device, const char * hwrevs, const char * version, const char * layout) { | |
278 | return image_alloc_from_fd(fd, file, type, device, hwrevs, version, layout, parts); | |
279 | ||
280 | } | |
281 | ||
282 | struct image * image_alloc_from_fd(int fd, const char * orig_filename, const char * type, const char * device, const char * hwrevs, const char * version, const char * layout, struct image_part * parts) { | |
261 | 283 | |
262 | 284 | off_t offset; |
263 | 285 | struct image * image = image_alloc(); |
290 | 312 | return NULL; |
291 | 313 | } |
292 | 314 | |
293 | if ( image_append(image, type, device, hwrevs, version, layout) < 0 ) | |
315 | if ( image_append(image, type, device, hwrevs, version, layout, parts) < 0 ) | |
294 | 316 | return NULL; |
295 | 317 | |
296 | 318 | if ( ( ! type || ! type[0] ) && ( ! device || ! device[0] ) && ( ! hwrevs || ! hwrevs[0] ) && ( ! version || ! version[0] ) ) |
302 | 324 | |
303 | 325 | } |
304 | 326 | |
305 | struct image * image_alloc_from_shared_fd(int fd, size_t size, size_t offset, uint16_t hash, const char * type, const char * device, const char * hwrevs, const char * version, const char * layout) { | |
327 | struct image * image_alloc_from_shared_fd(int fd, size_t size, size_t offset, uint16_t hash, const char * type, const char * device, const char * hwrevs, const char * version, const char * layout, struct image_part * parts) { | |
306 | 328 | |
307 | 329 | struct image * image = image_alloc(); |
308 | 330 | if ( ! image ) |
314 | 336 | image->offset = offset; |
315 | 337 | image->cur = 0; |
316 | 338 | |
317 | if ( image_append(image, type, device, hwrevs, version, layout) < 0 ) | |
339 | if ( image_append(image, type, device, hwrevs, version, layout, parts) < 0 ) | |
318 | 340 | return NULL; |
319 | 341 | |
320 | 342 | if ( ! noverify && image->hash != hash ) { |
344 | 366 | free(image->devices->hwrevs); |
345 | 367 | free(image->devices); |
346 | 368 | image->devices = next; |
369 | } | |
370 | ||
371 | while ( image->parts ) { | |
372 | struct image_part * next = image->parts->next; | |
373 | free(image->parts->name); | |
374 | free(image->parts); | |
375 | image->parts = next; | |
347 | 376 | } |
348 | 377 | |
349 | 378 | free(image->version); |
515 | 544 | [IMAGE_CMT_2ND] = "cmt-2nd", |
516 | 545 | [IMAGE_CMT_ALGO] = "cmt-algo", |
517 | 546 | [IMAGE_CMT_MCUSW] = "cmt-mcusw", |
547 | [IMAGE_1ST] = "1st", | |
548 | [IMAGE_CERT_SW] = "cert-sw", | |
549 | [IMAGE_APE_ALGO] = "ape-algo", | |
518 | 550 | }; |
519 | 551 | |
520 | 552 | enum image_type image_type_from_data(struct image * image) { |
36 | 36 | IMAGE_CMT_2ND, |
37 | 37 | IMAGE_CMT_ALGO, |
38 | 38 | IMAGE_CMT_MCUSW, |
39 | IMAGE_1ST, | |
40 | IMAGE_CERT_SW, | |
41 | IMAGE_APE_ALGO, | |
39 | 42 | IMAGE_COUNT, |
43 | }; | |
44 | ||
45 | struct image_part { | |
46 | struct image_part * next; | |
47 | uint32_t offset; | |
48 | uint32_t size; | |
49 | char * name; | |
40 | 50 | }; |
41 | 51 | |
42 | 52 | struct image { |
46 | 56 | char * layout; |
47 | 57 | uint16_t hash; |
48 | 58 | uint32_t size; |
59 | struct image_part * parts; | |
49 | 60 | |
50 | 61 | int fd; |
51 | 62 | int is_shared_fd; |
62 | 73 | struct image_list * next; |
63 | 74 | }; |
64 | 75 | |
65 | struct image * image_alloc_from_file(const char * file, const char * type, const char * device, const char * hwrevs, const char * version, const char * layout); | |
66 | struct image * image_alloc_from_fd(int fd, const char * orig_filename, const char * type, const char * device, const char * hwrevs, const char * version, const char * layout); | |
67 | struct image * image_alloc_from_shared_fd(int fd, size_t size, size_t offset, uint16_t hash, const char * type, const char * device, const char * hwrevs, const char * version, const char * layout); | |
76 | struct image * image_alloc_from_file(const char * file, const char * type, const char * device, const char * hwrevs, const char * version, const char * layout, struct image_part * parts); | |
77 | struct image * image_alloc_from_fd(int fd, const char * orig_filename, const char * type, const char * device, const char * hwrevs, const char * version, const char * layout, struct image_part * parts); | |
78 | struct image * image_alloc_from_shared_fd(int fd, size_t size, size_t offset, uint16_t hash, const char * type, const char * device, const char * hwrevs, const char * version, const char * layout, struct image_part * parts); | |
68 | 79 | void image_free(struct image * image); |
69 | 80 | void image_seek(struct image * image, size_t whence); |
70 | 81 | size_t image_read(struct image * image, void * buf, size_t count); |
75 | 86 | |
76 | 87 | uint16_t image_hash_from_data(struct image * image); |
77 | 88 | enum image_type image_type_from_data(struct image * image); |
78 | char * image_name_alloc_from_values(struct image * image); | |
89 | char * image_name_alloc_from_values(struct image * image, int part_num); | |
79 | 90 | enum image_type image_type_from_string(const char * type); |
80 | 91 | const char * image_type_to_string(enum image_type type); |
81 | 92 | int image_hwrev_is_valid(struct image * image, int16_t hwrev); |
18 | 18 | #include <stdio.h> |
19 | 19 | #include <stdlib.h> |
20 | 20 | #include <string.h> |
21 | #include <signal.h> | |
21 | 22 | |
22 | 23 | #include <sys/statvfs.h> |
23 | 24 | #include <sys/types.h> |
197 | 198 | |
198 | 199 | } |
199 | 200 | |
200 | int local_flash_image(struct image * image) { | |
201 | ||
202 | ERROR("Not implemented yet"); | |
203 | (void)image; | |
204 | return -1; | |
205 | ||
206 | } | |
207 | ||
208 | 201 | static int local_nanddump(const char * file, int mtd, int offset, int length) { |
209 | 202 | |
210 | 203 | struct statvfs buf; |
226 | 219 | return 1; |
227 | 220 | } |
228 | 221 | |
229 | size = snprintf(NULL, 0, "nanddump -o -b -s %d -l %d -f %s /dev/mtd%dro", offset, length, file, mtd); | |
222 | size = snprintf(NULL, 0, "nanddump --omitoob -s %d -l %d -f %s /dev/mtd%d", offset, length, file, mtd); | |
230 | 223 | |
231 | 224 | command = malloc(size+1); |
232 | 225 | if ( ! command ) |
233 | 226 | return 1; |
234 | 227 | |
235 | snprintf(command, size+1, "nanddump -o -b -s %d -l %d -f %s /dev/mtd%dro", offset, length, file, mtd); | |
236 | ||
237 | ret = system(command); | |
228 | snprintf(command, size+1, "nanddump --omitoob -s %d -l %d -f %s /dev/mtd%d", offset, length, file, mtd); | |
229 | ||
230 | if ( ! simulate ) | |
231 | ret = system(command); | |
232 | else | |
233 | ret = 0; | |
238 | 234 | |
239 | 235 | free(command); |
240 | 236 | |
242 | 238 | |
243 | 239 | } |
244 | 240 | |
245 | struct nanddump_args { | |
246 | int valid; | |
247 | int mtd; | |
248 | int offset; | |
249 | int length; | |
241 | static FILE * local_nandwrite(int mtd, int offset) { | |
242 | ||
243 | char * command; | |
244 | FILE * stream; | |
245 | size_t size; | |
246 | ||
247 | size = snprintf(NULL, 0, "nandwrite -a -s %d -p /dev/mtd%d -", offset, mtd); | |
248 | ||
249 | command = malloc(size+1); | |
250 | if ( ! command ) | |
251 | return NULL; | |
252 | ||
253 | snprintf(command, size+1, "nandwrite -a -s %d -p /dev/mtd%d -", offset, mtd); | |
254 | ||
255 | if ( ! simulate ) | |
256 | stream = popen(command, "w"); | |
257 | else | |
258 | stream = NULL; | |
259 | ||
260 | free(command); | |
261 | ||
262 | return stream; | |
263 | ||
264 | } | |
265 | ||
266 | struct nandpart_args { | |
267 | unsigned int mtd; | |
268 | unsigned int offset; | |
269 | unsigned int length; | |
270 | unsigned int header; | |
250 | 271 | }; |
251 | 272 | |
252 | static struct nanddump_args nanddump_rx51[] = { | |
253 | [IMAGE_XLOADER] = { 1, 0, 0x00000000, 0x00004000 }, | |
254 | [IMAGE_SECONDARY] = { 1, 0, 0x00004000, 0x0001C000 }, | |
255 | [IMAGE_KERNEL] = { 1, 3, 0x00000800, 0x001FF800 }, | |
256 | [IMAGE_INITFS] = { 1, 4, 0x00000000, 0x00200000 }, | |
257 | [IMAGE_ROOTFS] = { 1, 5, 0x00000000, 0x0fb40000 }, | |
273 | static struct nandpart_args nandpart_rx51[] = { | |
274 | [IMAGE_XLOADER] = { 0, 0x00000000, 0x00004000, 0x00000000 }, | |
275 | [IMAGE_SECONDARY] = { 0, 0x00004000, 0x0001C000, 0x00000000 }, | |
276 | [IMAGE_KERNEL] = { 3, 0x00000000, 0x00200000, 0x00000800 }, | |
277 | [IMAGE_INITFS] = { 4, 0x00000000, 0x00200000, 0x00000000 }, | |
278 | [IMAGE_ROOTFS] = { 5, 0x00000000, 0x0fb40000, 0x00000000 }, | |
258 | 279 | }; |
259 | 280 | |
260 | 281 | /* FIXME: Is this table correct? */ |
261 | static struct nanddump_args nanddump_rx4x[] = { | |
262 | [IMAGE_XLOADER] = { 1, 0, 0x00000200, 0x00003E00 }, | |
263 | [IMAGE_SECONDARY] = { 1, 0, 0x00004000, 0x0001C000 }, | |
264 | [IMAGE_KERNEL] = { 1, 2, 0x00000800, 0x0021F800 }, | |
265 | [IMAGE_INITFS] = { 1, 3, 0x00000000, 0x00400000 }, | |
266 | [IMAGE_ROOTFS] = { 1, 4, 0x00000000, 0x0f960000 }, | |
282 | static struct nandpart_args nandpart_rx4x[] = { | |
283 | [IMAGE_XLOADER] = { 0, 0x00000200, 0x00003E00, 0x00000000 }, | |
284 | [IMAGE_SECONDARY] = { 0, 0x00004000, 0x0001C000, 0x00000000 }, | |
285 | [IMAGE_KERNEL] = { 2, 0x00000000, 0x00220000, 0x00000800 }, | |
286 | [IMAGE_INITFS] = { 3, 0x00000000, 0x00400000, 0x00000000 }, | |
287 | [IMAGE_ROOTFS] = { 4, 0x00000000, 0x0f960000, 0x00000000 }, | |
267 | 288 | }; |
268 | 289 | |
269 | 290 | /* FIXME: Is this table correct? */ |
270 | static struct nanddump_args nanddump_old[] = { | |
271 | [IMAGE_XLOADER] = { 1, 0, 0x00000200, 0x00003E00 }, | |
272 | [IMAGE_SECONDARY] = { 1, 0, 0x00004000, 0x0001C000 }, | |
273 | [IMAGE_KERNEL] = { 1, 2, 0x00000800, 0x001FF800 }, | |
274 | [IMAGE_INITFS] = { 1, 3, 0x00000000, 0x00200000 }, | |
275 | [IMAGE_ROOTFS] = { 1, 4, 0x00000000, 0x0fb80000 }, | |
291 | static struct nandpart_args nandpart_old[] = { | |
292 | [IMAGE_XLOADER] = { 0, 0x00000200, 0x00003E00, 0x00000000 }, | |
293 | [IMAGE_SECONDARY] = { 0, 0x00004000, 0x0001C000, 0x00000000 }, | |
294 | [IMAGE_KERNEL] = { 2, 0x00000000, 0x00200000, 0x00000800 }, | |
295 | [IMAGE_INITFS] = { 3, 0x00000000, 0x00200000, 0x00000000 }, | |
296 | [IMAGE_ROOTFS] = { 4, 0x00000000, 0x0fb80000, 0x00000000 }, | |
276 | 297 | }; |
277 | 298 | |
278 | struct nanddump_device { | |
299 | struct nand_device { | |
279 | 300 | size_t count; |
280 | struct nanddump_args * args; | |
301 | struct nandpart_args * args; | |
281 | 302 | }; |
282 | 303 | |
283 | #define NANDDUMP(device, array) [device] = { .count = sizeof(array)/sizeof(array[0]), .args = array } | |
284 | ||
285 | static struct nanddump_device nanddump[] = { | |
286 | NANDDUMP(DEVICE_SU_18, nanddump_old), | |
287 | NANDDUMP(DEVICE_RX_34, nanddump_old), | |
288 | NANDDUMP(DEVICE_RX_44, nanddump_rx4x), | |
289 | NANDDUMP(DEVICE_RX_48, nanddump_rx4x), | |
290 | NANDDUMP(DEVICE_RX_51, nanddump_rx51), | |
304 | #define NAND_DEVICE(device, array) [device] = { .count = sizeof(array)/sizeof(array[0]), .args = array } | |
305 | ||
306 | static struct nand_device nand_device[] = { | |
307 | NAND_DEVICE(DEVICE_SU_18, nandpart_old), | |
308 | NAND_DEVICE(DEVICE_RX_34, nandpart_old), | |
309 | NAND_DEVICE(DEVICE_RX_44, nandpart_rx4x), | |
310 | NAND_DEVICE(DEVICE_RX_48, nandpart_rx4x), | |
311 | NAND_DEVICE(DEVICE_RX_51, nandpart_rx51), | |
291 | 312 | }; |
292 | 313 | |
293 | 314 | #undef NANDDUMP |
379 | 400 | |
380 | 401 | int local_dump_image(enum image_type image, const char * file) { |
381 | 402 | |
403 | unsigned char buf[20]; | |
382 | 404 | int ret = -1; |
383 | 405 | int fd = -1; |
406 | int header = 0; | |
384 | 407 | unsigned char * addr = NULL; |
385 | off_t nlen, len; | |
408 | off_t nlen = (off_t)-1; | |
409 | off_t len; | |
386 | 410 | int align; |
387 | 411 | int maj, min; |
388 | 412 | |
414 | 438 | |
415 | 439 | } else { |
416 | 440 | |
417 | if ( device >= sizeof(nanddump)/sizeof(nanddump[0]) ) { | |
441 | if ( device >= sizeof(nand_device)/sizeof(nand_device[0]) ) { | |
418 | 442 | ERROR("Unsupported device"); |
419 | 443 | goto clean; |
420 | 444 | } |
421 | 445 | |
422 | if ( image >= nanddump[device].count ) { | |
446 | if ( image >= nand_device[device].count ) { | |
423 | 447 | ERROR("Unsupported image type: %s", image_type_to_string(image)); |
424 | 448 | goto clean; |
425 | 449 | } |
426 | 450 | |
427 | ret = local_nanddump(file, nanddump[device].args[image].mtd, nanddump[device].args[image].offset, nanddump[device].args[image].length); | |
451 | header = nand_device[device].args[image].header; | |
452 | ||
453 | if ( header > 0 ) { | |
454 | ||
455 | ret = local_nanddump(file, nand_device[device].args[image].mtd, nand_device[device].args[image].offset, header); | |
456 | if ( ret != 0 ) { | |
457 | if ( ! simulate ) | |
458 | unlink(file); | |
459 | ret = -1; | |
460 | goto clean; | |
461 | } | |
462 | ||
463 | if ( ! simulate ) { | |
464 | ||
465 | fd = open(file, O_RDONLY); | |
466 | if ( fd >= 0 ) { | |
467 | if ( read(fd, buf, 20) == 20 ) { | |
468 | if ( memcmp(buf, "NOLO!img\x02\x00\x00\x00\x00\x00\x00\x00", 16) == 0 ) | |
469 | nlen = ((unsigned int)buf[16] << 0) | ((unsigned int)buf[17] << 8) | ((unsigned int)buf[18] << 16) | ((unsigned int)buf[19] << 24); | |
470 | else if ( memcmp(buf, "NOLO img", 8) == 0 ) | |
471 | nlen = ((unsigned int)buf[8] << 0) | ((unsigned int)buf[9] << 8) | ((unsigned int)buf[10] << 16) | ((unsigned int)buf[11] << 24); | |
472 | } | |
473 | close(fd); | |
474 | fd = -1; | |
475 | } | |
476 | ||
477 | unlink(file); | |
478 | ||
479 | } | |
480 | ||
481 | } | |
482 | ||
483 | ret = local_nanddump(file, nand_device[device].args[image].mtd, nand_device[device].args[image].offset + header, nand_device[device].args[image].length - header); | |
428 | 484 | |
429 | 485 | } |
430 | 486 | |
433 | 489 | goto clean; |
434 | 490 | } |
435 | 491 | |
492 | if ( simulate ) | |
493 | goto clean; | |
494 | ||
436 | 495 | fd = open(file, O_RDWR); |
437 | 496 | if ( fd < 0 ) |
438 | 497 | goto clean; |
441 | 500 | if ( len == (off_t)-1 || len == 0 ) |
442 | 501 | goto clean; |
443 | 502 | |
444 | addr = (unsigned char *)mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0); | |
445 | ||
446 | if ( addr == MAP_FAILED ) | |
447 | addr = NULL; | |
448 | ||
449 | if ( ! addr ) | |
450 | goto clean; | |
451 | ||
452 | for ( nlen = len; nlen > 0; --nlen ) | |
453 | if ( addr[nlen-1] != 0xFF ) | |
454 | break; | |
455 | ||
456 | for ( ; nlen > 0; --nlen ) | |
457 | if ( addr[nlen-1] != 0x00 ) | |
458 | break; | |
459 | ||
460 | if ( image == IMAGE_MMC ) | |
461 | align = 8; | |
462 | else | |
463 | align = 7; | |
464 | ||
465 | if ( ( nlen & ( ( 1ULL << align ) - 1 ) ) != 0 ) | |
466 | nlen = ((nlen >> align) + 1) << align; | |
467 | ||
468 | if ( nlen == 0 ) { | |
503 | if ( header <= 0 || nlen == (off_t)-1 ) { | |
504 | ||
505 | addr = (unsigned char *)mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0); | |
506 | ||
507 | if ( addr == MAP_FAILED ) | |
508 | addr = NULL; | |
509 | ||
510 | if ( ! addr ) | |
511 | goto clean; | |
512 | ||
513 | for ( nlen = len; nlen > 0; --nlen ) | |
514 | if ( addr[nlen-1] != 0xFF ) | |
515 | break; | |
516 | ||
517 | for ( ; nlen > 0; --nlen ) | |
518 | if ( addr[nlen-1] != 0x00 ) | |
519 | break; | |
520 | ||
521 | if ( image == IMAGE_MMC ) | |
522 | align = 8; | |
523 | else | |
524 | align = 7; | |
525 | ||
526 | if ( ( nlen & ( ( 1ULL << align ) - 1 ) ) != 0 ) | |
527 | nlen = ((nlen >> align) + 1) << align; | |
528 | ||
529 | } | |
530 | ||
531 | if ( header <= 0 && nlen == 0 ) { | |
469 | 532 | printf("File %s is empty, removing it...\n", file); |
470 | 533 | unlink(file); |
471 | 534 | } else if ( nlen != len ) { |
486 | 549 | |
487 | 550 | } |
488 | 551 | |
552 | int local_flash_image(struct image * image) { | |
553 | ||
554 | unsigned char buf[0x20000]; | |
555 | unsigned int remaining, size; | |
556 | void (*sighandler)(int); | |
557 | int min, maj, fd; | |
558 | FILE * stream; | |
559 | int ret; | |
560 | ||
561 | printf("Flash image:\n"); | |
562 | image_print_info(image); | |
563 | ||
564 | if ( image->type == IMAGE_MMC ) { | |
565 | ||
566 | maj = -1; | |
567 | min = -1; | |
568 | ||
569 | local_find_internal_mydocs(&maj, &min); | |
570 | if ( maj == -1 || min == -1 ) | |
571 | ERROR_RETURN("Cannot find MyDocs mmc device: Slot 'internal' was not found", -1); | |
572 | ||
573 | VERBOSE("Detected internal MyDocs mmc device: major=%d minor=%d\n", maj, min); | |
574 | ||
575 | fd = disk_open_dev(maj, min, 1, simulate ? 1 : 0); | |
576 | if ( fd < 0 ) | |
577 | ERROR_RETURN("Cannot open MyDocs mmc device in /dev/", -1); | |
578 | ||
579 | ret = disk_flash_dev(fd, image); | |
580 | ||
581 | close(fd); | |
582 | ||
583 | } else { | |
584 | ||
585 | if ( device >= sizeof(nand_device)/sizeof(nand_device[0]) ) | |
586 | ERROR_RETURN("Unsupported device", -1); | |
587 | ||
588 | if ( image->type >= nand_device[device].count ) { | |
589 | ERROR("Unsupported image type: %s", image_type_to_string(image->type)); | |
590 | return -1; | |
591 | } | |
592 | ||
593 | if ( image->size > nand_device[device].args[image->type].length - nand_device[device].args[image->type].header ) | |
594 | ERROR_RETURN("Image is too big", -1); | |
595 | ||
596 | printf("Using nandwrite for flashing %s image...\n", image_type_to_string(image->type)); | |
597 | ||
598 | stream = local_nandwrite(nand_device[device].args[image->type].mtd, nand_device[device].args[image->type].offset); | |
599 | if ( ! simulate && ! stream ) | |
600 | ERROR_RETURN("Cannot start nandwrite process", -1); | |
601 | ||
602 | ret = 0; | |
603 | sighandler = signal(SIGPIPE, SIG_IGN); | |
604 | ||
605 | /* Write NOLO!img or NOLO img header with size */ | |
606 | if ( nand_device[device].args[image->type].header > 0 ) { | |
607 | if ( device == DEVICE_RX_51 ) { | |
608 | memcpy(buf, "NOLO!img\x02\x00\x00\x00\x00\x00\x00\x00", 16); | |
609 | buf[16] = (image->size >> 0) & 0xFF; | |
610 | buf[17] = (image->size >> 8) & 0xFF; | |
611 | buf[18] = (image->size >> 16) & 0xFF; | |
612 | buf[19] = (image->size >> 24) & 0xFF; | |
613 | size = 20; | |
614 | } else { | |
615 | memcpy(buf, "NOLO img", 8); | |
616 | buf[ 8] = (image->size >> 0) & 0xFF; | |
617 | buf[ 9] = (image->size >> 8) & 0xFF; | |
618 | buf[10] = (image->size >> 16) & 0xFF; | |
619 | buf[11] = (image->size >> 24) & 0xFF; | |
620 | size = 12; | |
621 | } | |
622 | ||
623 | if ( ! simulate ) { | |
624 | if ( fwrite(buf, size, 1, stream) != 1 ) { | |
625 | ret = -1; | |
626 | goto clean; | |
627 | } | |
628 | } | |
629 | ||
630 | memset(buf, 0, sizeof(buf)); | |
631 | remaining = nand_device[device].args[image->type].header - size; | |
632 | while ( remaining > 0 ) { | |
633 | size = remaining < sizeof(buf) ? remaining : sizeof(buf); | |
634 | if ( ! simulate ) { | |
635 | if ( fwrite(buf, size, 1, stream) != 1 ) { | |
636 | ret = -1; | |
637 | goto clean; | |
638 | } | |
639 | } | |
640 | remaining -= size; | |
641 | } | |
642 | } | |
643 | ||
644 | /* Write image data */ | |
645 | image_seek(image, 0); | |
646 | remaining = image->size; | |
647 | while ( remaining > 0 ) { | |
648 | size = remaining < sizeof(buf) ? remaining : sizeof(buf); | |
649 | size = image_read(image, buf, size); | |
650 | if ( size == 0 ) { | |
651 | ERROR("Failed to read image"); | |
652 | ret = -1; | |
653 | goto clean; | |
654 | } | |
655 | if ( ! simulate ) { | |
656 | if ( fwrite(buf, size, 1, stream) != 1 ) { | |
657 | ret = -1; | |
658 | goto clean; | |
659 | } | |
660 | } | |
661 | remaining -= size; | |
662 | } | |
663 | ||
664 | /* Write filler zeros to clear previous data */ | |
665 | memset(buf, 0, sizeof(buf)); | |
666 | remaining = nand_device[device].args[image->type].length - (image->size + nand_device[device].args[image->type].header); | |
667 | while ( remaining > 0 ) { | |
668 | size = remaining < sizeof(buf) ? remaining : sizeof(buf); | |
669 | if ( ! simulate ) { | |
670 | if ( fwrite(buf, size, 1, stream) != 1 ) { | |
671 | ret = -1; | |
672 | goto clean; | |
673 | } | |
674 | } | |
675 | remaining -= size; | |
676 | } | |
677 | ||
678 | clean: | |
679 | if ( ! simulate ) { | |
680 | if ( ret == 0 ) | |
681 | ret = pclose(stream); | |
682 | else | |
683 | pclose(stream); | |
684 | } | |
685 | ||
686 | signal(SIGPIPE, sighandler); | |
687 | ||
688 | if ( ret != 0 ) | |
689 | ERROR("Flashing failed"); | |
690 | } | |
691 | ||
692 | if ( ret == 0 ) | |
693 | printf("Done\n"); | |
694 | ||
695 | return ret; | |
696 | ||
697 | } | |
698 | ||
489 | 699 | int local_check_badblocks(const char * device) { |
490 | 700 | |
491 | 701 | ERROR("Not implemented yet"); |
142 | 142 | int noverify; |
143 | 143 | int verbose; |
144 | 144 | |
145 | /* arg = [[[dev:[hw:]]ver:]type:]file[%%lay] */ | |
145 | /* arg = [[[dev:[hw:]]ver:]type:]file[%file2%file3...%lay] */ | |
146 | 146 | static void parse_image_arg(char * arg, struct image_list ** image_first) { |
147 | 147 | |
148 | 148 | struct stat st; |
153 | 153 | char * hwrevs; |
154 | 154 | char * version; |
155 | 155 | char * layout; |
156 | char * parts; | |
156 | 157 | char * layout_file; |
158 | char * ptr; | |
157 | 159 | int fd; |
158 | 160 | |
159 | 161 | /* First check if arg is file, then try to parse arg format */ |
160 | 162 | fd = open(arg, O_RDONLY); |
161 | 163 | if ( fd >= 0 ) { |
162 | 164 | if ( fstat(fd, &st) == 0 && !S_ISDIR(st.st_mode) ) { |
163 | image = image_alloc_from_fd(fd, arg, NULL, NULL, NULL, NULL, NULL); | |
165 | image = image_alloc_from_fd(fd, arg, NULL, NULL, NULL, NULL, NULL, NULL); | |
164 | 166 | if ( ! image ) { |
165 | 167 | ERROR("Cannot load image file %s", arg); |
166 | 168 | exit(1); |
174 | 176 | exit(1); |
175 | 177 | } |
176 | 178 | |
177 | layout_file = strchr(arg, '%'); | |
178 | if ( layout_file ) | |
179 | *(layout_file++) = 0; | |
179 | parts = strchr(arg, '%'); | |
180 | if ( parts ) | |
181 | *(parts++) = 0; | |
182 | ||
183 | layout_file = parts; | |
184 | if ( layout_file ) { | |
185 | while ( ( ptr = strchr(layout_file, '%') ) ) | |
186 | layout_file = ptr+1; | |
187 | } | |
180 | 188 | |
181 | 189 | type = NULL; |
182 | 190 | device = NULL; |
236 | 244 | close(fd); |
237 | 245 | } |
238 | 246 | |
239 | image = image_alloc_from_file(file, type, device, hwrevs, version, layout); | |
247 | /* TODO: alloc parts */ | |
248 | ||
249 | image = image_alloc_from_file(file, type, device, hwrevs, version, layout, NULL); | |
240 | 250 | |
241 | 251 | if ( layout ) |
242 | 252 | free(layout); |
425 | 435 | int i; |
426 | 436 | char buf[512]; |
427 | 437 | char * ptr = NULL; |
438 | char * ptr1 = NULL; | |
439 | char * ptr2 = NULL; | |
428 | 440 | char * tmp = NULL; |
429 | 441 | |
430 | 442 | char nolo_ver[512]; |
1035 | 1047 | /* filter images by device & hwrev */ |
1036 | 1048 | if ( detected_device ) |
1037 | 1049 | filter_images_by_device(dev->detected_device, &image_first); |
1038 | if ( detected_hwrev ) | |
1050 | if ( detected_hwrev > 0 ) | |
1039 | 1051 | filter_images_by_hwrev(dev->detected_hwrev, &image_first); |
1040 | if ( fiasco_in && ( detected_device || detected_hwrev ) ) | |
1052 | if ( fiasco_in && ( detected_device || detected_hwrev > 0 ) ) | |
1041 | 1053 | fiasco_in->first = image_first; |
1042 | 1054 | |
1043 | 1055 | /* set kernel and initfs images for loading */ |
1095 | 1107 | if ( dev_load ) { |
1096 | 1108 | if ( image_kernel ) { |
1097 | 1109 | ret = dev_load_image(dev, image_kernel->image); |
1098 | if ( ret < 0 ) | |
1110 | if ( ret == -EAGAIN ) | |
1099 | 1111 | goto again; |
1100 | 1112 | |
1101 | 1113 | if ( image_kernel == image_first ) |
1109 | 1121 | |
1110 | 1122 | if ( image_initfs ) { |
1111 | 1123 | ret = dev_load_image(dev, image_initfs->image); |
1112 | if ( ret < 0 ) | |
1124 | if ( ret == -EAGAIN ) | |
1113 | 1125 | goto again; |
1114 | 1126 | |
1115 | 1127 | if ( image_initfs == image_first ) |
1128 | 1140 | while ( image_ptr ) { |
1129 | 1141 | struct image_list * next = image_ptr->next; |
1130 | 1142 | ret = dev_flash_image(dev, image_ptr->image); |
1131 | if ( ret < 0 ) | |
1143 | if ( ret == -EAGAIN ) | |
1132 | 1144 | goto again; |
1133 | 1145 | |
1134 | 1146 | if ( image_ptr == image_first ) |
1264 | 1276 | continue; |
1265 | 1277 | |
1266 | 1278 | buf[0] = 0; |
1267 | snprintf(buf, sizeof(buf), "%hd", dev->detected_hwrev); | |
1279 | if ( dev->detected_hwrev > 0 ) | |
1280 | snprintf(buf, sizeof(buf), "%hd", dev->detected_hwrev); | |
1268 | 1281 | |
1269 | 1282 | switch ( i ) { |
1270 | 1283 | case IMAGE_2ND: |
1294 | 1307 | break; |
1295 | 1308 | } |
1296 | 1309 | |
1297 | image_dump = image_alloc_from_file(image_tmp_name(i), image_type_to_string(i), device_to_string(dev->detected_device), buf, ptr, NULL); | |
1310 | /* TODO: add support for dumping mmc layout and also other mmc partitions as image data parts */ | |
1311 | ||
1312 | image_dump = image_alloc_from_file(image_tmp_name(i), image_type_to_string(i), device_to_string(dev->detected_device), buf, ptr, NULL, NULL); | |
1298 | 1313 | |
1299 | 1314 | if ( ! image_dump ) |
1300 | 1315 | continue; |
1365 | 1380 | } |
1366 | 1381 | |
1367 | 1382 | buf[0] = 0; |
1368 | snprintf(buf, sizeof(buf), "%s-%s:%hd_%s", image_type_to_string(i), device_to_string(dev->detected_device), dev->detected_hwrev, ptr); | |
1383 | snprintf(buf, sizeof(buf), "%s", image_type_to_string(i)); | |
1384 | ptr1 = buf + strlen(buf); | |
1385 | ||
1386 | if ( dev->detected_device ) { | |
1387 | snprintf(ptr1, sizeof(buf)-(ptr1-buf), "-%s", device_to_string(dev->detected_device)); | |
1388 | ptr1 += strlen(ptr1); | |
1389 | } | |
1390 | ||
1391 | if ( dev->detected_hwrev > 0 ) | |
1392 | snprintf(ptr1, sizeof(buf)-(ptr1-buf), ":%hd", dev->detected_hwrev); | |
1393 | ptr2 = ptr1 + strlen(ptr1); | |
1394 | ||
1395 | if ( ptr && ptr[0] ) | |
1396 | snprintf(ptr2, sizeof(buf)-(ptr2-buf), "_%s", ptr); | |
1369 | 1397 | |
1370 | 1398 | rename_ret = rename(image_tmp_name(i), buf); |
1371 | 1399 | rename_errno = errno; |
1380 | 1408 | errno = rename_errno; |
1381 | 1409 | ERROR_INFO("Renaming failed"); |
1382 | 1410 | |
1383 | buf[0] = 0; | |
1384 | snprintf(buf, sizeof(buf), "%s-%s_%s", image_type_to_string(i), device_to_string(dev->detected_device), ptr); | |
1411 | *ptr2 = 0; | |
1385 | 1412 | printf("Trying to rename %s image file to %s...\n", image_type_to_string(i), buf); |
1386 | 1413 | |
1387 | if ( rename(image_tmp_name(i), buf) < 0 ) | |
1414 | if ( rename(image_tmp_name(i), buf) < 0 ) { | |
1415 | ||
1388 | 1416 | ERROR_INFO("Renaming failed"); |
1417 | ||
1418 | *ptr1 = 0; | |
1419 | printf("Trying to rename %s image file to %s...\n", image_type_to_string(i), buf); | |
1420 | ||
1421 | if ( rename(image_tmp_name(i), buf) < 0 ) | |
1422 | ERROR_INFO("Renaming failed"); | |
1423 | ||
1424 | } | |
1389 | 1425 | |
1390 | 1426 | } |
1391 | 1427 |
212 | 212 | msg1 = (struct mkii_message *)buf1; |
213 | 213 | ptr = msg->data; |
214 | 214 | |
215 | /* Signature */ | |
216 | memcpy(ptr, "\x2E\x19\x01\x01", 4); | |
217 | ptr += 4; | |
218 | ||
219 | /* Space */ | |
220 | memcpy(ptr, "\x00", 1); | |
215 | /* File data header */ | |
216 | memcpy(ptr, "\x2E", 1); | |
221 | 217 | ptr += 1; |
218 | ||
219 | /* Length of file data */ | |
220 | memcpy(ptr, "\x19", 1); | |
221 | ptr += 1; | |
222 | ||
223 | /* File data (ignored): asic index: APE (0x01), device type: NAND (0x01), device index: 0 */ | |
224 | memcpy(ptr, "\x01\x01\x00", 3); | |
225 | ptr += 3; | |
222 | 226 | |
223 | 227 | /* Hash */ |
224 | 228 | hash = htons(image->hash); |
238 | 242 | memcpy(ptr, &size, 4); |
239 | 243 | ptr += 4; |
240 | 244 | |
241 | /* Space */ | |
245 | /* Load address (ignored) */ | |
242 | 246 | memcpy(ptr, "\x00\x00\x00\x00", 4); |
243 | 247 | ptr += 4; |
244 | 248 |
268 | 268 | |
269 | 269 | ptr = buf; |
270 | 270 | |
271 | /* Signature */ | |
272 | memcpy(ptr, "\x2E\x19\x01\x01", 4); | |
273 | ptr += 4; | |
274 | ||
275 | /* Space */ | |
276 | memcpy(ptr, "\x00", 1); | |
271 | /* File data header */ | |
272 | memcpy(ptr, "\x2E", 1); | |
277 | 273 | ptr += 1; |
274 | ||
275 | /* Length of file data */ | |
276 | memcpy(ptr, "\x19", 1); | |
277 | ptr += 1; | |
278 | ||
279 | /* File data (ignored by NOLO): asic index: APE (0x01), device type: NAND (0x01), device index: 0 */ | |
280 | memcpy(ptr, "\x01\x01\x00", 3); | |
281 | ptr += 3; | |
278 | 282 | |
279 | 283 | /* Hash */ |
280 | 284 | hash = htons(image->hash); |
294 | 298 | memcpy(ptr, &size, 4); |
295 | 299 | ptr += 4; |
296 | 300 | |
297 | /* Space */ | |
301 | /* Load address (ignored by NOLO) */ | |
298 | 302 | memcpy(ptr, "\x00\x00\x00\x00", 4); |
299 | 303 | ptr += 4; |
300 | 304 |