1 /*
2  * Copyright (c) 2023 Antmicro <www.antmicro.com>
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #ifndef __EXT2_STRUCT_H__
8 #define __EXT2_STRUCT_H__
9 
10 #include <zephyr/kernel.h>
11 #include "ext2.h"
12 
13 /* Disk structures ---------------------------------------------------------- */
14 
15 struct ext2_disk_superblock {
16 	uint32_t s_inodes_count;
17 	uint32_t s_blocks_count;
18 	uint32_t s_r_blocks_count;
19 	uint32_t s_free_blocks_count;
20 	uint32_t s_free_inodes_count;
21 	uint32_t s_first_data_block;
22 	uint32_t s_log_block_size;
23 	uint32_t s_log_frag_size;
24 	uint32_t s_blocks_per_group;
25 	uint32_t s_frags_per_group;
26 	uint32_t s_inodes_per_group;
27 	uint32_t s_mtime;
28 	uint32_t s_wtime;
29 	uint16_t s_mnt_count;
30 	uint16_t s_max_mnt_count;
31 	uint16_t s_magic;
32 	uint16_t s_state;
33 	uint16_t s_errors;
34 	uint16_t s_minor_rev_level;
35 	uint32_t s_lastcheck;
36 	uint32_t s_checkinterval;
37 	uint32_t s_creator_os;
38 	uint32_t s_rev_level;
39 	uint16_t s_def_resuid;
40 	uint16_t s_def_resgid;
41 	uint32_t s_first_ino;
42 	uint16_t s_inode_size;
43 	uint16_t s_block_group_nr;
44 	uint32_t s_feature_compat;
45 	uint32_t s_feature_incompat;
46 	uint32_t s_feature_ro_compat;
47 	uint8_t s_uuid[16];
48 	uint8_t s_volume_name[16];
49 	uint8_t s_last_mounted[64];
50 	uint32_t s_algo_bitmap;
51 	uint8_t s_prealloc_blocks;
52 	uint8_t s_prealloc_dir_blocks;
53 	uint8_t s_align[2];
54 	uint8_t s_journal_uuid[16];
55 	uint32_t s_journal_inum;
56 	uint32_t s_journal_dev;
57 	uint32_t s_last_orphan;
58 	uint8_t  s_padding[788];
59 } __packed;
60 
61 struct ext2_disk_bgroup {
62 	uint32_t bg_block_bitmap;
63 	uint32_t bg_inode_bitmap;
64 	uint32_t bg_inode_table;
65 	uint16_t bg_free_blocks_count;
66 	uint16_t bg_free_inodes_count;
67 	uint16_t bg_used_dirs_count;
68 	uint16_t bg_pad;
69 	uint8_t bg_reserved[12];
70 } __packed;
71 
72 struct ext2_disk_inode {
73 	uint16_t i_mode;
74 	uint16_t i_uid;
75 	uint32_t i_size;
76 	uint32_t i_atime;
77 	uint32_t i_ctime;
78 	uint32_t i_mtime;
79 	uint32_t i_dtime;
80 	uint16_t i_gid;
81 	uint16_t i_links_count;
82 	uint32_t i_blocks;
83 	uint32_t i_flags;
84 	uint32_t i_osd1;
85 	uint32_t i_block[15];
86 	uint32_t i_generation;
87 	uint32_t i_file_acl;
88 	uint32_t i_dir_acl;
89 	uint32_t i_faddr;
90 	uint8_t i_osd2[12];
91 } __packed;
92 
93 struct ext2_disk_direntry {
94 	uint32_t de_inode;
95 	uint16_t de_rec_len;
96 	uint8_t de_name_len;
97 	uint8_t de_file_type;
98 	char de_name[];
99 } __packed;
100 
101 /* Program structures ------------------------------------------------------- */
102 
103 struct ext2_superblock {
104 	uint32_t s_inodes_count;
105 	uint32_t s_blocks_count;
106 	uint32_t s_free_blocks_count;
107 	uint32_t s_free_inodes_count;
108 	uint32_t s_first_data_block;
109 	uint32_t s_log_block_size;
110 	uint32_t s_log_frag_size;
111 	uint32_t s_blocks_per_group;
112 	uint32_t s_frags_per_group;
113 	uint32_t s_inodes_per_group;
114 	uint16_t s_mnt_count;
115 	uint16_t s_max_mnt_count;
116 	uint16_t s_magic;
117 	uint16_t s_state;
118 	uint16_t s_errors;
119 	uint32_t s_creator_os;
120 	uint32_t s_rev_level;
121 	uint32_t s_first_ino;
122 	uint16_t s_inode_size;
123 	uint16_t s_block_group_nr;
124 	uint32_t s_feature_compat;
125 	uint32_t s_feature_incompat;
126 	uint32_t s_feature_ro_compat;
127 };
128 
129 #define EXT2_BLOCK_NUM_SIZE (sizeof(uint32_t))
130 #define EXT2_DISK_DIRENTRY_BY_OFFSET(addr, offset) \
131 	((struct ext2_disk_direntry *)(((uint8_t *)(addr)) + (offset)))
132 
133 #define EXT2_BLOCK_ASSIGNED BIT(0)
134 
135 struct ext2_block {
136 	uint32_t num;
137 	uint8_t flags;
138 	uint8_t *data;
139 } __aligned(sizeof(void *));
140 
141 #define BGROUP_INODE_TABLE(bg) ((struct ext2_disk_inode *)(bg)->inode_table->data)
142 #define BGROUP_INODE_BITMAP(bg) ((uint8_t *)(bg)->inode_bitmap->data)
143 #define BGROUP_BLOCK_BITMAP(bg) ((uint8_t *)(bg)->block_bitmap->data)
144 
145 struct ext2_bgroup {
146 	struct ext2_data *fs;       /* pointer to file system data */
147 
148 	struct ext2_block *inode_table;  /* fetched block of inode table */
149 	struct ext2_block *inode_bitmap; /* inode bitmap */
150 	struct ext2_block *block_bitmap; /* block bitmap */
151 
152 	int32_t num;                /* number of described block group */
153 	uint32_t inode_table_block; /* number of fetched block (relative) */
154 
155 	uint32_t bg_block_bitmap;
156 	uint32_t bg_inode_bitmap;
157 	uint32_t bg_inode_table;
158 	uint16_t bg_free_blocks_count;
159 	uint16_t bg_free_inodes_count;
160 	uint16_t bg_used_dirs_count;
161 };
162 
163 /* Flags for inode */
164 #define INODE_FETCHED_BLOCK BIT(0)
165 #define INODE_REMOVE BIT(1)
166 
167 struct ext2_inode {
168 	struct ext2_data *i_fs;      /* pointer to file system data */
169 	uint8_t  i_ref;              /* reference count */
170 
171 	uint8_t  flags;
172 	uint32_t i_id;             /* inode number */
173 	uint16_t i_mode;           /* mode */
174 	uint16_t i_links_count;    /* link count */
175 	uint32_t i_size;           /* size */
176 	uint32_t i_blocks;         /* number of reserved blocks (of size 512B) */
177 	uint32_t i_block[15];      /* numbers of blocks */
178 
179 	int block_lvl;             /* level of current block */
180 	uint32_t block_num;        /* relative number of fetched block */
181 	uint32_t offsets[4];       /* offsets describing path to fetched block */
182 	struct ext2_block *blocks[4];   /* fetched blocks for each level */
183 };
184 
inode_current_block(struct ext2_inode * inode)185 static inline struct ext2_block *inode_current_block(struct ext2_inode *inode)
186 {
187 	return inode->blocks[inode->block_lvl];
188 }
189 
inode_current_block_mem(struct ext2_inode * inode)190 static inline uint8_t *inode_current_block_mem(struct ext2_inode *inode)
191 {
192 	return (uint8_t *)inode_current_block(inode)->data;
193 }
194 
195 struct ext2_direntry {
196 	uint32_t de_inode;
197 	uint16_t de_rec_len;
198 	uint8_t de_name_len;
199 	uint8_t de_file_type;
200 	char de_name[];
201 };
202 
203 /* Max size of directory entry that could be allocated from heap. */
204 #define MAX_DIRENTRY_SIZE (sizeof(struct ext2_direntry) + UINT8_MAX)
205 
206 /* Structure common for files and directories representation */
207 struct ext2_file {
208 	struct ext2_inode *f_inode;
209 	uint32_t f_off;
210 	uint8_t f_flags;
211 };
212 
213 #define EXT2_DATA_FLAGS_RO  BIT(0)
214 #define EXT2_DATA_FLAGS_ERR BIT(1)
215 
216 struct ext2_data;
217 
218 struct ext2_backend_ops {
219 	int64_t (*get_device_size)(struct ext2_data *fs);
220 	int64_t (*get_write_size)(struct ext2_data *fs);
221 	int (*read_block)(struct ext2_data *fs, void *buf, uint32_t num);
222 	int (*write_block)(struct ext2_data *fs, const void *buf, uint32_t num);
223 	int (*read_superblock)(struct ext2_data *fs, struct ext2_disk_superblock *sb);
224 	int (*sync)(struct ext2_data *fs);
225 };
226 
227 #define MAX_INODES (CONFIG_MAX_FILES + 2)
228 
229 struct ext2_data {
230 	struct ext2_superblock sblock; /* superblock */
231 	struct ext2_bgroup bgroup;     /* block group */
232 
233 	int32_t open_inodes;
234 	int32_t open_files;
235 	struct ext2_inode *inode_pool[MAX_INODES];
236 
237 	uint32_t sblock_offset;
238 	uint32_t block_size; /* fs block size */
239 	uint32_t write_size; /* dev minimal write size */
240 	uint64_t device_size;
241 	struct k_thread sync_thr;
242 
243 	void *backend; /* pointer to implementation specific resource */
244 	const struct ext2_backend_ops *backend_ops;
245 	uint8_t flags;
246 };
247 
248 #endif /* __EXT2_STRUCT_H__ */
249