Home | History | Annotate | Line # | Download | only in ews4800mips
      1 /*	$NetBSD: disksubr.c,v 1.8 2009/08/02 12:04:28 uch Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 2004 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by UCHIYAMA Yasushi.
      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  *
     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.
     30  */
     31 
     32 #include <sys/cdefs.h>
     33 __KERNEL_RCSID(0, "$NetBSD: disksubr.c,v 1.8 2009/08/02 12:04:28 uch Exp $");
     34 
     35 #include <sys/param.h>
     36 #include <sys/systm.h>
     37 #include <sys/disk.h>
     38 #include <sys/buf.h>
     39 #include <sys/disklabel.h>
     40 
     41 #include <machine/sector.h>
     42 
     43 #define	DISKLABEL_DEBUG
     44 
     45 #ifdef DISKLABEL_DEBUG
     46 #define	DPRINTF(fmt, args...)	printf(fmt, ##args)
     47 #else
     48 #define	DPRINTF(arg...)		((void)0)
     49 #endif
     50 
     51 const char *
     52 readdisklabel(dev_t dev, void (*strategy)(struct buf *), struct disklabel *d,
     53     struct cpu_disklabel *ux)
     54 {
     55 	uint8_t buf[DEV_BSIZE];
     56 	struct pdinfo_sector *pdinfo = &ux->pdinfo;
     57 	struct vtoc_sector *vtoc = &ux->vtoc;
     58 	bool disklabel_available = false;
     59 	bool vtoc_available = false;
     60 	void *rwops;
     61 
     62 	if ((rwops = sector_init(dev, strategy)) == 0)
     63 		return "can't read/write disk";
     64 
     65 	/* Read VTOC */
     66 	if (!pdinfo_sector(rwops, pdinfo) || !pdinfo_sanity(pdinfo)) {
     67 		DPRINTF("%s: PDINFO not found.\n", __func__);
     68 	} else if (vtoc_sector(rwops, vtoc, pdinfo->logical_sector) &&
     69 	    vtoc_sanity(vtoc)) {
     70 		vtoc_available = true;
     71 
     72 		/* Read BSD DISKLABEL (if any) */
     73 		sector_read(rwops, buf, LABELSECTOR);
     74 		if (disklabel_sanity((struct disklabel *)buf)) {
     75 			disklabel_available = true;
     76 			memcpy(d, buf, sizeof(struct disklabel));
     77 		} else {
     78 			DPRINTF("%s: no BSD disklabel.\n", __func__);
     79 		}
     80 	} else {
     81 		DPRINTF("%s: PDINFO found, but VTOC not found.\n", __func__);
     82 	}
     83 	sector_fini(rwops);
     84 
     85 	/* If there is no BSD disklabel, convert from VTOC */
     86 	if (!disklabel_available) {
     87 		if (vtoc_available) {
     88 			DPRINTF("%s: creating disklabel from VTOC.\n",
     89 			    __func__);
     90 		} else {
     91 			DPRINTF("%s: no VTOC. creating default disklabel.\n",
     92 			    __func__);
     93 			vtoc_set_default(ux, d);
     94 		}
     95 		disklabel_set_default(d);
     96 		vtoc_to_disklabel(ux, d);
     97 	}
     98 
     99 	return 0;
    100 }
    101 
    102 int
    103 setdisklabel(struct disklabel *od, struct disklabel *nd, u_long openmask,
    104     struct cpu_disklabel *ux)
    105 {
    106 
    107 	KDASSERT(openmask == 0); /* openmask is obsolete. -uch */
    108 
    109 	if (!disklabel_sanity(nd))
    110 		return EINVAL;
    111 
    112 	*od = *nd;
    113 
    114 	return 0;
    115 }
    116 
    117 int
    118 writedisklabel(dev_t dev, void (*strategy)(struct buf *), struct disklabel *d,
    119     struct cpu_disklabel *ux)
    120 {
    121 	uint8_t buf[DEV_BSIZE];
    122 	int err = 0;
    123 	void *rwops;
    124 
    125 	if (!disklabel_sanity(d))
    126 		return EINVAL;
    127 
    128 	/* 1. Update VTOC */
    129 	disklabel_to_vtoc(ux, d);
    130 	DPRINTF("%s: logical_sector=%d\n", __func__, ux->pdinfo.logical_sector);
    131 
    132 	if ((rwops = sector_init(dev, strategy)) == 0)
    133 		return ENOMEM;
    134 	pdinfo_sanity(&ux->pdinfo);
    135 	vtoc_sanity(&ux->vtoc);
    136 
    137 	/* 2. Write VTOC to bootblock */
    138 	sector_write(rwops, (void *)&ux->pdinfo, PDINFO_SECTOR);
    139 	sector_write(rwops, (void *)&ux->vtoc,
    140 	    ux->pdinfo.logical_sector + VTOC_SECTOR);
    141 
    142 	/* 3. Write disklabel to LABELSECTOR */
    143 	memset(buf, 0, sizeof buf);
    144 	memcpy(buf, d, sizeof *d);
    145 	if (!sector_write(rwops, buf, LABELSECTOR)) {
    146 		DPRINTF("%s: failed to write disklabel.\n", __func__);
    147 		err = EIO;
    148 	}
    149 	sector_fini(rwops);
    150 
    151 	return err;
    152 }
    153