⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 disk.c

📁 redboot 源代码
💻 C
字号:
//==========================================================================////      disk.c////      RedBoot disk support////==========================================================================//####ECOSGPLCOPYRIGHTBEGIN####// -------------------------------------------// This file is part of eCos, the Embedded Configurable Operating System.// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.// Copyright (C) 2002 Gary Thomas//// eCos is free software; you can redistribute it and/or modify it under// the terms of the GNU General Public License as published by the Free// Software Foundation; either version 2 or (at your option) any later version.//// eCos is distributed in the hope that it will be useful, but WITHOUT ANY// WARRANTY; without even the implied warranty of MERCHANTABILITY or// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License// for more details.//// You should have received a copy of the GNU General Public License along// with eCos; if not, write to the Free Software Foundation, Inc.,// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.//// As a special exception, if other files instantiate templates or use macros// or inline functions from this file, or you compile this file and link it// with other works to produce a work based on this file, this file does not// by itself cause the resulting work to be covered by the GNU General Public// License. However the source code for this file must still be made available// in accordance with section (3) of the GNU General Public License.//// This exception does not invalidate any other reasons why a work based on// this file might be covered by the GNU General Public License.//// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.// at http://sources.redhat.com/ecos/ecos-license/// -------------------------------------------//####ECOSGPLCOPYRIGHTEND####//==========================================================================//#####DESCRIPTIONBEGIN####//// Author(s):    msalter// Contributors: msalter// Date:         2001-07-14// Purpose:      // Description:  //              // This code is part of RedBoot (tm).////####DESCRIPTIONEND####////==========================================================================#include <redboot.h>#include <fs/disk.h>#ifdef CYGSEM_REDBOOT_DISK_EXT2FS#include <fs/e2fs.h>#endif#ifdef CYGSEM_REDBOOT_DISK_ISO9660#include <fs/iso9660fs.h>#endifstatic void do_disks(int argc, char *argv[]);RedBoot_cmd("disks",             "Display disks/partitions.",            "",            do_disks    );static disk_t disk_table[CYGNUM_REDBOOT_MAX_DISKS];static int    disk_count = 0;static intfind_dos_partitions(disk_t *d, cyg_uint8 *mbr){    cyg_uint32 s, n, tmp;    struct mbr_partition *p;    int i, found = 0;    p = (struct mbr_partition *)(mbr + MBR_PTABLE_OFFSET);    // Look for primary partitions    for (i = 0; i < 4 && i < CYGNUM_REDBOOT_MAX_PARTITIONS; i++) {	// Have to use memcpy because of alignment	memcpy(&tmp, p->start_sect, 4);	s = SWAB_LE32(tmp);	memcpy(&tmp, p->nr_sects, 4);	n = SWAB_LE32(tmp);	if (s && n) {	    ++found;	    d->partitions[i].disk = d;	    d->partitions[i].start_sector = s;	    d->partitions[i].nr_sectors = n;	    d->partitions[i].systype = p->sys_ind;	    d->partitions[i].bootflag = p->boot_ind;	}	p++;    }#if CYGNUM_REDBOOT_MAX_PARTITIONS > 4    {	cyg_uint32 buf[SECTOR_SIZE/sizeof(cyg_uint32)], xoffset;	cyg_uint16 magic;	int nextp;	// Go back through and find extended partitions	for (i = 0, nextp = 4; i < 4 && nextp < CYGNUM_REDBOOT_MAX_PARTITIONS; i++) {	    if (d->partitions[i].systype == SYSTYPE_EXTENDED) {		// sector offsets in partition tables are relative to start		// of extended partition.		xoffset = d->partitions[i].start_sector;		for ( ; nextp < CYGNUM_REDBOOT_MAX_PARTITIONS; ++nextp) {		    // read partition boot record (same format as mbr except		    // there should only be 2 entries max: a normal partition		    // and another extended partition		    if (DISK_READ(d, xoffset, buf, 1) <= 0)			break;		    magic = *(cyg_uint16 *)((char *)buf + MBR_MAGIC_OFFSET);		    if (SWAB_LE16(magic) != MBR_MAGIC)			break;		    p = (struct mbr_partition *)((char *)buf + MBR_PTABLE_OFFSET);		    // Have to use memcpy because of alignment		    memcpy(&tmp, p->start_sect, 4);		    s = SWAB_LE32(tmp);		    memcpy(&tmp, p->nr_sects, 4);		    n = SWAB_LE32(tmp);		    if (s && n) {			++found;			d->partitions[nextp].disk = d;			d->partitions[nextp].start_sector = s + xoffset;			d->partitions[nextp].nr_sectors = n;			d->partitions[nextp].systype = p->sys_ind;			d->partitions[nextp].bootflag = p->boot_ind;		    }		    ++p;		    memcpy(&tmp, p->start_sect, 4);		    s = SWAB_LE32(tmp);		    memcpy(&tmp, p->nr_sects, 4);		    n = SWAB_LE32(tmp);		    // more extended partitions?		    if (p->sys_ind != SYSTYPE_EXTENDED || !s || !n)			break;		    xoffset += s;		}	    }	}    }#endif    return found;}// Find partitions on given disk.// Return number of partitions foundstatic intfind_partitions(disk_t *d){    cyg_uint32 buf[SECTOR_SIZE/sizeof(cyg_uint32)];    cyg_uint16 magic;    partition_t *p;    int i, found = 0;    if (d->kind == DISK_IDE_CDROM) {#ifdef CYGSEM_REDBOOT_DISK_ISO9660	// no partition table, so fake it	p = d->partitions;	p->disk = d;	p->start_sector = 0;	p->nr_sectors = d->nr_sectors;	p->funs = &redboot_iso9660fs_funs;	return 1;#else        return 0;#endif    }    // read Master Boot Record    if (DISK_READ(d, 0, buf, 1) <= 0)	return 0;    // Check for DOS MBR    magic = *(cyg_uint16 *)((char *)buf + MBR_MAGIC_OFFSET);    if (SWAB_LE16(magic) == MBR_MAGIC) {	found = find_dos_partitions(d, (cyg_uint8 *)buf);    } else {	// Might want to handle other MBR types, here...    }    // Now go through all partitions and install the correct    // funcs for supported filesystems.    for (i = 0, p = d->partitions; i < CYGNUM_REDBOOT_MAX_PARTITIONS; i++, p++) {	switch (p->systype) {#ifdef CYGSEM_REDBOOT_DISK_EXT2FS	  case SYSTYPE_LINUX:	    p->funs = &redboot_e2fs_funs;	    break;#endif#ifdef CYGSEM_REDBOOT_DISK_FAT16	  case SYSTYPE_FAT16:	    p->funs = &redboot_fat16_funs;	    break;#endif#ifdef CYGSEM_REDBOOT_DISK_FAT32	  case SYSTYPE_FAT32:	    p->funs = &redboot_fat32_funs;	    break;#endif	  default:	    break;  // ignore unsupported filesystems	}    }    return found;}// Add a disk to the disk table.// Return zero if no more room in table.externC intdisk_register(disk_t *d){    int i;    // make sure we have room for it    if (disk_count >= CYGNUM_REDBOOT_MAX_DISKS)	return 0;    // Set the index    d->index = 0;    for (i = 0; i < disk_count; i++)	if (disk_table[i].kind == d->kind)	    d->index++;    // put it in the table    disk_table[disk_count] = *d;    // fill in partition info    find_partitions(&disk_table[disk_count++]);    return 1;}// Convert a filename in the form <partition_name>:<filename> into// a partition and path.//static intdisk_parse_filename(const char *name, partition_t **part, const char **path){    int i, kind, index, pindex;    kind = index = pindex = 0;    if (name[0] == 'h' && name[1] == 'd') {	// IDE hard drives	kind = DISK_IDE_HD;	if (name[2] < 'a' || name[2] > 'z')	    return 0;	index = name[2] - 'a';	if (name[3] < '1' || name[3] >= ('1' + CYGNUM_REDBOOT_MAX_PARTITIONS))	    return 0;	pindex = name[3] - '1';	if (name[4] != ':')	    return 0;	*path = &name[5];    }#ifdef CYGSEM_REDBOOT_DISK_ISO9660    else if (name[0] == 'c' && name[1] == 'd') {	// CD drives	kind = DISK_IDE_CDROM;	if (name[2] < '0' || name[2] > '9')	    return 0;	index = name[2] - '0';	if (name[3] != ':')	    return 0;	*path = &name[4];    }#endif    if (kind) {	for (i = 0; i < CYGNUM_REDBOOT_MAX_DISKS; i++) {	    if (disk_table[i].kind == kind && disk_table[i].index == index) {		*part = &disk_table[i].partitions[pindex];		return 1;	    }	}    }    return 0;}static const struct {    int        kind;    const char *str;} systype_names[] = {    { SYSTYPE_FAT12,      "FAT12" },    { SYSTYPE_FAT16_32M,  "FAT16 <32M" },    { SYSTYPE_FAT16,      "FAT16" },    { SYSTYPE_EXTENDED,   "Extended" },    { SYSTYPE_LINUX_SWAP, "Linux Swap" },    { SYSTYPE_LINUX,      "Linux" }};static const char *systype_name(int systype){    int i;        for (i = 0; i < sizeof(systype_names)/sizeof(systype_names[0]); i++)	if (systype_names[i].kind == systype)	    return systype_names[i].str;    return "Unknown";}// List disk partitionsstatic voiddo_disks(int argc, char *argv[]){    int i, j;    disk_t *d;    partition_t *p;    char name[16];    for (i = 0, d = disk_table;  i < disk_count;  i++, d++) {        switch (d->kind) {          case DISK_IDE_HD:            for (j = 0, p = d->partitions;                 j < CYGNUM_REDBOOT_MAX_PARTITIONS;                 j++, p++) {                if (p->systype) {                    diag_sprintf(name, "hd%c%d", 'a' + d->index, j+1);                    diag_printf("%-8s %s\n", name, systype_name(p->systype));                }            }            break;          case DISK_IDE_CDROM:            diag_sprintf(name, "cd%d", d->index);            diag_printf("%-8s ISO9660\n", name);            break;        }    }}static void *fileptr;static partition_t *file_part;externC int disk_stream_open(connection_info_t *info, int *err){    const char *filepath;    char *filename = info->filename;    // The filename is in <disk>:<path> format.    // Convert to a partition and path.    if (!disk_parse_filename(filename, &file_part, &filepath)) {	*err = diskerr_badname;	return -1;    }    if (file_part->disk->kind != DISK_IDE_CDROM && file_part->systype == 0) {	*err = diskerr_partition;	return -1;    }    if (file_part->funs == (fs_funs_t *)0) {	*err = diskerr_partition;	return -1;    }    fileptr = (file_part->funs->open)(file_part, filepath);    if (fileptr == NULL) {	*err = diskerr_open;	return -1;    }    return 0;}externC int disk_stream_read(char *buf, int size, int *err){    int nread;    if ((nread = (file_part->funs->read)(fileptr, buf, size)) < 0) {	*err = diskerr_read;	return -1;    }    return nread;}externC voiddisk_stream_close(int *err){    fileptr = NULL;}externC char *disk_error(int err){    switch (err) {    case diskerr_badname:        return "Bad filename";        break;    case diskerr_partition:        return "Unsupported filesystem";        break;    case diskerr_open:        return "Can't open file";        break;    case diskerr_read:        return "Can't read file";        break;    default:        return "Unknown error";        break;    }}//// RedBoot interface//GETC_IO_FUNCS(disk_io, disk_stream_open, disk_stream_close,              0, disk_stream_read, disk_error);RedBoot_load(disk, disk_io, true, true, 0);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -