blob: e6100aec25666cb1d153c5eefa1cd0d7ef690ff6 [file] [log] [blame]
Sven-Göran Bergh93696342013-08-01 11:05:08 +02001/*
2 * volume_id - reads filesystem label and uuid
3 *
4 * Copyright (C) 2012 S-G Bergh <sgb@systemasis.org>
5 *
6 * Licensed under GPLv2, see file LICENSE in this source tree.
7 */
Sven-Göran Bergh93696342013-08-01 11:05:08 +02008//config:config FEATURE_VOLUMEID_F2FS
9//config: bool "f2fs filesystem"
10//config: default y
11//config: depends on VOLUMEID
12//config: help
Denys Vlasenko72089cf2017-07-21 09:50:55 +020013//config: F2FS (aka Flash-Friendly File System) is a log-structured file system,
14//config: which is adapted to newer forms of storage. F2FS also remedies some
15//config: known issues of the older log structured file systems, such as high
16//config: cleaning overhead.
Sven-Göran Bergh93696342013-08-01 11:05:08 +020017
Denys Vlasenko0c4dbd42017-09-18 16:28:43 +020018//kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_F2FS) += f2fs.o
19
Sven-Göran Bergh93696342013-08-01 11:05:08 +020020#include "volume_id_internal.h"
21
22#define F2FS_MAGIC 0xF2F52010 // F2FS Magic Number
23#define F2FS_UUID_SIZE 16
24#define F2FS_LABEL_SIZE 512
25#define F2FS_LABEL_BYTES 1024
26#define F2FS_SB1_OFFSET 0x400 // offset for 1:st super block
27/*
28#define F2FS_SB2_OFFSET 0x1400 // offset for 2:nd super block
29*/
30
31struct f2fs_super_block { // According to version 1.1
32/* 0x00 */ uint32_t magic; // Magic Number
33/* 0x04 */ uint16_t major_ver; // Major Version
34/* 0x06 */ uint16_t minor_ver; // Minor Version
35/* 0x08 */ uint32_t log_sectorsize; // log2 sector size in bytes
36/* 0x0C */ uint32_t log_sectors_per_block; // log2 # of sectors per block
37/* 0x10 */ uint32_t log_blocksize; // log2 block size in bytes
38/* 0x14 */ uint32_t log_blocks_per_seg; // log2 # of blocks per segment
39/* 0x18 */ uint32_t segs_per_sec; // # of segments per section
40/* 0x1C */ uint32_t secs_per_zone; // # of sections per zone
41/* 0x20 */ uint32_t checksum_offset; // checksum offset inside super block
42/* 0x24 */ uint64_t block_count; // total # of user blocks
43/* 0x2C */ uint32_t section_count; // total # of sections
44/* 0x30 */ uint32_t segment_count; // total # of segments
45/* 0x34 */ uint32_t segment_count_ckpt; // # of segments for checkpoint
46/* 0x38 */ uint32_t segment_count_sit; // # of segments for SIT
47/* 0x3C */ uint32_t segment_count_nat; // # of segments for NAT
48/* 0x40 */ uint32_t segment_count_ssa; // # of segments for SSA
49/* 0x44 */ uint32_t segment_count_main; // # of segments for main area
50/* 0x48 */ uint32_t segment0_blkaddr; // start block address of segment 0
51/* 0x4C */ uint32_t cp_blkaddr; // start block address of checkpoint
52/* 0x50 */ uint32_t sit_blkaddr; // start block address of SIT
53/* 0x54 */ uint32_t nat_blkaddr; // start block address of NAT
54/* 0x58 */ uint32_t ssa_blkaddr; // start block address of SSA
55/* 0x5C */ uint32_t main_blkaddr; // start block address of main area
56/* 0x60 */ uint32_t root_ino; // root inode number
57/* 0x64 */ uint32_t node_ino; // node inode number
58/* 0x68 */ uint32_t meta_ino; // meta inode number
59/* 0x6C */ uint8_t uuid[F2FS_UUID_SIZE]; // 128-bit uuid for volume
60/* 0x7C */ uint16_t volume_name[F2FS_LABEL_SIZE]; // volume name
61// /* 0x47C */ uint32_t extension_count; // # of extensions below
62// /* 0x480 */ uint8_t extension_list[64][8]; // extension array
63} PACKED;
64
65
66int FAST_FUNC volume_id_probe_f2fs(struct volume_id *id /*,uint64_t off*/)
67{
68 struct f2fs_super_block *sb;
69
70 // Go for primary super block (ignore second sb)
71 dbg("f2fs: probing at offset 0x%x", F2FS_SB1_OFFSET);
72 sb = volume_id_get_buffer(id, F2FS_SB1_OFFSET, sizeof(*sb));
73
74 if (!sb)
75 return -1;
76
77 if (sb->magic != cpu_to_le32(F2FS_MAGIC))
78 return -1;
79
80 IF_FEATURE_BLKID_TYPE(id->type = "f2fs");
81
82 // For version 1.0 we don't know sb structure and can't set label/uuid
83 if (sb->major_ver == cpu_to_le16(1) && sb->minor_ver == cpu_to_le16(0))
84 return 0;
85
86 volume_id_set_label_unicode16(id, (uint8_t *)sb->volume_name,
87 LE, MIN(F2FS_LABEL_BYTES, VOLUME_ID_LABEL_SIZE));
88
89 volume_id_set_uuid(id, sb->uuid, UUID_DCE);
90
91 return 0;
92}