2 * FIS table updating code for mtd
4 * Copyright (C) 2009 Felix Fietkau <nbd@openwrt.org>
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License v2
8 * as published by the Free Software Foundation.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
25 struct fis_image_hdr
{
26 unsigned char name
[16];
32 } __attribute__((packed
));
34 struct fis_image_crc
{
37 } __attribute__((packed
));
39 struct fis_image_desc
{
40 struct fis_image_hdr hdr
;
41 char _pad
[256 - sizeof(struct fis_image_hdr
) - sizeof(struct fis_image_crc
)];
42 struct fis_image_crc crc
;
43 } __attribute__((packed
));
45 static int fis_fd
= -1;
46 static struct fis_image_desc
*fis_desc
;
47 static int fis_erasesize
= 0;
53 munmap(fis_desc
, fis_erasesize
);
62 static struct fis_image_desc
*
65 struct fis_image_desc
*desc
;
70 fis_fd
= mtd_check_open("FIS directory");
75 fis_fd
= mtd_open("FIS directory", true);
79 fis_erasesize
= erasesize
;
80 desc
= mmap(NULL
, erasesize
, PROT_READ
|PROT_WRITE
, MAP_SHARED
|MAP_LOCKED
, fis_fd
, 0);
81 if (desc
== MAP_FAILED
)
93 fis_validate(struct fis_part
*old
, int n_old
, struct fis_part
*new, int n_new
)
95 struct fis_image_desc
*desc
;
104 for (i
= 0; i
< n_new
- 1; i
++) {
106 fprintf(stderr
, "FIS error: only the last partition can detect the size automatically\n");
113 end
= (char *) end
+ fis_erasesize
;
114 while ((void *) desc
< end
) {
115 if (!desc
->hdr
.name
[0] || (desc
->hdr
.name
[0] == 0xff))
118 for (i
= 0; i
< n_old
; i
++) {
119 if (!strncmp((char *) desc
->hdr
.name
, (char *) old
[i
].name
, sizeof(desc
->hdr
.name
))) {
140 fis_remap(struct fis_part
*old
, int n_old
, struct fis_part
*new, int n_new
)
142 struct fis_image_desc
*fisdir
= NULL
;
143 struct fis_image_desc
*redboot
= NULL
;
144 struct fis_image_desc
*first
= NULL
;
145 struct fis_image_desc
*last
= NULL
;
146 struct fis_image_desc
*first_fb
= NULL
;
147 struct fis_image_desc
*last_fb
= NULL
;
148 struct fis_image_desc
*desc
;
149 struct fis_part
*part
;
150 uint32_t offset
= 0, size
= 0;
151 char *start
, *end
, *tmp
;
159 fprintf(stderr
, "Updating FIS table... \n");
161 start
= (char *) desc
;
162 end
= (char *) desc
+ fis_erasesize
;
163 while ((char *) desc
< end
) {
164 if (!desc
->hdr
.name
[0] || (desc
->hdr
.name
[0] == 0xff))
167 if (!strcmp((char *) desc
->hdr
.name
, "FIS directory"))
170 if (!strcmp((char *) desc
->hdr
.name
, "RedBoot"))
173 /* update max offset */
174 if (offset
< desc
->hdr
.flash_base
)
175 offset
= desc
->hdr
.flash_base
;
177 for (i
= 0; i
< n_old
; i
++) {
178 if (!strncmp((char *) desc
->hdr
.name
, (char *) old
[i
].name
, sizeof(desc
->hdr
.name
))) {
192 if (first_fb
->hdr
.flash_base
> last_fb
->hdr
.flash_base
) {
197 /* determine size of available space */
198 desc
= (struct fis_image_desc
*) start
;
199 while ((char *) desc
< end
) {
200 if (!desc
->hdr
.name
[0] || (desc
->hdr
.name
[0] == 0xff))
203 if (desc
->hdr
.flash_base
> last_fb
->hdr
.flash_base
&&
204 desc
->hdr
.flash_base
< offset
)
205 offset
= desc
->hdr
.flash_base
;
211 size
= offset
- first_fb
->hdr
.flash_base
;
215 if (redboot
&& (desc
>= redboot
)) {
216 if (first
->hdr
.flash_base
- desc
->hdr
.size
> desc
->hdr
.flash_base
) {
217 int delta
= first
->hdr
.flash_base
- desc
->hdr
.size
- desc
->hdr
.flash_base
;
226 desc
= first
+ n_new
;
227 offset
= first_fb
->hdr
.flash_base
;
235 memmove(desc
, last
, end
- tmp
);
237 tmp
= end
- (last
- desc
) * sizeof(struct fis_image_desc
);
238 memset(tmp
, 0xff, tmp
- end
);
242 for (part
= new, desc
= first
; desc
< first
+ n_new
; desc
++, part
++) {
243 memset(desc
, 0, sizeof(struct fis_image_desc
));
244 memcpy(desc
->hdr
.name
, part
->name
, sizeof(desc
->hdr
.name
));
248 desc
->hdr
.flash_base
= offset
;
249 desc
->hdr
.mem_base
= part
->loadaddr
;
250 desc
->hdr
.entry_point
= part
->loadaddr
;
251 desc
->hdr
.size
= (part
->size
> 0) ? part
->size
: size
;
252 desc
->hdr
.data_length
= desc
->hdr
.size
;
254 offset
+= desc
->hdr
.size
;
255 size
-= desc
->hdr
.size
;
258 msync(fis_desc
, fis_erasesize
, MS_SYNC
|MS_INVALIDATE
);