📄 ext2fs.c
字号:
//==========================================================================//// e2fs.c//// RedBoot support for second extended filesystem////==========================================================================//####ECOSGPLCOPYRIGHTBEGIN####// -------------------------------------------// This file is part of eCos, the Embedded Configurable Operating System.// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.// Copyright (C) 2003 Gary Thomas <gary@mind.be>//// 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 <define.h>#include <api.h>#include <board_config.h>#include <sl2312.h>#ifdef BOARD_SUPPORT_IDE#include "ide.h"#include "ext2fs.h"#define MAX_FILES 2#define ext2fs_printf// only one open file every timeFILE_T file_info[MAX_FILES];static UINT32 blockbuf[EXT2_MAX_BLOCK_SIZE/sizeof(UINT32)];static EXT2_DESC_T ext2fs_desc;FILE_T *kernel_fp;FILE_T *initrd_fp;FILE_T *ext2fs_open(char *filepath);static int ext2fs_mount(IDE_PART_T *part, EXT2_DESC_T *desc);static int ext2fs_get_gdesc(EXT2_DESC_T *ext2fs, UINT32 group_nr, EXT2_GROUP_T *gdesc);static int ext2fs_get_inode(EXT2_DESC_T *ext2fs, int ino, EXT2_INODE_T *ip);static int ext2fs_inode_block(EXT2_DESC_T *ext2fs, EXT2_INODE_T *inode, UINT32 bindex, UINT32 *pblknr);static EXT2_DIR_T *search_dir_block(EXT2_DESC_T *ext2fs, UINT32 *blkbuf, char *name, int namelen, int type);static EXT2_DIR_T * ext2fs_dir_lookup(EXT2_DESC_T *ext2fs, UINT32 dir_ino, char *name, int namelen, int type);static int ext2fs_follow_symlink(EXT2_DESC_T *ext2fs, UINT32 dir_ino, UINT32 sym_ino, INODE_INFO_T *info);static int ext2fs_inode_lookup(EXT2_DESC_T *ext2fs, UINT32 dir_ino, char *pathname, INODE_INFO_T *info, int type);int ext2fs_read(void *fp, char *buf, UINT32 nbytes);int ext2fs_close(void *fp);#define __READ_BLOCK(n) \ PARTITION_READ(ext2fs->part, EXT2_BLOCK_TO_SECTOR(ext2fs, (n)), \ ext2fs->blocksize/IDE_SECTOR_SIZE, (UINT16 *)blockbuf)/*----------------------------------------------------------------------* ext2fs_init*----------------------------------------------------------------------*/int ext2fs_init(void){ int p; IDE_PART_T *part; memset((void *)&file_info, 0, sizeof(file_info)); memset((void *)blockbuf, 0, sizeof(blockbuf)); // looking for zImage.gz part = (IDE_PART_T *)&ide_partitions[0]; for (p=0; p<ide_part_num; p++, part++) { if (!part->present) continue; if (part->part_id != 0) // only handle first partition per disk continue; if (ext2fs_mount(part, &ext2fs_desc) != 0) { ext2fs_printf(("Failed to mount!\n")); continue; } kernel_fp = NULL; initrd_fp = NULL; if ((kernel_fp = ext2fs_open((char *)sys_get_kernel_name())) && (initrd_fp = ext2fs_open((char *)sys_get_initrd_name()))) { ext2fs_close(kernel_fp); ext2fs_close(initrd_fp); return 1; } if (kernel_fp) ext2fs_close(kernel_fp); if (initrd_fp) ext2fs_close(initrd_fp); } printf("Not found files: %s and %s\n", sys_get_kernel_name(), sys_get_initrd_name()); return 0; }/*----------------------------------------------------------------------* ext2fs_open* open a file in a desired partition*----------------------------------------------------------------------*/FILE_T *ext2fs_open(char *filepath){ int i; FILE_T *file; // get a new file handler // currently only support one file at the same time file = (FILE_T *)&file_info; for (i=0; i<MAX_FILES; i++, file++) { if (!file->opened) break; } if (i == MAX_FILES) return NULL; memset((void *)file, 0, sizeof(FILE_T)); file->opened = 1; // find file inode if (!ext2fs_inode_lookup(&ext2fs_desc, EXT2_ROOT_INO, filepath, &file->inode_info, 0)) { ext2fs_printf(("ext2fs_inode_lookup failed\n")); return NULL; } // read inode if (!ext2fs_get_inode(&ext2fs_desc, file->inode_info.ino, &file->inode)) { ext2fs_printf(("ext2fs_get_inode failed for ino[%d]\n", file->inode_info.ino)); return NULL; } file->ext2fs_desc = &ext2fs_desc; file->file_size = SWAB_LE32(file->inode.size); file->file_pos = 0; return file;}/*----------------------------------------------------------------------* ext2fs_mount*----------------------------------------------------------------------*/static int ext2fs_mount(IDE_PART_T *part, EXT2_DESC_T *desc){ int sb_block = 1; UINT32 sb_buf[EXT2_MIN_BLOCK_SIZE/sizeof(UINT32)]; EXT2_SB_T *sb = (EXT2_SB_T *)sb_buf; UINT16 magic; desc->part = part; // Read super block. Super Block is the 2nd block if (!PARTITION_READ(part, sb_block*(EXT2_MIN_BLOCK_SIZE/IDE_SECTOR_SIZE), EXT2_MIN_BLOCK_SIZE/IDE_SECTOR_SIZE, (UINT16 *)sb)) { return -1; } if (SWAB_LE16(sb->magic) != EXT2_SUPER_MAGIC) { ext2fs_printf(("Bad magic 0x%x\n", SWAB_LE16(magic))); return -1; } // save some stuff for easy access desc->blocksize = EXT2_BLOCK_SIZE(sb); desc->nr_ind_blocks = (desc)->blocksize / sizeof(UINT32); desc->nr_dind_blocks = desc->nr_ind_blocks * ((desc)->blocksize / sizeof(UINT32)); desc->nr_tind_blocks = desc->nr_dind_blocks * ((desc)->blocksize / sizeof(UINT32)); desc->blocks_per_group = SWAB_LE32(sb->blocks_per_group); desc->ngroups = (SWAB_LE32(sb->blocks_count) + desc->blocks_per_group - 1) / desc->blocks_per_group; desc->inodes_per_group = SWAB_LE32(sb->inodes_per_group); // Find the group descriptors which follow superblock desc->gdesc_block = ((sb_block * EXT2_MIN_BLOCK_SIZE) / desc->blocksize) + 1; desc->gdesc_first = 0; // cache group 0 initially if (!PARTITION_READ(part, EXT2_BLOCK_TO_SECTOR(desc, desc->gdesc_block), 1, (UINT16 *)desc->gdesc_cache)) { return -1; } return 0;}/*----------------------------------------------------------------------* ext2fs_get_gdesc*----------------------------------------------------------------------*/static int ext2fs_get_gdesc(EXT2_DESC_T *ext2fs, UINT32 group_nr, EXT2_GROUP_T *gdesc){ UINT32 sec_nr; if (group_nr < ext2fs->gdesc_first || group_nr >= (ext2fs->gdesc_first + EXT2_GDESC_CACHE_SIZE)) { // cache miss sec_nr = EXT2_BLOCK_TO_SECTOR(ext2fs, ext2fs->gdesc_block); sec_nr += (group_nr / EXT2_GDESC_PER_SECTOR); if (!PARTITION_READ(ext2fs->part, sec_nr, sizeof(ext2fs->gdesc_cache)/IDE_SECTOR_SIZE, (UINT16 *)ext2fs->gdesc_cache)) return 0; ext2fs->gdesc_first = (group_nr / EXT2_GDESC_CACHE_SIZE) * EXT2_GDESC_CACHE_SIZE; } memcpy((void *)gdesc, (void *)&ext2fs->gdesc_cache[group_nr - ext2fs->gdesc_first], sizeof(EXT2_GROUP_T)); return 1;}/*----------------------------------------------------------------------* ext2fs_get_inode*----------------------------------------------------------------------*/static int ext2fs_get_inode(EXT2_DESC_T *ext2fs, int ino, EXT2_INODE_T *ip){ UINT32 offset, sec_nr, buf[IDE_SECTOR_SIZE/sizeof(UINT32)]; EXT2_GROUP_T gdesc; // get descriptor for group which this inode belongs to if (!ext2fs_get_gdesc(ext2fs, (ino - 1) / ext2fs->inodes_per_group, &gdesc)) return 0; if (gdesc.inode_table == 0) return 0; // byte offset within group inode table offset = ((ino - 1) % ext2fs->inodes_per_group) * sizeof(EXT2_INODE_T); // figure out which sector holds the inode sec_nr = EXT2_BLOCK_TO_SECTOR(ext2fs, SWAB_LE32(gdesc.inode_table)); sec_nr += offset / IDE_SECTOR_SIZE; // and the offset within that sector. offset %= IDE_SECTOR_SIZE; if (!PARTITION_READ(ext2fs->part, sec_nr, 1, (UINT16 *)buf)) return 0; memcpy((void *)ip, (char *)buf + offset, sizeof(EXT2_INODE_T)); return 1;}/*----------------------------------------------------------------------* ext2fs_inode_block* Convert a block index into inode data into a block_nr.* If successful, store block number in pblknr and return non-zero.** NB: This needs some block/sector caching to be speedier. But* that takes memory and speed is not too bad now for files* small enough to avoid double and triple indirection.**----------------------------------------------------------------------*/static int ext2fs_inode_block(EXT2_DESC_T *ext2fs, EXT2_INODE_T *inode, UINT32 bindex, UINT32 *pblknr){ if (bindex < EXT2_NR_DIR_BLOCKS) { *pblknr = SWAB_LE32(inode->block[bindex]); return 1; } bindex -= EXT2_NR_DIR_BLOCKS; if (bindex < ext2fs->nr_ind_blocks) { // Indirect block if (!__READ_BLOCK(SWAB_LE32(inode->block[EXT2_IND_BLOCK]))) return 0; *pblknr = SWAB_LE32(blockbuf[bindex]); return 1; } bindex -= ext2fs->nr_ind_blocks; if (bindex < ext2fs->nr_dind_blocks) { // Double indirect block if (!__READ_BLOCK(SWAB_LE32(inode->block[EXT2_DIND_BLOCK]))) return 0; if (!__READ_BLOCK(SWAB_LE32(blockbuf[bindex / ext2fs->nr_ind_blocks]))) return 0; *pblknr = SWAB_LE32(blockbuf[bindex % ext2fs->nr_ind_blocks]); return 1; } bindex -= ext2fs->nr_dind_blocks; // Triple indirect block if (!__READ_BLOCK(SWAB_LE32(inode->block[EXT2_TIND_BLOCK]))) return 0; if (!__READ_BLOCK(SWAB_LE32(blockbuf[bindex / ext2fs->nr_dind_blocks]))) return 0; bindex %= ext2fs->nr_dind_blocks; if (!__READ_BLOCK(SWAB_LE32(blockbuf[bindex / ext2fs->nr_ind_blocks]))) return 0; *pblknr = SWAB_LE32(blockbuf[bindex % ext2fs->nr_ind_blocks]); return 1;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -