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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [redboot/] [current/] [src/] [fs/] [disk.c] - Blame information for rev 856

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 786 skrzyp
//==========================================================================
2
//
3
//      disk.c
4
//
5
//      RedBoot disk support
6
//
7
//==========================================================================
8
// ####ECOSGPLCOPYRIGHTBEGIN####                                            
9
// -------------------------------------------                              
10
// This file is part of eCos, the Embedded Configurable Operating System.   
11
// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004 Free Software Foundation, Inc.
12
//
13
// eCos is free software; you can redistribute it and/or modify it under    
14
// the terms of the GNU General Public License as published by the Free     
15
// Software Foundation; either version 2 or (at your option) any later      
16
// version.                                                                 
17
//
18
// eCos is distributed in the hope that it will be useful, but WITHOUT      
19
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or    
20
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License    
21
// for more details.                                                        
22
//
23
// You should have received a copy of the GNU General Public License        
24
// along with eCos; if not, write to the Free Software Foundation, Inc.,    
25
// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.            
26
//
27
// As a special exception, if other files instantiate templates or use      
28
// macros or inline functions from this file, or you compile this file      
29
// and link it with other works to produce a work based on this file,       
30
// this file does not by itself cause the resulting work to be covered by   
31
// the GNU General Public License. However the source code for this file    
32
// must still be made available in accordance with section (3) of the GNU   
33
// General Public License v2.                                               
34
//
35
// This exception does not invalidate any other reasons why a work based    
36
// on this file might be covered by the GNU General Public License.         
37
// -------------------------------------------                              
38
// ####ECOSGPLCOPYRIGHTEND####                                              
39
//==========================================================================
40
//#####DESCRIPTIONBEGIN####
41
//
42
// Author(s):    msalter
43
// Contributors: msalter
44
// Date:         2001-07-14
45
// Purpose:      
46
// Description:  
47
//              
48
// This code is part of RedBoot (tm).
49
//
50
//####DESCRIPTIONEND####
51
//
52
//==========================================================================
53
 
54
#include <redboot.h>
55
#include <fs/disk.h>
56
 
57
#ifdef CYGSEM_REDBOOT_DISK_EXT2FS
58
#include <fs/e2fs.h>
59
#endif
60
#ifdef CYGSEM_REDBOOT_DISK_ISO9660
61
#include <fs/iso9660fs.h>
62
#endif
63
 
64
static void do_disks(int argc, char *argv[]);
65
 
66
RedBoot_cmd("disks",
67
            "Display disks/partitions.",
68
            "",
69
            do_disks
70
    );
71
 
72
static disk_t disk_table[CYGNUM_REDBOOT_MAX_DISKS];
73
static int    disk_count = 0;
74
 
75
static inline cyg_uint32
76
u32_unaligned(void *p)
77
{
78
    cyg_uint32 val;
79
    char *d = (char *)&val;
80
    char *s = p;
81
    int i;
82
 
83
    for (i = 0; i < 4; i++)
84
        *d++ = *s++;
85
 
86
    return val;
87
}
88
 
89
static int
90
find_dos_partitions(disk_t *d, cyg_uint8 *mbr)
91
{
92
    cyg_uint32 s, n;
93
    struct mbr_partition *p;
94
    int i, found = 0;
95
 
96
    p = (struct mbr_partition *)(mbr + MBR_PTABLE_OFFSET);
97
 
98
    // Look for primary partitions
99
    for (i = 0; i < 4 && i < CYGNUM_REDBOOT_MAX_PARTITIONS; i++) {
100
 
101
        s = SWAB_LE32(u32_unaligned(p->start_sect));
102
        n = SWAB_LE32(u32_unaligned(p->nr_sects));
103
 
104
        if (s && n) {
105
            ++found;
106
            d->partitions[i].disk = d;
107
            d->partitions[i].start_sector = s;
108
            d->partitions[i].nr_sectors = n;
109
            d->partitions[i].systype = p->sys_ind;
110
            d->partitions[i].bootflag = p->boot_ind;
111
        }
112
        p++;
113
    }
114
 
115
#if CYGNUM_REDBOOT_MAX_PARTITIONS > 4
116
    {
117
        cyg_uint32 buf[SECTOR_SIZE/sizeof(cyg_uint32)], xoffset;
118
        cyg_uint16 magic;
119
        int nextp;
120
 
121
        // Go back through and find extended partitions
122
        for (i = 0, nextp = 4; i < 4 && nextp < CYGNUM_REDBOOT_MAX_PARTITIONS; i++) {
123
            if (d->partitions[i].systype == SYSTYPE_EXTENDED) {
124
                // sector offsets in partition tables are relative to start
125
                // of extended partition.
126
                xoffset = d->partitions[i].start_sector;
127
                for ( ; nextp < CYGNUM_REDBOOT_MAX_PARTITIONS; ++nextp) {
128
 
129
                    // read partition boot record (same format as mbr except
130
                    // there should only be 2 entries max: a normal partition
131
                    // and another extended partition
132
                    if (DISK_READ(d, xoffset, buf, 1) <= 0)
133
                        break;
134
 
135
                    magic = *(cyg_uint16 *)((char *)buf + MBR_MAGIC_OFFSET);
136
                    if (SWAB_LE16(magic) != MBR_MAGIC)
137
                        break;
138
 
139
                    p = (struct mbr_partition *)((char *)buf + MBR_PTABLE_OFFSET);
140
 
141
                    s = SWAB_LE32(u32_unaligned(p->start_sect));
142
                    n = SWAB_LE32(u32_unaligned(p->nr_sects));
143
 
144
                    if (s && n) {
145
                        ++found;
146
                        d->partitions[nextp].disk = d;
147
                        d->partitions[nextp].start_sector = s + xoffset;
148
                        d->partitions[nextp].nr_sectors = n;
149
                        d->partitions[nextp].systype = p->sys_ind;
150
                        d->partitions[nextp].bootflag = p->boot_ind;
151
                    }
152
                    ++p;
153
 
154
                    s = SWAB_LE32(u32_unaligned(p->start_sect));
155
                    n = SWAB_LE32(u32_unaligned(p->nr_sects));
156
 
157
                    // more extended partitions?
158
                    if (p->sys_ind != SYSTYPE_EXTENDED || !s || !n)
159
                        break;
160
 
161
                    xoffset += s;
162
                }
163
            }
164
        }
165
    }
166
#endif
167
    return found;
168
}
169
 
