bigbiff bigbiff | e60683a | 2013-02-22 20:55:50 -0500 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2013 Alejandro Martinez Ruiz <alex@nowcomputing.com> |
| 3 | * |
| 4 | * This file may be redistributed under the terms of the |
| 5 | * GNU Lesser General Public License |
| 6 | */ |
| 7 | |
| 8 | #include <stddef.h> |
| 9 | #include <string.h> |
| 10 | |
| 11 | #include "superblocks.h" |
| 12 | |
| 13 | #define F2FS_MAGIC "\x10\x20\xF5\xF2" |
| 14 | #define F2FS_MAGIC_OFF 0 |
| 15 | #define F2FS_UUID_SIZE 16 |
| 16 | #define F2FS_LABEL_SIZE 512 |
| 17 | #define F2FS_SB1_OFF 0x400 |
| 18 | #define F2FS_SB1_KBOFF (F2FS_SB1_OFF >> 10) |
| 19 | #define F2FS_SB2_OFF 0x1400 |
| 20 | #define F2FS_SB2_KBOFF (F2FS_SB2_OFF >> 10) |
| 21 | |
| 22 | struct f2fs_super_block { /* According to version 1.1 */ |
| 23 | /* 0x00 */ uint32_t magic; /* Magic Number */ |
| 24 | /* 0x04 */ uint16_t major_ver; /* Major Version */ |
| 25 | /* 0x06 */ uint16_t minor_ver; /* Minor Version */ |
| 26 | /* 0x08 */ uint32_t log_sectorsize; /* log2 sector size in bytes */ |
| 27 | /* 0x0C */ uint32_t log_sectors_per_block; /* log2 # of sectors per block */ |
| 28 | /* 0x10 */ uint32_t log_blocksize; /* log2 block size in bytes */ |
| 29 | /* 0x14 */ uint32_t log_blocks_per_seg; /* log2 # of blocks per segment */ |
| 30 | /* 0x18 */ uint32_t segs_per_sec; /* # of segments per section */ |
| 31 | /* 0x1C */ uint32_t secs_per_zone; /* # of sections per zone */ |
| 32 | /* 0x20 */ uint32_t checksum_offset; /* checksum offset inside super block */ |
| 33 | /* 0x24 */ uint64_t block_count; /* total # of user blocks */ |
| 34 | /* 0x2C */ uint32_t section_count; /* total # of sections */ |
| 35 | /* 0x30 */ uint32_t segment_count; /* total # of segments */ |
| 36 | /* 0x34 */ uint32_t segment_count_ckpt; /* # of segments for checkpoint */ |
| 37 | /* 0x38 */ uint32_t segment_count_sit; /* # of segments for SIT */ |
| 38 | /* 0x3C */ uint32_t segment_count_nat; /* # of segments for NAT */ |
| 39 | /* 0x40 */ uint32_t segment_count_ssa; /* # of segments for SSA */ |
| 40 | /* 0x44 */ uint32_t segment_count_main; /* # of segments for main area */ |
| 41 | /* 0x48 */ uint32_t segment0_blkaddr; /* start block address of segment 0 */ |
| 42 | /* 0x4C */ uint32_t cp_blkaddr; /* start block address of checkpoint */ |
| 43 | /* 0x50 */ uint32_t sit_blkaddr; /* start block address of SIT */ |
| 44 | /* 0x54 */ uint32_t nat_blkaddr; /* start block address of NAT */ |
| 45 | /* 0x58 */ uint32_t ssa_blkaddr; /* start block address of SSA */ |
| 46 | /* 0x5C */ uint32_t main_blkaddr; /* start block address of main area */ |
| 47 | /* 0x60 */ uint32_t root_ino; /* root inode number */ |
| 48 | /* 0x64 */ uint32_t node_ino; /* node inode number */ |
| 49 | /* 0x68 */ uint32_t meta_ino; /* meta inode number */ |
| 50 | /* 0x6C */ uint8_t uuid[F2FS_UUID_SIZE]; /* 128-bit uuid for volume */ |
| 51 | /* 0x7C */ uint16_t volume_name[F2FS_LABEL_SIZE]; /* volume name */ |
| 52 | #if 0 |
| 53 | /* 0x47C */ uint32_t extension_count; /* # of extensions below */ |
| 54 | /* 0x480 */ uint8_t extension_list[64][8]; /* extension array */ |
| 55 | #endif |
| 56 | } __attribute__((packed)); |
| 57 | |
| 58 | static int probe_f2fs(blkid_probe pr, const struct blkid_idmag *mag) |
| 59 | { |
| 60 | struct f2fs_super_block *sb; |
| 61 | uint16_t major, minor; |
| 62 | |
| 63 | sb = blkid_probe_get_sb(pr, mag, struct f2fs_super_block); |
| 64 | if (!sb) |
bigbiff | 7b4c7a6 | 2015-01-01 19:44:14 -0500 | [diff] [blame] | 65 | return errno ? -errno : 1; |
bigbiff bigbiff | e60683a | 2013-02-22 20:55:50 -0500 | [diff] [blame] | 66 | |
| 67 | major = le16_to_cpu(sb->major_ver); |
| 68 | minor = le16_to_cpu(sb->minor_ver); |
| 69 | |
| 70 | /* For version 1.0 we cannot know the correct sb structure */ |
| 71 | if (major == 1 && minor == 0) |
| 72 | return 0; |
| 73 | |
| 74 | if (*((unsigned char *) sb->volume_name)) |
| 75 | blkid_probe_set_utf8label(pr, (unsigned char *) sb->volume_name, |
| 76 | sizeof(sb->volume_name), |
| 77 | BLKID_ENC_UTF16LE); |
| 78 | |
| 79 | blkid_probe_set_uuid(pr, sb->uuid); |
| 80 | blkid_probe_sprintf_version(pr, "%u.%u", major, minor); |
| 81 | return 0; |
| 82 | } |
| 83 | |
| 84 | const struct blkid_idinfo f2fs_idinfo = |
| 85 | { |
| 86 | .name = "f2fs", |
| 87 | .usage = BLKID_USAGE_FILESYSTEM, |
| 88 | .probefunc = probe_f2fs, |
| 89 | .magics = |
| 90 | { |
| 91 | { |
| 92 | .magic = F2FS_MAGIC, |
| 93 | .len = 4, |
| 94 | .kboff = F2FS_SB1_KBOFF, |
| 95 | .sboff = F2FS_MAGIC_OFF |
| 96 | }, |
| 97 | { NULL } |
| 98 | } |
| 99 | }; |