SVN-Revision: 17659master
parent
87a8e8ac10
commit
63c91af404
@ -0,0 +1,226 @@ |
||||
#include <sys/mman.h> |
||||
#include <stdint.h> |
||||
#include <stdlib.h> |
||||
#include <string.h> |
||||
#include <unistd.h> |
||||
#include <stdio.h> |
||||
#include "crc32.h" |
||||
#include "mtd.h" |
||||
#include "fis.h" |
||||
|
||||
struct fis_image_hdr { |
||||
unsigned char name[16]; |
||||
uint32_t flash_base; |
||||
uint32_t mem_base; |
||||
uint32_t size; |
||||
uint32_t entry_point; |
||||
uint32_t data_length; |
||||
} __attribute__((packed)); |
||||
|
||||
struct fis_image_crc { |
||||
uint32_t desc; |
||||
uint32_t file; |
||||
} __attribute__((packed)); |
||||
|
||||
struct fis_image_desc { |
||||
struct fis_image_hdr hdr; |
||||
char _pad[256 - sizeof(struct fis_image_hdr) - sizeof(struct fis_image_crc)]; |
||||
struct fis_image_crc crc; |
||||
} __attribute__((packed)); |
||||
|
||||
static int fis_fd = -1; |
||||
static struct fis_image_desc *fis_desc; |
||||
static int fis_erasesize = 0; |
||||
|
||||
static void |
||||
fis_close(void) |
||||
{ |
||||
if (fis_desc) |
||||
munmap(fis_desc, fis_erasesize); |
||||
|
||||
if (fis_fd >= 0) |
||||
close(fis_fd); |
||||
|
||||
fis_fd = -1; |
||||
fis_desc = NULL; |
||||
} |
||||
|
||||
static struct fis_image_desc * |
||||
fis_open(void) |
||||
{ |
||||
struct fis_image_desc *desc; |
||||
|
||||
if (fis_fd >= 0) |
||||
fis_close(); |
||||
|
||||
fis_fd = mtd_check_open("FIS directory"); |
||||
if (fis_fd < 0) |
||||
goto error; |
||||
|
||||
close(fis_fd); |
||||
fis_fd = mtd_open("FIS directory", true); |
||||
if (fis_fd < 0) |
||||
goto error; |
||||
|
||||
fis_erasesize = erasesize; |
||||
desc = mmap(NULL, erasesize, PROT_READ|PROT_WRITE, MAP_SHARED, fis_fd, 0); |
||||
if (desc == MAP_FAILED) |
||||
goto error; |
||||
|
||||
fis_desc = desc; |
||||
return desc; |
||||
|
||||
error: |
||||
fis_close(); |
||||
return NULL; |
||||
} |
||||
|
||||
int |
||||
fis_validate(struct fis_part *old, int n_old, struct fis_part *new, int n_new) |
||||
{ |
||||
struct fis_image_desc *desc; |
||||
void *end; |
||||
int found = 0; |
||||
int i; |
||||
|
||||
desc = fis_open(); |
||||
if (!desc) |
||||
return 0; |
||||
|
||||
for (i = 0; i < n_new - 1; i++) { |
||||
if (!new[i].size) { |
||||
fprintf(stderr, "FIS error: only the last partition can detect the size automatically\n"); |
||||
i = -1; |
||||
goto done; |
||||
} |
||||
} |
||||
|
||||
end = desc; |
||||
end = (char *) end + fis_erasesize; |
||||
while ((void *) desc < end) { |
||||
if (!desc->hdr.name[0] || (desc->hdr.name[0] == 0xff)) |
||||
break; |
||||
|
||||
for (i = 0; i < n_old; i++) { |
||||
if (!strncmp((char *) desc->hdr.name, (char *) old[i].name, sizeof(desc->hdr.name))) { |
||||
found++; |
||||
goto next; |
||||
} |
||||
} |
||||
next: |
||||
desc++; |
||||
continue; |
||||
} |
||||
|
||||
if (found == n_old) |
||||
i = 1; |
||||
else |
||||
i = -1; |
||||
|
||||
done: |
||||
fis_close(); |
||||
return i; |
||||
} |
||||
|
||||
int |
||||
fis_remap(struct fis_part *old, int n_old, struct fis_part *new, int n_new) |
||||
{ |
||||
struct fis_image_desc *fisdir = NULL; |
||||
struct fis_image_desc *redboot = NULL; |
||||
struct fis_image_desc *first = NULL; |
||||
struct fis_image_desc *last = NULL; |
||||
struct fis_image_desc *desc; |
||||
struct fis_part *part; |
||||
uint32_t offset = 0, size = 0; |
||||
char *end, *tmp; |
||||
int i; |
||||
|
||||
desc = fis_open(); |
||||
if (!desc) |
||||
return -1; |
||||
|
||||
if (!quiet) |
||||
fprintf(stderr, "Updating FIS table... \n"); |
||||
|
||||
end = (char *) desc + fis_erasesize; |
||||
while ((char *) desc < end) { |
||||
if (!desc->hdr.name[0] || (desc->hdr.name[0] == 0xff)) |
||||
break; |
||||
|
||||
if (!strcmp((char *) desc->hdr.name, "FIS directory")) |
||||
fisdir = desc; |
||||
|
||||
if (!strcmp((char *) desc->hdr.name, "RedBoot")) |
||||
redboot = desc; |
||||
|
||||
for (i = 0; i < n_old; i++) { |
||||
if (!strncmp((char *) desc->hdr.name, (char *) old[i].name, sizeof(desc->hdr.name))) { |
||||
size += desc->hdr.size; |
||||
last = desc; |
||||
if (!first) |
||||
first = desc; |
||||
break; |
||||
} |
||||
} |
||||
desc++; |
||||
} |
||||
desc--; |
||||
|
||||
if (desc == last) { |
||||
desc = fisdir; |
||||
} |
||||
|
||||
/* size fixup */ |
||||
if (desc && (last->hdr.flash_base < desc->hdr.flash_base - last->hdr.size)) |
||||
size += (desc->hdr.flash_base - last->hdr.flash_base) - last->hdr.size; |
||||
|
||||
#ifdef notyet |
||||
desc = first - 1; |
||||
if (redboot && (desc >= redboot)) { |
||||
if (first->hdr.flash_base - desc->hdr.size > desc->hdr.flash_base) { |
||||
int delta = first->hdr.flash_base - desc->hdr.size - desc->hdr.flash_base; |
||||
|
||||
offset -= delta; |
||||
size += delta; |
||||
} |
||||
} |
||||
#endif |
||||
|
||||
last++; |
||||
desc = first + n_new; |
||||
offset = first->hdr.flash_base; |
||||
|
||||
if (desc != last) { |
||||
if (desc > last) |
||||
tmp = (char *) desc; |
||||
else |
||||
tmp = (char *) last; |
||||
|
||||
memmove(desc, last, end - tmp); |
||||
if (desc < last) { |
||||
tmp = end - (last - desc) * sizeof(struct fis_image_desc); |
||||
memset(tmp, 0xff, tmp - end); |
||||
} |
||||
} |
||||
|
||||
for (part = new, desc = first; desc < first + n_new; desc++, part++) { |
||||
memset(desc, 0, sizeof(struct fis_image_desc)); |
||||
memcpy(desc->hdr.name, part->name, sizeof(desc->hdr.name)); |
||||
desc->crc.desc = 0; |
||||
desc->crc.file = 0; |
||||
|
||||
desc->hdr.flash_base = offset; |
||||
desc->hdr.mem_base = part->loadaddr; |
||||
desc->hdr.entry_point = part->loadaddr; |
||||
desc->hdr.size = (part->size > 0) ? part->size : size; |
||||
desc->hdr.data_length = desc->hdr.size; |
||||
|
||||
offset += desc->hdr.size; |
||||
size -= desc->hdr.size; |
||||
} |
||||
|
||||
msync(fis_desc, fis_erasesize, MS_SYNC|MS_INVALIDATE); |
||||
fis_close(); |
||||
|
||||
return 0; |
||||
} |
@ -0,0 +1,14 @@ |
||||
#ifndef __FIS_H |
||||
#define __FIS_H |
||||
|
||||
struct fis_part { |
||||
unsigned char name[16]; |
||||
uint32_t offset; |
||||
uint32_t loadaddr; |
||||
uint32_t size; |
||||
}; |
||||
|
||||
int fis_validate(struct fis_part *old, int n_old, struct fis_part *new, int n_new); |
||||
int fis_remap(struct fis_part *old, int n_old, struct fis_part *new, int n_new); |
||||
|
||||
#endif |
Loading…
Reference in new issue