2 * Copyright (c) 2008 Jakub Jermar
3 * Copyright (c) 2011 Oleg Romanenko
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * - Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * - Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * - The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 #ifndef EXFAT_EXFAT_H_
35 #define EXFAT_EXFAT_H_
37 #include "exfat_fat.h"
38 #include <fibril_synch.h>
42 #include "../../vfs/vfs.h"
45 #define dprintf(...) printf(__VA_ARGS__)
51 #define BPS(bs) ((uint32_t) (1 << (bs->bytes_per_sector)))
52 #define SPC(bs) ((uint32_t) (1 << (bs->sec_per_cluster)))
53 #define BPC(bs) ((uint32_t) (BPS(bs) * SPC(bs)))
54 #define VOL_FS(bs) uint64_t_le2host(bs->volume_start)
55 #define VOL_CNT(bs) uint64_t_le2host(bs->volume_count)
56 #define FAT_FS(bs) uint32_t_le2host(bs->fat_sector_start)
57 #define FAT_CNT(bs) uint32_t_le2host(bs->fat_sector_count)
58 #define DATA_FS(bs) uint32_t_le2host(bs->data_start_sector)
59 #define DATA_CNT(bs) uint32_t_le2host(bs->data_clusters)
60 #define ROOT_FC(bs) uint32_t_le2host(bs->rootdir_cluster)
61 #define VOL_FLAGS(bs) uint16_t_le2host(bs->volume_flags)
63 #define EXFAT_NODE(node) ((node) ? (exfat_node_t *) (node)->data : NULL)
64 #define FS_NODE(node) ((node) ? (node)->bp : NULL)
65 #define DPS(bs) (BPS((bs)) / sizeof(exfat_dentry_t))
67 typedef struct exfat_bs
{
68 uint8_t jump
[3]; /* 0x00 jmp and nop instructions */
69 uint8_t oem_name
[8]; /* 0x03 "EXFAT " */
70 uint8_t __reserved
[53]; /* 0x0B always 0 */
71 uint64_t volume_start
; /* 0x40 partition first sector */
72 uint64_t volume_count
; /* 0x48 partition sectors count */
73 uint32_t fat_sector_start
; /* 0x50 FAT first sector */
74 uint32_t fat_sector_count
; /* 0x54 FAT sectors count */
75 uint32_t data_start_sector
; /* 0x58 Data region first cluster sector */
76 uint32_t data_clusters
; /* 0x5C total clusters count */
77 uint32_t rootdir_cluster
; /* 0x60 first cluster of the root dir */
78 uint32_t volume_serial
; /* 0x64 volume serial number */
79 struct { /* 0x68 FS version */
82 } __attribute__((packed
)) version
;
83 uint16_t volume_flags
; /* 0x6A volume state flags */
84 uint8_t bytes_per_sector
; /* 0x6C sector size as (1 << n) */
85 uint8_t sec_per_cluster
; /* 0x6D sectors per cluster as (1 << n) */
86 uint8_t fat_count
; /* 0x6E always 1 */
87 uint8_t drive_no
; /* 0x6F always 0x80 */
88 uint8_t allocated_percent
; /* 0x70 percentage of allocated space */
89 uint8_t _reserved2
[7]; /* 0x71 reserved */
90 uint8_t bootcode
[390]; /* Boot code */
91 uint16_t signature
; /* the value of 0xAA55 */
92 } __attribute__((__packed__
)) exfat_bs_t
;
106 /** Used indices (position) hash table link. */
108 /** Used indices (index) hash table link. */
112 service_id_t service_id
;
115 /* Does parent node fragmented or not? */
116 bool parent_fragmented
;
118 * Parent node's first cluster.
119 * Zero is used if this node is not linked, in which case nodep must
120 * contain a pointer to the in-core node structure.
121 * One is used when the parent is the root directory.
124 /** Directory entry index within the parent node. */
126 /** Pointer to in-core node instance. */
127 struct exfat_node
*nodep
;
130 /** exFAT in-core node. */
131 typedef struct exfat_node
{
132 /** Back pointer to the FS node. */
136 exfat_node_type_t type
;
139 * Node's first cluster.
140 * Zero is used for zero-length nodes.
141 * One is used to mark root directory.
143 exfat_cluster_t firstc
;
144 /** exFAT in-core node free list link. */
150 /* Should we do walk-on-FAT or not */
154 * Cache of the node's last and "current" cluster to avoid some
155 * unnecessary FAT walks.
157 /* Node's last cluster in FAT. */
158 bool lastc_cached_valid
;
159 exfat_cluster_t lastc_cached_value
;
160 /* Node's "current" cluster, i.e. where the last I/O took place. */
161 bool currc_cached_valid
;
162 aoff64_t currc_cached_bn
;
163 exfat_cluster_t currc_cached_value
;
167 extern vfs_out_ops_t exfat_ops
;
168 extern libfs_ops_t exfat_libfs_ops
;
170 extern errno_t
exfat_idx_get_new(exfat_idx_t
**, service_id_t
);
171 extern exfat_idx_t
*exfat_idx_get_by_pos(service_id_t
, exfat_cluster_t
, unsigned);
172 extern exfat_idx_t
*exfat_idx_get_by_index(service_id_t
, fs_index_t
);
173 extern void exfat_idx_destroy(exfat_idx_t
*);
174 extern void exfat_idx_hashin(exfat_idx_t
*);
175 extern void exfat_idx_hashout(exfat_idx_t
*);
177 extern errno_t
exfat_idx_init(void);
178 extern void exfat_idx_fini(void);
179 extern errno_t
exfat_idx_init_by_service_id(service_id_t
);
180 extern void exfat_idx_fini_by_service_id(service_id_t
);
182 extern errno_t
exfat_node_expand(service_id_t
, exfat_node_t
*, exfat_cluster_t
);
183 extern errno_t
exfat_node_put(fs_node_t
*);
184 extern errno_t
exfat_bitmap_get(fs_node_t
**, service_id_t
);
185 extern errno_t
exfat_uctable_get(fs_node_t
**, service_id_t
);