1*9f8e6353SEvgeniy Ivanov /* $NetBSD: bbinfo.c,v 1.14 2009/04/05 11:55:39 lukem Exp $ */
2*9f8e6353SEvgeniy Ivanov
3*9f8e6353SEvgeniy Ivanov /*-
4*9f8e6353SEvgeniy Ivanov * Copyright (c) 1998, 2002 The NetBSD Foundation, Inc.
5*9f8e6353SEvgeniy Ivanov * All rights reserved.
6*9f8e6353SEvgeniy Ivanov *
7*9f8e6353SEvgeniy Ivanov * This code is derived from software contributed to The NetBSD Foundation
8*9f8e6353SEvgeniy Ivanov * by Matt Fredette, Paul Kranenburg, and Luke Mewburn.
9*9f8e6353SEvgeniy Ivanov *
10*9f8e6353SEvgeniy Ivanov * Redistribution and use in source and binary forms, with or without
11*9f8e6353SEvgeniy Ivanov * modification, are permitted provided that the following conditions
12*9f8e6353SEvgeniy Ivanov * are met:
13*9f8e6353SEvgeniy Ivanov * 1. Redistributions of source code must retain the above copyright
14*9f8e6353SEvgeniy Ivanov * notice, this list of conditions and the following disclaimer.
15*9f8e6353SEvgeniy Ivanov * 2. Redistributions in binary form must reproduce the above copyright
16*9f8e6353SEvgeniy Ivanov * notice, this list of conditions and the following disclaimer in the
17*9f8e6353SEvgeniy Ivanov * documentation and/or other materials provided with the distribution.
18*9f8e6353SEvgeniy Ivanov *
19*9f8e6353SEvgeniy Ivanov * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20*9f8e6353SEvgeniy Ivanov * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21*9f8e6353SEvgeniy Ivanov * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22*9f8e6353SEvgeniy Ivanov * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23*9f8e6353SEvgeniy Ivanov * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24*9f8e6353SEvgeniy Ivanov * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25*9f8e6353SEvgeniy Ivanov * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26*9f8e6353SEvgeniy Ivanov * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27*9f8e6353SEvgeniy Ivanov * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28*9f8e6353SEvgeniy Ivanov * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29*9f8e6353SEvgeniy Ivanov * POSSIBILITY OF SUCH DAMAGE.
30*9f8e6353SEvgeniy Ivanov */
31*9f8e6353SEvgeniy Ivanov
32*9f8e6353SEvgeniy Ivanov #if HAVE_NBTOOL_CONFIG_H
33*9f8e6353SEvgeniy Ivanov #include "nbtool_config.h"
34*9f8e6353SEvgeniy Ivanov #endif
35*9f8e6353SEvgeniy Ivanov
36*9f8e6353SEvgeniy Ivanov #include <sys/cdefs.h>
37*9f8e6353SEvgeniy Ivanov #if !defined(__lint)
38*9f8e6353SEvgeniy Ivanov __RCSID("$NetBSD: bbinfo.c,v 1.14 2009/04/05 11:55:39 lukem Exp $");
39*9f8e6353SEvgeniy Ivanov #endif /* !__lint */
40*9f8e6353SEvgeniy Ivanov
41*9f8e6353SEvgeniy Ivanov #include <sys/param.h>
42*9f8e6353SEvgeniy Ivanov #ifndef HAVE_NBTOOL_CONFIG_H
43*9f8e6353SEvgeniy Ivanov #include <sys/ioctl.h>
44*9f8e6353SEvgeniy Ivanov #include <sys/dkio.h>
45*9f8e6353SEvgeniy Ivanov #include <errno.h>
46*9f8e6353SEvgeniy Ivanov #endif
47*9f8e6353SEvgeniy Ivanov
48*9f8e6353SEvgeniy Ivanov #include <assert.h>
49*9f8e6353SEvgeniy Ivanov #include <err.h>
50*9f8e6353SEvgeniy Ivanov #include <stddef.h>
51*9f8e6353SEvgeniy Ivanov #include <stdio.h>
52*9f8e6353SEvgeniy Ivanov #include <stdlib.h>
53*9f8e6353SEvgeniy Ivanov #include <string.h>
54*9f8e6353SEvgeniy Ivanov #include <unistd.h>
55*9f8e6353SEvgeniy Ivanov
56*9f8e6353SEvgeniy Ivanov #include "installboot.h"
57*9f8e6353SEvgeniy Ivanov
58*9f8e6353SEvgeniy Ivanov int
shared_bbinfo_clearboot(ib_params * params,struct bbinfo_params * bbparams,int (* callback)(ib_params *,struct bbinfo_params *,uint8_t *))59*9f8e6353SEvgeniy Ivanov shared_bbinfo_clearboot(ib_params *params, struct bbinfo_params *bbparams,
60*9f8e6353SEvgeniy Ivanov int (*callback)(ib_params *, struct bbinfo_params *, uint8_t *))
61*9f8e6353SEvgeniy Ivanov {
62*9f8e6353SEvgeniy Ivanov uint8_t *bb;
63*9f8e6353SEvgeniy Ivanov ssize_t rv;
64*9f8e6353SEvgeniy Ivanov int retval;
65*9f8e6353SEvgeniy Ivanov
66*9f8e6353SEvgeniy Ivanov assert(params != NULL);
67*9f8e6353SEvgeniy Ivanov assert(params->fsfd != -1);
68*9f8e6353SEvgeniy Ivanov assert(params->filesystem != NULL);
69*9f8e6353SEvgeniy Ivanov assert(bbparams != NULL);
70*9f8e6353SEvgeniy Ivanov assert((strlen(bbparams->magic) + 1) == 32);
71*9f8e6353SEvgeniy Ivanov
72*9f8e6353SEvgeniy Ivanov retval = 0;
73*9f8e6353SEvgeniy Ivanov if ((bb = malloc(bbparams->maxsize)) == NULL) {
74*9f8e6353SEvgeniy Ivanov warn("Allocating %lu bytes for bbinfo",
75*9f8e6353SEvgeniy Ivanov (unsigned long) bbparams->maxsize);
76*9f8e6353SEvgeniy Ivanov goto done;
77*9f8e6353SEvgeniy Ivanov }
78*9f8e6353SEvgeniy Ivanov
79*9f8e6353SEvgeniy Ivanov /* First check that it _could_ exist here */
80*9f8e6353SEvgeniy Ivanov rv = pread(params->fsfd, bb, bbparams->maxsize, bbparams->offset);
81*9f8e6353SEvgeniy Ivanov if (rv == -1) {
82*9f8e6353SEvgeniy Ivanov warn("Reading `%s'", params->filesystem);
83*9f8e6353SEvgeniy Ivanov goto done;
84*9f8e6353SEvgeniy Ivanov } else if ((uint32_t)rv != bbparams->maxsize) {
85*9f8e6353SEvgeniy Ivanov warnx("Reading `%s': short read", params->filesystem);
86*9f8e6353SEvgeniy Ivanov goto done;
87*9f8e6353SEvgeniy Ivanov }
88*9f8e6353SEvgeniy Ivanov
89*9f8e6353SEvgeniy Ivanov /* Now clear out (past the header offset) */
90*9f8e6353SEvgeniy Ivanov memset(bb + bbparams->headeroffset, 0,
91*9f8e6353SEvgeniy Ivanov bbparams->maxsize - bbparams->headeroffset);
92*9f8e6353SEvgeniy Ivanov if (callback != NULL && ! (*callback)(params, bbparams, bb))
93*9f8e6353SEvgeniy Ivanov goto done;
94*9f8e6353SEvgeniy Ivanov
95*9f8e6353SEvgeniy Ivanov if (params->flags & IB_VERBOSE)
96*9f8e6353SEvgeniy Ivanov printf("%slearing boot block\n",
97*9f8e6353SEvgeniy Ivanov (params->flags & IB_NOWRITE) ? "Not c" : "C");
98*9f8e6353SEvgeniy Ivanov if (params->flags & IB_NOWRITE) {
99*9f8e6353SEvgeniy Ivanov retval = 1;
100*9f8e6353SEvgeniy Ivanov goto done;
101*9f8e6353SEvgeniy Ivanov }
102*9f8e6353SEvgeniy Ivanov
103*9f8e6353SEvgeniy Ivanov rv = pwrite(params->fsfd, bb, bbparams->maxsize, bbparams->offset);
104*9f8e6353SEvgeniy Ivanov #ifdef DIOCWLABEL
105*9f8e6353SEvgeniy Ivanov if (rv == -1 && errno == EROFS) {
106*9f8e6353SEvgeniy Ivanov /*
107*9f8e6353SEvgeniy Ivanov * The first sector might be protected by
108*9f8e6353SEvgeniy Ivanov * bounds_check_with_label(9)
109*9f8e6353SEvgeniy Ivanov */
110*9f8e6353SEvgeniy Ivanov int enable;
111*9f8e6353SEvgeniy Ivanov
112*9f8e6353SEvgeniy Ivanov enable = 1;
113*9f8e6353SEvgeniy Ivanov rv = ioctl(params->fsfd, DIOCWLABEL, &enable);
114*9f8e6353SEvgeniy Ivanov if (rv != 0) {
115*9f8e6353SEvgeniy Ivanov warn("Cannot enable writes to the label sector");
116*9f8e6353SEvgeniy Ivanov goto done;
117*9f8e6353SEvgeniy Ivanov }
118*9f8e6353SEvgeniy Ivanov
119*9f8e6353SEvgeniy Ivanov rv = pwrite(params->fsfd, bb, bbparams->maxsize,
120*9f8e6353SEvgeniy Ivanov bbparams->offset);
121*9f8e6353SEvgeniy Ivanov
122*9f8e6353SEvgeniy Ivanov /* Reset write-protect. */
123*9f8e6353SEvgeniy Ivanov enable = 0;
124*9f8e6353SEvgeniy Ivanov (void)ioctl(params->fsfd, DIOCWLABEL, &enable);
125*9f8e6353SEvgeniy Ivanov }
126*9f8e6353SEvgeniy Ivanov #endif
127*9f8e6353SEvgeniy Ivanov if (rv == -1) {
128*9f8e6353SEvgeniy Ivanov warn("Writing `%s'", params->filesystem);
129*9f8e6353SEvgeniy Ivanov goto done;
130*9f8e6353SEvgeniy Ivanov } else if ((uint32_t)rv != bbparams->maxsize) {
131*9f8e6353SEvgeniy Ivanov warnx("Writing `%s': short write", params->filesystem);
132*9f8e6353SEvgeniy Ivanov goto done;
133*9f8e6353SEvgeniy Ivanov } else
134*9f8e6353SEvgeniy Ivanov retval = 1;
135*9f8e6353SEvgeniy Ivanov
136*9f8e6353SEvgeniy Ivanov done:
137*9f8e6353SEvgeniy Ivanov if (bb != NULL)
138*9f8e6353SEvgeniy Ivanov free(bb);
139*9f8e6353SEvgeniy Ivanov return (retval);
140*9f8e6353SEvgeniy Ivanov }
141*9f8e6353SEvgeniy Ivanov
142*9f8e6353SEvgeniy Ivanov int
shared_bbinfo_setboot(ib_params * params,struct bbinfo_params * bbparams,int (* callback)(ib_params *,struct bbinfo_params *,uint8_t *))143*9f8e6353SEvgeniy Ivanov shared_bbinfo_setboot(ib_params *params, struct bbinfo_params *bbparams,
144*9f8e6353SEvgeniy Ivanov int (*callback)(ib_params *, struct bbinfo_params *, uint8_t *))
145*9f8e6353SEvgeniy Ivanov {
146*9f8e6353SEvgeniy Ivanov uint8_t *bb;
147*9f8e6353SEvgeniy Ivanov int retval;
148*9f8e6353SEvgeniy Ivanov ssize_t rv;
149*9f8e6353SEvgeniy Ivanov size_t bbi;
150*9f8e6353SEvgeniy Ivanov struct shared_bbinfo *bbinfop; /* bbinfo in prototype image */
151*9f8e6353SEvgeniy Ivanov uint32_t maxblk, nblk, blk_i;
152*9f8e6353SEvgeniy Ivanov ib_block *blocks;
153*9f8e6353SEvgeniy Ivanov
154*9f8e6353SEvgeniy Ivanov assert(params != NULL);
155*9f8e6353SEvgeniy Ivanov assert(params->fsfd != -1);
156*9f8e6353SEvgeniy Ivanov assert(params->filesystem != NULL);
157*9f8e6353SEvgeniy Ivanov assert(params->fstype != NULL);
158*9f8e6353SEvgeniy Ivanov assert(params->s1fd != -1);
159*9f8e6353SEvgeniy Ivanov assert(params->stage1 != NULL);
160*9f8e6353SEvgeniy Ivanov assert(bbparams != NULL);
161*9f8e6353SEvgeniy Ivanov assert((strlen(bbparams->magic) + 1) == 32);
162*9f8e6353SEvgeniy Ivanov
163*9f8e6353SEvgeniy Ivanov bbinfop = NULL; /* XXXGCC -Wuninitialized [sparc64] */
164*9f8e6353SEvgeniy Ivanov retval = 0;
165*9f8e6353SEvgeniy Ivanov blocks = NULL;
166*9f8e6353SEvgeniy Ivanov if ((bb = malloc(bbparams->maxsize)) == NULL) {
167*9f8e6353SEvgeniy Ivanov warn("Allocating %lu bytes for bbinfo",
168*9f8e6353SEvgeniy Ivanov (unsigned long) bbparams->maxsize);
169*9f8e6353SEvgeniy Ivanov goto done;
170*9f8e6353SEvgeniy Ivanov }
171*9f8e6353SEvgeniy Ivanov
172*9f8e6353SEvgeniy Ivanov if (params->stage2 == NULL) {
173*9f8e6353SEvgeniy Ivanov warnx("Name of secondary bootstrap not provided");
174*9f8e6353SEvgeniy Ivanov goto done;
175*9f8e6353SEvgeniy Ivanov }
176*9f8e6353SEvgeniy Ivanov
177*9f8e6353SEvgeniy Ivanov if (params->s1stat.st_size >
178*9f8e6353SEvgeniy Ivanov bbparams->maxsize - bbparams->headeroffset) {
179*9f8e6353SEvgeniy Ivanov warnx("`%s' cannot be larger than %lu bytes",
180*9f8e6353SEvgeniy Ivanov params->stage1, (unsigned long)(bbparams->maxsize -
181*9f8e6353SEvgeniy Ivanov bbparams->headeroffset));
182*9f8e6353SEvgeniy Ivanov goto done;
183*9f8e6353SEvgeniy Ivanov }
184*9f8e6353SEvgeniy Ivanov
185*9f8e6353SEvgeniy Ivanov memset(bb, 0, bbparams->maxsize);
186*9f8e6353SEvgeniy Ivanov rv = read(params->s1fd, bb + bbparams->headeroffset,
187*9f8e6353SEvgeniy Ivanov bbparams->maxsize - bbparams->headeroffset);
188*9f8e6353SEvgeniy Ivanov if (rv == -1) {
189*9f8e6353SEvgeniy Ivanov warn("Reading `%s'", params->stage1);
190*9f8e6353SEvgeniy Ivanov goto done;
191*9f8e6353SEvgeniy Ivanov }
192*9f8e6353SEvgeniy Ivanov
193*9f8e6353SEvgeniy Ivanov /*
194*9f8e6353SEvgeniy Ivanov * Quick sanity check that the bootstrap given
195*9f8e6353SEvgeniy Ivanov * is *not* an ELF executable.
196*9f8e6353SEvgeniy Ivanov */
197*9f8e6353SEvgeniy Ivanov if (memcmp(bb + bbparams->headeroffset + 1, "ELF", strlen("ELF"))
198*9f8e6353SEvgeniy Ivanov == 0) {
199*9f8e6353SEvgeniy Ivanov warnx("`%s' is an ELF executable; need raw binary",
200*9f8e6353SEvgeniy Ivanov params->stage1);
201*9f8e6353SEvgeniy Ivanov goto done;
202*9f8e6353SEvgeniy Ivanov }
203*9f8e6353SEvgeniy Ivanov
204*9f8e6353SEvgeniy Ivanov #define HOSTTOTARGET32(x) ((bbparams->endian == BBINFO_LITTLE_ENDIAN) \
205*9f8e6353SEvgeniy Ivanov ? (uint32_t)htole32((x)) : (uint32_t)htobe32((x)))
206*9f8e6353SEvgeniy Ivanov #define TARGET32TOHOST(x) ((bbparams->endian == BBINFO_LITTLE_ENDIAN) \
207*9f8e6353SEvgeniy Ivanov ? (uint32_t)le32toh((x)) : (uint32_t)be32toh((x)))
208*9f8e6353SEvgeniy Ivanov
209*9f8e6353SEvgeniy Ivanov /* Look for the bbinfo structure. */
210*9f8e6353SEvgeniy Ivanov bbinfop = NULL;
211*9f8e6353SEvgeniy Ivanov for (bbi = 0; bbi < bbparams->maxsize; bbi += sizeof(uint32_t)) {
212*9f8e6353SEvgeniy Ivanov bbinfop = (void *) (bb + bbparams->headeroffset + bbi);
213*9f8e6353SEvgeniy Ivanov if (memcmp(bbinfop->bbi_magic, bbparams->magic,
214*9f8e6353SEvgeniy Ivanov sizeof(bbinfop->bbi_magic)) == 0)
215*9f8e6353SEvgeniy Ivanov break;
216*9f8e6353SEvgeniy Ivanov }
217*9f8e6353SEvgeniy Ivanov if (bbi >= bbparams->maxsize) {
218*9f8e6353SEvgeniy Ivanov warnx("%s bbinfo structure not found in `%s'",
219*9f8e6353SEvgeniy Ivanov params->machine->name, params->stage1);
220*9f8e6353SEvgeniy Ivanov goto done;
221*9f8e6353SEvgeniy Ivanov }
222*9f8e6353SEvgeniy Ivanov maxblk = TARGET32TOHOST(bbinfop->bbi_block_count);
223*9f8e6353SEvgeniy Ivanov if (maxblk == 0 || maxblk > (bbparams->maxsize / sizeof(uint32_t))) {
224*9f8e6353SEvgeniy Ivanov warnx("%s bbinfo structure in `%s' has preposterous size `%u'",
225*9f8e6353SEvgeniy Ivanov params->machine->name, params->stage1, maxblk);
226*9f8e6353SEvgeniy Ivanov goto done;
227*9f8e6353SEvgeniy Ivanov }
228*9f8e6353SEvgeniy Ivanov
229*9f8e6353SEvgeniy Ivanov /* Allocate space for our block list. */
230*9f8e6353SEvgeniy Ivanov blocks = malloc(sizeof(*blocks) * maxblk);
231*9f8e6353SEvgeniy Ivanov if (blocks == NULL) {
232*9f8e6353SEvgeniy Ivanov warn("Allocating %lu bytes",
233*9f8e6353SEvgeniy Ivanov (unsigned long)sizeof(*blocks) * maxblk);
234*9f8e6353SEvgeniy Ivanov goto done;
235*9f8e6353SEvgeniy Ivanov }
236*9f8e6353SEvgeniy Ivanov
237*9f8e6353SEvgeniy Ivanov if (S_ISREG(params->fsstat.st_mode)) {
238*9f8e6353SEvgeniy Ivanov if (fsync(params->fsfd) == -1)
239*9f8e6353SEvgeniy Ivanov warn("Synchronising file system `%s'",
240*9f8e6353SEvgeniy Ivanov params->filesystem);
241*9f8e6353SEvgeniy Ivanov } else {
242*9f8e6353SEvgeniy Ivanov /* Ensure the secondary bootstrap is on disk. */
243*9f8e6353SEvgeniy Ivanov sync();
244*9f8e6353SEvgeniy Ivanov }
245*9f8e6353SEvgeniy Ivanov
246*9f8e6353SEvgeniy Ivanov /* Collect the blocks for the secondary bootstrap. */
247*9f8e6353SEvgeniy Ivanov nblk = maxblk;
248*9f8e6353SEvgeniy Ivanov if (! params->fstype->findstage2(params, &nblk, blocks))
249*9f8e6353SEvgeniy Ivanov goto done;
250*9f8e6353SEvgeniy Ivanov if (nblk == 0) {
251*9f8e6353SEvgeniy Ivanov warnx("Secondary bootstrap `%s' is empty",
252*9f8e6353SEvgeniy Ivanov params->stage2);
253*9f8e6353SEvgeniy Ivanov goto done;
254*9f8e6353SEvgeniy Ivanov }
255*9f8e6353SEvgeniy Ivanov
256*9f8e6353SEvgeniy Ivanov /* Save those blocks in the primary bootstrap. */
257*9f8e6353SEvgeniy Ivanov bbinfop->bbi_block_count = HOSTTOTARGET32(nblk);
258*9f8e6353SEvgeniy Ivanov bbinfop->bbi_block_size = HOSTTOTARGET32(blocks[0].blocksize);
259*9f8e6353SEvgeniy Ivanov for (blk_i = 0; blk_i < nblk; blk_i++) {
260*9f8e6353SEvgeniy Ivanov bbinfop->bbi_block_table[blk_i] =
261*9f8e6353SEvgeniy Ivanov HOSTTOTARGET32(blocks[blk_i].block);
262*9f8e6353SEvgeniy Ivanov if (blocks[blk_i].blocksize < blocks[0].blocksize &&
263*9f8e6353SEvgeniy Ivanov blk_i + 1 != nblk) {
264*9f8e6353SEvgeniy Ivanov warnx("Secondary bootstrap `%s' blocks do not have "
265*9f8e6353SEvgeniy Ivanov "a uniform size", params->stage2);
266*9f8e6353SEvgeniy Ivanov goto done;
267*9f8e6353SEvgeniy Ivanov }
268*9f8e6353SEvgeniy Ivanov }
269*9f8e6353SEvgeniy Ivanov if (callback != NULL && ! (*callback)(params, bbparams, bb))
270*9f8e6353SEvgeniy Ivanov goto done;
271*9f8e6353SEvgeniy Ivanov
272*9f8e6353SEvgeniy Ivanov if (params->flags & IB_VERBOSE) {
273*9f8e6353SEvgeniy Ivanov printf("Bootstrap start sector: %u\n",
274*9f8e6353SEvgeniy Ivanov bbparams->offset / bbparams->blocksize);
275*9f8e6353SEvgeniy Ivanov printf("Bootstrap byte count: %u\n", (unsigned)rv);
276*9f8e6353SEvgeniy Ivanov printf("Bootstrap block table: "
277*9f8e6353SEvgeniy Ivanov "%u entries of %u bytes available, %u used:",
278*9f8e6353SEvgeniy Ivanov maxblk, blocks[0].blocksize, nblk);
279*9f8e6353SEvgeniy Ivanov for (blk_i = 0; blk_i < nblk; blk_i++)
280*9f8e6353SEvgeniy Ivanov printf(" %llu",
281*9f8e6353SEvgeniy Ivanov (unsigned long long)blocks[blk_i].block);
282*9f8e6353SEvgeniy Ivanov printf("\n%sriting bootstrap\n",
283*9f8e6353SEvgeniy Ivanov (params->flags & IB_NOWRITE) ? "Not w" : "W");
284*9f8e6353SEvgeniy Ivanov }
285*9f8e6353SEvgeniy Ivanov if (params->flags & IB_NOWRITE) {
286*9f8e6353SEvgeniy Ivanov retval = 1;
287*9f8e6353SEvgeniy Ivanov goto done;
288*9f8e6353SEvgeniy Ivanov }
289*9f8e6353SEvgeniy Ivanov
290*9f8e6353SEvgeniy Ivanov rv = pwrite(params->fsfd, bb, bbparams->maxsize, bbparams->offset);
291*9f8e6353SEvgeniy Ivanov #ifdef DIOCWLABEL
292*9f8e6353SEvgeniy Ivanov if (rv == -1 && errno == EROFS) {
293*9f8e6353SEvgeniy Ivanov /*
294*9f8e6353SEvgeniy Ivanov * The first sector might be protected by
295*9f8e6353SEvgeniy Ivanov * bounds_check_with_label(9)
296*9f8e6353SEvgeniy Ivanov */
297*9f8e6353SEvgeniy Ivanov int enable;
298*9f8e6353SEvgeniy Ivanov
299*9f8e6353SEvgeniy Ivanov enable = 1;
300*9f8e6353SEvgeniy Ivanov rv = ioctl(params->fsfd, DIOCWLABEL, &enable);
301*9f8e6353SEvgeniy Ivanov if (rv != 0) {
302*9f8e6353SEvgeniy Ivanov warn("Cannot enable writes to the label sector");
303*9f8e6353SEvgeniy Ivanov goto done;
304*9f8e6353SEvgeniy Ivanov }
305*9f8e6353SEvgeniy Ivanov
306*9f8e6353SEvgeniy Ivanov rv = pwrite(params->fsfd, bb, bbparams->maxsize,
307*9f8e6353SEvgeniy Ivanov bbparams->offset);
308*9f8e6353SEvgeniy Ivanov
309*9f8e6353SEvgeniy Ivanov /* Reset write-protect. */
310*9f8e6353SEvgeniy Ivanov enable = 0;
311*9f8e6353SEvgeniy Ivanov (void)ioctl(params->fsfd, DIOCWLABEL, &enable);
312*9f8e6353SEvgeniy Ivanov }
313*9f8e6353SEvgeniy Ivanov #endif
314*9f8e6353SEvgeniy Ivanov if (rv == -1) {
315*9f8e6353SEvgeniy Ivanov warn("Writing `%s'", params->filesystem);
316*9f8e6353SEvgeniy Ivanov goto done;
317*9f8e6353SEvgeniy Ivanov } else if ((uint32_t)rv != bbparams->maxsize) {
318*9f8e6353SEvgeniy Ivanov warnx("Writing `%s': short write", params->filesystem);
319*9f8e6353SEvgeniy Ivanov goto done;
320*9f8e6353SEvgeniy Ivanov } else {
321*9f8e6353SEvgeniy Ivanov retval = 1;
322*9f8e6353SEvgeniy Ivanov }
323*9f8e6353SEvgeniy Ivanov
324*9f8e6353SEvgeniy Ivanov done:
325*9f8e6353SEvgeniy Ivanov if (blocks != NULL)
326*9f8e6353SEvgeniy Ivanov free(blocks);
327*9f8e6353SEvgeniy Ivanov if (bb != NULL)
328*9f8e6353SEvgeniy Ivanov free(bb);
329*9f8e6353SEvgeniy Ivanov return (retval);
330*9f8e6353SEvgeniy Ivanov }
331