~ubuntu-branches/ubuntu/trusty/util-linux/trusty-proposed

« back to all changes in this revision

Viewing changes to shlibs/blkid/src/partitions/bsd.c

  • Committer: Package Import Robot
  • Author(s): LaMont Jones
  • Date: 2011-11-03 15:38:23 UTC
  • mto: (4.5.5 sid) (1.6.4)
  • mto: This revision was merged to the branch mainline in revision 85.
  • Revision ID: package-import@ubuntu.com-20111103153823-10sx16jprzxlhkqf
ImportĀ upstreamĀ versionĀ 2.20.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * BSD/OSF partition parsing code
3
 
 *
4
 
 * Copyright (C) 2009 Karel Zak <kzak@redhat.com>
5
 
 *
6
 
 * This file may be redistributed under the terms of the
7
 
 * GNU Lesser General Public License.
8
 
 *
9
 
 * Inspired by fdisk, partx, Linux kernel, libparted and openbsd header files.
10
 
 */
11
 
#include <stdio.h>
12
 
#include <string.h>
13
 
#include <stdlib.h>
14
 
#include <stdint.h>
15
 
 
16
 
#include "partitions.h"
17
 
 
18
 
#define BSD_MAXPARTITIONS       16
19
 
#define BSD_FS_UNUSED           0
20
 
 
21
 
struct bsd_disklabel {
22
 
        uint32_t        d_magic;                /* the magic number */
23
 
        int16_t         d_type;                 /* drive type */
24
 
        int16_t         d_subtype;              /* controller/d_type specific */
25
 
        char            d_typename[16];         /* type name, e.g. "eagle" */
26
 
        char            d_packname[16];         /* pack identifier */
27
 
 
28
 
                        /* disk geometry: */
29
 
        uint32_t        d_secsize;              /* # of bytes per sector */
30
 
        uint32_t        d_nsectors;             /* # of data sectors per track */
31
 
        uint32_t        d_ntracks;              /* # of tracks per cylinder */
32
 
        uint32_t        d_ncylinders;           /* # of data cylinders per unit */
33
 
        uint32_t        d_secpercyl;            /* # of data sectors per cylinder */
34
 
        uint32_t        d_secperunit;           /* # of data sectors per unit */
35
 
 
36
 
        /*
37
 
         * Spares (bad sector replacements) below
38
 
         * are not counted in d_nsectors or d_secpercyl.
39
 
         * Spare sectors are assumed to be physical sectors
40
 
         * which occupy space at the end of each track and/or cylinder.
41
 
         */
42
 
        uint16_t        d_sparespertrack;       /* # of spare sectors per track */
43
 
        uint16_t        d_sparespercyl;         /* # of spare sectors per cylinder */
44
 
 
45
 
        /*
46
 
         * Alternate cylinders include maintenance, replacement,
47
 
         * configuration description areas, etc.
48
 
         */
49
 
        uint32_t        d_acylinders;           /* # of alt. cylinders per unit */
50
 
 
51
 
                        /* hardware characteristics: */
52
 
        /*
53
 
         * d_interleave, d_trackskew and d_cylskew describe perturbations
54
 
         * in the media format used to compensate for a slow controller.
55
 
         * Interleave is physical sector interleave, set up by the formatter
56
 
         * or controller when formatting.  When interleaving is in use,
57
 
         * logically adjacent sectors are not physically contiguous,
58
 
         * but instead are separated by some number of sectors.
59
 
         * It is specified as the ratio of physical sectors traversed
60
 
         * per logical sector.  Thus an interleave of 1:1 implies contiguous
61
 
         * layout, while 2:1 implies that logical sector 0 is separated
62
 
         * by one sector from logical sector 1.
63
 
         * d_trackskew is the offset of sector 0 on track N
64
 
         * relative to sector 0 on track N-1 on the same cylinder.
65
 
         * Finally, d_cylskew is the offset of sector 0 on cylinder N
66
 
         * relative to sector 0 on cylinder N-1.
67
 
         */
68
 
        uint16_t        d_rpm;                  /* rotational speed */
69
 
        uint16_t        d_interleave;           /* hardware sector interleave */
70
 
        uint16_t        d_trackskew;            /* sector 0 skew, per track */
71
 
        uint16_t        d_cylskew;              /* sector 0 skew, per cylinder */
72
 
        uint32_t        d_headswitch;           /* head switch time, usec */
73
 
        uint32_t        d_trkseek;              /* track-to-track seek, usec */
74
 
        uint32_t        d_flags;                /* generic flags */
75
 
        uint32_t        d_drivedata[5];         /* drive-type specific information */
76
 
        uint32_t        d_spare[5];             /* reserved for future use */
77
 
        uint32_t        d_magic2;               /* the magic number (again) */
78
 
        uint16_t        d_checksum;             /* xor of data incl. partitions */
79
 
 
80
 
                        /* filesystem and partition information: */
81
 
        uint16_t        d_npartitions;          /* number of partitions in following */
82
 
        uint32_t        d_bbsize;               /* size of boot area at sn0, bytes */
83
 
        uint32_t        d_sbsize;               /* max size of fs superblock, bytes */
84
 
 
85
 
        struct bsd_partition     {              /* the partition table */
86
 
                uint32_t        p_size;         /* number of sectors in partition */
87
 
                uint32_t        p_offset;       /* starting sector */
88
 
                uint32_t        p_fsize;        /* filesystem basic fragment size */
89
 
                uint8_t         p_fstype;       /* filesystem type, see below */
90
 
                uint8_t         p_frag;         /* filesystem fragments per block */
91
 
                uint16_t        p_cpg;          /* filesystem cylinders per group */
92
 
        } __attribute__((packed)) d_partitions[BSD_MAXPARTITIONS];      /* actually may be more */
93
 
} __attribute__((packed));
94
 
 
95
 
 
96
 
/* Returns 'blkid_idmag' in 512-sectors */
97
 
#define BLKID_MAG_SECTOR(_mag)  (((_mag)->kboff * 2)  + ((_mag)->sboff >> 9))
98
 
 
99
 
/* Returns 'blkid_idmag' in bytes */
100
 
#define BLKID_MAG_OFFSET(_mag)  ((_mag)->kboff >> 10) + ((_mag)->sboff)
101
 
 
102
 
/* Returns 'blkid_idmag' offset in bytes within the last sector */
103
 
#define BLKID_MAG_LASTOFFSET(_mag) \
104
 
                 (BLKID_MAG_OFFSET(_mag) - (BLKID_MAG_SECTOR(_mag) << 9))
105
 
 
106
 
static int probe_bsd_pt(blkid_probe pr, const struct blkid_idmag *mag)
107
 
