blob: f151f46ae4589ad24c6d619c3a9d851dfaf85d85 [file] [log] [blame]
bigbiff bigbiffe60683a2013-02-22 20:55:50 -05001/*
2 * sun (solaris-sparc) 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#include <stdio.h>
10#include <string.h>
11#include <stdlib.h>
12#include <stdint.h>
13#include <stddef.h>
14
15#include "partitions.h"
16
17/* Supported VTOC setting */
18#define SUN_VTOC_SANITY 0x600DDEEE /* magic number */
19#define SUN_VTOC_VERSION 1
20
21#define SUN_MAXPARTITIONS 8
22
23/* Partition IDs */
24#define SUN_TAG_WHOLEDISK 0x05
25
26struct sun_disklabel {
27 unsigned char info[128]; /* Informative text string */
28
29 struct sun_vtoc {
30 uint32_t version; /* version */
31 char volume[8]; /* volume name */
32 uint16_t nparts; /* num of partitions */
33
34 struct sun_info { /* partition information */
35 uint16_t id; /* tag */
36 uint16_t flags;
37 } __attribute__ ((packed)) infos[8];
38
39 uint16_t padding; /* padding */
40 uint32_t bootinfo[3]; /* info needed by mboot */
41 uint32_t sanity; /* magic number */
42 uint32_t reserved[10]; /* padding */
43 uint32_t timestamp[8]; /* partition timestamp */
44 } __attribute__ ((packed)) vtoc;
45
46 uint32_t write_reinstruct; /* sectors to skip, writes */
47 uint32_t read_reinstruct; /* sectors to skip, reads */
48 unsigned char spare[148]; /* padding */
49 uint16_t rspeed; /* disk rotational speed */
50 uint16_t pcylcount; /* physical cylinder count */
51 uint16_t sparecyl; /* extra sects per cylinder */
52 uint16_t obs1;
53 uint16_t obs2;
54 uint16_t ilfact; /* interleave factor */
55 uint16_t ncyl; /* data cylinder count */
56 uint16_t nacyl; /* alt. cylinder count */
57 uint16_t ntrks; /* tracks per cylinder <---- */
58 uint16_t nsect; /* sectors per track <---- */
59 uint16_t obs3;
60 uint16_t obs4;
61
62 struct sun_partition { /* partitions */
63 uint32_t start_cylinder;
64 uint32_t num_sectors;
65 } __attribute__ ((packed)) partitions[8];
66
67 uint16_t magic; /* magic number */
68 uint16_t csum; /* label xor'd checksum */
69} __attribute__ ((packed));
70
71
72uint16_t count_checksum(struct sun_disklabel *label)
73{
74 uint16_t *ptr = ((uint16_t *) (label + 1)) - 1;
75 uint16_t sum;
76
77 for (sum = 0; ptr >= ((uint16_t *) label);)
78 sum ^= *ptr--;
79
80 return sum;
81}
82
83static int probe_sun_pt(blkid_probe pr,
84 const struct blkid_idmag *mag __attribute__((__unused__)))
85{
86 struct sun_disklabel *l;
87 struct sun_partition *p;
88 blkid_parttable tab = NULL;
89 blkid_partlist ls;
90 uint16_t nparts;
91 blkid_loff_t spc;
92 int i, use_vtoc;
93
94 l = (struct sun_disklabel *) blkid_probe_get_sector(pr, 0);
95 if (!l)
96 goto nothing;
97
98 if (count_checksum(l)) {
99 DBG(DEBUG_LOWPROBE, printf(
100 "detected corrupted sun disk label -- ignore\n"));
101 goto nothing;
102 }
103
104 if (blkid_partitions_need_typeonly(pr))
105 /* caller does not ask for details about partitions */
106 return 0;
107
108 ls = blkid_probe_get_partlist(pr);
109 if (!ls)
110 goto err;
111
112 tab = blkid_partlist_new_parttable(ls, "sun", 0);
113 if (!tab)
114 goto err;
115
116 /* sectors per cylinder (partition offset is in cylinders...) */
117 spc = be16_to_cpu(l->ntrks) * be16_to_cpu(l->nsect);
118
119 DBG(DEBUG_LOWPROBE,
120 printf("Sun VTOC sanity=%u version=%u nparts=%u\n",
121 be32_to_cpu(l->vtoc.sanity),
122 be32_to_cpu(l->vtoc.version),
123 be16_to_cpu(l->vtoc.nparts)));
124
125 /* Check to see if we can use the VTOC table */
126 use_vtoc = ((be32_to_cpu(l->vtoc.sanity) == SUN_VTOC_SANITY) &&
127 (be32_to_cpu(l->vtoc.version) == SUN_VTOC_VERSION) &&
128 (be16_to_cpu(l->vtoc.nparts) <= SUN_MAXPARTITIONS));
129
130 /* Use 8 partition entries if not specified in validated VTOC */
131 nparts = use_vtoc ? be16_to_cpu(l->vtoc.nparts) : SUN_MAXPARTITIONS;
132
133 /*
134 * So that old Linux-Sun partitions continue to work,
135 * alow the VTOC to be used under the additional condition ...
136 */
137 use_vtoc = use_vtoc || !(l->vtoc.sanity || l->vtoc.version || l->vtoc.nparts);
138
139 for (i = 0, p = l->partitions; i < nparts; i++, p++) {
140
141 blkid_loff_t start, size;
142 uint16_t type = 0, flags = 0;
143 blkid_partition par;
144
145 start = be32_to_cpu(p->start_cylinder) * spc;
146 size = be32_to_cpu(p->num_sectors);
147 if (use_vtoc) {
148 type = be16_to_cpu(l->vtoc.infos[i].id);
149 flags = be16_to_cpu(l->vtoc.infos[i].flags);
150 }
151
152 if (type == SUN_TAG_WHOLEDISK || !size) {
153 blkid_partlist_increment_partno(ls);
154 continue;
155 }
156 par = blkid_partlist_add_partition(ls, tab, start, size);
157 if (!par)
158 goto err;
159
160 if (type)
161 blkid_partition_set_type(par, type);
162 if (flags)
163 blkid_partition_set_flags(par, flags);
164 }
165 return 0;
166
167nothing:
168 return 1;
169err:
170 return -1;
171}
172
173
174const struct blkid_idinfo sun_pt_idinfo =
175{
176 .name = "sun",
177 .probefunc = probe_sun_pt,
178 .magics =
179 {
180 {
181 .magic = "\xDA\xBE", /* big-endian magic string */
182 .len = 2,
183 .sboff = offsetof(struct sun_disklabel, magic)
184 },
185 { NULL }
186 }
187};
188