OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [mtd/] [redboot.c] - Blame information for rev 62

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
2
 * $Id: redboot.c,v 1.21 2006/03/30 18:34:37 bjd Exp $
3
 *
4
 * Parse RedBoot-style Flash Image System (FIS) tables and
5
 * produce a Linux partition array to match.
6
 */
7
 
8
#include <linux/kernel.h>
9
#include <linux/slab.h>
10
#include <linux/init.h>
11
#include <linux/vmalloc.h>
12
 
13
#include <linux/mtd/mtd.h>
14
#include <linux/mtd/partitions.h>
15
 
16
struct fis_image_desc {
17
    unsigned char name[16];      // Null terminated name
18
    uint32_t      flash_base;    // Address within FLASH of image
19
    uint32_t      mem_base;      // Address in memory where it executes
20
    uint32_t      size;          // Length of image
21
    uint32_t      entry_point;   // Execution entry point
22
    uint32_t      data_length;   // Length of actual data
23
    unsigned char _pad[256-(16+7*sizeof(uint32_t))];
24
    uint32_t      desc_cksum;    // Checksum over image descriptor
25
    uint32_t      file_cksum;    // Checksum over image data
26
};
27
 
28
struct fis_list {
29
        struct fis_image_desc *img;
30
        struct fis_list *next;
31
};
32
 
33
static int directory = CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK;
34
module_param(directory, int, 0);
35
 
36
static inline int redboot_checksum(struct fis_image_desc *img)
37
{
38
        /* RedBoot doesn't actually write the desc_cksum field yet AFAICT */
39
        return 1;
40
}
41
 
42
static int parse_redboot_partitions(struct mtd_info *master,
43
                             struct mtd_partition **pparts,
44
                             unsigned long fis_origin)
