HelenOS sources

root/uspace/srv/fs/exfat/exfat.h

/* [<][>][^][v][top][bottom][index][help] */

INCLUDED FROM


/*
 * Copyright (c) 2008 Jakub Jermar
 * Copyright (c) 2011 Oleg Romanenko
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * - Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 * - Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the distribution.
 * - The name of the author may not be used to endorse or promote products
 *   derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/** @addtogroup exfat
 * @{
 */

#ifndef EXFAT_EXFAT_H_
#define EXFAT_EXFAT_H_

#include "exfat_fat.h"
#include <fibril_synch.h>
#include <libfs.h>
#include <stdint.h>
#include <stdbool.h>
#include "../../vfs/vfs.h"

#ifndef dprintf
#define dprintf(...)    printf(__VA_ARGS__)
#endif

#define BS_BLOCK                0
#define BS_SIZE                 512

#define BPS(bs)                 ((uint32_t) (1 << (bs->bytes_per_sector)))
#define SPC(bs)                 ((uint32_t) (1 << (bs->sec_per_cluster)))
#define BPC(bs)                 ((uint32_t) (BPS(bs) * SPC(bs)))
#define VOL_FS(bs)              uint64_t_le2host(bs->volume_start)
#define VOL_CNT(bs)             uint64_t_le2host(bs->volume_count)
#define FAT_FS(bs)              uint32_t_le2host(bs->fat_sector_start)
#define FAT_CNT(bs)             uint32_t_le2host(bs->fat_sector_count)
#define DATA_FS(bs)             uint32_t_le2host(bs->data_start_sector)
#define DATA_CNT(bs)            uint32_t_le2host(bs->data_clusters)
#define ROOT_FC(bs)             uint32_t_le2host(bs->rootdir_cluster)
#define VOL_FLAGS(bs)           uint16_t_le2host(bs->volume_flags)

#define EXFAT_NODE(node)        ((node) ? (exfat_node_t *) (node)->data : NULL)
#define FS_NODE(node)   ((node) ? (node)->bp : NULL)
#define DPS(bs) (BPS((bs)) / sizeof(exfat_dentry_t))

typedef struct exfat_bs {
        uint8_t jump[3];                                /* 0x00 jmp and nop instructions */
        uint8_t oem_name[8];                    /* 0x03 "EXFAT   " */
        uint8_t __reserved[53];                 /* 0x0B always 0 */
        uint64_t volume_start;                  /* 0x40 partition first sector */
        uint64_t volume_count;                  /* 0x48 partition sectors count */
        uint32_t fat_sector_start;              /* 0x50 FAT first sector */
        uint32_t fat_sector_count;              /* 0x54 FAT sectors count */
        uint32_t data_start_sector;             /* 0x58 Data region first cluster sector */
        uint32_t data_clusters;                 /* 0x5C total clusters count */
        uint32_t rootdir_cluster;               /* 0x60 first cluster of the root dir */
        uint32_t volume_serial;                 /* 0x64 volume serial number */
        struct {                                                /* 0x68 FS version */
                uint8_t minor;
                uint8_t major;
        } __attribute__((packed)) version;
        uint16_t volume_flags;                  /* 0x6A volume state flags */
        uint8_t bytes_per_sector;               /* 0x6C sector size as (1 << n) */
        uint8_t sec_per_cluster;                /* 0x6D sectors per cluster as (1 << n) */
        uint8_t fat_count;                              /* 0x6E always 1 */
        uint8_t drive_no;                               /* 0x6F always 0x80 */
        uint8_t allocated_percent;              /* 0x70 percentage of allocated space */
        uint8_t _reserved2[7];                  /* 0x71 reserved */
        uint8_t bootcode[390];                  /* Boot code */
        uint16_t signature;                             /* the value of 0xAA55 */
} __attribute__((__packed__)) exfat_bs_t;

typedef enum {
        EXFAT_UNKNOW,
        EXFAT_DIRECTORY,
        EXFAT_FILE,
        EXFAT_BITMAP,
        EXFAT_UCTABLE
} exfat_node_type_t;

struct exfat_node;
struct exfat_idx_t;

typedef struct {
        /** Used indices (position) hash table link. */
        ht_link_t               uph_link;
        /** Used indices (index) hash table link. */
        ht_link_t               uih_link;

        fibril_mutex_t  lock;
        service_id_t    service_id;
        fs_index_t      index;

        /* Does parent node fragmented or not? */
        bool parent_fragmented;
        /**
         * Parent node's first cluster.
         * Zero is used if this node is not linked, in which case nodep must
         * contain a pointer to the in-core node structure.
         * One is used when the parent is the root directory.
         */
        exfat_cluster_t pfc;
        /** Directory entry index within the parent node. */
        unsigned        pdi;
        /** Pointer to in-core node instance. */
        struct exfat_node       *nodep;
} exfat_idx_t;

/** exFAT in-core node. */
typedef struct exfat_node {
        /** Back pointer to the FS node. */
        fs_node_t               *bp;

        fibril_mutex_t          lock;
        exfat_node_type_t       type;
        exfat_idx_t                     *idx;
        /**
         *  Node's first cluster.
         *  Zero is used for zero-length nodes.
         *  One is used to mark root directory.
         */
        exfat_cluster_t         firstc;
        /** exFAT in-core node free list link. */
        link_t                  ffn_link;
        aoff64_t                size;
        unsigned                lnkcnt;
        unsigned                refcnt;
        bool                    dirty;
        /* Should we do walk-on-FAT or not */
        bool                    fragmented;

        /*
         * Cache of the node's last and "current" cluster to avoid some
         * unnecessary FAT walks.
         */
        /* Node's last cluster in FAT. */
        bool            lastc_cached_valid;
        exfat_cluster_t lastc_cached_value;
        /* Node's "current" cluster, i.e. where the last I/O took place. */
        bool            currc_cached_valid;
        aoff64_t        currc_cached_bn;
        exfat_cluster_t currc_cached_value;
} exfat_node_t;

extern vfs_out_ops_t exfat_ops;
extern libfs_ops_t exfat_libfs_ops;

extern errno_t exfat_idx_get_new(exfat_idx_t **, service_id_t);
extern exfat_idx_t *exfat_idx_get_by_pos(service_id_t, exfat_cluster_t, unsigned);
extern exfat_idx_t *exfat_idx_get_by_index(service_id_t, fs_index_t);
extern void exfat_idx_destroy(exfat_idx_t *);
extern void exfat_idx_hashin(exfat_idx_t *);
extern void exfat_idx_hashout(exfat_idx_t *);

extern errno_t exfat_idx_init(void);
extern void exfat_idx_fini(void);
extern errno_t exfat_idx_init_by_service_id(service_id_t);
extern void exfat_idx_fini_by_service_id(service_id_t);

extern errno_t exfat_node_expand(service_id_t, exfat_node_t *, exfat_cluster_t);
extern errno_t exfat_node_put(fs_node_t *);
extern errno_t exfat_bitmap_get(fs_node_t **, service_id_t);
extern errno_t exfat_uctable_get(fs_node_t **, service_id_t);

#endif

/**
 * @}
 */

/* [<][>][^][v][top][bottom][index][help] */
HelenOS homepage, sources at GitHub