{
108
 
        struct bsd_disklabel *l;
109
 
        struct bsd_partition *p;
110
 
        const char *name = "bsd" ;
111
 
        blkid_parttable tab = NULL;
112
 
        blkid_partition parent;
113
 
        blkid_partlist ls;
114
 
        int i, nparts = BSD_MAXPARTITIONS;
115
 
        unsigned char *data;
116
 
 
117
 
        if (blkid_partitions_need_typeonly(pr))
118
 
                /* caller does not ask for details about partitions */
119
 
                return 0;
120
 
 
121
 
        data = blkid_probe_get_sector(pr, BLKID_MAG_SECTOR(mag));
122
 
        if (!data)
123
 
                goto nothing;
124
 
 
125
 
        l = (struct bsd_disklabel *) data + BLKID_MAG_LASTOFFSET(mag);
126
 
 
127
 
        ls = blkid_probe_get_partlist(pr);
128
 
        if (!ls)
129
 
                goto err;
130
 
 
131
 
        /* try to determine the real type of BSD system according to
132
 
         * (parental) primary partition */
133
 
        parent = blkid_partlist_get_parent(ls);
134
 
        if (parent) {
135
 
                switch(blkid_partition_get_type(parent)) {
136
 
                case BLKID_FREEBSD_PARTITION:
137
 
                        name = "freebsd";
138
 
                        break;
139
 
                case BLKID_NETBSD_PARTITION:
140
 
                        name = "netbsd";
141
 
                        break;
142
 
                case BLKID_OPENBSD_PARTITION:
143
 
                        name = "openbsd";
144
 
                        break;
145
 
                default:
146
 
                        DBG(DEBUG_LOWPROBE, printf(
147
 
                                "WARNING: BSD label detected on unknown (0x%x) "
148
 
                                "primary partition\n",
149
 
                                blkid_partition_get_type(parent)));
150
 
                        break;
151
 
                }
152
 
        }
153
 
 
154
 
        tab = blkid_partlist_new_parttable(ls, name, BLKID_MAG_OFFSET(mag));
155
 
        if (!tab)
156
 
                goto err;
157
 
 
158
 
        if (le16_to_cpu(l->d_npartitions) < BSD_MAXPARTITIONS)
159
 
                nparts = le16_to_cpu(l->d_npartitions);
160
 
 
161
 
        else if (le16_to_cpu(l->d_npartitions) > BSD_MAXPARTITIONS)
162
 
                DBG(DEBUG_LOWPROBE, printf(
163
 
                        "WARNING: ignore %d more BSD partitions\n",
164
 
                        le16_to_cpu(l->d_npartitions) - BSD_MAXPARTITIONS));
165
 
 
166
 
        for (i = 0, p = l->d_partitions; i < nparts; i++, p++) {
167
 
                blkid_partition par;
168
 
                uint32_t start, size;
169
 
 
170
 
                /* TODO: in fdisk-mode returns all non-zero (p_size) partitions */
171
 
                if (p->p_fstype == BSD_FS_UNUSED)
172
 
                        continue;
173
 
 
174
 
                start = le32_to_cpu(p->p_offset);
175
 
                size = le32_to_cpu(p->p_size);
176
 
 
177
 
                if (parent && !blkid_is_nested_dimension(parent, start, size)) {
178
 
                        DBG(DEBUG_LOWPROBE, printf(
179
 
                                "WARNING: BSD partition (%d) overflow "
180
 
                                "detected, ignore\n", i));
181
 
                        continue;
182
 
                }
183
 
 
184
 
                par = blkid_partlist_add_partition(ls, tab, start, size);
185
 
                if (!par)
186
 
                        goto err;
187
 
 
188
 
                blkid_partition_set_type(par, p->p_fstype);
189
 
        }
190
 
 
191
 
        return 0;
192
 
 
193
 
nothing:
194
 
        return 1;
195
 
err:
196
 
        return -1;
197
 
}
198
 
 
199
 
 
200
 
/*
201
 
 * All BSD variants use the same magic string (little-endian),
202
 
 * and the same disklabel.
203
 
 *
204
 
 * The difference between {Free,Open,...}BSD is in the (parental)
205
 
 * primary partition type.
206
 
 *
207
 
 * See also: http://en.wikipedia.org/wiki/BSD_disklabel
208
 
 *
209
 
 * The location of BSD disk label is architecture specific and in defined by
210
 
 * LABELSECTOR and LABELOFFSET macros in the disklabel.h file. The location
211
 
 * also depends on BSD variant, FreeBSD uses only one location, NetBSD and
212
 
 * OpenBSD are more creative...
213
 
 *
214
 
 * The basic overview:
215
 
 *
216
 
 * arch                    | LABELSECTOR | LABELOFFSET
217
 
 * ------------------------+-------------+------------
218
 
 * amd64 arm hppa hppa64   |             |
219
 
 * i386, macppc, mvmeppc   |      1      |      0
220
 
 * sgi, aviion, sh, socppc |             |
221
 
 * ------------------------+-------------+------------
222
 
 * alpha luna88k mac68k    |      0      |     64
223
 
 * sparc(OpenBSD) vax      |             |
224
 
 * ------------------------+-------------+------------
225
 
 * spark64 sparc(NetBSD)   |      0      |    128
226
 
 * ------------------------+-------------+------------
227
 
 *
228
 
 * ...and more (see http://fxr.watson.org/fxr/ident?v=NETBSD;i=LABELSECTOR)
229
 
 *
230
 
 */
231
 
const struct blkid_idinfo bsd_pt_idinfo =
232
 
{
233
 
        .name           = "bsd",
234
 
        .probefunc      = probe_bsd_pt,
235
 
        .magics         =
236
 
        {
237
 
                { .magic = "\x57\x45\x56\x82", .len = 4, .sboff = 512 },
238
 
                { .magic = "\x57\x45\x56\x82", .len = 4, .sboff = 64 },
239
 
                { .magic = "\x57\x45\x56\x82", .len = 4, .sboff = 128 },
240
 
                { NULL }
241
 
        }
242
 
};
243