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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [ecos-2.0/] [packages/] [redboot/] [v2_0/] [src/] [fs/] [disk.c] - Blame information for rev 1773

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

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