/* $NetBSD: ofdev.c,v 1.37 2017/09/15 13:25:34 martin Exp $ */
/*
* Copyright (C) 1995, 1996 Wolfgang Solfrank.
* Copyright (C) 1995, 1996 TooLs GmbH.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by TooLs GmbH.
* 4. The name of TooLs GmbH may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Device I/O routines using Open Firmware
*/
#include <sys/param.h>
#include <sys/disklabel.h>
#ifdef NETBOOT
#include <netinet/in.h>
#endif
/************************************************************************
*
* The rest of this was taken from arch/sparc64/scsi/sun_disklabel.c
* and then substantially rewritten by Gordon W. Ross
*
************************************************************************/
/* What partition types to assume for Sun disklabels: */
static u_char
sun_fstypes[8] = {
FS_BSDFFS, /* a */
FS_SWAP, /* b */
FS_OTHER, /* c - whole disk */
FS_BSDFFS, /* d */
FS_BSDFFS, /* e */
FS_BSDFFS, /* f */
FS_BSDFFS, /* g */
FS_BSDFFS, /* h */
};
/*
* Given a SunOS disk label, set lp to a BSD disk label.
* Returns NULL on success, else an error string.
*
* The BSD label is cleared out before this is called.
*/
static char *
disklabel_sun_to_bsd(char *cp, struct disklabel *lp)
{
struct sun_disklabel *sl;
struct partition *npp;
struct sun_dkpart *spp;
int i, secpercyl;
u_short cksum, *sp1, *sp2;
sl = (struct sun_disklabel *)cp;
/* Verify the XOR check. */
sp1 = (u_short *)sl;
sp2 = (u_short *)(sl + 1);
cksum = 0;
while (sp1 < sp2)
cksum ^= *sp1++;
if (cksum != 0)
return("SunOS disk label, bad checksum");
lp->d_npartitions = 8;
/* These are as defined in <ufs/ffs/fs.h> */
lp->d_bbsize = 8192; /* XXX */
lp->d_sbsize = 8192; /* XXX */
for (i = 0; i < 8; i++) {
spp = &sl->sl_part[i];
npp = &lp->d_partitions[i];
npp->p_offset = spp->sdkp_cyloffset * secpercyl;
npp->p_size = spp->sdkp_nsectors;
DPRINTF(("partition %d start %x size %x\n", i, (int)npp->p_offset, (int)npp->p_size));
if (npp->p_size == 0) {
npp->p_fstype = FS_UNUSED;
} else {
npp->p_fstype = sun_fstypes[i];
if (npp->p_fstype == FS_BSDFFS) {
/*
* The sun label does not store the FFS fields,
* so just set them with default values here.
*/
npp->p_fsize = 1024;
npp->p_frag = 8;
npp->p_cpg = 16;
}
}
}
/* minimal requirements for archtypal disk label */
if (lp->d_secperunit == 0)
lp->d_secperunit = 0x1fffffff;
lp->d_npartitions = 1;
if (lp->d_partitions[0].p_size == 0)
lp->d_partitions[0].p_size = 0x1fffffff;
lp->d_partitions[0].p_offset = 0;
if (strategy(devp, F_READ, LABELSECTOR, DEV_BSIZE, buf, &readsize)
|| readsize != DEV_BSIZE)
return ("Cannot read label");
/* Check for a NetBSD disk label. */
dlp = (struct disklabel *) (buf + LABELOFFSET);
if (dlp->d_magic == DISKMAGIC) {
if (dkcksum(dlp))
return ("NetBSD disk label corrupted");
*lp = *dlp;
DPRINTF(("search_label: found NetBSD label\n"));
return (NULL);
}
/* Check for a Sun disk label (for PROM compatibility). */
slp = (struct sun_disklabel *) buf;
if (slp->sl_magic == SUN_DKMAGIC)
return (disklabel_sun_to_bsd(buf, lp));
memset(buf, 0, DEV_BSIZE);
return ("no disk label");
}
/* init the data passed to the kernel */
bootinfo_pass_bootunit = false;
memset(&bi_unit, 0, sizeof(bi_unit));
/* save old my-self value */
OF_interpret("my-self", 0, 1, &myself);
/* set our device as my-self */
OF_interpret("to my-self", 1, 0, HDL2CELL(ihandle));
/*
* my-unit delivers a variable number of cells, we could
* walk up the path and find a #address-cells value that
* describes it, but it seems to just work this simple
* way.
*/
OF_interpret("depth", 0, 1, &odepth);
OF_interpret("my-unit depth", 0, 5, &depth,
&units[0], &units[1], &units[2], &units[3]);
cnt = depth-odepth;
/*
* Old versions of QEMU's OpenBIOS have a bug in the
* CIF implementation for instance_to_package, test
* for that explicitly here and work around it if needed.
*/
phandle = OF_instance_to_package(ihandle);
OF_package_to_path(phandle, buf, sizeof(buf));
buf[sizeof(buf)-1] = 0;
if (strlen(buf) > 2 && strlen(dev) > 2 &&
strncmp(buf, dev, strlen(buf)) != 0) {
DPRINTF(("OpenBIOS workaround: phandle %" PRIx32 "is %s, "
"does not match %s\n", (uint32_t)phandle, buf, dev));
OF_interpret("my-self ihandle>non-interposed-phandle",
0, 1, &phandle);
OF_package_to_path(phandle, buf, sizeof(buf));
DPRINTF(("new phandle %" PRIx32 " is %s\n",
(uint32_t)phandle, buf));
}