summaryrefslogtreecommitdiffstats
path: root/libblkid/src/partitions/unixware.c
blob: 845924e480711e5ebab7f038c66ffa36d640ddae (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
/*
 * unixware partition parsing code
 *
 * Copyright (C) 2009 Karel Zak <kzak@redhat.com>
 *
 * This file may be redistributed under the terms of the
 * GNU Lesser General Public License.
 *
 *
 * The interesting information about unixware PT:
 *   - Linux kernel / partx
 *   - vtoc(7) SCO UNIX command man page
 *   - evms source code (http://evms.sourceforge.net/)
 *   - vxtools source code (http://martin.hinner.info/fs/vxfs/)
 */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>

#include "partitions.h"

/* disklabel location */
#define UNIXWARE_SECTOR		29
#define UNIXWARE_OFFSET		(UNIXWARE_SECTOR << 9)	/* offset in bytes */
#define UNIXWARE_KBOFFSET	(UNIXWARE_OFFSET >> 10)	/* offset in 1024-blocks */

/* disklabel->d_magic offset within the last 1024 block */
#define UNIXWARE_MAGICOFFSET	(UNIXWARE_OFFSET - UNIXWARE_KBOFFSET + 4)

#define UNIXWARE_VTOCMAGIC	0x600DDEEEUL
#define UNIXWARE_MAXPARTITIONS	16

/* unixware_partition->s_label flags */
#define UNIXWARE_TAG_UNUSED       0x0000  /* unused partition */
#define UNIXWARE_TAG_BOOT         0x0001  /* boot fs */
#define UNIXWARE_TAG_ROOT         0x0002  /* root fs */
#define UNIXWARE_TAG_SWAP         0x0003  /* swap fs */
#define UNIXWARE_TAG_USER         0x0004  /* user fs */
#define UNIXWARE_TAG_ENTIRE_DISK  0x0005  /* whole disk */
#define UNIXWARE_TAG_ALT_S        0x0006  /* alternate sector space */
#define UNIXWARE_TAG_OTHER        0x0007  /* non unix */
#define UNIXWARE_TAG_ALT_T        0x0008  /* alternate track space */
#define UNIXWARE_TAG_STAND        0x0009  /* stand partition */
#define UNIXWARE_TAG_VAR          0x000a  /* var partition */
#define UNIXWARE_TAG_HOME         0x000b  /* home partition */
#define UNIXWARE_TAG_DUMP         0x000c  /* dump partition */
#define UNIXWARE_TAG_ALT_ST       0x000d  /* alternate sector track */
#define UNIXWARE_TAG_VM_PUBLIC    0x000e  /* volume mgt public partition */
#define UNIXWARE_TAG_VM_PRIVATE   0x000f  /* volume mgt private partition */


/* unixware_partition->s_flags flags */
#define UNIXWARE_FLAG_VALID	0x0200

struct unixware_partition {
	uint16_t	s_label;	/* partition label (tag) */
	uint16_t	s_flags;	/* permission flags */
	uint32_t	start_sect;	/* starting sector */
	uint32_t	nr_sects;	/* number of sectors */
} __attribute__((packed));

struct unixware_disklabel {
	uint32_t	d_type;		/* drive type */
	uint32_t	d_magic;	/* the magic number */
	uint32_t	d_version;	/* version number */
	char		d_serial[12];	/* serial number of the device */
	uint32_t	d_ncylinders;	/* # of data cylinders per device */
	uint32_t	d_ntracks;	/* # of tracks per cylinder */
	uint32_t	d_nsectors;	/* # of data sectors per track */
	uint32_t	d_secsize;	/* # of bytes per sector */
	uint32_t	d_part_start;	/* # of first sector of this partition */
	uint32_t	d_unknown1[12];	/* ? */
	uint32_t	d_alt_tbl;	/* byte offset of alternate table */
	uint32_t	d_alt_len;	/* byte length of alternate table */
	uint32_t	d_phys_cyl;	/* # of physical cylinders per device */
	uint32_t	d_phys_trk;	/* # of physical tracks per cylinder */
	uint32_t	d_phys_sec;	/* # of physical sectors per track */
	uint32_t	d_phys_bytes;	/* # of physical bytes per sector */
	uint32_t	d_unknown2;	/* ? */
	uint32_t	d_unknown3;	/* ? */
	uint32_t	d_pad[8];	/* pad */

	struct unixware_vtoc {
		uint32_t	v_magic;	/* the magic number */
		uint32_t	v_version;	/* version number */
		char		v_name[8];	/* volume name */
		uint16_t	v_nslices;	/* # of partitions */
		uint16_t	v_unknown1;	/* ? */
		uint32_t	v_reserved[10];	/* reserved */

		struct unixware_partition
			v_slice[UNIXWARE_MAXPARTITIONS]; /* partition */
	} __attribute__((packed)) vtoc;
};

static int probe_unixware_pt(blkid_probe pr,
		const struct blkid_idmag *mag __attribute__((__unused__)))
{
	struct unixware_disklabel *l;
	struct unixware_partition *p;
	blkid_parttable tab = NULL;
	blkid_partition parent;
	blkid_partlist ls;
	int i;

	l = (struct unixware_disklabel *)
			blkid_probe_get_sector(pr, UNIXWARE_SECTOR);
	if (!l) {
		if (errno)
			return -errno;
		goto nothing;
	}

	if (le32_to_cpu(l->vtoc.v_magic) != UNIXWARE_VTOCMAGIC)
		goto nothing;

	if (blkid_partitions_need_typeonly(pr))
		/* caller does not ask for details about partitions */
		return BLKID_PROBE_OK;

	ls = blkid_probe_get_partlist(pr);
	if (!ls)
		goto nothing;

	parent = blkid_partlist_get_parent(ls);

	tab = blkid_partlist_new_parttable(ls, "unixware", UNIXWARE_OFFSET);
	if (!tab)
		goto err;

	/* Skip the first partition that describe whole disk
	 */
	for (i = 1, p = &l->vtoc.v_slice[1];
			i < UNIXWARE_MAXPARTITIONS; i++, p++) {

		uint32_t start, size;
		uint16_t tag, flg;
		blkid_partition par;

		tag = le16_to_cpu(p->s_label);
		flg = le16_to_cpu(p->s_flags);

		if (tag == UNIXWARE_TAG_UNUSED ||
		    tag == UNIXWARE_TAG_ENTIRE_DISK ||
		    flg != UNIXWARE_FLAG_VALID)
			continue;

		start = le32_to_cpu(p->start_sect);
		size = le32_to_cpu(p->nr_sects);

		if (parent && !blkid_is_nested_dimension(parent, start, size)) {
			DBG(LOWPROBE, ul_debug(
				"WARNING: unixware partition (%d) overflow "
				"detected, ignore", i));
			continue;
		}

		par = blkid_partlist_add_partition(ls, tab, start, size);
		if (!par)
			goto err;

		blkid_partition_set_type(par, tag);
		blkid_partition_set_flags(par, flg);
	}

	return BLKID_PROBE_OK;

nothing:
	return BLKID_PROBE_NONE;
err:
	return -ENOMEM;
}


/*
 * The unixware partition table is within primary DOS partition.  The PT is
 * located on 29 sector, PT magic string is d_magic member of 'struct
 * unixware_disklabel'.
 */
const struct blkid_idinfo unixware_pt_idinfo =
{
	.name		= "unixware",
	.probefunc	= probe_unixware_pt,
	.minsz		= 1024 * 1440 + 1,		/* ignore floppies */
	.magics		=
	{
		{
		  .magic = "\x0D\x60\xE5\xCA",	/* little-endian magic string */
		  .len = 4,			/* d_magic size in bytes */
		  .kboff = UNIXWARE_KBOFFSET,
		  .sboff = UNIXWARE_MAGICOFFSET
		},
		{ NULL }
	}
};