1 /* $NetBSD: write.c,v 1.5 2008/04/28 20:23:15 martin Exp $ */
4 * Copyright (c) 1999 The NetBSD Foundation, Inc.
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
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.
41 #include <sys/ioctl.h>
43 #define BSL_MAGIC 0xa5
48 * Write AHDI partitions to disk
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
;
57 u_int32_t xgmsec
, nbdsec
;
59 if (!(fd
= openraw (diskname
, O_RDWR
)))
62 if ((i
= ahdi_checklabel (ptable
)) < 0) {
67 if (flags
& AHDI_KEEP_BOOT
) {
68 if ((root
= disk_read (fd
, AHDI_BBLOCK
, 1)) == NULL
) {
71 cksum_ok
= ahdi_cksum (root
) == root
->ar_checksum
;
73 printf ("Previous root sector checksum was ");
74 cksum_ok
? printf (" correct\n") : printf (" incorrect\n");
76 bzero ((void *) root
->ar_parts
,
77 sizeof (struct ahdi_part
) * AHDI_MAXRPD
);
79 if ((root
= malloc (sizeof (struct ahdi_root
))) == NULL
) {
83 bzero ((void *) root
, sizeof (struct ahdi_root
));
86 printf ("Clearing root sector - forcing incorrect checksum\n");
92 printf ("Writing root sector\n");
95 /* All partitions in root sector (including first XGM) */
99 for (i
= 0; i
< ptable
->nparts
; i
++) {
100 if (ptable
->parts
[i
].root
== 0) {
102 printf (" Partition %d - ", j
);
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
];
109 printf ("%c", root
->ar_parts
[j
].ap_id
[k
]);
112 root
->ar_parts
[j
].ap_st
= ptable
->parts
[i
].start
;
113 root
->ar_parts
[j
].ap_size
= ptable
->parts
[i
].size
;
115 printf ("/%u/%u\n", root
->ar_parts
[j
].ap_st
,
116 root
->ar_parts
[j
].ap_size
);
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;
128 xgmsec
= ptable
->parts
[i
].root
;
130 printf (" Partition %d - XGM/%u/%u\n", j
,
131 root
->ar_parts
[j
].ap_st
,
132 root
->ar_parts
[j
].ap_size
);
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])
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
);
155 root
->ar_checksum
^= 0x5555;
157 printf ("Setting incorrect checksum\n");
159 printf ("Setting correct checksum\n");
163 if (!disk_write (fd
, AHDI_BBLOCK
, 1, root
)) {
169 /* Auxiliary roots */
170 for (i
= firstxgm
; i
< ptable
->nparts
; i
++) {
172 if (ptable
->parts
[i
].root
== 0)
175 printf ("Writing auxiliary root at sector %u\n",
176 ptable
->parts
[i
].root
);
178 bzero ((void *) root
, sizeof (struct ahdi_root
));
179 rsec
= ptable
->parts
[i
].root
;
181 printf (" Partition %d - ", j
);
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
];
188 printf ("%c", root
->ar_parts
[j
].ap_id
[k
]);
191 root
->ar_parts
[j
].ap_st
= ptable
->parts
[i
].start
-
193 root
->ar_parts
[j
].ap_size
= ptable
->parts
[i
].size
;
195 printf ("/%u/%u\n", root
->ar_parts
[j
].ap_st
,
196 root
->ar_parts
[j
].ap_size
);
199 if (i
< ptable
->nparts
- 1) {
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;
212 printf (" Partition %d - XGM/%u/%u\n", j
,
213 root
->ar_parts
[j
].ap_st
,
214 root
->ar_parts
[j
].ap_size
);
217 if (ptable
->parts
[i
].root
== ptable
->parts
[i
+1].root
) {
218 /* Next partition has same auxiliary root */
220 printf (" Partition %d - ", j
);
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
];
227 printf ("%c", root
->ar_parts
[j
].ap_id
[k
]);
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
;
235 printf ("/%u/%u\n", root
->ar_parts
[j
].ap_st
,
236 root
->ar_parts
[j
].ap_size
);
243 if (!disk_write (fd
, rsec
, 1, root
)) {
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])
255 nbdsec
= ptable
->parts
[i
].start
;
261 if (!(flags
& AHDI_KEEP_BSL
) && !write_bsl (fd
)) {
266 if (!(flags
& AHDI_KEEP_NBDA
) && !invalidate_netbsd_label(fd
, nbdsec
)) {
272 printf ("Forcing disk label re-read\n");
275 if (ioctl (fd
, DIOCKLABEL
, &keep
) < 0) {
285 * Write a bad sector list (empty).
292 if ((bsl
= malloc (sizeof (u_int8_t
) * BSL_SIZE
* DEV_BSIZE
)) == NULL
)
294 bzero ((void *) bsl
, sizeof (u_int8_t
) * DEV_BSIZE
);
297 printf ("Writing bad sector list\n");
300 if (!disk_write (fd
, (u_int
) BSL_OFFSET
, (u_int
) BSL_SIZE
, bsl
)) {
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
;
318 nsec
= (BBMINSIZE
+ (DEV_BSIZE
- 1)) / DEV_BSIZE
;
320 if ((bb
= disk_read (fd
, nbdsec
, nsec
)) == NULL
) {
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;
329 printf ("Invalidating old NBDA/AHDI label (sector %u)\n",
332 if (!disk_write (fd
, nbdsec
, nsec
, bb
)) {
343 disk_write (fd
, start
, count
, buf
)
352 size
= count
* DEV_BSIZE
;
353 offset
= start
* DEV_BSIZE
;
355 if (lseek (fd
, offset
, SEEK_SET
) != offset
)
357 if (write (fd
, buf
, size
) != size
)