| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: disklabel.c,v 1.6 2011/10/01 15:59:00 chs Exp $ */ | | 1 | /* $NetBSD: disklabel.c,v 1.7 2016/03/13 08:54:45 tsutsui Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (c) 1995 Waldi Ravens | | 4 | * Copyright (c) 1995 Waldi Ravens |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * Redistribution and use in source and binary forms, with or without | | 7 | * Redistribution and use in source and binary forms, with or without |
8 | * modification, are permitted provided that the following conditions | | 8 | * modification, are permitted provided that the following conditions |
9 | * are met: | | 9 | * are met: |
10 | * 1. Redistributions of source code must retain the above copyright | | 10 | * 1. Redistributions of source code must retain the above copyright |
11 | * notice, this list of conditions and the following disclaimer. | | 11 | * notice, this list of conditions and the following disclaimer. |
12 | * 2. Redistributions in binary form must reproduce the above copyright | | 12 | * 2. Redistributions in binary form must reproduce the above copyright |
13 | * notice, this list of conditions and the following disclaimer in the | | 13 | * notice, this list of conditions and the following disclaimer in the |
14 | * documentation and/or other materials provided with the distribution. | | 14 | * documentation and/or other materials provided with the distribution. |
| @@ -47,201 +47,197 @@ | | | @@ -47,201 +47,197 @@ |
47 | #endif | | 47 | #endif |
48 | | | 48 | |
49 | struct ahdilabel { | | 49 | struct ahdilabel { |
50 | u_int nsecs; | | 50 | u_int nsecs; |
51 | daddr_t bslst; | | 51 | daddr_t bslst; |
52 | daddr_t bslend; | | 52 | daddr_t bslend; |
53 | u_int nroots; | | 53 | u_int nroots; |
54 | daddr_t *roots; | | 54 | daddr_t *roots; |
55 | u_int nparts; | | 55 | u_int nparts; |
56 | struct ahdi_part *parts; | | 56 | struct ahdi_part *parts; |
57 | }; | | 57 | }; |
58 | | | 58 | |
59 | u_int dkcksum(struct disklabel *); | | 59 | u_int dkcksum(struct disklabel *); |
60 | u_int32_t readdisklabel(char *, struct disklabel *); | | 60 | uint32_t readdisklabel(char *, struct disklabel *); |
61 | | | 61 | |
62 | static int bsd_label(int, off_t, struct disklabel *); | | 62 | static int bsd_label(int, off_t, struct disklabel *); |
63 | static int ahdi_label(int, u_int32_t *, struct disklabel *); | | 63 | static int ahdi_label(int, uint32_t *, struct disklabel *); |
64 | static int ahdi_getparts(int, daddr_t, daddr_t, struct ahdilabel *); | | 64 | static int ahdi_getparts(int, daddr_t, daddr_t, struct ahdilabel *); |
65 | | | 65 | |
66 | u_int | | 66 | u_int |
67 | dkcksum (struct disklabel *dl) | | 67 | dkcksum (struct disklabel *dl) |
68 | { | | 68 | { |
69 | u_int16_t sum = 0, | | 69 | uint16_t sum = 0, |
70 | *st = (u_int16_t *)dl, | | 70 | *st = (uint16_t *)dl, |
71 | *end = (u_int16_t *)&dl->d_partitions[dl->d_npartitions]; | | 71 | *end = (uint16_t *)&dl->d_partitions[dl->d_npartitions]; |
72 | | | 72 | |
73 | while (st < end) | | 73 | while (st < end) |
74 | sum ^= *st++; | | 74 | sum ^= *st++; |
75 | return(sum); | | 75 | return sum; |
76 | } | | 76 | } |
77 | | | 77 | |
78 | u_int32_t | | 78 | uint32_t |
79 | readdisklabel (char *fn, struct disklabel *dl) | | 79 | readdisklabel(char *fn, struct disklabel *dl) |
80 | { | | 80 | { |
81 | int fd, e; | | 81 | int fd, e; |
82 | u_int32_t bbsec; | | 82 | uint32_t bbsec; |
83 | | | 83 | |
84 | memset(dl, 0, sizeof *dl); | | 84 | memset(dl, 0, sizeof *dl); |
85 | | | 85 | |
86 | if ((fd = open(fn, O_RDONLY)) < 0) | | 86 | if ((fd = open(fn, O_RDONLY)) < 0) |
87 | err(EXIT_FAILURE, "%s", fn); | | 87 | err(EXIT_FAILURE, "%s", fn); |
88 | | | 88 | |
89 | /* Try NetBSD/Atari format first */ | | 89 | /* Try NetBSD/Atari format first */ |
90 | if ((e = bsd_label(fd, (off_t)0, dl)) < 0) | | 90 | if ((e = bsd_label(fd, (off_t)0, dl)) < 0) |
91 | err(EXIT_FAILURE, "%s", fn); | | 91 | err(EXIT_FAILURE, "%s", fn); |
92 | if (!e) | | 92 | if (e == 0) |
93 | return(0); | | 93 | return 0; |
94 | | | 94 | |
95 | /* Try unprotected AHDI format last */ | | 95 | /* Try unprotected AHDI format last */ |
96 | if ((e = ahdi_label(fd, &bbsec, dl)) < 0) | | 96 | if ((e = ahdi_label(fd, &bbsec, dl)) < 0) |
97 | err(EXIT_FAILURE, "%s", fn); | | 97 | err(EXIT_FAILURE, "%s", fn); |
98 | if (!e) | | 98 | if (e == 0) |
99 | return(bbsec); | | 99 | return bbsec; |
100 | | | 100 | |
101 | warnx("%s: Unknown disk label format.", fn); | | 101 | warnx("%s: Unknown disk label format.", fn); |
102 | return(NO_BOOT_BLOCK); | | 102 | return NO_BOOT_BLOCK; |
103 | } | | 103 | } |
104 | | | 104 | |
105 | static int | | 105 | static int |
106 | bsd_label (int fd, off_t offs, struct disklabel *label) | | 106 | bsd_label(int fd, off_t offs, struct disklabel *label) |
107 | { | | 107 | { |
108 | struct bootblock bb; | | 108 | struct bootblock bb; |
109 | struct disklabel *p; | | 109 | struct disklabel *p; |
110 | | | 110 | |
111 | if (lseek(fd, offs, SEEK_SET) != offs) | | 111 | if (lseek(fd, offs, SEEK_SET) != offs) |
112 | return(-1); | | 112 | return -1; |
113 | if (read(fd, &bb, sizeof(bb)) != sizeof(bb)) | | 113 | if (read(fd, &bb, sizeof(bb)) != sizeof(bb)) |
114 | return(-1); | | 114 | return -1; |
115 | | | 115 | |
116 | p = (struct disklabel *)bb.bb_label; | | 116 | p = (struct disklabel *)bb.bb_label; |
117 | if ( (offs == 0 && bb.bb_magic != NBDAMAGIC) | | 117 | if ((offs == 0 && bb.bb_magic != NBDAMAGIC) || |
118 | || (offs != 0 && bb.bb_magic != AHDIMAGIC) | | 118 | (offs != 0 && bb.bb_magic != AHDIMAGIC) || |
119 | || p->d_npartitions > MAXPARTITIONS | | 119 | p->d_npartitions > MAXPARTITIONS || |
120 | || p->d_magic2 != DISKMAGIC | | 120 | p->d_magic2 != DISKMAGIC || |
121 | || p->d_magic != DISKMAGIC | | 121 | p->d_magic != DISKMAGIC || |
122 | || dkcksum(p) != 0 | | 122 | dkcksum(p) != 0) { |
123 | ) { | | 123 | return 1; |
124 | return(1); | | | |
125 | } | | 124 | } |
126 | | | 125 | |
127 | *label = *p; | | 126 | *label = *p; |
128 | return(0); | | 127 | return 0; |
129 | } | | 128 | } |
130 | | | 129 | |
131 | static int | | 130 | static int |
132 | ahdi_label (int fd, u_int32_t *bbsec, struct disklabel *label) | | 131 | ahdi_label(int fd, uint32_t *bbsec, struct disklabel *label) |
133 | { | | 132 | { |
134 | struct ahdilabel al; | | 133 | struct ahdilabel al; |
135 | u_int i, j; | | 134 | u_int i, j; |
136 | int e; | | 135 | int e; |
137 | | | 136 | |
138 | memset(&al, 0, sizeof(al)); | | 137 | memset(&al, 0, sizeof(al)); |
139 | if ((e = ahdi_getparts(fd, AHDI_BBLOCK, AHDI_BBLOCK, &al))) | | 138 | if ((e = ahdi_getparts(fd, AHDI_BBLOCK, AHDI_BBLOCK, &al)) != 0) |
140 | return(e); | | 139 | return e; |
141 | | | 140 | |
142 | /* | | 141 | /* |
143 | * Perform sanity checks. | | 142 | * Perform sanity checks. |
144 | */ | | 143 | */ |
145 | if (al.bslst == 0 || al.bslend == 0) | | 144 | if (al.bslst == 0 || al.bslend == 0) |
146 | return(1); | | 145 | return 1; |
147 | if (al.nsecs == 0 || al.nparts == 0) | | 146 | if (al.nsecs == 0 || al.nparts == 0) |
148 | return(1); | | 147 | return 1; |
149 | if (al.nparts > AHDI_MAXPARTS) | | 148 | if (al.nparts > AHDI_MAXPARTS) |
150 | warnx("Too many AHDI partitions (%u).", al.nparts); | | 149 | warnx("Too many AHDI partitions (%u).", al.nparts); |
151 | for (i = 0; i < al.nparts; ++i) { | | 150 | for (i = 0; i < al.nparts; ++i) { |
152 | struct ahdi_part *p1 = &al.parts[i]; | | 151 | struct ahdi_part *p1 = &al.parts[i]; |
153 | for (j = 0; j < al.nroots; ++j) { | | 152 | for (j = 0; j < al.nroots; ++j) { |
154 | daddr_t aux = al.roots[j]; | | 153 | daddr_t aux = al.roots[j]; |
155 | if (aux >= p1->ap_st && aux <= p1->ap_end) | | 154 | if (aux >= p1->ap_st && aux <= p1->ap_end) |
156 | return(1); | | 155 | return 1; |
157 | } | | 156 | } |
158 | for (j = i + 1; j < al.nparts; ++j) { | | 157 | for (j = i + 1; j < al.nparts; ++j) { |
159 | struct ahdi_part *p2 = &al.parts[j]; | | 158 | struct ahdi_part *p2 = &al.parts[j]; |
160 | if (p1->ap_st >= p2->ap_st && p1->ap_st <= p2->ap_end) | | 159 | if (p1->ap_st >= p2->ap_st && p1->ap_st <= p2->ap_end) |
161 | return(1); | | 160 | return 1; |
162 | if (p2->ap_st >= p1->ap_st && p2->ap_st <= p1->ap_end) | | 161 | if (p2->ap_st >= p1->ap_st && p2->ap_st <= p1->ap_end) |
163 | return(1); | | 162 | return 1; |
164 | } | | 163 | } |
165 | if (p1->ap_st >= al.bslst && p1->ap_st <= al.bslend) | | 164 | if (p1->ap_st >= al.bslst && p1->ap_st <= al.bslend) |
166 | return(1); | | 165 | return 1; |
167 | if (al.bslst >= p1->ap_st && al.bslst <= p1->ap_end) | | 166 | if (al.bslst >= p1->ap_st && al.bslst <= p1->ap_end) |
168 | return(1); | | 167 | return 1; |
169 | } | | 168 | } |
170 | | | 169 | |
171 | /* | | 170 | /* |
172 | * Search for a NetBSD boot block | | 171 | * Search for a NetBSD boot block |
173 | */ | | 172 | */ |
174 | for (i = 0; i < al.nparts; ++i) { | | 173 | for (i = 0; i < al.nparts; ++i) { |
175 | struct ahdi_part *pd = &al.parts[i]; | | 174 | struct ahdi_part *pd = &al.parts[i]; |
176 | u_int id; | | 175 | u_int id; |
177 | | | 176 | |
178 | memcpy(&id, &pd->ap_flg, sizeof (id)); | | 177 | memcpy(&id, &pd->ap_flg, sizeof (id)); |
179 | if (id == AHDI_PID_NBD || id == AHDI_PID_RAW) { | | 178 | if (id == AHDI_PID_NBD || id == AHDI_PID_RAW) { |
180 | off_t offs = pd->ap_st * AHDI_BSIZE; | | 179 | off_t offs = pd->ap_st * AHDI_BSIZE; |
181 | if ((e = bsd_label(fd, offs, label)) < 0) | | 180 | if ((e = bsd_label(fd, offs, label)) < 0) |
182 | return(e); | | 181 | return e; |
183 | if (!e) { | | 182 | if (e == 0) { |
184 | *bbsec = pd->ap_st; /* got it */ | | 183 | *bbsec = pd->ap_st; /* got it */ |
185 | return(0); | | 184 | return 0; |
186 | } | | 185 | } |
187 | } | | 186 | } |
188 | } | | 187 | } |
189 | *bbsec = NO_BOOT_BLOCK; /* AHDI label, no NetBSD boot block */ | | 188 | *bbsec = NO_BOOT_BLOCK; /* AHDI label, no NetBSD boot block */ |
190 | return(0); | | 189 | return 0; |
191 | } | | 190 | } |
192 | | | 191 | |
193 | static int | | 192 | static int |
194 | ahdi_getparts(fd, rsec, esec, alab) | | 193 | ahdi_getparts(int fd, daddr_t rsec, daddr_t esec, struct ahdilabel *alab) |
195 | int fd; | | | |
196 | daddr_t rsec, | | | |
197 | esec; | | | |
198 | struct ahdilabel *alab; | | | |
199 | { | | 194 | { |
200 | struct ahdi_part *part, *end; | | 195 | struct ahdi_part *part, *end; |
201 | struct ahdi_root root; | | 196 | struct ahdi_root root; |
202 | off_t ro; | | 197 | off_t ro; |
203 | | | 198 | |
204 | ro = rsec * AHDI_BSIZE; | | 199 | ro = rsec * AHDI_BSIZE; |
205 | if (lseek(fd, ro, SEEK_SET) != ro) { | | 200 | if (lseek(fd, ro, SEEK_SET) != ro) { |
206 | off_t mend = lseek(fd, 0, SEEK_END); | | 201 | off_t mend = lseek(fd, 0, SEEK_END); |
207 | if (mend == -1 || mend > ro) | | 202 | if (mend == -1 || mend > ro) |
208 | return(-1); | | 203 | return -1; |
209 | return(1); | | 204 | return 1; |
210 | } | | 205 | } |
211 | if (read(fd, &root, sizeof(root)) != sizeof(root)) | | 206 | if (read(fd, &root, sizeof(root)) != sizeof(root)) |
212 | return(-1); | | 207 | return -1; |
213 | | | 208 | |
214 | if (rsec == AHDI_BBLOCK) | | 209 | if (rsec == AHDI_BBLOCK) |
215 | end = &root.ar_parts[AHDI_MAXRPD]; | | 210 | end = &root.ar_parts[AHDI_MAXRPD]; |
216 | else end = &root.ar_parts[AHDI_MAXARPD]; | | 211 | else |
| | | 212 | end = &root.ar_parts[AHDI_MAXARPD]; |
217 | for (part = root.ar_parts; part < end; ++part) { | | 213 | for (part = root.ar_parts; part < end; ++part) { |
218 | u_int id; | | 214 | u_int id; |
219 | | | 215 | |
220 | memcpy(&id, &part->ap_flg, sizeof (id)); | | 216 | memcpy(&id, &part->ap_flg, sizeof (id)); |
221 | if (!(id & 0x01000000)) | | 217 | if ((id & 0x01000000) == 0) |
222 | continue; | | 218 | continue; |
223 | if ((id &= 0x00ffffff) == AHDI_PID_XGM) { | | 219 | if ((id &= 0x00ffffff) == AHDI_PID_XGM) { |
224 | int e; | | 220 | int e; |
225 | daddr_t aux = part->ap_st + esec; | | 221 | daddr_t aux = part->ap_st + esec; |
226 | alab->roots = realloc(alab->roots, | | 222 | alab->roots = realloc(alab->roots, |
227 | (alab->nroots + 1) * sizeof(*alab->roots)); | | 223 | (alab->nroots + 1) * sizeof(*alab->roots)); |
228 | alab->roots[alab->nroots++] = aux; | | 224 | alab->roots[alab->nroots++] = aux; |
229 | e = ahdi_getparts(fd, aux, | | 225 | e = ahdi_getparts(fd, aux, |
230 | esec == AHDI_BBLOCK ? aux : esec, alab); | | 226 | esec == AHDI_BBLOCK ? aux : esec, alab); |
231 | if (e) | | 227 | if (e != 0) |
232 | return(e); | | 228 | return e; |
233 | } else { | | 229 | } else { |
234 | struct ahdi_part *p; | | 230 | struct ahdi_part *p; |
235 | alab->parts = realloc(alab->parts, | | 231 | alab->parts = realloc(alab->parts, |
236 | (alab->nparts + 1) * sizeof(*alab->parts)); | | 232 | (alab->nparts + 1) * sizeof(*alab->parts)); |
237 | p = &alab->parts[alab->nparts++]; | | 233 | p = &alab->parts[alab->nparts++]; |
238 | memcpy(&p->ap_flg, &id, sizeof (id)); | | 234 | memcpy(&p->ap_flg, &id, sizeof (id)); |
239 | p->ap_st = part->ap_st + rsec; | | 235 | p->ap_st = part->ap_st + rsec; |
240 | p->ap_end = p->ap_st + part->ap_size - 1; | | 236 | p->ap_end = p->ap_st + part->ap_size - 1; |
241 | } | | 237 | } |
242 | } | | 238 | } |
243 | alab->nsecs = root.ar_hdsize; | | 239 | alab->nsecs = root.ar_hdsize; |
244 | alab->bslst = root.ar_bslst; | | 240 | alab->bslst = root.ar_bslst; |
245 | alab->bslend = root.ar_bslst + root.ar_bslsize - 1; | | 241 | alab->bslend = root.ar_bslst + root.ar_bslsize - 1; |
246 | return(0); | | 242 | return 0; |
247 | } | | 243 | } |