170
 
171
// Find partitions on given disk.
172
// Return number of partitions found
173
static int
174
find_partitions(disk_t *d)
175
{
176
    cyg_uint32 buf[SECTOR_SIZE/sizeof(cyg_uint32)];
177
    cyg_uint16 magic;
178
    partition_t *p;
179
    int i, found = 0;
180
 
181
 
182
    if (d->kind == DISK_IDE_CDROM) {
183
#ifdef CYGSEM_REDBOOT_DISK_ISO9660
184
        // no partition table, so fake it
185
        p = d->partitions;
186
        p->disk = d;
187
        p->start_sector = 0;
188
        p->nr_sectors = d->nr_sectors;
189
        p->funs = &redboot_iso9660fs_funs;
190
        return 1;
191
#else
192
        return 0;
193
#endif
194
    }
195
 
196
    // read Master Boot Record
197
    if (DISK_READ(d, 0, buf, 1) <= 0)
198
        return 0;
199
 
200
    // Check for DOS MBR
201
    magic = *(cyg_uint16 *)((char *)buf + MBR_MAGIC_OFFSET);
202
    if (SWAB_LE16(magic) == MBR_MAGIC) {
203
        found = find_dos_partitions(d, (cyg_uint8 *)buf);
204
    } else {
205
        // Might want to handle other MBR types, here...
206
    }
207
 
208
    // Now go through all partitions and install the correct
209
    // funcs for supported filesystems.
210
    for (i = 0, p = d->partitions; i < CYGNUM_REDBOOT_MAX_PARTITIONS; i++, p++) {
211
        switch (p->systype) {
212
#ifdef CYGSEM_REDBOOT_DISK_EXT2FS
213
          case SYSTYPE_LINUX:
214
            p->funs = &redboot_e2fs_funs;
215
            break;
216
#endif
217
#ifdef CYGSEM_REDBOOT_DISK_FAT16
218
          case SYSTYPE_FAT16:
219
            p->funs = &redboot_fat16_funs;
220
            break;
221
#endif
222
#ifdef CYGSEM_REDBOOT_DISK_FAT32
223
          case SYSTYPE_FAT32:
224
            p->funs = &redboot_fat32_funs;
225
            break;
226
#endif
227
          default:
228
            break;  // ignore unsupported filesystems
229
        }
230
    }
231
 
232
    return found;
233
}
234
 
235
// Add a disk to the disk table.
236
// Return zero if no more room in table.
237
externC int
238
disk_register(disk_t *d)
239
{
240
    int i;
241
 
242
    // make sure we have room for it
243
    if (disk_count >= CYGNUM_REDBOOT_MAX_DISKS)
244
        return 0;
245
 
246
    // Set the index
247
    d->index = 0;
248
    for (i = 0; i < disk_count; i++)
249
        if (disk_table[i].kind == d->kind)
250
            d->index++;
251
 
252
    // put it in the table
253
    disk_table[disk_count] = *d;
254
 
255
    // fill in partition info
256
    find_partitions(&disk_table[disk_count++]);
257
 
258
    return 1;
259
}
260
 
