| 1 | /* | 
|---|
| 2 |  * fat32/fat32_context.c - fat32 context related operations | 
|---|
| 3 |  * | 
|---|
| 4 |  * Copyright (c) 2008,2009,2010,2011,2012 Ghassan Almaless | 
|---|
| 5 |  * Copyright (c) 2011,2012 UPMC Sorbonne Universites | 
|---|
| 6 |  * | 
|---|
| 7 |  * This file is part of ALMOS-kernel. | 
|---|
| 8 |  * | 
|---|
| 9 |  * ALMOS-kernel is free software; you can redistribute it and/or modify it | 
|---|
| 10 |  * under the terms of the GNU General Public License as published by | 
|---|
| 11 |  * the Free Software Foundation; version 2.0 of the License. | 
|---|
| 12 |  * | 
|---|
| 13 |  * ALMOS-kernel is distributed in the hope that it will be useful, but | 
|---|
| 14 |  * WITHOUT ANY WARRANTY; without even the implied warranty of | 
|---|
| 15 |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
|---|
| 16 |  * General Public License for more details. | 
|---|
| 17 |  * | 
|---|
| 18 |  * You should have received a copy of the GNU General Public License | 
|---|
| 19 |  * along with ALMOS-kernel; if not, write to the Free Software Foundation, | 
|---|
| 20 |  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | 
|---|
| 21 |  */ | 
|---|
| 22 |  | 
|---|
| 23 | #include <kdmsg.h> | 
|---|
| 24 | #include <device.h> | 
|---|
| 25 | #include <driver.h> | 
|---|
| 26 | #include <kmem.h> | 
|---|
| 27 | #include <rwlock.h> | 
|---|
| 28 | #include <string.h> | 
|---|
| 29 | #include <page.h> | 
|---|
| 30 | #include <cluster.h> | 
|---|
| 31 | #include <thread.h> | 
|---|
| 32 | #include <mapper.h> | 
|---|
| 33 | #include <atomic.h> | 
|---|
| 34 | #include <vfs.h> | 
|---|
| 35 |   | 
|---|
| 36 | #include <fat32.h> | 
|---|
| 37 | #include <fat32-private.h> | 
|---|
| 38 |  | 
|---|
| 39 | static error_t vfat_context_init(struct vfat_context_s *ctx) | 
|---|
| 40 | { | 
|---|
| 41 |         size_t blk_sz; | 
|---|
| 42 |         dev_params_t params; | 
|---|
| 43 |         struct vfat_bpb_s *bpb; | 
|---|
| 44 |         struct page_s *page; | 
|---|
| 45 |         struct mapper_s *mapper; | 
|---|
| 46 |    | 
|---|
| 47 |         if((ctx->dev->op.dev.get_params(ctx->dev, ¶ms))) | 
|---|
| 48 |                 return -1; | 
|---|
| 49 |  | 
|---|
| 50 |         blk_sz                = params.sector_size; | 
|---|
| 51 |         ctx->bytes_per_sector = blk_sz; | 
|---|
| 52 |         mapper                = ctx->mapper; | 
|---|
| 53 |         | 
|---|
| 54 |         page = mapper_get_page(mapper, 0, MAPPER_SYNC_OP); | 
|---|
| 55 |  | 
|---|
| 56 |         if(page == NULL)  | 
|---|
| 57 |         { | 
|---|
| 58 |                 printk(ERROR, "ERROR: VFAT context_init: I/O error, could not read bpb from the device.\n"); | 
|---|
| 59 |                 return -1; | 
|---|
| 60 |         } | 
|---|
| 61 |  | 
|---|
| 62 |         bpb = (struct vfat_bpb_s *) ppm_page2addr(page); | 
|---|
| 63 |  | 
|---|
| 64 |         ctx->bytes_per_sector = bpb->BPB_BytsPerSec; | 
|---|
| 65 |  | 
|---|
| 66 |         if (blk_sz != ctx->bytes_per_sector) | 
|---|
| 67 |                 PANIC("VFAT drv error: bpb/device block size mismatch bpb block %d, devBlk %d\n", | 
|---|
| 68 |                       ctx->bytes_per_sector, blk_sz); | 
|---|
| 69 |  | 
|---|
| 70 |         ctx->fat_begin_lba         = bpb->BPB_RsvdSecCnt; | 
|---|
| 71 |         ctx->fat_blk_count         = bpb->BPB_FATSz32; | 
|---|
| 72 |         ctx->cluster_begin_lba     = ctx->fat_begin_lba + (bpb->BPB_NumFATs * bpb->BPB_FATSz32); | 
|---|
| 73 |         ctx->sectors_per_cluster   = bpb->BPB_SecPerClus; | 
|---|
| 74 |         ctx->rootdir_first_cluster = bpb->BPB_RootClus; | 
|---|
| 75 |         ctx->bytes_per_cluster     = ctx->bytes_per_sector * ctx->sectors_per_cluster; | 
|---|
| 76 |         ctx->last_allocated_sector = ctx->fat_begin_lba; | 
|---|
| 77 |         ctx->last_allocated_index  = 2; | 
|---|
| 78 |  | 
|---|
| 79 |         vfat_dmsg(1,  | 
|---|
| 80 |                   "%s:\n\tbegin_lba %d\n\tblk_count %d\n\tcluster_begin_lba %d\n\t" | 
|---|
| 81 |                   "sectors_per_cluster %d\n\trootdir_first_cluster  %d\n\tbytes_per_cluster %d\n\t" | 
|---|
| 82 |                   "MediaType %x (@%x)\n", | 
|---|
| 83 |                   __FUNCTION__, | 
|---|
| 84 |                   ctx->fat_begin_lba,  | 
|---|
| 85 |                   ctx->fat_blk_count, | 
|---|
| 86 |                   ctx->cluster_begin_lba,  | 
|---|
| 87 |                   ctx->sectors_per_cluster, | 
|---|
| 88 |                   ctx->rootdir_first_cluster,  | 
|---|
| 89 |                   ctx->bytes_per_cluster, | 
|---|
| 90 |                   bpb->BPB_Media, | 
|---|
| 91 |                   &bpb->BPB_Media); | 
|---|
| 92 |  | 
|---|
| 93 |         vfat_dmsg(1, "DEBUG: context_init: last allocated sector %d, last allocated index %d\n", | 
|---|
| 94 |                   ctx->last_allocated_sector, ctx->last_allocated_index); | 
|---|
| 95 |  | 
|---|
| 96 |          | 
|---|
| 97 |         return 0; | 
|---|
| 98 | } | 
|---|
| 99 |  | 
|---|
| 100 | VFS_CREATE_CONTEXT(vfat_create_context) | 
|---|
| 101 | { | 
|---|
| 102 |         kmem_req_t req; | 
|---|
| 103 |         struct vfat_context_s *vfat_ctx; | 
|---|
| 104 |         struct mapper_s *mapper; | 
|---|
| 105 |         error_t err; | 
|---|
| 106 |  | 
|---|
| 107 |         vfat_dmsg(1, "%s: started\n", __FUNCTION__); | 
|---|
| 108 |    | 
|---|
| 109 |         vfat_ctx = &context->ctx_vfat; | 
|---|
| 110 |  | 
|---|
| 111 |         vfat_ctx->dev = context->ctx_dev;//necessary ? | 
|---|
| 112 |  | 
|---|
| 113 |         rwlock_init(&vfat_ctx->lock); | 
|---|
| 114 |  | 
|---|
| 115 |         req.type = KMEM_MAPPER; | 
|---|
| 116 |         req.size = sizeof(*mapper); | 
|---|
| 117 |         mapper   = kmem_alloc(&req); | 
|---|
| 118 |  | 
|---|
| 119 |         if(mapper == NULL) | 
|---|
| 120 |         { | 
|---|
| 121 |                 err = ENOMEM; | 
|---|
| 122 |                 goto fail_mapper; | 
|---|
| 123 |         } | 
|---|
| 124 |  | 
|---|
| 125 |         err = mapper_init(mapper, &vfat_inode_mapper_op, NULL, vfat_ctx); | 
|---|
| 126 |  | 
|---|
| 127 |         if(err) | 
|---|
| 128 |         { | 
|---|
| 129 |                 printk(ERROR, "ERROR: %s: failed to init mapper, err %d\n", __FUNCTION__, err); | 
|---|
| 130 |                 goto fail_mapper_init; | 
|---|
| 131 |         } | 
|---|
| 132 |  | 
|---|
| 133 |         vfat_ctx->mapper = mapper; | 
|---|
| 134 |         vfat_ctx->fat_cid = current_cid; | 
|---|
| 135 |  | 
|---|
| 136 |         if ((err = vfat_context_init(vfat_ctx))) | 
|---|
| 137 |         { | 
|---|
| 138 |                 printk(ERROR, "ERROR: vfat_create_context: INITIALIZING VFAT CONTEXT err %d\n",err); | 
|---|
| 139 |                 goto fail_ctx_init; | 
|---|
| 140 |         } | 
|---|
| 141 |  | 
|---|
| 142 |         context->ctx_flags      |= VFS_FS_USE_MAPPER; | 
|---|
| 143 |         context->ctx_type       = VFS_VFAT_TYPE; | 
|---|
| 144 |         context->ctx_blksize    = vfat_ctx->bytes_per_sector; | 
|---|
| 145 |         context->ctx_op         = (struct vfs_context_op_s *) &vfat_ctx_op; | 
|---|
| 146 |         context->ctx_inode_op   = (struct vfs_inode_op_s *) &vfat_i_op; | 
|---|
| 147 |         context->ctx_dirent_op  = (struct vfs_dirent_op_s *) &vfat_d_op; | 
|---|
| 148 |         context->ctx_file_op    = (struct vfs_file_op_s *) &vfat_f_op; | 
|---|
| 149 |  | 
|---|
| 150 |         return 0; | 
|---|
| 151 |  | 
|---|
| 152 | fail_ctx_init: | 
|---|
| 153 | fail_mapper_init: | 
|---|
| 154 |         mapper_destroy(mapper, false); | 
|---|
| 155 |         req.type = KMEM_MAPPER; | 
|---|
| 156 |         req.ptr  = mapper; | 
|---|
| 157 |         kmem_free(&req); | 
|---|
| 158 |  | 
|---|
| 159 | fail_mapper: | 
|---|
| 160 |         req.type = KMEM_VFAT_CTX; | 
|---|
| 161 |         req.ptr  = vfat_ctx; | 
|---|
| 162 |         kmem_free(&req); | 
|---|
| 163 |  | 
|---|
| 164 |         rwlock_destroy(&vfat_ctx->lock); | 
|---|
| 165 |         return err; | 
|---|
| 166 | } | 
|---|
| 167 |  | 
|---|
| 168 | VFS_DESTROY_CONTEXT(vfat_destroy_context) | 
|---|
| 169 | { | 
|---|
| 170 |         struct vfat_context_s *ctx; | 
|---|
| 171 |  | 
|---|
| 172 |         ctx = &context->ctx_vfat; | 
|---|
| 173 |         mapper_destroy(ctx->mapper, true); | 
|---|
| 174 |         rwlock_destroy(&ctx->lock); | 
|---|
| 175 |         return 0; | 
|---|
| 176 | } | 
|---|
| 177 |  | 
|---|
| 178 |  | 
|---|
| 179 | VFS_READ_ROOT(vfat_read_root) | 
|---|
| 180 | { | 
|---|
| 181 |         struct vfat_context_s *ctx; | 
|---|
| 182 |         struct vfat_inode_s * i_info; | 
|---|
| 183 |          | 
|---|
| 184 |         ctx = &context->ctx_vfat; | 
|---|
| 185 |  | 
|---|
| 186 |         root->i_type            |= VFS_DIR;//? | 
|---|
| 187 |         root->i_links           = 1; | 
|---|
| 188 |         root->i_attr            |= VFS_DIR; | 
|---|
| 189 |         root->i_size            = vfat_cluster_count(ctx, ctx->rootdir_first_cluster);//does a dir has a size? | 
|---|
| 190 |         root->i_mapper->m_inode = root; | 
|---|
| 191 |         root->i_mapper->m_ops   = &vfat_inode_mapper_op; | 
|---|
| 192 |         root->i_number          = vfs_inum_new(context); | 
|---|
| 193 |  | 
|---|
| 194 |         assert(root->i_pv); | 
|---|
| 195 |         i_info                 = root->i_pv; | 
|---|
| 196 |         i_info->flags          = VFAT_ATTR_DIRECTORY; | 
|---|
| 197 |         i_info->first_cluster  = ctx->rootdir_first_cluster; | 
|---|
| 198 |         //i_info->parent_cluster = 0; | 
|---|
| 199 |         //i_info->entry_index    = 0; | 
|---|
| 200 |  | 
|---|
| 201 |         return 0; | 
|---|
| 202 | } | 
|---|
| 203 |  | 
|---|
| 204 |  | 
|---|
| 205 | VFS_WRITE_ROOT(vfat_write_root) | 
|---|
| 206 | { | 
|---|
| 207 |         return 0; | 
|---|
| 208 | } | 
|---|
| 209 |  | 
|---|
| 210 |  | 
|---|
| 211 | KMEM_OBJATTR_INIT(vfat_kmem_context_init) | 
|---|
| 212 | { | 
|---|
| 213 |         attr->type   = KMEM_VFAT_CTX; | 
|---|
| 214 |         attr->name   = "KCM VFAT CTX"; | 
|---|
| 215 |         attr->size   = sizeof(struct vfat_context_s); | 
|---|
| 216 |         attr->aligne = 0; | 
|---|
| 217 |         attr->min    = CONFIG_VFAT_CTX_MIN; | 
|---|
| 218 |         attr->max    = CONFIG_VFAT_CTX_MAX; | 
|---|
| 219 |         attr->ctor   = NULL; | 
|---|
| 220 |         attr->dtor   = NULL; | 
|---|
| 221 |         return 0; | 
|---|
| 222 | } | 
|---|
| 223 |  | 
|---|
| 224 | const struct vfs_context_op_s vfat_ctx_op = | 
|---|
| 225 | { | 
|---|
| 226 |         .create     = vfat_create_context, | 
|---|
| 227 |         .destroy    = vfat_destroy_context, | 
|---|
| 228 |         .read_root  = vfat_read_root, | 
|---|
| 229 |         .write_root = vfat_write_root, | 
|---|
| 230 |         .repli_root = NULL | 
|---|
| 231 | }; | 
|---|