write.c revision 1.1 1 /* $NetBSD: write.c,v 1.1 2000/08/07 09:23:40 leo Exp $ */
2
3 /*
4 * Copyright (c) 1999 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Julian Coleman, Waldi Ravens and Leo Weppelman.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the NetBSD
21 * Foundation, Inc. and its contributors.
22 * 4. Neither the name of The NetBSD Foundation nor the names of its
23 * contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
37 */
38
39 #include "privahdi.h"
40 #include <fcntl.h>
41 #include <stdlib.h>
42 #include <strings.h>
43 #include <unistd.h>
44 #include <sys/dkio.h>
45 #include <sys/ioctl.h>
46
47 #define BSL_MAGIC 0xa5
48 #define BSL_OFFSET 1
49 #define BSL_SIZE 1
50
51 /*
52 * Write AHDI partitions to disk
53 */
54
55 int
56 ahdi_writelabel (ptable, diskname, flags)
57 struct ahdi_ptable *ptable;
58 char *diskname;
59 int flags;
60 {
61 int fd, i, j, k, firstxgm, keep;
62 struct ahdi_root *root;
63 u_int rsec;
64 u_int32_t xgmsec, nbdsec;
65
66 if (!(fd = openraw (diskname, O_RDWR)))
67 return (-1);
68
69 if ((i = ahdi_checklabel (ptable)) < 0) {
70 close (fd);
71 return (i);
72 }
73
74 if (flags & AHDI_KEEP_BOOT) {
75 if ((root = disk_read (fd, AHDI_BBLOCK, 1)) == NULL) {
76 return (-1);
77 }
78 bzero ((void *) root->ar_parts,
79 sizeof (struct ahdi_part) * AHDI_MAXRPD);
80 } else {
81 if ((root = malloc (sizeof (struct ahdi_root))) == NULL) {
82 close (fd);
83 return (-1);
84 }
85 bzero ((void *) root, sizeof (struct ahdi_root));
86 }
87
88 nbdsec = 0;
89 #ifdef DEBUG
90 printf ("Writing root sector\n");
91 #endif
92
93 /* All partitions in root sector (including first XGM) */
94 j = 0;
95 firstxgm = 0;
96 for (i = 0; i < ptable->nparts; i++) {
97 if (ptable->parts[i].root == 0) {
98 #ifdef DEBUG
99 printf (" Partition %d - ", j);
100 #endif
101 root->ar_parts[j].ap_flg = 0x01;
102 for (k = 0; k < 3; k++) {
103 root->ar_parts[j].ap_id[k] =
104 ptable->parts[i].id[k];
105 #ifdef DEBUG
106 printf ("%c", root->ar_parts[j].ap_id[k]);
107 #endif
108 }
109 root->ar_parts[j].ap_st = ptable->parts[i].start;
110 root->ar_parts[j].ap_size = ptable->parts[i].size;
111 #ifdef DEBUG
112 printf ("/%u/%u\n", root->ar_parts[j].ap_st,
113 root->ar_parts[j].ap_size);
114 #endif
115
116 j++;
117 } else if (!firstxgm) {
118 root->ar_parts[j].ap_flg = 0x01;
119 root->ar_parts[j].ap_id[0] = 'X';
120 root->ar_parts[j].ap_id[1] = 'G';
121 root->ar_parts[j].ap_id[2] = 'M';
122 root->ar_parts[j].ap_st = ptable->parts[i].root;
123 root->ar_parts[j].ap_size = ptable->parts[i].size + 1;
124 firstxgm = i;
125 xgmsec = ptable->parts[i].root;
126 #ifdef DEBUG
127 printf (" Partition %d - XGM/%u/%u\n", j,
128 root->ar_parts[j].ap_st,
129 root->ar_parts[j].ap_size);
130 #endif
131 j++;
132 }
133 /*
134 * Note first netbsd partition for invalidate_netbsd_label().
135 */
136 if (!nbdsec && AHDI_MKPID (ptable->parts[i].id[0],
137 ptable->parts[i].id[1], ptable->parts[i].id[2])
138 == AHDI_PID_NBD) {
139 nbdsec = ptable->parts[i].start;
140 }
141 }
142
143 root->ar_hdsize = ptable->secperunit;
144 if (!(flags & AHDI_KEEP_BSL)) {
145 root->ar_bslst = (u_int32_t) BSL_OFFSET;
146 root->ar_bslsize = (u_int32_t) BSL_SIZE;
147 }
148 root->ar_checksum = ahdi_cksum (root);
149
150 if (!disk_write (fd, AHDI_BBLOCK, 1, root)) {
151 free (root);
152 close (fd);
153 return (-1);
154 }
155
156 /* Auxiliary roots */
157 for (i = firstxgm; i < ptable->nparts; i++) {
158 j = 0;
159 if (ptable->parts[i].root == 0)
160 continue;
161 #ifdef DEBUG
162 printf ("Writing auxiliary root at sector %u\n",
163 ptable->parts[i].root);
164 #endif
165 bzero ((void *) root, sizeof (struct ahdi_root));
166 rsec = ptable->parts[i].root;
167 #ifdef DEBUG
168 printf (" Partition %d - ", j);
169 #endif
170 root->ar_parts[j].ap_flg = 0x01;
171 for (k = 0; k < 3; k++) {
172 root->ar_parts[j].ap_id[k] =
173 ptable->parts[i].id[k];
174 #ifdef DEBUG
175 printf ("%c", root->ar_parts[j].ap_id[k]);
176 #endif
177 }
178 root->ar_parts[j].ap_st = ptable->parts[i].start -
179 rsec;
180 root->ar_parts[j].ap_size = ptable->parts[i].size;
181 #ifdef DEBUG
182 printf ("/%u/%u\n", root->ar_parts[j].ap_st,
183 root->ar_parts[j].ap_size);
184 #endif
185 j++;
186 if (i < ptable->nparts - 1) {
187 /* Need an XGM? */
188 if (ptable->parts[i].root != ptable->parts[i+1].root &&
189 ptable->parts[i+1].root != 0) {
190 root->ar_parts[j].ap_flg = 0x01;
191 root->ar_parts[j].ap_id[0] = 'X';
192 root->ar_parts[j].ap_id[1] = 'G';
193 root->ar_parts[j].ap_id[2] = 'M';
194 root->ar_parts[j].ap_st =
195 ptable->parts[i+1].root - xgmsec;
196 root->ar_parts[j].ap_size =
197 ptable->parts[i+1].size + 1;
198 #ifdef DEBUG
199 printf (" Partition %d - XGM/%u/%u\n", j,
200 root->ar_parts[j].ap_st,
201 root->ar_parts[j].ap_size);
202 #endif
203 root->ar_parts[j].ap_size = 0;
204 }
205 if (ptable->parts[i].root == ptable->parts[i+1].root) {
206 /* Next partition has same auxiliary root */
207 #ifdef DEBUG
208 printf (" Partition %d - ", j);
209 #endif
210 root->ar_parts[j].ap_flg = 0x01;
211 for (k = 0; k < 3; k++) {
212 root->ar_parts[j].ap_id[k] =
213 ptable->parts[i+1].id[k];
214 #ifdef DEBUG
215 printf ("%c", root->ar_parts[j].ap_id[k]);
216 #endif
217 }
218 root->ar_parts[j].ap_st =
219 ptable->parts[i+1].start - rsec;
220 root->ar_parts[j].ap_size =
221 ptable->parts[i+1].size;
222 #ifdef DEBUG
223 printf ("/%u/%u\n", root->ar_parts[j].ap_st,
224 root->ar_parts[j].ap_size);
225 #endif
226 i++;
227 }
228 j++;
229 }
230
231 if (!disk_write (fd, rsec, 1, root)) {
232 close (fd);
233 free (root);
234 return (-1);
235 }
236
237 /*
238 * Note first netbsd partition for invalidate_netbsd_label().
239 */
240 if (!nbdsec && AHDI_MKPID (ptable->parts[i].id[0],
241 ptable->parts[i].id[1], ptable->parts[i].id[2])
242 == AHDI_PID_NBD) {
243 nbdsec = ptable->parts[i].start;
244 }
245 }
246
247 free (root);
248
249 if (!(flags & AHDI_KEEP_BSL) && !write_bsl (fd)) {
250 close (fd);
251 return (-1);
252 }
253
254 if (!(flags & AHDI_KEEP_NBDA) && !invalidate_netbsd_label(fd, nbdsec)) {
255 close (fd);
256 return (-1);
257 }
258
259 #ifdef DEBUG
260 printf ("Forcing disk label re-read\n");
261 #endif
262 keep = 0;
263 if (ioctl (fd, DIOCKLABEL, &keep) < 0) {
264 close (fd);
265 return (-1);
266 }
267
268 close (fd);
269 return (1);
270 }
271
272 /*
273 * Write a bad sector list (empty).
274 */
275 int
276 write_bsl (fd)
277 int fd;
278 {
279 u_int8_t *bsl;
280
281 if ((bsl = malloc (sizeof (u_int8_t) * BSL_SIZE * DEV_BSIZE)) == NULL)
282 return (0);
283 bzero ((void *) bsl, sizeof (u_int8_t) * DEV_BSIZE);
284
285 #ifdef DEBUG
286 printf ("Writing bad sector list\n");
287 #endif
288 bsl[3] = BSL_MAGIC;
289 if (!disk_write (fd, (u_int) BSL_OFFSET, (u_int) BSL_SIZE, bsl)) {
290 free (bsl);
291 return (0);
292 }
293 free (bsl);
294 return (1);
295 }
296
297 /*
298 * Invalidate any previous AHDI/NBDA disklabel.
299 * Otherwise this make take precedence when we next open the disk.
300 */
301 int
302 invalidate_netbsd_label (fd, nbdsec)
303 int fd;
304 u_int32_t nbdsec;
305 {
306 struct bootblock *bb;
307 u_int nsec;
308
309 nsec = (BBMINSIZE + (DEV_BSIZE - 1)) / DEV_BSIZE;
310
311 if ((bb = disk_read (fd, nbdsec, nsec)) == NULL) {
312 return (0);
313 }
314
315 if (bb->bb_magic == NBDAMAGIC || bb->bb_magic == AHDIMAGIC) {
316 bb->bb_magic = bb->bb_magic & 0xffffff00;
317 bb->bb_magic = bb->bb_magic | 0x5f;
318
319 #ifdef DEBUG
320 printf ("Invalidating old NBDA/AHDI label (sector %u)\n",
321 nbdsec);
322 #endif
323 if (!disk_write (fd, nbdsec, nsec, bb)) {
324 free (bb);
325 return (0);
326 }
327 }
328
329 free (bb);
330 return (1);
331 }
332
333 int
334 disk_write (fd, start, count, buf)
335 int fd;
336 u_int start,
337 count;
338 void *buf;
339 {
340 off_t offset;
341 size_t size;
342
343 size = count * DEV_BSIZE;
344 offset = start * DEV_BSIZE;
345
346 if (lseek (fd, offset, SEEK_SET) != offset)
347 return (0);
348 if (write (fd, buf, size) != size)
349 return (0);
350 return (1);
351 }
352