261
// Convert a filename in the form <partition_name>:<filename> into
262
// a partition and path.
263
//
264
static int
265
disk_parse_filename(const char *name, partition_t **part, const char **path)
266
{
267
    int i, kind, index, pindex;
268
 
269
    kind = index = pindex = 0;
270
 
271
    if (name[0] == 'h' && name[1] == 'd') {
272
        // IDE hard drives
273
        kind = DISK_IDE_HD;
274
        if (name[2] < 'a' || name[2] > 'z')
275
            return 0;
276
        index = name[2] - 'a';
277
        if (name[3] < '1' || name[3] >= ('1' + CYGNUM_REDBOOT_MAX_PARTITIONS))
278
            return 0;
279
        pindex = name[3] - '1';
280
        if (name[4] != ':')
281
            return 0;
282
        *path = &name[5];
283
    }
284
#ifdef CYGSEM_REDBOOT_DISK_ISO9660
285
    else if (name[0] == 'c' && name[1] == 'd') {
286
        // CD drives
287
        kind = DISK_IDE_CDROM;
288
        if (name[2] < '0' || name[2] > '9')
289
            return 0;
290
        index = name[2] - '0';
291
        if (name[3] != ':')
292
            return 0;
293
        *path = &name[4];
294
    }
295
#endif
296
 
297
    if (kind) {
298
        for (i = 0; i < CYGNUM_REDBOOT_MAX_DISKS; i++) {
299
            if (disk_table[i].kind == kind && disk_table[i].index == index) {
300
                *part = &disk_table[i].partitions[pindex];
301
                return 1;
302
            }
303
        }
304
    }
305
    return 0;
306
}
307
 
308
static const struct {
309
    int        kind;
310
    const char *str;
311
} systype_names[] = {
312
    { SYSTYPE_FAT12,      "FAT12" },
313
    { SYSTYPE_FAT16_32M,  "FAT16 <32M" },
314
    { SYSTYPE_FAT16,      "FAT16" },
315
    { SYSTYPE_EXTENDED,   "Extended" },
316
    { SYSTYPE_LINUX_SWAP, "Linux Swap" },
317
    { SYSTYPE_LINUX,      "Linux" }
318
};
319
 
320
static const char *
321
systype_name(int systype)
322
{
323
    int i;
324
 
325
    for (i = 0; i < sizeof(systype_names)/sizeof(systype_names[0]); i++)
326
        if (systype_names[i].kind == systype)
327
            return systype_names[i].str;
328
    return "Unknown";
329
}
330
 
331
// List disk partitions
332
static void
333
do_disks(int argc, char *argv[])
334
{
335
    int i, j;
336
    disk_t *d;
337
    partition_t *p;
338
    char name[16];
339
 
340
    for (i = 0, d = disk_table;  i < disk_count;  i++, d++) {
341
        switch (d->kind) {
342
          case DISK_IDE_HD:
343
            for (j = 0, p = d->partitions;
344
                 j < CYGNUM_REDBOOT_MAX_PARTITIONS;
345
                 j++, p++) {
346
                if (p->systype) {
347
                    diag_sprintf(name, "hd%c%d", 'a' + d->index, j+1);
348
                    diag_printf("%-8s %s\n", name, systype_name(p->systype));
349
                }
350
            }
351
            break;
352
          case DISK_IDE_CDROM:
353
            diag_sprintf(name, "cd%d", d->index);
354
            diag_printf("%-8s ISO9660\n", name);
355
            break;
356
        }
357
    }
358
}
359
 
360
static void *fileptr;
361
static partition_t *file_part;
362
 
363
externC int
364
disk_stream_open(connection_info_t *info, int *err)
365
{
366
    const char *filepath;
367
    char *filename = info->filename;
368
 
369
    // The filename is in <disk>:<path> format.
370
    // Convert to a partition and path.
371
    if (!disk_parse_filename(filename, &file_part, &filepath)) {
372
        *err = diskerr_badname;
373
        return -1;
374
    }
375
 
376
    if (file_part->disk->kind != DISK_IDE_CDROM && file_part->systype == 0) {
377
        *err = diskerr_partition;
378
        return -1;
379
    }
380
 
381
    if (file_part->funs == (fs_funs_t *)0) {
382
        *err = diskerr_partition;
383
        return -1;
384
    }
385
 
386
    fileptr = (file_part->funs->open)(file_part, filepath);
387
    if (fileptr == NULL) {
388
        *err = diskerr_open;
389
        return -1;
390
    }
391
    return 0;
392
}
393
 
394
externC int
395
disk_stream_read(char *buf, int size, int *err)
396
{
397
    int nread;
398
 
399
    if ((nread = (file_part->funs->read)(fileptr, buf, size)) < 0) {
400
        *err = diskerr_read;
401
        return -1;
402
    }
403
    return nread;
404
}
405
 
406
externC void
407
disk_stream_close(int *err)
408
{
409
    fileptr = NULL;
410
}
411
 
412
externC char *
413
disk_error(int err)
414
{
415
    switch (err) {
416
    case diskerr_badname:
417
        return "Bad filename";
418
        break;
419
    case diskerr_partition:
420
        return "Unsupported filesystem";
421
        break;
422
    case diskerr_open:
423
        return "Can't open file";
424
        break;
425
    case diskerr_read:
426
        return "Can't read file";
427
        break;
428
    default:
429
        return "Unknown error";
430
        break;
431
    }
432
}
433
 
434
//
435
// RedBoot interface
436
//
437
GETC_IO_FUNCS(disk_io, disk_stream_open, disk_stream_close,
438
              0, disk_stream_read, disk_error);
439
RedBoot_load(disk, disk_io, true, true, 0);

powered by: WebSVN 2.1.0

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