/* * filesystem operations */ static s32_t cpiofs_mount(struct mount * m, char * dev, s32_t flag) { struct blkdev * blk; struct cpio_newc_header header; if(dev == NULL) return EINVAL; blk = (struct blkdev *)m->m_dev; if(!blk) return EACCES; if(get_blkdev_total_size(blk) <= sizeof(struct cpio_newc_header)) return EINTR; if(bio_read(blk, (u8_t *)(&header), 0, sizeof(struct cpio_newc_header)) != sizeof(struct cpio_newc_header)) return EIO; if(strncmp((const char *)(header.c_magic), (const char *)"070701", 6) != 0) return EINVAL; m->m_flags = (flag & MOUNT_MASK) | MOUNT_RDONLY; m->m_root->v_data = 0; m->m_data = NULL; return 0; }
static s32_t devfs_lookup(struct vnode * dnode, char * name, struct vnode * node) { struct device * dev; struct chrdev * chr; struct blkdev * blk; dev = search_device(name); if(dev == NULL) return -1; if(dev->type == CHAR_DEVICE) { chr = (struct chrdev *)(dev->priv); node->v_type = VCHR; node->v_size = 0; } else if(dev->type == BLOCK_DEVICE) { blk = (struct blkdev *)(dev->priv); node->v_type = VBLK; node->v_size = get_blkdev_total_size(blk); } else { return -1; } node->v_data = (void *)dev; node->v_mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH; return 0; }
/* * filesystem operations */ static s32_t fatfs_mount(struct mount_t * m, char * dev, s32_t flag) { struct fatfs_mount_data * md; struct blkdev_t * blk; struct fat_boot_sector fbs; u32_t sector_size; u32_t tmp; if(dev == NULL) return EINVAL; blk = (struct blkdev_t *)m->m_dev; if(!blk || !blk->info) return ENODEV; if(get_blkdev_total_size(blk) <= sizeof(struct fat_boot_sector)) return EINTR; if(block_read(blk, (u8_t *)(&fbs), 0, sizeof(struct fat_boot_sector)) != sizeof(struct fat_boot_sector)) return EIO; /* * check both signature (0x55, 0xaa) */ if((fbs.signature[0] != 0x55) || fbs.signature[1] != 0xaa) return EINVAL; /* the logical sector size (bytes 11-12) is a power of two, at least 512 */ sector_size = (fbs.bytes_per_sector[1] << 8) | fbs.bytes_per_sector[0]; if( (sector_size < 512) || (!is_power_of_2(sector_size)) ) return EINVAL; /* the cluster size (byte 13) is a power of two */ if(! is_power_of_2(fbs.sectors_per_cluster)) return EINVAL; /* the number of reserved sectors (bytes 14-15) is nonzero */ tmp = (fbs.reserved_sectors[1] << 8) | fbs.reserved_sectors[0]; if(tmp == 0) return EINVAL; /* the number of fats (byte 16) is nonzero */ if(fbs.num_of_fats == 0x00) return EINVAL; /* the number of root directory entries (bytes 17-18) must be sector aligned */ tmp = (fbs.root_entries[1] << 8) | fbs.root_entries[0]; if(tmp % (sector_size / sizeof(struct fat_dirent)) != 0) return EINVAL; /* the sector per track (byte 24-25) is nonzero */ tmp = (fbs.sectors_per_track[1] << 8) | fbs.sectors_per_track[0]; if(tmp == 0) return EINVAL; /* the number of heads (byte 26-27) is nonzero */ tmp = (fbs.num_of_heads[1] << 8) | fbs.num_of_heads[0]; if(tmp == 0) return EINVAL; md = malloc(sizeof(struct fatfs_mount_data)); if(!md) return ENOMEM; /* determine the type of fat */ if( strncmp((const s8_t *)fbs.x.fat12.fs_type, (const s8_t *)"FAT12 ", 8) == 0 ) { md->type = FAT_TYPE_FAT12; } else if( strncmp((const s8_t *)fbs.x.fat16.fs_type, (const s8_t *)"FAT16 ", 8) == 0 ) { md->type = FAT_TYPE_FAT16; } else if( strncmp((const s8_t *)fbs.x.fat32.fs_type, (const s8_t *)"FAT32 ", 8) == 0 ) { md->type = FAT_TYPE_FAT32; } else { free(md); return EINVAL; } /* build mount data */ switch(md->type) { case FAT_TYPE_FAT12: md->sector_size = sector_size; md->sectors_per_cluster = fbs.sectors_per_cluster; md->cluster_size = md->sectors_per_cluster * md->sector_size; tmp = ((fbs.hidden_sectors[3] << 24) | (fbs.hidden_sectors[2] << 16) | (fbs.hidden_sectors[1] << 8) | (fbs.hidden_sectors[0] << 0)); md->fat_start = tmp + ((fbs.reserved_sectors[1] << 8) | (fbs.reserved_sectors[0] << 0)); md->root_start = md->fat_start + (fbs.num_of_fats * ((fbs.sectors_per_fat[1] << 8) | (fbs.sectors_per_fat[0] << 0))); md->data_start = md->root_start + ( ((fbs.root_entries[1] << 8) | (fbs.root_entries[0] << 0)) / (sector_size / sizeof(struct fat_dirent)) ); tmp = ((fbs.total_sectors[1] << 8) | (fbs.total_sectors[0] << 0)); if(tmp == 0) tmp = ((fbs.big_total_sectors[3] << 24) | (fbs.big_total_sectors[2] << 16) | (fbs.big_total_sectors[1] << 8) | (fbs.big_total_sectors[0] << 0)); if(tmp == 0) { free(md); return EINVAL; } md->last_cluster = (tmp - md->data_start) / md->sectors_per_cluster + 2; md->free_scan = 2; md->fat_mask = 0x00000fff; md->fat_eof = 0xffffffff & 0x00000fff; break; case FAT_TYPE_FAT16: md->sector_size = sector_size; md->sectors_per_cluster = fbs.sectors_per_cluster; md->cluster_size = md->sectors_per_cluster * md->sector_size; tmp = ((fbs.hidden_sectors[3] << 24) | (fbs.hidden_sectors[2] << 16) | (fbs.hidden_sectors[1] << 8) | (fbs.hidden_sectors[0] << 0)); md->fat_start = tmp + ((fbs.reserved_sectors[1] << 8) | (fbs.reserved_sectors[0] << 0)); md->root_start = md->fat_start + (fbs.num_of_fats * ((fbs.sectors_per_fat[1] << 8) | (fbs.sectors_per_fat[0] << 0))); md->data_start = md->root_start + ( ((fbs.root_entries[1] << 8) | (fbs.root_entries[0] << 0)) / (sector_size / sizeof(struct fat_dirent)) ); tmp = ((fbs.total_sectors[1] << 8) | (fbs.total_sectors[0] << 0)); if(tmp == 0) tmp = ((fbs.big_total_sectors[3] << 24) | (fbs.big_total_sectors[2] << 16) | (fbs.big_total_sectors[1] << 8) | (fbs.big_total_sectors[0] << 0)); if(tmp == 0) { free(md); return EINVAL; } md->last_cluster = (tmp - md->data_start) / md->sectors_per_cluster + 2; md->free_scan = 2; md->fat_mask = 0x0000ffff; md->fat_eof = 0xffffffff & 0x0000ffff; break; case FAT_TYPE_FAT32: md->sector_size = sector_size; md->sectors_per_cluster = fbs.sectors_per_cluster; md->cluster_size = md->sectors_per_cluster * md->sector_size; tmp = ((fbs.hidden_sectors[3] << 24) | (fbs.hidden_sectors[2] << 16) | (fbs.hidden_sectors[1] << 8) | (fbs.hidden_sectors[0] << 0)); md->fat_start = tmp + ((fbs.reserved_sectors[1] << 8) | (fbs.reserved_sectors[0] << 0)); md->root_start = md->fat_start + (fbs.num_of_fats * ((fbs.x.fat32.sectors_per_fat_32[3] << 24) | (fbs.x.fat32.sectors_per_fat_32[2] << 16) | (fbs.x.fat32.sectors_per_fat_32[1] << 8) | (fbs.x.fat32.sectors_per_fat_32[0] << 0))); md->data_start = md->root_start + 1; break; default: free(md); return EINVAL; } md->io_buf = malloc(md->cluster_size); if(!md->io_buf) { free(md); return ENOMEM; } md->fat_buf = malloc(md->sector_size * 2); if(!md->fat_buf) { free(md->io_buf); free(md); return ENOMEM; } md->dir_buf = malloc(md->sector_size); if(!md->dir_buf) { free(md->fat_buf); free(md->io_buf); free(md); return ENOMEM; } md->blk = blk; m->m_flags = flag & MOUNT_MASK; m->m_data = md; // for debug switch(md->type) { case FAT_TYPE_FAT12: break; case FAT_TYPE_FAT16: break; case FAT_TYPE_FAT32: break; default: break; } LOG("sector size: %ld\r\n", md->sector_size); LOG("sectors per cluster: %ld\r\n", md->sectors_per_cluster); LOG("cluster size: %ld\r\n", md->cluster_size); LOG("fat start: %ld\r\n", md->fat_start); LOG("root start: %ld\r\n", md->root_start); LOG("data start: %ld\r\n", md->data_start); LOG("last cluster: %ld\r\n", md->last_cluster); LOG("free scan: %ld\r\n", md->free_scan); LOG("fat mask: 0x%08x\r\n", md->fat_mask); LOG("fat eof: 0x%08x\r\n", md->fat_eof); return 0; }