zephyr/subsys/fs/ext2/ext2_struct.h
Franciszek Zdobylak 1eb104795e fs: ext2: Use disk structs to access data on disk
This commits changes how data on the disk is accessed. There are disk
structures which are packed and their fields are stored in little endian
byte order. To use data in the program structures it has to be translated
from little endian to cpu endianness.

Signed-off-by: Franciszek Zdobylak <fzdobylak@antmicro.com>
2023-08-03 12:22:01 -04:00

249 lines
6.4 KiB
C

/*
* Copyright (c) 2023 Antmicro <www.antmicro.com>
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef __EXT2_STRUCT_H__
#define __EXT2_STRUCT_H__
#include <zephyr/kernel.h>
#include "ext2.h"
/* Disk structures ---------------------------------------------------------- */
struct ext2_disk_superblock {
uint32_t s_inodes_count;
uint32_t s_blocks_count;
uint32_t s_r_blocks_count;
uint32_t s_free_blocks_count;
uint32_t s_free_inodes_count;
uint32_t s_first_data_block;
uint32_t s_log_block_size;
uint32_t s_log_frag_size;
uint32_t s_blocks_per_group;
uint32_t s_frags_per_group;
uint32_t s_inodes_per_group;
uint32_t s_mtime;
uint32_t s_wtime;
uint16_t s_mnt_count;
uint16_t s_max_mnt_count;
uint16_t s_magic;
uint16_t s_state;
uint16_t s_errors;
uint16_t s_minor_rev_level;
uint32_t s_lastcheck;
uint32_t s_checkinterval;
uint32_t s_creator_os;
uint32_t s_rev_level;
uint16_t s_def_resuid;
uint16_t s_def_resgid;
uint32_t s_first_ino;
uint16_t s_inode_size;
uint16_t s_block_group_nr;
uint32_t s_feature_compat;
uint32_t s_feature_incompat;
uint32_t s_feature_ro_compat;
uint8_t s_uuid[16];
uint8_t s_volume_name[16];
uint8_t s_last_mounted[64];
uint32_t s_algo_bitmap;
uint8_t s_prealloc_blocks;
uint8_t s_prealloc_dir_blocks;
uint8_t s_align[2];
uint8_t s_journal_uuid[16];
uint32_t s_journal_inum;
uint32_t s_journal_dev;
uint32_t s_last_orphan;
uint8_t s_padding[788];
} __packed;
struct ext2_disk_bgroup {
uint32_t bg_block_bitmap;
uint32_t bg_inode_bitmap;
uint32_t bg_inode_table;
uint16_t bg_free_blocks_count;
uint16_t bg_free_inodes_count;
uint16_t bg_used_dirs_count;
uint16_t bg_pad;
uint8_t bg_reserved[12];
} __packed;
struct ext2_disk_inode {
uint16_t i_mode;
uint16_t i_uid;
uint32_t i_size;
uint32_t i_atime;
uint32_t i_ctime;
uint32_t i_mtime;
uint32_t i_dtime;
uint16_t i_gid;
uint16_t i_links_count;
uint32_t i_blocks;
uint32_t i_flags;
uint32_t i_osd1;
uint32_t i_block[15];
uint32_t i_generation;
uint32_t i_file_acl;
uint32_t i_dir_acl;
uint32_t i_faddr;
uint8_t i_osd2[12];
} __packed;
struct ext2_disk_direntry {
uint32_t de_inode;
uint16_t de_rec_len;
uint8_t de_name_len;
uint8_t de_file_type;
char de_name[];
} __packed;
/* Program structures ------------------------------------------------------- */
struct ext2_superblock {
uint32_t s_inodes_count;
uint32_t s_blocks_count;
uint32_t s_free_blocks_count;
uint32_t s_free_inodes_count;
uint32_t s_first_data_block;
uint32_t s_log_block_size;
uint32_t s_log_frag_size;
uint32_t s_blocks_per_group;
uint32_t s_frags_per_group;
uint32_t s_inodes_per_group;
uint16_t s_mnt_count;
uint16_t s_max_mnt_count;
uint16_t s_magic;
uint16_t s_state;
uint16_t s_errors;
uint32_t s_creator_os;
uint32_t s_rev_level;
uint32_t s_first_ino;
uint16_t s_inode_size;
uint16_t s_block_group_nr;
uint32_t s_feature_compat;
uint32_t s_feature_incompat;
uint32_t s_feature_ro_compat;
};
#define EXT2_BLOCK_NUM_SIZE (sizeof(uint32_t))
#define EXT2_DISK_DIRENTRY_BY_OFFSET(addr, offset) \
((struct ext2_disk_direntry *)(((uint8_t *)(addr)) + (offset)))
#define EXT2_BLOCK_ASSIGNED BIT(0)
struct ext2_block {
uint32_t num;
uint8_t flags;
uint8_t *data;
} __aligned(sizeof(void *));
#define BGROUP_INODE_TABLE(bg) ((struct ext2_disk_inode *)(bg)->inode_table->data)
#define BGROUP_INODE_BITMAP(bg) ((uint8_t *)(bg)->inode_bitmap->data)
#define BGROUP_BLOCK_BITMAP(bg) ((uint8_t *)(bg)->block_bitmap->data)
struct ext2_bgroup {
struct ext2_data *fs; /* pointer to file system data */
struct ext2_block *inode_table; /* fetched block of inode table */
struct ext2_block *inode_bitmap; /* inode bitmap */
struct ext2_block *block_bitmap; /* block bitmap */
int32_t num; /* number of described block group */
uint32_t inode_table_block; /* number of fetched block (relative) */
uint32_t bg_block_bitmap;
uint32_t bg_inode_bitmap;
uint32_t bg_inode_table;
uint16_t bg_free_blocks_count;
uint16_t bg_free_inodes_count;
uint16_t bg_used_dirs_count;
};
/* Flags for inode */
#define INODE_FETCHED_BLOCK BIT(0)
#define INODE_REMOVE BIT(1)
struct ext2_inode {
struct ext2_data *i_fs; /* pointer to file system data */
uint8_t i_ref; /* reference count */
uint8_t flags;
uint32_t i_id; /* inode number */
uint16_t i_mode; /* mode */
uint16_t i_links_count; /* link count */
uint32_t i_size; /* size */
uint32_t i_blocks; /* number of reserved blocks (of size 512B) */
uint32_t i_block[15]; /* numbers of blocks */
int block_lvl; /* level of current block */
uint32_t block_num; /* relative number of fetched block */
uint32_t offsets[4]; /* offsets describing path to fetched block */
struct ext2_block *blocks[4]; /* fetched blocks for each level */
};
static inline struct ext2_block *inode_current_block(struct ext2_inode *inode)
{
return inode->blocks[inode->block_lvl];
}
static inline uint8_t *inode_current_block_mem(struct ext2_inode *inode)
{
return (uint8_t *)inode_current_block(inode)->data;
}
struct ext2_direntry {
uint32_t de_inode;
uint16_t de_rec_len;
uint8_t de_name_len;
uint8_t de_file_type;
char de_name[];
};
/* Max size of directory entry that could be allocated from heap. */
#define MAX_DIRENTRY_SIZE (sizeof(struct ext2_direntry) + UINT8_MAX)
/* Structure common for files and directories representation */
struct ext2_file {
struct ext2_inode *f_inode;
uint32_t f_off;
uint8_t f_flags;
};
#define EXT2_DATA_FLAGS_RO BIT(0)
#define EXT2_DATA_FLAGS_ERR BIT(1)
struct ext2_data;
struct ext2_backend_ops {
int64_t (*get_device_size)(struct ext2_data *fs);
int64_t (*get_write_size)(struct ext2_data *fs);
int (*read_block)(struct ext2_data *fs, void *buf, uint32_t num);
int (*write_block)(struct ext2_data *fs, const void *buf, uint32_t num);
int (*read_superblock)(struct ext2_data *fs, struct ext2_disk_superblock *sb);
int (*sync)(struct ext2_data *fs);
};
#define MAX_INODES (CONFIG_MAX_FILES + 2)
struct ext2_data {
struct ext2_superblock sblock; /* superblock */
struct ext2_bgroup bgroup; /* block group */
int32_t open_inodes;
int32_t open_files;
struct ext2_inode *inode_pool[MAX_INODES];
uint32_t sblock_offset;
uint32_t block_size; /* fs block size */
uint32_t write_size; /* dev minimal write size */
uint64_t device_size;
struct k_thread sync_thr;
void *backend; /* pointer to implementation specific resource */
const struct ext2_backend_ops *backend_ops;
uint8_t flags;
};
#endif /* __EXT2_STRUCT_H__ */