// Mount an e2fs filesystem on the given partition. // Return 0 if successful. // static int e2fs_mount(partition_t *part, e2fs_desc_t *e2fs) { int sb_block = 1; cyg_uint32 sb_buf[E2FS_MIN_BLOCK_SIZE/sizeof(cyg_uint32)]; struct e2fs_super_block *sb = (struct e2fs_super_block *)sb_buf; e2fs->part = part; if (!PARTITION_READ(part, sb_block*(E2FS_MIN_BLOCK_SIZE/SECTOR_SIZE), (cyg_uint32 *)sb, E2FS_MIN_BLOCK_SIZE/SECTOR_SIZE)) return -1; if (SWAB_LE16(sb->magic) != E2FS_SUPER_MAGIC) { diag_printf("ext2_mount: bad magic 0x%x\n", SWAB_LE16(sb->magic)); return -1; } // save some stuff for easy access e2fs->blocksize = E2FS_BLOCK_SIZE(sb); e2fs->nr_ind_blocks = (e2fs)->blocksize / sizeof(cyg_uint32); e2fs->nr_dind_blocks = e2fs->nr_ind_blocks * ((e2fs)->blocksize / sizeof(cyg_uint32)); e2fs->nr_tind_blocks = e2fs->nr_dind_blocks * ((e2fs)->blocksize / sizeof(cyg_uint32)); e2fs->blocks_per_group = SWAB_LE32(sb->blocks_per_group); e2fs->ngroups = (SWAB_LE32(sb->blocks_count) + e2fs->blocks_per_group - 1) / e2fs->blocks_per_group; e2fs->inodes_per_group = SWAB_LE32(sb->inodes_per_group); // Find the group descriptors which follow superblock e2fs->gdesc_block = ((sb_block * E2FS_MIN_BLOCK_SIZE) / e2fs->blocksize) + 1; e2fs->gdesc_first = 0; // cache group 0 initially if (!PARTITION_READ(part, E2FS_BLOCK_TO_SECTOR(e2fs,e2fs->gdesc_block), (cyg_uint32 *)e2fs->gdesc_cache, 1)) return -1; #if DEBUG_E2FS > 1 diag_printf("E2FS superblock:\n"); diag_printf(" [%d] inodes\n", SWAB_LE32(sb->inodes_count)); diag_printf(" [%d] blocks\n", SWAB_LE32(sb->blocks_count)); diag_printf(" [%d] blocksize\n", e2fs->blocksize); diag_printf(" [%d] blocks per group\n", e2fs->blocks_per_group); diag_printf(" [%d] ngroups\n", e2fs->ngroups); #endif #if DEBUG_E2FS > 4 dump_sb(sb); #endif return 0; }
static void dump_inode(struct e2fs_inode *i) { int j, n; diag_printf("mode: %o\n", SWAB_LE16(i->mode)); diag_printf("uid: %o\n", SWAB_LE16(i->uid)); diag_printf("size: %d\n", SWAB_LE32(i->size)); diag_printf("gid: %o\n", SWAB_LE16(i->gid)); diag_printf("links: %d\n", SWAB_LE16(i->links_count)); diag_printf("blocks: %d\n", SWAB_LE32(i->blocks)); n = i->blocks; if (n > E2FS_N_BLOCKS) n = E2FS_N_BLOCKS; for (j = 0; j < n; j++) diag_printf(" block: %d\n", SWAB_LE32(i->block[j])); }
// search a single directory block in memory looking for an // entry with the given name. Return pointer to entry if // found, NULL if not. // static e2fs_dir_entry_t * search_dir_block(e2fs_desc_t *e2fs, cyg_uint32 *blkbuf, const char *name, int namelen) { e2fs_dir_entry_t *dir; cyg_uint16 reclen, len; cyg_uint32 offset; offset = 0; while (offset < e2fs->blocksize) { dir = (e2fs_dir_entry_t *)((char *)blkbuf + offset); reclen = SWAB_LE16(dir->reclen); offset += reclen; len = dir->namelen; // terminate on anything which doesn't make sense if (reclen < 8 || (len + 8) > reclen || offset > (e2fs->blocksize + 1)) return NULL; if (dir->inode && len == namelen && !strncmp(dir->name, name, len)) return dir; } return NULL; }
static void dump_sb(struct e2fs_super_block *s) { diag_printf("inode_count: %d\n", SWAB_LE32(s->inodes_count)); diag_printf("blocks_count: %d\n", SWAB_LE32(s->blocks_count)); diag_printf("r_blocks_count: %d\n", SWAB_LE32(s->r_blocks_count)); diag_printf("free_blocks_count: %d\n", SWAB_LE32(s->free_blocks_count)); diag_printf("free_inodes_count: %d\n", SWAB_LE32(s->free_inodes_count)); diag_printf("first_data_block: %d\n", SWAB_LE32(s->first_data_block)); diag_printf("log_block_size: %d\n", SWAB_LE32(s->log_block_size)); diag_printf("log_frag_size: %d\n", SWAB_LE32(s->log_frag_size)); diag_printf("blocks_per_group: %d\n", SWAB_LE32(s->blocks_per_group)); diag_printf("frags_per_group: %d\n", SWAB_LE32(s->frags_per_group)); diag_printf("inodes_per_group: %d\n", SWAB_LE32(s->inodes_per_group)); diag_printf("mnt_count: %d\n", SWAB_LE16(s->mnt_count)); diag_printf("max_mnt_count: %d\n", SWAB_LE16(s->max_mnt_count)); diag_printf("magic: %d\n", SWAB_LE16(s->magic)); diag_printf("state: %d\n", SWAB_LE16(s->state)); diag_printf("errors: %d\n", SWAB_LE16(s->errors)); diag_printf("minor_rev_level: %d\n", SWAB_LE16(s->minor_rev_level)); diag_printf("lastcheck: %d\n", SWAB_LE32(s->lastcheck)); diag_printf("checkinterval: %d\n", SWAB_LE32(s->checkinterval)); diag_printf("creator_os: %d\n", SWAB_LE32(s->creator_os)); diag_printf("rev_level: %d\n", SWAB_LE32(s->rev_level)); }
static int find_dos_partitions(disk_t *d, cyg_uint8 *mbr) { cyg_uint32 s, n; 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++) { s = SWAB_LE32(u32_unaligned(p->start_sect)); n = SWAB_LE32(u32_unaligned(p->nr_sects)); 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); s = SWAB_LE32(u32_unaligned(p->start_sect)); n = SWAB_LE32(u32_unaligned(p->nr_sects)); 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; s = SWAB_LE32(u32_unaligned(p->start_sect)); n = SWAB_LE32(u32_unaligned(p->nr_sects)); // 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 found static int find_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; }