2 * $Id: redboot.c,v 1.6 2001/10/25 09:16:06 dwmw2 Exp $
4 * Parse RedBoot-style Flash Image System (FIS) tables and
5 * produce a Linux partition array to match.
8 #include <linux/kernel.h>
9 #include <linux/slab.h>
11 #include <linux/mtd/mtd.h>
12 #include <linux/mtd/partitions.h>
14 struct fis_image_desc {
15 unsigned char name[16]; // Null terminated name
16 unsigned long flash_base; // Address within FLASH of image
17 unsigned long mem_base; // Address in memory where it executes
18 unsigned long size; // Length of image
19 unsigned long entry_point; // Execution entry point
20 unsigned long data_length; // Length of actual data
21 unsigned char _pad[256-(16+7*sizeof(unsigned long))];
22 unsigned long desc_cksum; // Checksum over image descriptor
23 unsigned long file_cksum; // Checksum over image data
27 struct fis_image_desc *img;
28 struct fis_list *next;
31 static inline int redboot_checksum(struct fis_image_desc *img)
33 /* RedBoot doesn't actually write the desc_cksum field yet AFAICT */
37 int parse_redboot_partitions(struct mtd_info *master, struct mtd_partition **pparts)
40 struct fis_image_desc *buf;
41 struct mtd_partition *parts;
42 struct fis_list *fl = NULL, *tmp_fl;
48 buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
53 /* Read the start of the last erase block */
54 ret = master->read(master, master->size - master->erasesize,
55 PAGE_SIZE, &retlen, (void *)buf);
60 if (retlen != PAGE_SIZE) {
65 /* RedBoot image could appear in any of the first three slots */
66 for (i = 0; i < 3; i++) {
67 if (!memcmp(buf[i].name, "RedBoot", 8))
72 printk(KERN_NOTICE "No RedBoot partition table detected in %s\n",
78 for (i = 0; i < PAGE_SIZE / sizeof(struct fis_image_desc); i++) {
79 struct fis_list *new_fl, **prev;
81 if (buf[i].name[0] == 0xff)
83 if (!redboot_checksum(&buf[i]))
86 new_fl = kmalloc(sizeof(struct fis_list), GFP_KERNEL);
87 namelen += strlen(buf[i].name)+1;
92 new_fl->img = &buf[i];
93 buf[i].flash_base &= master->size-1;
95 /* I'm sure the JFFS2 code has done me permanent damage.
96 * I now think the following is _normal_
99 while(*prev && (*prev)->img->flash_base < new_fl->img->flash_base)
100 prev = &(*prev)->next;
101 new_fl->next = *prev;
106 if (fl->img->flash_base)
109 for (tmp_fl = fl; tmp_fl->next; tmp_fl = tmp_fl->next) {
110 if (tmp_fl->img->flash_base + tmp_fl->img->size + master->erasesize < tmp_fl->next->img->flash_base)
113 parts = kmalloc(sizeof(*parts)*nrparts + namelen, GFP_KERNEL);
119 names = (char *)&parts[nrparts];
120 memset(parts, 0, sizeof(*parts)*nrparts + namelen);
123 if (fl->img->flash_base) {
124 parts[0].name = "unallocated space";
125 parts[0].size = fl->img->flash_base;
128 for ( ; i<nrparts; i++) {
129 parts[i].size = fl->img->size;
130 parts[i].offset = fl->img->flash_base;
131 parts[i].name = names;
133 strcpy(names, fl->img->name);
134 names += strlen(names)+1;
136 if(fl->next && fl->img->flash_base + fl->img->size + master->erasesize < fl->next->img->flash_base) {
138 parts[i].offset = parts[i-1].size + parts[i-1].offset;
139 parts[i].size = fl->next->img->flash_base - parts[i].offset;
140 parts[i].name = "unallocated space";
150 struct fis_list *old = fl;
158 EXPORT_SYMBOL(parse_redboot_partitions);
160 MODULE_LICENSE("GPL");
161 MODULE_AUTHOR("Red Hat, Inc. - David Woodhouse <dwmw2@cambridge.redhat.com>");
162 MODULE_DESCRIPTION("Parsing code for RedBoot Flash Image System (FIS) tables");