diff options
Diffstat (limited to 'sys/arch/loongson/stand/boot/dev.c')
-rw-r--r-- | sys/arch/loongson/stand/boot/dev.c | 219 |
1 files changed, 219 insertions, 0 deletions
diff --git a/sys/arch/loongson/stand/boot/dev.c b/sys/arch/loongson/stand/boot/dev.c new file mode 100644 index 00000000000..ed8f8c070c4 --- /dev/null +++ b/sys/arch/loongson/stand/boot/dev.c @@ -0,0 +1,219 @@ +/* $OpenBSD: dev.c,v 1.1 2010/02/14 22:39:33 miod Exp $ */ + +/* + * Copyright (c) 2010 Miodrag Vallat. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +/*- + * Copyright (c) 2003 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Manuel Bouyer. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``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 THE FOUNDATION OR CONTRIBUTORS + * 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. + */ + +#include <sys/types.h> +#include "libsa.h" +#include <sys/disklabel.h> +#include <machine/param.h> +#include <machine/cpu.h> +#include <machine/pmon.h> + +/* + * PMON I/O + */ + +char pmon_bootdev[1 + 256]; + +struct pmon_iodata { + int fd; + struct disklabel label; + off_t partoff; + off_t curpos; +}; + +int pmon_getdisklabel(struct pmon_iodata *pi); + +int +pmon_iostrategy(void *f, int rw, daddr_t dblk, size_t size, void *buf, + size_t *rsize) +{ + struct pmon_iodata *pi = (struct pmon_iodata *)f; + off_t offs, pos; + int rc; + + if (size == 0) + return 0; + + if (rw != F_READ) + return EOPNOTSUPP; + + offs = ((daddr64_t)dblk + pi->partoff) * DEV_BSIZE; + if (offs != pi->curpos) { + pos = pmon_lseek(pi->fd, offs, 0 /* SEEK_SET */); + if (pos != offs) + return EINVAL; + } + + /* note this expects size to fit in 32 bits */ + rc = pmon_read(pi->fd, buf, size); + if (rc >= 0) { + pi->curpos += rc; + *rsize = rc; + } else + *rsize = 0; + + if (rc != size) + return EIO; + return 0; +} + +int +pmon_ioopen(struct open_file *f, ...) +{ + struct pmon_iodata *pi; + int rc; + va_list ap; + uint unit, part; + + pi = alloc(sizeof *pi); + if (pi == NULL) + return ENOMEM; + bzero(pi, sizeof *pi); + f->f_devdata = pi; + + va_start(ap, f); + unit = va_arg(ap, uint); + part = va_arg(ap, uint); + va_end(ap); + + /* + * Open the raw device through PMON. + */ + + snprintf(pmon_bootdev, sizeof pmon_bootdev, "/dev/disk/%s%d", + f->f_dev->dv_name, unit); + rc = pmon_open(pmon_bootdev, 0 /* O_RDONLY */); + if (rc < 0) + return ENXIO; + + pi->fd = rc; + + /* + * Read disklabel. + */ + + if (pmon_getdisklabel(pi) != 0) { + pmon_ioclose(f); + return ENXIO; + } + + if (part >= pi->label.d_npartitions) { + pmon_ioclose(f); + return EPART; + } + + pi->partoff = DL_GETPOFFSET(&pi->label.d_partitions[part]); + pi->curpos = 0; + + return 0; +} + +int +pmon_ioclose(struct open_file *f) +{ + struct pmon_iodata *pi; + int rc; + + if (f->f_devdata != NULL) { + pi = (struct pmon_iodata *)f->f_devdata; + rc = pmon_close(pi->fd); + free(pi, sizeof *pi); + f->f_devdata = NULL; + } else + rc = 0; + + return rc; +} + +/* + * Read disk label from the device. + */ +int +pmon_getdisklabel(struct pmon_iodata *pi) +{ + char *msg; + int sector; + size_t rsize; + struct disklabel *lp = &pi->label; + char buf[DEV_BSIZE]; + + bzero(lp, sizeof *lp); + + /* + * Find OpenBSD Partition in DOS partition table. + */ + sector = 0; + if (pmon_iostrategy(pi, F_READ, DOSBBSECTOR, DEV_BSIZE, buf, &rsize)) + return ENXIO; + + if (*(u_int16_t *)&buf[DOSMBR_SIGNATURE_OFF] == DOSMBR_SIGNATURE) { + int i; + struct dos_partition *dp = (struct dos_partition *)buf; + + /* + * Lookup OpenBSD slice. If there is none, go ahead + * and try to read the disklabel off sector #0. + */ + memcpy(dp, &buf[DOSPARTOFF], NDOSPART * sizeof(*dp)); + for (i = 0; i < NDOSPART; i++) { + if (dp[i].dp_typ == DOSPTYP_OPENBSD) { + sector = letoh32(dp[i].dp_start); + break; + } + } + } + + if (pmon_iostrategy(pi, F_READ, sector + LABELSECTOR, DEV_BSIZE, + buf, &rsize)) + return ENXIO; + + if ((msg = getdisklabel(buf + LABELOFFSET, lp))) { + printf("getdisklabel: %s\n", msg); + return ENXIO; + } + + return 0; +} |