Sync usage with man page.
[netbsd-mini2440.git] / sys / arch / atari / stand / ahdilabel / write.c
blobf4f38742463f009e35744818782cf8fdbb7fe2b4
1 /* $NetBSD: write.c,v 1.5 2008/04/28 20:23:15 martin Exp $ */
3 /*
4 * Copyright (c) 1999 The NetBSD Foundation, Inc.
5 * All rights reserved.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Julian Coleman, Waldi Ravens and Leo Weppelman.
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.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
32 #include "privahdi.h"
33 #include <fcntl.h>
34 #ifdef DEBUG
35 #include <stdio.h>
36 #endif
37 #include <stdlib.h>
38 #include <strings.h>
39 #include <unistd.h>
40 #include <sys/dkio.h>
41 #include <sys/ioctl.h>
43 #define BSL_MAGIC 0xa5
44 #define BSL_OFFSET 1
45 #define BSL_SIZE 1
48 * Write AHDI partitions to disk
51 int
52 ahdi_writelabel (struct ahdi_ptable *ptable, char *diskname, int flags)
54 int fd, i, j, k, firstxgm, keep, cksum_ok;
55 struct ahdi_root *root;
56 u_int rsec;
57 u_int32_t xgmsec, nbdsec;
59 if (!(fd = openraw (diskname, O_RDWR)))
60 return (-1);
62 if ((i = ahdi_checklabel (ptable)) < 0) {
63 close (fd);
64 return (i);
67 if (flags & AHDI_KEEP_BOOT) {
68 if ((root = disk_read (fd, AHDI_BBLOCK, 1)) == NULL) {
69 return (-1);
71 cksum_ok = ahdi_cksum (root) == root->ar_checksum;
72 #ifdef DEBUG
73 printf ("Previous root sector checksum was ");
74 cksum_ok ? printf (" correct\n") : printf (" incorrect\n");
75 #endif
76 bzero ((void *) root->ar_parts,
77 sizeof (struct ahdi_part) * AHDI_MAXRPD);
78 } else {
79 if ((root = malloc (sizeof (struct ahdi_root))) == NULL) {
80 close (fd);
81 return (-1);
83 bzero ((void *) root, sizeof (struct ahdi_root));
84 cksum_ok = 0;
85 #ifdef DEBUG
86 printf ("Clearing root sector - forcing incorrect checksum\n");
87 #endif
90 nbdsec = 0;
91 #ifdef DEBUG
92 printf ("Writing root sector\n");
93 #endif
95 /* All partitions in root sector (including first XGM) */
96 j = 0;
97 firstxgm = 0;
98 xgmsec = 0;
99 for (i = 0; i < ptable->nparts; i++) {
100 if (ptable->parts[i].root == 0) {
101 #ifdef DEBUG
102 printf (" Partition %d - ", j);
103 #endif
104 root->ar_parts[j].ap_flg = 0x01;
105 for (k = 0; k < 3; k++) {
106 root->ar_parts[j].ap_id[k] =
107 ptable->parts[i].id[k];
108 #ifdef DEBUG
109 printf ("%c", root->ar_parts[j].ap_id[k]);
110 #endif
112 root->ar_parts[j].ap_st = ptable->parts[i].start;
113 root->ar_parts[j].ap_size = ptable->parts[i].size;
114 #ifdef DEBUG
115 printf ("/%u/%u\n", root->ar_parts[j].ap_st,
116 root->ar_parts[j].ap_size);
117 #endif
119 j++;
120 } else if (!firstxgm) {
121 root->ar_parts[j].ap_flg = 0x01;
122 root->ar_parts[j].ap_id[0] = 'X';
123 root->ar_parts[j].ap_id[1] = 'G';
124 root->ar_parts[j].ap_id[2] = 'M';
125 root->ar_parts[j].ap_st = ptable->parts[i].root;
126 root->ar_parts[j].ap_size = ptable->parts[i].size + 1;
127 firstxgm = i;
128 xgmsec = ptable->parts[i].root;
129 #ifdef DEBUG
130 printf (" Partition %d - XGM/%u/%u\n", j,
131 root->ar_parts[j].ap_st,
132 root->ar_parts[j].ap_size);
133 #endif
134 j++;
137 * Note first netbsd partition for invalidate_netbsd_label().
139 if (!nbdsec && AHDI_MKPID (ptable->parts[i].id[0],
140 ptable->parts[i].id[1], ptable->parts[i].id[2])
141 == AHDI_PID_NBD) {
142 nbdsec = ptable->parts[i].start;
146 root->ar_hdsize = ptable->secperunit;
147 if (!(flags & AHDI_KEEP_BSL)) {
148 root->ar_bslst = (u_int32_t) BSL_OFFSET;
149 root->ar_bslsize = (u_int32_t) BSL_SIZE;
152 /* Write correct checksum? */
153 root->ar_checksum = ahdi_cksum (root);
154 if (!cksum_ok) {
155 root->ar_checksum ^= 0x5555;
156 #ifdef DEBUG
157 printf ("Setting incorrect checksum\n");
158 } else {
159 printf ("Setting correct checksum\n");
160 #endif
163 if (!disk_write (fd, AHDI_BBLOCK, 1, root)) {
164 free (root);
165 close (fd);
166 return (-1);
169 /* Auxiliary roots */
170 for (i = firstxgm; i < ptable->nparts; i++) {
171 j = 0;
172 if (ptable->parts[i].root == 0)
173 continue;
174 #ifdef DEBUG
175 printf ("Writing auxiliary root at sector %u\n",
176 ptable->parts[i].root);
177 #endif
178 bzero ((void *) root, sizeof (struct ahdi_root));
179 rsec = ptable->parts[i].root;
180 #ifdef DEBUG
181 printf (" Partition %d - ", j);
182 #endif
183 root->ar_parts[j].ap_flg = 0x01;
184 for (k = 0; k < 3; k++) {
185 root->ar_parts[j].ap_id[k] =
186 ptable->parts[i].id[k];
187 #ifdef DEBUG
188 printf ("%c", root->ar_parts[j].ap_id[k]);
189 #endif
191 root->ar_parts[j].ap_st = ptable->parts[i].start -
192 rsec;
193 root->ar_parts[j].ap_size = ptable->parts[i].size;
194 #ifdef DEBUG
195 printf ("/%u/%u\n", root->ar_parts[j].ap_st,
196 root->ar_parts[j].ap_size);
197 #endif
198 j++;
199 if (i < ptable->nparts - 1) {
200 /* Need an XGM? */
201 if (ptable->parts[i].root != ptable->parts[i+1].root &&
202 ptable->parts[i+1].root != 0) {
203 root->ar_parts[j].ap_flg = 0x01;
204 root->ar_parts[j].ap_id[0] = 'X';
205 root->ar_parts[j].ap_id[1] = 'G';
206 root->ar_parts[j].ap_id[2] = 'M';
207 root->ar_parts[j].ap_st =
208 ptable->parts[i+1].root - xgmsec;
209 root->ar_parts[j].ap_size =
210 ptable->parts[i+1].size + 1;
211 #ifdef DEBUG
212 printf (" Partition %d - XGM/%u/%u\n", j,
213 root->ar_parts[j].ap_st,
214 root->ar_parts[j].ap_size);
215 #endif
217 if (ptable->parts[i].root == ptable->parts[i+1].root) {
218 /* Next partition has same auxiliary root */
219 #ifdef DEBUG
220 printf (" Partition %d - ", j);
221 #endif
222 root->ar_parts[j].ap_flg = 0x01;
223 for (k = 0; k < 3; k++) {
224 root->ar_parts[j].ap_id[k] =
225 ptable->parts[i+1].id[k];
226 #ifdef DEBUG
227 printf ("%c", root->ar_parts[j].ap_id[k]);
228 #endif
230 root->ar_parts[j].ap_st =
231 ptable->parts[i+1].start - rsec;
232 root->ar_parts[j].ap_size =
233 ptable->parts[i+1].size;
234 #ifdef DEBUG
235 printf ("/%u/%u\n", root->ar_parts[j].ap_st,
236 root->ar_parts[j].ap_size);
237 #endif
238 i++;
240 j++;
243 if (!disk_write (fd, rsec, 1, root)) {
244 close (fd);
245 free (root);
246 return (-1);
250 * Note first netbsd partition for invalidate_netbsd_label().
252 if (!nbdsec && AHDI_MKPID (ptable->parts[i].id[0],
253 ptable->parts[i].id[1], ptable->parts[i].id[2])
254 == AHDI_PID_NBD) {
255 nbdsec = ptable->parts[i].start;
259 free (root);
261 if (!(flags & AHDI_KEEP_BSL) && !write_bsl (fd)) {
262 close (fd);
263 return (-1);
266 if (!(flags & AHDI_KEEP_NBDA) && !invalidate_netbsd_label(fd, nbdsec)) {
267 close (fd);
268 return (-1);
271 #ifdef DEBUG
272 printf ("Forcing disk label re-read\n");
273 #endif
274 keep = 0;
275 if (ioctl (fd, DIOCKLABEL, &keep) < 0) {
276 close (fd);
277 return (-1);
280 close (fd);
281 return (1);
285 * Write a bad sector list (empty).
288 write_bsl (int fd)
290 u_int8_t *bsl;
292 if ((bsl = malloc (sizeof (u_int8_t) * BSL_SIZE * DEV_BSIZE)) == NULL)
293 return (0);
294 bzero ((void *) bsl, sizeof (u_int8_t) * DEV_BSIZE);
296 #ifdef DEBUG
297 printf ("Writing bad sector list\n");
298 #endif
299 bsl[3] = BSL_MAGIC;
300 if (!disk_write (fd, (u_int) BSL_OFFSET, (u_int) BSL_SIZE, bsl)) {
301 free (bsl);
302 return (0);
304 free (bsl);
305 return (1);
309 * Invalidate any previous AHDI/NBDA disklabel.
310 * Otherwise this make take precedence when we next open the disk.
313 invalidate_netbsd_label (int fd, u_int32_t nbdsec)
315 struct bootblock *bb;
316 u_int nsec;
318 nsec = (BBMINSIZE + (DEV_BSIZE - 1)) / DEV_BSIZE;
320 if ((bb = disk_read (fd, nbdsec, nsec)) == NULL) {
321 return (0);
324 if (bb->bb_magic == NBDAMAGIC || bb->bb_magic == AHDIMAGIC) {
325 bb->bb_magic = bb->bb_magic & 0xffffff00;
326 bb->bb_magic = bb->bb_magic | 0x5f;
328 #ifdef DEBUG
329 printf ("Invalidating old NBDA/AHDI label (sector %u)\n",
330 nbdsec);
331 #endif
332 if (!disk_write (fd, nbdsec, nsec, bb)) {
333 free (bb);
334 return (0);
338 free (bb);
339 return (1);
343 disk_write (fd, start, count, buf)
344 int fd;
345 u_int start,
346 count;
347 void *buf;
349 off_t offset;
350 size_t size;
352 size = count * DEV_BSIZE;
353 offset = start * DEV_BSIZE;
355 if (lseek (fd, offset, SEEK_SET) != offset)
356 return (0);
357 if (write (fd, buf, size) != size)
358 return (0);
359 return (1);