45
{
46
        int nrparts = 0;
47
        struct fis_image_desc *buf;
48
        struct mtd_partition *parts;
49
        struct fis_list *fl = NULL, *tmp_fl;
50
        int ret, i;
51
        size_t retlen;
52
        char *names;
53
        char *nullname;
54
        int namelen = 0;
55
        int nulllen = 0;
56
        int numslots;
57
        unsigned long offset;
58
#ifdef CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED
59
        static char nullstring[] = "unallocated";
60
#endif
61
 
62
        buf = vmalloc(master->erasesize);
63
 
64
        if (!buf)
65
                return -ENOMEM;
66
 
67
        if ( directory < 0 )
68
                offset = master->size + directory*master->erasesize;
69
        else
70
                offset = directory*master->erasesize;
71
 
72
        printk(KERN_NOTICE "Searching for RedBoot partition table in %s at offset 0x%lx\n",
73
               master->name, offset);
74
 
75
        ret = master->read(master, offset,
76
                           master->erasesize, &retlen, (void *)buf);
77
 
78
        if (ret)
79
                goto out;
80
 
81
        if (retlen != master->erasesize) {
82
                ret = -EIO;
83
                goto out;
84
        }
85
 
86
        numslots = (master->erasesize / sizeof(struct fis_image_desc));
87
        for (i = 0; i < numslots; i++) {
88
                if (!memcmp(buf[i].name, "FIS directory", 14)) {
89
                        /* This is apparently the FIS directory entry for the
90
                         * FIS directory itself.  The FIS directory size is
91
                         * one erase block; if the buf[i].size field is
92
                         * swab32(erasesize) then we know we are looking at
93
                         * a byte swapped FIS directory - swap all the entries!
94
                         * (NOTE: this is 'size' not 'data_length'; size is
95
                         * the full size of the entry.)
96
                         */
97
 
98
                        /* RedBoot can combine the FIS directory and
99
                           config partitions into a single eraseblock;
100
                           we assume wrong-endian if either the swapped
101
                           'size' matches the eraseblock size precisely,
102
                           or if the swapped size actually fits in an
103
                           eraseblock while the unswapped size doesn't. */
104
                        if (swab32(buf[i].size) == master->erasesize ||
105
                            (buf[i].size > master->erasesize
106
                             && swab32(buf[i].size) < master->erasesize)) {
107
                                int j;
108
                                /* Update numslots based on actual FIS directory size */
109
                                numslots = swab32(buf[i].size) / sizeof (struct fis_image_desc);
110
                                for (j = 0; j < numslots; ++j) {
111
 
112
                                        /* A single 0xff denotes a deleted entry.
113
                                         * Two of them in a row is the end of the table.
114
                                         */
115
                                        if (buf[j].name[0] == 0xff) {
116
                                                if (buf[j].name[1] == 0xff) {
117
                                                        break;
118
                                                } else {
119
                                                        continue;
120
                                                }
121
                                        }
122
 
123
                                        /* The unsigned long fields were written with the
124
                                         * wrong byte sex, name and pad have no byte sex.
125
                                         */
126
                                        swab32s(&buf[j].flash_base);
127
                                        swab32s(&buf[j].mem_base);
128
                                        swab32s(&buf[j].size);
129
                                        swab32s(&buf[j].entry_point);
130
                                        swab32s(&buf[j].data_length);
131
                                        swab32s(&buf[j].desc_cksum);
132
                                        swab32s(&buf[j].file_cksum);
133
                                }
134
                        } else if (buf[i].size < master->erasesize) {
135
                                /* Update numslots based on actual FIS directory size */
136
                                numslots = buf[i].size / sizeof(struct fis_image_desc);
137
                        }
138
                        break;
139
                }
140
        }
141
        if (i == numslots) {
142
                /* Didn't find it */
143
                printk(KERN_NOTICE "No RedBoot partition table detected in %s\n",
144
                       master->name);
145
                ret = 0;
146
                goto out;
147
        }
148
 
149
        for (i = 0; i < numslots; i++) {
150
                struct fis_list *new_fl, **prev;
151
 
152
                if (buf[i].name[0] == 0xff) {
153
                        if (buf[i].name[1] == 0xff) {
154
                                break;
155
                        } else {
156
                                continue;
157
                        }
158
                }
159
                if (!redboot_checksum(&buf[i]))
160
                        break;
161
 
162
                new_fl = kmalloc(sizeof(struct fis_list), GFP_KERNEL);
163
                namelen += strlen(buf[i].name)+1;
164
                if (!new_fl) {
165
                        ret = -ENOMEM;
166
                        goto out;
167
                }
168
                new_fl->img = &buf[i];
169
                if (fis_origin) {
170
                        buf[i].flash_base -= fis_origin;
171
                } else {
172
                        buf[i].flash_base &= master->size-1;
173
                }
174
 
175
                /* I'm sure the JFFS2 code has done me permanent damage.
176
                 * I now think the following is _normal_
177
                 */
178
                prev = &fl;
179
                while(*prev && (*prev)->img->flash_base < new_fl->img->flash_base)
180
                        prev = &(*prev)->next;
181
                new_fl->next = *prev;
182
                *prev = new_fl;
183
 
184
                nrparts++;
185
        }
186
#ifdef CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED
187
        if (fl->img->flash_base) {
188
                nrparts++;
189
                nulllen = sizeof(nullstring);
190
        }
191
 
192
        for (tmp_fl = fl; tmp_fl->next; tmp_fl = tmp_fl->next) {
193
                if (tmp_fl->img->flash_base + tmp_fl->img->size + master->erasesize <= tmp_fl->next->img->flash_base) {
194
                        nrparts++;
195
                        nulllen = sizeof(nullstring);
196
                }
197
        }
198
#endif
199
        parts = kzalloc(sizeof(*parts)*nrparts + nulllen + namelen, GFP_KERNEL);
200
 
201
        if (!parts) {
202
                ret = -ENOMEM;
203
                goto out;
204
        }
205
 
206
        nullname = (char *)&parts[nrparts];
207
#ifdef CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED
208
        if (nulllen > 0) {
209
                strcpy(nullname, nullstring);
210
        }
211
#endif
212
        names = nullname + nulllen;
213
 
214
        i=0;
215
 
216
#ifdef CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED
217
        if (fl->img->flash_base) {
218
               parts[0].name = nullname;
219
               parts[0].size = fl->img->flash_base;
220
               parts[0].offset = 0;
221
                i++;
222
        }
223
#endif
224
        for ( ; i<nrparts; i++) {
225
                parts[i].size = fl->img->size;
226
                parts[i].offset = fl->img->flash_base;
227
                parts[i].name = names;
228
 
229
                strcpy(names, fl->img->name);
230
#ifdef CONFIG_MTD_REDBOOT_PARTS_READONLY
231
                if (!memcmp(names, "RedBoot", 8) ||
232
                                !memcmp(names, "RedBoot config", 15) ||
233
                                !memcmp(names, "FIS directory", 14)) {
234
                        parts[i].mask_flags = MTD_WRITEABLE;
235
                }
236
#endif
237
                names += strlen(names)+1;
238
 
239
#ifdef CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED
240
                if(fl->next && fl->img->flash_base + fl->img->size + master->erasesize <= fl->next->img->flash_base) {
241
                        i++;
242
                        parts[i].offset = parts[i-1].size + parts[i-1].offset;
243
                        parts[i].size = fl->next->img->flash_base - parts[i].offset;
244
                        parts[i].name = nullname;
245
                }
246
#endif
247
                tmp_fl = fl;
248
                fl = fl->next;
249
                kfree(tmp_fl);
250
        }
251
        ret = nrparts;
252
        *pparts = parts;
253
 out:
254
        while (fl) {
255
                struct fis_list *old = fl;
256
                fl = fl->next;
257
                kfree(old);
258
        }
259
        vfree(buf);
260
        return ret;
261
}
262
 
263
static struct mtd_part_parser redboot_parser = {
264
        .owner = THIS_MODULE,
265
        .parse_fn = parse_redboot_partitions,
266
        .name = "RedBoot",
267
};
268
 
269
static int __init redboot_parser_init(void)
270
{
271
        return register_mtd_parser(&redboot_parser);
272
}
273
 
274
static void __exit redboot_parser_exit(void)
275
{
276
        deregister_mtd_parser(&redboot_parser);
277
}
278
 
279
module_init(redboot_parser_init);
280
module_exit(redboot_parser_exit);
281
 
282
MODULE_LICENSE("GPL");
283
MODULE_AUTHOR("Red Hat, Inc. - David Woodhouse <dwmw2@cambridge.redhat.com>");
284
MODULE_DESCRIPTION("Parsing code for RedBoot Flash Image System (FIS) tables");

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.