📄 fs_ext2.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 + -