/* * fat32/fat32_context.c - fat32 context related operations * * Copyright (c) 2008,2009,2010,2011,2012 Ghassan Almaless * Copyright (c) 2011,2012 UPMC Sorbonne Universites * * This file is part of ALMOS-kernel. * * ALMOS-kernel 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; version 2.0 of the License. * * ALMOS-kernel 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 ALMOS-kernel; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include static error_t vfat_context_init(struct vfat_context_s *ctx) { size_t blk_sz; dev_params_t params; struct vfat_bpb_s *bpb; struct page_s *page; struct mapper_s *mapper; if((ctx->dev->op.dev.get_params(ctx->dev, ¶ms))) return -1; blk_sz = params.sector_size; ctx->bytes_per_sector = blk_sz; mapper = ctx->mapper; page = mapper_get_page(mapper, 0, MAPPER_SYNC_OP); if(page == NULL) { printk(ERROR, "ERROR: VFAT context_init: I/O error, could not read bpb from the device.\n"); return -1; } bpb = (struct vfat_bpb_s *) ppm_page2addr(page); ctx->bytes_per_sector = bpb->BPB_BytsPerSec; if (blk_sz != ctx->bytes_per_sector) PANIC("VFAT drv error: bpb/device block size mismatch bpb block %d, devBlk %d\n", ctx->bytes_per_sector, blk_sz); ctx->fat_begin_lba = bpb->BPB_RsvdSecCnt; ctx->fat_blk_count = bpb->BPB_FATSz32; ctx->cluster_begin_lba = ctx->fat_begin_lba + (bpb->BPB_NumFATs * bpb->BPB_FATSz32); ctx->sectors_per_cluster = bpb->BPB_SecPerClus; ctx->rootdir_first_cluster = bpb->BPB_RootClus; ctx->bytes_per_cluster = ctx->bytes_per_sector * ctx->sectors_per_cluster; ctx->last_allocated_sector = ctx->fat_begin_lba; ctx->last_allocated_index = 2; vfat_dmsg(1, "%s:\n\tbegin_lba %d\n\tblk_count %d\n\tcluster_begin_lba %d\n\t" "sectors_per_cluster %d\n\trootdir_first_cluster %d\n\tbytes_per_cluster %d\n\t" "MediaType %x (@%x)\n", __FUNCTION__, ctx->fat_begin_lba, ctx->fat_blk_count, ctx->cluster_begin_lba, ctx->sectors_per_cluster, ctx->rootdir_first_cluster, ctx->bytes_per_cluster, bpb->BPB_Media, &bpb->BPB_Media); vfat_dmsg(1, "DEBUG: context_init: last allocated sector %d, last allocated index %d\n", ctx->last_allocated_sector, ctx->last_allocated_index); return 0; } VFS_CREATE_CONTEXT(vfat_create_context) { kmem_req_t req; struct vfat_context_s *vfat_ctx; struct mapper_s *mapper; error_t err; vfat_dmsg(1, "%s: started\n", __FUNCTION__); vfat_ctx = &context->ctx_vfat; vfat_ctx->dev = context->ctx_dev;//necessary ? rwlock_init(&vfat_ctx->lock); req.type = KMEM_MAPPER; req.size = sizeof(*mapper); mapper = kmem_alloc(&req); if(mapper == NULL) { err = ENOMEM; goto fail_mapper; } err = mapper_init(mapper, &vfat_inode_mapper_op, NULL, vfat_ctx); if(err) { printk(ERROR, "ERROR: %s: failed to init mapper, err %d\n", __FUNCTION__, err); goto fail_mapper_init; } vfat_ctx->mapper = mapper; vfat_ctx->fat_cid = current_cid; if ((err = vfat_context_init(vfat_ctx))) { printk(ERROR, "ERROR: vfat_create_context: INITIALIZING VFAT CONTEXT err %d\n",err); goto fail_ctx_init; } context->ctx_flags |= VFS_FS_USE_MAPPER; context->ctx_type = VFS_VFAT_TYPE; context->ctx_blksize = vfat_ctx->bytes_per_sector; context->ctx_op = (struct vfs_context_op_s *) &vfat_ctx_op; context->ctx_inode_op = (struct vfs_inode_op_s *) &vfat_i_op; context->ctx_dirent_op = (struct vfs_dirent_op_s *) &vfat_d_op; context->ctx_file_op = (struct vfs_file_op_s *) &vfat_f_op; return 0; fail_ctx_init: fail_mapper_init: mapper_destroy(mapper, false); req.type = KMEM_MAPPER; req.ptr = mapper; kmem_free(&req); fail_mapper: req.type = KMEM_VFAT_CTX; req.ptr = vfat_ctx; kmem_free(&req); rwlock_destroy(&vfat_ctx->lock); return err; } VFS_DESTROY_CONTEXT(vfat_destroy_context) { struct vfat_context_s *ctx; ctx = &context->ctx_vfat; mapper_destroy(ctx->mapper, true); rwlock_destroy(&ctx->lock); return 0; } VFS_READ_ROOT(vfat_read_root) { struct vfat_context_s *ctx; struct vfat_inode_s * i_info; ctx = &context->ctx_vfat; root->i_type |= VFS_DIR;//? root->i_links = 1; root->i_attr |= VFS_DIR; root->i_size = vfat_cluster_count(ctx, ctx->rootdir_first_cluster);//does a dir has a size? root->i_mapper->m_inode = root; root->i_mapper->m_ops = &vfat_inode_mapper_op; root->i_number = vfs_inum_new(context); assert(root->i_pv); i_info = root->i_pv; i_info->flags = VFAT_ATTR_DIRECTORY; i_info->first_cluster = ctx->rootdir_first_cluster; //i_info->parent_cluster = 0; //i_info->entry_index = 0; return 0; } VFS_WRITE_ROOT(vfat_write_root) { return 0; } KMEM_OBJATTR_INIT(vfat_kmem_context_init) { attr->type = KMEM_VFAT_CTX; attr->name = "KCM VFAT CTX"; attr->size = sizeof(struct vfat_context_s); attr->aligne = 0; attr->min = CONFIG_VFAT_CTX_MIN; attr->max = CONFIG_VFAT_CTX_MAX; attr->ctor = NULL; attr->dtor = NULL; return 0; } const struct vfs_context_op_s vfat_ctx_op = { .create = vfat_create_context, .destroy = vfat_destroy_context, .read_root = vfat_read_root, .write_root = vfat_write_root, .repli_root = NULL };