Upload Tizen:Base source
[framework/base/util-linux-ng.git] / shlibs / blkid / src / probers / ufs.c
1 /*
2  * Copyright (C) 2008 Karel Zak <kzak@redhat.com>
3  *
4  * Inspired by libvolume_id by
5  *     Kay Sievers <kay.sievers@vrfy.org>
6  *
7  * This file may be redistributed under the terms of the
8  * GNU Lesser General Public License.
9  */
10
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <unistd.h>
14 #include <string.h>
15 #include <errno.h>
16 #include <ctype.h>
17 #include <stdint.h>
18
19 #include "blkidP.h"
20
21 struct ufs_super_block {
22         uint32_t        fs_link;
23         uint32_t        fs_rlink;
24         uint32_t        fs_sblkno;
25         uint32_t        fs_cblkno;
26         uint32_t        fs_iblkno;
27         uint32_t        fs_dblkno;
28         uint32_t        fs_cgoffset;
29         uint32_t        fs_cgmask;
30         uint32_t        fs_time;
31         uint32_t        fs_size;
32         uint32_t        fs_dsize;
33         uint32_t        fs_ncg;
34         uint32_t        fs_bsize;
35         uint32_t        fs_fsize;
36         uint32_t        fs_frag;
37         uint32_t        fs_minfree;
38         uint32_t        fs_rotdelay;
39         uint32_t        fs_rps;
40         uint32_t        fs_bmask;
41         uint32_t        fs_fmask;
42         uint32_t        fs_bshift;
43         uint32_t        fs_fshift;
44         uint32_t        fs_maxcontig;
45         uint32_t        fs_maxbpg;
46         uint32_t        fs_fragshift;
47         uint32_t        fs_fsbtodb;
48         uint32_t        fs_sbsize;
49         uint32_t        fs_csmask;
50         uint32_t        fs_csshift;
51         uint32_t        fs_nindir;
52         uint32_t        fs_inopb;
53         uint32_t        fs_nspf;
54         uint32_t        fs_optim;
55         uint32_t        fs_npsect_state;
56         uint32_t        fs_interleave;
57         uint32_t        fs_trackskew;
58         uint32_t        fs_id[2];
59         uint32_t        fs_csaddr;
60         uint32_t        fs_cssize;
61         uint32_t        fs_cgsize;
62         uint32_t        fs_ntrak;
63         uint32_t        fs_nsect;
64         uint32_t        fs_spc;
65         uint32_t        fs_ncyl;
66         uint32_t        fs_cpg;
67         uint32_t        fs_ipg;
68         uint32_t        fs_fpg;
69         struct ufs_csum {
70                 uint32_t        cs_ndir;
71                 uint32_t        cs_nbfree;
72                 uint32_t        cs_nifree;
73                 uint32_t        cs_nffree;
74         } fs_cstotal;
75         int8_t          fs_fmod;
76         int8_t          fs_clean;
77         int8_t          fs_ronly;
78         int8_t          fs_flags;
79         union {
80                 struct {
81                         int8_t  fs_fsmnt[512];
82                         uint32_t        fs_cgrotor;
83                         uint32_t        fs_csp[31];
84                         uint32_t        fs_maxcluster;
85                         uint32_t        fs_cpc;
86                         uint16_t        fs_opostbl[16][8];
87                 } fs_u1;
88                 struct {
89                         int8_t          fs_fsmnt[468];
90                         uint8_t         fs_volname[32];
91                         uint64_t        fs_swuid;
92                         int32_t         fs_pad;
93                         uint32_t        fs_cgrotor;
94                         uint32_t        fs_ocsp[28];
95                         uint32_t        fs_contigdirs;
96                         uint32_t        fs_csp;
97                         uint32_t        fs_maxcluster;
98                         uint32_t        fs_active;
99                         int32_t         fs_old_cpc;
100                         int32_t         fs_maxbsize;
101                         int64_t         fs_sparecon64[17];
102                         int64_t         fs_sblockloc;
103                         struct ufs2_csum_total {
104                                 uint64_t        cs_ndir;
105                                 uint64_t        cs_nbfree;
106                                 uint64_t        cs_nifree;
107                                 uint64_t        cs_nffree;
108                                 uint64_t        cs_numclusters;
109                                 uint64_t        cs_spare[3];
110                         } fs_cstotal;
111                         struct ufs_timeval {
112                                 int32_t         tv_sec;
113                                 int32_t         tv_usec;
114                         } fs_time;
115                         int64_t         fs_size;
116                         int64_t         fs_dsize;
117                         uint64_t        fs_csaddr;
118                         int64_t         fs_pendingblocks;
119                         int32_t         fs_pendinginodes;
120                 } __attribute__((packed)) fs_u2;
121         }  fs_u11;
122         union {
123                 struct {
124                         int32_t         fs_sparecon[53];
125                         int32_t         fs_reclaim;
126                         int32_t         fs_sparecon2[1];
127                         int32_t         fs_state;
128                         uint32_t        fs_qbmask[2];
129                         uint32_t        fs_qfmask[2];
130                 } fs_sun;
131                 struct {
132                         int32_t         fs_sparecon[53];
133                         int32_t         fs_reclaim;
134                         int32_t         fs_sparecon2[1];
135                         uint32_t        fs_npsect;
136                         uint32_t        fs_qbmask[2];
137                         uint32_t        fs_qfmask[2];
138                 } fs_sunx86;
139                 struct {
140                         int32_t         fs_sparecon[50];
141                         int32_t         fs_contigsumsize;
142                         int32_t         fs_maxsymlinklen;
143                         int32_t         fs_inodefmt;
144                         uint32_t        fs_maxfilesize[2];
145                         uint32_t        fs_qbmask[2];
146                         uint32_t        fs_qfmask[2];
147                         int32_t         fs_state;
148                 } fs_44;
149         } fs_u2;
150         int32_t         fs_postblformat;
151         int32_t         fs_nrpos;
152         int32_t         fs_postbloff;
153         int32_t         fs_rotbloff;
154         uint32_t        fs_magic;
155         uint8_t         fs_space[1];
156 } __attribute__((packed));
157
158 #define UFS_MAGIC                       0x00011954
159 #define UFS2_MAGIC                      0x19540119
160 #define UFS_MAGIC_FEA                   0x00195612
161 #define UFS_MAGIC_LFN                   0x00095014
162 #define UFS_MAGIC_SEC                   0x00612195
163 #define UFS_MAGIC_4GB                   0x05231994
164
165 static int probe_ufs(blkid_probe pr, const struct blkid_idmag *mag)
166 {
167         int offsets[] = { 0, 8, 64, 256 };
168         int mags[] = {
169                 UFS2_MAGIC, UFS_MAGIC, UFS_MAGIC_FEA, UFS_MAGIC_LFN,
170                 UFS_MAGIC_SEC, UFS_MAGIC_4GB
171         };
172         int i;
173         uint32_t magic;
174         struct ufs_super_block *ufs;
175
176         for (i = 0; i < ARRAY_SIZE(offsets); i++) {
177                 uint32_t magLE, magBE;
178                 int y;
179
180                 ufs = (struct ufs_super_block *)
181                                 blkid_probe_get_buffer(pr,
182                                         offsets[i] * 1024,
183                                         sizeof(struct ufs_super_block));
184                 if (!ufs)
185                         return -1;
186
187                 magBE = be32_to_cpu(ufs->fs_magic);
188                 magLE = le32_to_cpu(ufs->fs_magic);
189
190                 for (y = 0; y < ARRAY_SIZE(mags); y++) {
191                         if (magLE == mags[y] || magBE == mags[y]) {
192                                 magic = mags[y];
193                                 goto found;
194                         }
195                 }
196         }
197
198         return 1;
199
200 found:
201         if (magic == UFS2_MAGIC) {
202                 blkid_probe_set_version(pr, "2");
203                 blkid_probe_set_label(pr, ufs->fs_u11.fs_u2.fs_volname,
204                                 sizeof(ufs->fs_u11.fs_u2.fs_volname));
205         } else
206                 blkid_probe_set_version(pr, "1");
207
208         return 0;
209 }
210
211 /*
212  * According to libvolume_id the UFS superblock could be on four positions.
213  * The original libblkid has checked one position (.kboff=8) only.
214  *
215  * We know four UFS magic strings and UFS could be both little-endian and
216  * big-endian. ... so we have:
217  *
218  *      4 position * 4 string * 2 version = 32 magic strings
219  *
220  * It seems simpler to check for these string in probing function that hardcode
221  * all in the .magic array.
222  */
223 const struct blkid_idinfo ufs_idinfo =
224 {
225         .name           = "ufs",
226         .usage          = BLKID_USAGE_FILESYSTEM,
227         .probefunc      = probe_ufs,
228         .magics         = BLKID_NONE_MAGIC
229 };
230