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

📄 fs_ext2.c

📁 Hermit-at-1.1.3,一款bootloader
💻 C
字号:
#include <target/io.h>#include <target/herrno.h>#include <target/htypes.h>#include <target/memcmp.h>#include "ide_core.h"#include "fs_ext2.h"#define CORE_NAME "ext2"#undef DEBUG#if defined(DEBUG)#define DEBUG_FUNC()        hprintf("*" CORE_NAME ": %s()\n", __FUNCTION__)#define DEBUG_INFO(args...) hprintf("*" CORE_NAME ": " args)#define DEBUG_ERR(args...)  hprintf("*" CORE_NAME ": " args)#define DEBUG_RAW(args...)  hprintf(args)#else#define DEBUG_FUNC()#define DEBUG_INFO(args...)#define DEBUG_ERR(args...)#define DEBUG_RAW(args...)#endif#define PRINT_INFO(args...) hprintf(CORE_NAME ": " args)#define PRINT_ERR(args...)  hprintf(CORE_NAME ": " args)#define PRINT_RAW(args...)  hprintf(args)/**************************************************************************** *  ****************************************************************************/intext2_find_image(ide_info_t *info, file_t *file, ext2_super_block_t *sb){	ext2_group_desc_t *ext2gd;	ext2_inode_t *ext2inode;	ext2_dir_entry_t *ext2de;	u32 sectors_per_block;	u32 blocks_per_group, inodes_per_group, group_desc_sector;	u32 first_inode_table, inode_table_sector;	u32 dir_entry_table_sector;	u32 group, inode;	u8 buf[SECTOR_SIZE * 8];	int  ext = 0;	int ret;	int i, j;	DEBUG_FUNC();	if (sb->s_inode_size != INODE_SIZE) {		PRINT_ERR("Bad inode size.\n");		return -H_EIO;	}	if (sb->s_log_block_size > 2) {		PRINT_ERR("Bad block size.\n");		return -H_EIO;	}	sectors_per_block = 2;	for (i=0; i<sb->s_log_block_size; i++)		sectors_per_block *= 2;	blocks_per_group = sb->s_blocks_per_group;	inodes_per_group = sb->s_inodes_per_group;	group_desc_sector = (file->partition_start +			     sectors_per_block * (1 + sb->s_first_data_block));	ret = info->read_sectors(info, group_desc_sector, buf, 1);	if (ret < 0) {		PRINT_ERR("Group desc read error.\n");		return -H_EIO;	}	ext2gd = (ext2_group_desc_t *)buf;	first_inode_table = ext2gd->bg_inode_table;	inode_table_sector = (file->partition_start +			      sectors_per_block * first_inode_table);	ret = info->read_sectors (info, inode_table_sector, buf, 1);	if (ret < 0) {		PRINT_ERR("Inode table read error.\n");		return -H_EIO;	}	for (j = 0; j < SECTOR_SIZE; j += INODE_SIZE) {		ext2inode = (ext2_inode_t *)(buf + j);		if ((ext2inode->i_mode & 0xf000) == 0x4000) {			break;		}	}	if (j >= SECTOR_SIZE) {		PRINT_ERR("Can't find root.\n");		return -H_EIO;	}	dir_entry_table_sector = (file->partition_start +				  sectors_per_block * ext2inode->i_block[0]);	ret = info->read_sectors(info, dir_entry_table_sector, buf,				 sectors_per_block);	if (ret < 0) {		PRINT_ERR("Root directory entry read error.\n");		return -H_EIO;	}	ext2de = (ext2_dir_entry_t *)buf;	for (;	     ((addr_t)ext2de - (addr_t)buf) <= 	       (SECTOR_SIZE * sectors_per_block - 12);	     (ext2de = (ext2_dir_entry_t *)(((addr_t)ext2de) +					    ext2de->rec_len))) {		if (!ext2de->rec_len)			break;		if (ext2de->name_len == 4)			if (!memcmp (ext2de->name, "boot", 4))				break;	}	if ((addr_t)ext2de - (addr_t)buf >	    SECTOR_SIZE * sectors_per_block - 12 ||	    !ext2de->rec_len) {		PRINT_ERR("Can't find /boot\n");		return -H_EIO;	}	group = (ext2de->inode - 1) / inodes_per_group;	inode = (ext2de->inode - 1) % inodes_per_group;	inode_table_sector = (file->partition_start + sectors_per_block *			      (blocks_per_group * group + first_inode_table) +			      inode / (SECTOR_SIZE / INODE_SIZE));	ret = info->read_sectors (info, inode_table_sector, buf, 1);	if (ret < 0) {		PRINT_ERR("Inode table read error.\n");		return -H_EIO;	}	ext2inode = (ext2_inode_t *)		(buf + INODE_SIZE * (inode % (SECTOR_SIZE / INODE_SIZE)));	if ((ext2inode->i_mode & 0xf000) != 0x4000) {		PRINT_ERR("/boot is not directory.\n");		return -H_EIO;	}	dir_entry_table_sector = (file->partition_start +				  sectors_per_block * ext2inode->i_block[0]);	ret = info->read_sectors(info, dir_entry_table_sector, buf,				 sectors_per_block);	if (ret < 0) {		PRINT_ERR("/boot directory entry read error.\n");		return -H_EIO;	}	for (ext2de = (ext2_dir_entry_t *)buf;	     ((addr_t)ext2de - (addr_t)buf) <=	       (SECTOR_SIZE * sectors_per_block - 16);	     ext2de = (ext2_dir_entry_t *)(((addr_t)ext2de) +					   ext2de->rec_len)) {		if (!ext2de->rec_len)			break;		ext = 0;		if (ext2de->name_len >= 5) {			if (!memcmp(ext2de->name, "Image", 5) ||			    !memcmp(ext2de->name, "linux", 5)) {				if (ext2de->name_len == 5)					break;				if (ext2de->name_len >= 9) {					if (!memcmp(ext2de->name + 5,						    ".bin", 4)) {						ext = 4;						if (ext2de->name_len == 9)							break;					}				}				if (ext2de->name_len == 5 + ext + 3) {					if (!memcmp(ext2de->name + 5 + ext,						    ".gz", 3)) {						file->compressed = 1;						break;					}				}			}		}	}		if ((((addr_t)ext2de - (addr_t)buf) >	    (SECTOR_SIZE * sectors_per_block - 16)) || 	    !ext2de->rec_len) {		PRINT_ERR("Can't find /boot/Image(or linux)(.bin)(.gz)\n");		return -H_EIO;	}	memcpy (file->name, ext2de->name, ext2de->name_len);	file->name[ext2de->name_len] = '\0';	group = (ext2de->inode - 1) / inodes_per_group;	inode = (ext2de->inode - 1) % inodes_per_group;	inode_table_sector = (file->partition_start +			      sectors_per_block *			      (blocks_per_group * group + first_inode_table) +			      inode / (SECTOR_SIZE / INODE_SIZE));	ret = info->read_sectors (info, inode_table_sector, buf, 1);	if (ret < 0) {		PRINT_ERR("Inode table read error.\n");		return -H_EIO;	}	ext2inode = (ext2_inode_t *)(buf + INODE_SIZE * 				     (inode % (SECTOR_SIZE / INODE_SIZE)));	if ((ext2inode->i_mode & 0xf000) != 0x8000) {		PRINT_ERR("%s is not file.\n", file->name);		return -H_EIO;	}	file->size = ext2inode->i_size;	if (file->size <= 0) {		PRINT_ERR("%s size is zero.\n", file->name);		return -H_EIO;	}	for (j = 0; j < 15; j++)		file->blocks[j] = ext2inode->i_block[j];	return 0;}

⌨️ 快捷键说明

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