Index: head/sys/boot/alpha/boot1/boot1.c =================================================================== --- head/sys/boot/alpha/boot1/boot1.c (revision 113582) +++ head/sys/boot/alpha/boot1/boot1.c (revision 113583) @@ -1,279 +1,278 @@ /* * $FreeBSD$ * From $NetBSD: bootxx.c,v 1.4 1997/09/06 14:08:29 drochner Exp $ */ /* * Copyright (c) 1995 Carnegie-Mellon University. * All rights reserved. * * Author: Chris G. Demetriou * * Permission to use, copy, modify and distribute this software and * its documentation is hereby granted, provided that both the copyright * notice and this permission notice appear in all copies of the * software, derivative works or modified versions, and any portions * thereof, and that both notices appear in supporting documentation. * * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. * * Carnegie Mellon requests users of this software to return to * * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU * School of Computer Science * Carnegie Mellon University * Pittsburgh PA 15213-3890 * * any improvements or extensions that they make and grant Carnegie the * rights to redistribute these changes. */ #include #include #include -#include #include #include #define DEBUGxx void puts(const char *s); void puthex(u_long v); static int dskread(void *, u_int64_t, size_t); #define printf(...) \ while (0) #define memcpy(dst, src, len) \ bcopy(src, dst, len) #include "ufsread.c" extern end[]; int errno; char *heap = (char*) end; void bcopy(const void *src, void *dst, size_t len) { const char *s; char *d; for (d = dst, s = src; len; len--) *d++ = *s++; } void putchar(int c) { if (c == '\n') prom_putchar('\r'); prom_putchar(c); } int getchar() { return prom_getchar(); } int ischar() { return prom_poll(); } void puts(const char *s) { while (*s) putchar(*s++); } void panic(const char *message, ...) { puts(message); puts("\r\n"); halt(); } int prom_fd = 0; int devopen() { prom_return_t ret; char devname[64]; if (prom_fd) return; ret.bits = prom_getenv(PROM_E_BOOTED_DEV, devname, sizeof devname); ret.bits = prom_open(devname, ret.u.retval + 1); if (ret.u.status) panic("devopen: open failed\n"); prom_fd = ret.u.retval; /* XXX read disklabel and setup partition offset */ return 0; } #ifdef DEBUG void puthex(u_long v) { int digit; char hex[] = "0123456789abcdef"; puts("0x"); if (!v) { puts("0"); return; } for (digit = 0; v >= (0x10L << digit); digit += 4) ; for (; digit >= 0; digit -= 4) putchar(hex[(v >> digit) & 0xf]); } #endif int dskread(void *buf, u_int64_t block, size_t size) { #ifdef DEBUG puts("dskread("); puthex((u_long)buf); puts(","); puthex(block); puts(","); puthex(size); puts(")\n"); #endif prom_read(prom_fd, size * DEV_BSIZE, buf, block); return (0); } static inline void devclose() { if (prom_fd) { prom_close(prom_fd); prom_fd = 0; } } static inline void getfilename(char *filename, const char *defname) { int c; char *p = filename; puts("Boot: "); while ((c = getchar()) != '\r') { if (c == '\b' || c == 0177) { if (p > filename) { puts("\b \b"); p--; } } else { putchar(c); *p++ = c; } } putchar('\n'); *p = '\0'; if (!*filename) strcpy(filename, defname); return; } static struct dmadat __dmadat; static inline void loadfile(char *name, char *addr) { int n; char *p; ino_t ino; puts("Loading "); puts(name); puts("\n"); dmadat = &__dmadat; if (devopen() || (ino = lookup(name)) == 0) { puts("Can't open file "); puts(name); puts("\n"); halt(); } p = addr; do { n = fsread(ino, p, VBLKSIZE); if (n < 0) { puts("Can't read file "); puts(name); puts("\n"); halt(); } p += n; twiddle(); } while (n == VBLKSIZE); devclose(); } static inline u_long rpcc() { u_long v; __asm__ __volatile__ ("rpcc %0" : "=r"(v)); return v & 0xffffffff; } int main() { char *loadaddr = (char*) SECONDARY_LOAD_ADDRESS; char *name = "/boot/loader"; char *p; char filename[512]; void (*entry)(void); u_long start, freq; int i; init_prom_calls(); start = rpcc(); freq = ((struct rpb *)HWRPB_ADDR)->rpb_cc_freq; while (((rpcc() - start) & 0xffffffff) < freq) { twiddle(); if (ischar()) { getfilename(filename, name); name = filename; break; } } loadfile(name, loadaddr); entry = (void (*)())loadaddr; (*entry)(); return 0; } Index: head/sys/boot/arc/lib/arcdisk.c =================================================================== --- head/sys/boot/arc/lib/arcdisk.c (revision 113582) +++ head/sys/boot/arc/lib/arcdisk.c (revision 113583) @@ -1,362 +1,361 @@ /*- * Copyright (c) 1998 Michael Smith * Copyright (c) 1998 Doug Rabson * 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. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. * * $FreeBSD$ */ /* * ARC disk device handling. * * Ideas and algorithms from: * * - NetBSD libi386/biosdisk.c * - FreeBSD biosboot/disk.c * */ #include -#include #include #include "bootstrap.h" #include "libarc.h" #include "arctypes.h" #include "arcfuncs.h" #define ARCDISK_SECSIZE 512 #define BUFSIZE (1 * ARCDISK_SECSIZE) #define MAXBDDEV MAXDEV #ifdef DISK_DEBUG # define D(x) x #else # define D(x) #endif static int bd_init(void); static int bd_strategy(void *devdata, int flag, daddr_t dblk, size_t size, char *buf, size_t *rsize); static int bd_realstrategy(void *devdata, int flag, daddr_t dblk, size_t size, char *buf, size_t *rsize); static int bd_open(struct open_file *f, ...); static int bd_close(struct open_file *f); static void bd_print(int verbose); struct open_disk { int od_fd; int od_unit; /* our unit number */ int od_boff; /* block offset from beginning of ARC disk */ int od_flags; #define BD_FLOPPY (1<<2) u_char od_buf[BUFSIZE]; /* transfer buffer (do we want/need this?) */ }; struct devsw arcdisk = { "disk", DEVT_DISK, bd_init, bd_strategy, bd_open, bd_close, noioctl, bd_print }; /* * List of ARC devices, translation from disk unit number to * ARC unit number. */ static struct { char bd_name[64]; int bd_unit; /* ARC unit number */ int bd_namelen; int bd_flags; } bdinfo [MAXBDDEV]; static int nbdinfo = 0; /* * Quiz ARC for disk devices, save a little info about them. */ static int bd_init(void) { nbdinfo++; return (0); } /* * Print information about disks */ static void bd_print(int verbose) { int i; char line[80]; for (i = 0; i < nbdinfo; i++) { sprintf(line, " disk%d: ARC drive %s", i, bdinfo[i].bd_name); pager_output(line); /* XXX more detail? */ pager_output("\n"); } } /* * Attempt to open the disk described by (dev) for use by (f). * * Note that the philosophy here is "give them exactly what * they ask for". This is necessary because being too "smart" * about what the user might want leads to complications. * (eg. given no slice or partition value, with a disk that is * sliced - are they after the first BSD slice, or the DOS * slice before it?) */ static int bd_open(struct open_file *f, ...) { struct arc_devdesc *dev; struct dos_partition *dptr; struct open_disk *od; struct disklabel *lp; int sector, slice, i; int error; int unit; u_int32_t fd; va_list ap; va_start(ap, f); dev = va_arg(ap, struct arc_devdesc *); va_end(ap); unit = dev->d_kind.arcdisk.unit; if (unit >= nbdinfo) { D(printf("attempt to open nonexistent disk\n")); return(ENXIO); } if (Open("scsi(0)disk(0)rdisk(0)partition(0)", OpenReadOnly, &fd) != ESUCCESS) if (Open("scsi(0)disk(1)rdisk(0)partition(0)", OpenReadOnly, &fd) != ESUCCESS) if (Open("multi(0)disk(0)fdisk(0)partition(0)", OpenReadOnly, &fd) != ESUCCESS) return(ENXIO); od = (struct open_disk *) malloc(sizeof(struct open_disk)); if (!od) { D(printf("arcdiskopen: no memory\n")); return (ENOMEM); } /* Look up ARC unit number, intialise open_disk structure */ od->od_fd = fd; od->od_unit = dev->d_kind.arcdisk.unit; od->od_flags = bdinfo[od->od_unit].bd_flags; od->od_boff = 0; error = 0; #if 0 /* Get geometry for this open (removable device may have changed) */ if (set_geometry(&od->od_ll)) { D(printf("bd_open: can't get geometry\n")); error = ENXIO; goto out; } #endif /* * Following calculations attempt to determine the correct value * for d->od_boff by looking for the slice and partition specified, * or searching for reasonable defaults. */ #if 0 /* * Find the slice in the DOS slice table. */ if (readsects(&od->od_ll, 0, 1, od->od_buf, 0)) { D(printf("bd_open: error reading MBR\n")); error = EIO; goto out; } /* * Check the slice table magic. */ if ((od->od_buf[0x1fe] != 0xff) || (od->od_buf[0x1ff] != 0xaa)) { /* If a slice number was explicitly supplied, this is an error */ if (dev->d_kind.arcdisk.slice > 0) { D(printf("bd_open: no slice table/MBR (no magic)\n")); error = ENOENT; goto out; } sector = 0; goto unsliced; /* may be a floppy */ } dptr = (struct dos_partition *) & od->od_buf[DOSPARTOFF]; /* * XXX No support here for 'extended' slices */ if (dev->d_kind.arcdisk.slice <= 0) { /* * Search for the first FreeBSD slice; this also works on "unsliced" * disks, as they contain a "historically bogus" MBR. */ for (i = 0; i < NDOSPART; i++, dptr++) if (dptr->dp_typ == DOSPTYP_386BSD) { sector = dptr->dp_start; break; } /* Did we find something? */ if (sector == -1) { error = ENOENT; goto out; } } else { /* * Accept the supplied slice number unequivocally (we may be looking * for a DOS partition) if we can handle it. */ if ((dev->d_kind.arcdisk.slice > NDOSPART) || (dev->d_kind.arcdisk.slice < 1)) { error = ENOENT; goto out; } dptr += (dev->d_kind.arcdisk.slice - 1); sector = dptr->dp_start; } unsliced: #else sector = 0; #endif /* * Now we have the slice, look for the partition in the disklabel if we have * a partition to start with. */ if (dev->d_kind.arcdisk.partition < 0) { od->od_boff = sector; /* no partition, must be after the slice */ } else { if (bd_strategy(od, F_READ, sector + LABELSECTOR, 512, od->od_buf, 0)) { D(printf("bd_open: error reading disklabel\n")); error = EIO; goto out; } lp = (struct disklabel *) (od->od_buf + LABELOFFSET); if (lp->d_magic != DISKMAGIC) { D(printf("bd_open: no disklabel\n")); error = ENOENT; goto out; } else if (dev->d_kind.arcdisk.partition >= lp->d_npartitions) { /* * The partition supplied is out of bounds; this is fatal. */ D(printf("partition '%c' exceeds partitions in table (a-'%c')\n", 'a' + dev->d_kind.arcdisk.partition, 'a' + lp->d_npartitions)); error = EPART; goto out; } else { /* * Complain if the partition type is wrong and it shouldn't be, but * regardless accept this partition. */ D(if ((lp->d_partitions[dev->d_kind.arcdisk.partition].p_fstype == FS_UNUSED) && !(od->od_flags & BD_FLOPPY)) /* Floppies often have bogus fstype */ printf("bd_open: warning, partition marked as unused\n");); od->od_boff = lp->d_partitions[dev->d_kind.arcdisk.partition].p_offset; } } /* * Save our context */ f->f_devdata = od; out: if (error) free(od); return(error); } static int bd_close(struct open_file *f) { struct open_disk *od = f->f_devdata; Close(od->od_fd); free(od); f->f_devdata = NULL; return(0); } static int bd_strategy(void *devdata, int rw, daddr_t dblk, size_t size, char *buf, size_t *rsize) { struct bcache_devdata bcd; struct arc_devdesc *dev = (struct arc_devdesc *)devdata; bcd.dv_strategy = bd_realstrategy; bcd.dv_devdata = devdata; return(bcache_strategy(&bcd, dev->d_kind.arcdisk.unit, rw, dblk, size, buf, rsize)); } static int bd_realstrategy(void *devdata, int flag, daddr_t dblk, size_t size, char *buf, size_t *rsize) { struct open_disk *od = (struct open_disk *)devdata; fpos_t seek; u_int32_t count; if (size % ARCDISK_SECSIZE) panic("bd_strategy: I/O not block multiple"); if (flag != F_READ) return(EROFS); if (rsize) *rsize = 0; seek = 512 * (dblk + od->od_boff); Seek(od->od_fd, &seek, SeekAbsolute); if (Read(od->od_fd, buf, size, &count) != ESUCCESS) { D(printf("read error\n")); return (EIO); } if (rsize) *rsize = count; return (0); } Index: head/sys/boot/arc/lib/devicename.c =================================================================== --- head/sys/boot/arc/lib/devicename.c (revision 113582) +++ head/sys/boot/arc/lib/devicename.c (revision 113583) @@ -1,236 +1,235 @@ /*- * Copyright (c) 1998 Michael Smith * 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. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. * * $FreeBSD$ */ #include #include -#include #include "bootstrap.h" #include "libarc.h" static int arc_parsedev(struct arc_devdesc **dev, const char *devspec, const char **path); /* * Point (dev) at an allocated device specifier for the device matching the * path in (devspec). If it contains an explicit device specification, * use that. If not, use the default device. */ int arc_getdev(void **vdev, const char *devspec, const char **path) { struct arc_devdesc **dev = (struct arc_devdesc **)vdev; int rv; /* * If it looks like this is just a path and no * device, go with the current device. */ if ((devspec == NULL) || (devspec[0] == '/') || (strchr(devspec, ':') == NULL)) { if (((rv = arc_parsedev(dev, getenv("currdev"), NULL)) == 0) && (path != NULL)) *path = devspec; return(rv); } /* * Try to parse the device name off the beginning of the devspec */ return(arc_parsedev(dev, devspec, path)); } /* * Point (dev) at an allocated device specifier matching the string version * at the beginning of (devspec). Return a pointer to the remaining * text in (path). * * In all cases, the beginning of (devspec) is compared to the names * of known devices in the device switch, and then any following text * is parsed according to the rules applied to the device type. * * For disk-type devices, the syntax is: * * disk[s][]: * */ static int arc_parsedev(struct arc_devdesc **dev, const char *devspec, const char **path) { struct arc_devdesc *idev; struct devsw *dv; int i, unit, slice, partition, err; char *cp; const char *np; /* minimum length check */ if (strlen(devspec) < 2) return(EINVAL); /* look for a device that matches */ for (i = 0, dv = NULL; devsw[i] != NULL; i++) { if (!strncmp(devspec, devsw[i]->dv_name, strlen(devsw[i]->dv_name))) { dv = devsw[i]; break; } } if (dv == NULL) return(ENOENT); idev = malloc(sizeof(struct arc_devdesc)); err = 0; np = (devspec + strlen(dv->dv_name)); switch(dv->dv_type) { case DEVT_NONE: /* XXX what to do here? Do we care? */ break; case DEVT_DISK: unit = -1; slice = -1; partition = -1; if (*np && (*np != ':')) { unit = strtol(np, &cp, 10); /* next comes the unit number */ if (cp == np) { err = EUNIT; goto fail; } if (*cp == 's') { /* got a slice number */ np = cp + 1; slice = strtol(np, &cp, 10); if (cp == np) { err = ESLICE; goto fail; } } if (*cp && (*cp != ':')) { partition = *cp - 'a'; /* get a partition number */ if ((partition < 0) || (partition >= MAXPARTITIONS)) { err = EPART; goto fail; } cp++; } } if (*cp && (*cp != ':')) { err = EINVAL; goto fail; } idev->d_kind.arcdisk.unit = unit; idev->d_kind.arcdisk.slice = slice; idev->d_kind.arcdisk.partition = partition; if (path != NULL) *path = (*cp == 0) ? cp : cp + 1; break; case DEVT_NET: unit = 0; if (*np && (*np != ':')) { unit = strtol(np, &cp, 0); /* get unit number if present */ if (cp == np) { err = EUNIT; goto fail; } } if (*cp && (*cp != ':')) { err = EINVAL; goto fail; } idev->d_kind.netif.unit = unit; if (path != NULL) *path = (*cp == 0) ? cp : cp + 1; break; default: err = EINVAL; goto fail; } idev->d_dev = dv; idev->d_type = dv->dv_type; if (dev == NULL) { free(idev); } else { *dev = idev; } return(0); fail: free(idev); return(err); } char * arc_fmtdev(void *vdev) { struct arc_devdesc *dev = (struct arc_devdesc *)vdev; static char buf[128]; /* XXX device length constant? */ char *cp; switch(dev->d_type) { case DEVT_NONE: strcpy(buf, "(no device)"); break; case DEVT_DISK: cp = buf; cp += sprintf(cp, "%s%d", dev->d_dev->dv_name, dev->d_kind.arcdisk.unit); if (dev->d_kind.arcdisk.slice > 0) cp += sprintf(cp, "s%d", dev->d_kind.arcdisk.slice); if (dev->d_kind.arcdisk.partition >= 0) cp += sprintf(cp, "%c", dev->d_kind.arcdisk.partition + 'a'); strcat(cp, ":"); break; case DEVT_NET: sprintf(buf, "%s%d:", dev->d_dev->dv_name, dev->d_kind.netif.unit); break; } return(buf); } /* * Set currdev to suit the value being supplied in (value) */ int arc_setcurrdev(struct env_var *ev, int flags, void *value) { struct arc_devdesc *ncurr; int rv; if ((rv = arc_parsedev(&ncurr, value, NULL)) != 0) return(rv); free(ncurr); env_setenv(ev->ev_name, flags | EV_NOHOOK, value, NULL, NULL); return(0); } Index: head/sys/boot/ofw/libofw/devicename.c =================================================================== --- head/sys/boot/ofw/libofw/devicename.c (revision 113582) +++ head/sys/boot/ofw/libofw/devicename.c (revision 113583) @@ -1,127 +1,126 @@ /*- * Copyright (c) 1998 Michael Smith * 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. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. * * $FreeBSD$ */ #include -#include #include "libofw.h" static int ofw_parsedev(struct ofw_devdesc **, const char *, const char **); /* * Point (dev) at an allocated device specifier for the device matching the * path in (devspec). If it contains an explicit device specification, * use that. If not, use the default device. */ int ofw_getdev(void **vdev, const char *devspec, const char **path) { struct ofw_devdesc **dev = (struct ofw_devdesc **)vdev; int rv; /* * If it looks like this is just a path and no * device, go with the current device. */ if ((devspec == NULL) || (strchr(devspec, '@') == NULL)) { if (((rv = ofw_parsedev(dev, getenv("currdev"), NULL)) == 0) && (path != NULL)) *path = devspec; return(rv); } /* * Try to parse the device name off the beginning of the devspec */ return(ofw_parsedev(dev, devspec, path)); } /* * Point (dev) at an allocated device specifier matching the string version * at the beginning of (devspec). Return a pointer to the remaining * text in (path). */ static int ofw_parsedev(struct ofw_devdesc **dev, const char *devspec, const char **path) { struct ofw_devdesc *idev; struct devsw *dv; phandle_t handle; const char *p; const char *s; char name[256]; char type[64]; int len; int i; for (p = s = devspec; *s != '\0'; p = s) { if ((s = strchr(p + 1, '/')) == NULL) s = strchr(p, '\0'); len = s - devspec; bcopy(devspec, name, len); name[len] = '\0'; if ((handle = OF_finddevice(name)) == -1) break; if (OF_getprop(handle, "device_type", type, sizeof(type)) == -1) continue; for (i = 0; (dv = devsw[i]) != NULL; i++) { if (strncmp(dv->dv_name, type, strlen(dv->dv_name)) == 0) goto found; } } return(ENOENT); found: if (*s != '\0') *path = s; idev = malloc(sizeof(struct ofw_devdesc)); strcpy(idev->d_path, name); idev->d_dev = dv; idev->d_type = dv->dv_type; if (dev == NULL) { free(idev); } else { *dev = idev; } return(0); } int ofw_setcurrdev(struct env_var *ev, int flags, void *value) { struct ofw_devdesc *ncurr; int rv; if ((rv = ofw_parsedev(&ncurr, value, NULL)) != 0) return rv; free(ncurr); env_setenv(ev->ev_name, flags | EV_NOHOOK, value, NULL, NULL); return 0; } Index: head/sys/boot/ofw/libofw/ofw_disk.c =================================================================== --- head/sys/boot/ofw/libofw/ofw_disk.c (revision 113582) +++ head/sys/boot/ofw/libofw/ofw_disk.c (revision 113583) @@ -1,127 +1,126 @@ /* * Copyright (C) 2000 Benno Rice. * 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. * * THIS SOFTWARE IS PROVIDED BY Benno Rice ``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. * * $FreeBSD$ */ /* * Disk I/O routines using Open Firmware */ #include -#include #include #include #include #include "bootstrap.h" #include "libofw.h" static int ofwd_init(void); static int ofwd_strategy(void *devdata, int flag, daddr_t dblk, size_t size, char *buf, size_t *rsize); static int ofwd_open(struct open_file *f, ...); static int ofwd_close(struct open_file *f); static int ofwd_ioctl(struct open_file *f, u_long cmd, void *data); static void ofwd_print(int verbose); struct devsw ofwdisk = { "block", DEVT_DISK, ofwd_init, ofwd_strategy, ofwd_open, ofwd_close, ofwd_ioctl, ofwd_print }; static int ofwd_init(void) { return 0; } static int ofwd_strategy(void *devdata, int flag, daddr_t dblk, size_t size, char *buf, size_t *rsize) { struct ofw_devdesc *dp = (struct ofw_devdesc *)devdata; unsigned long pos; int n; int i, j; pos = dblk * 512; do { if (OF_seek(dp->d_handle, pos) < 0) return EIO; n = OF_read(dp->d_handle, buf, size); if (n < 0 && n != -2) return EIO; } while (n == -2); *rsize = size; return 0; } static int ofwd_open(struct open_file *f, ...) { struct ofw_devdesc *dp; phandle_t handle; va_list vl; va_start(vl, f); dp = va_arg(vl, struct ofw_devdesc *); va_end(vl); if ((handle = OF_open(dp->d_path)) == -1) { printf("ofwd_open: Could not open %s\n", dp->d_path); return 1; } dp->d_handle = handle; return 0; } static int ofwd_close(struct open_file *f) { struct ofw_devdesc *dev = f->f_devdata; OF_close(dev->d_handle); return 0; } static int ofwd_ioctl(struct open_file *f, u_long cmd, void *data) { return (EINVAL); } static void ofwd_print(int verbose) { } Index: head/sys/boot/sparc64/boot1/boot1.c =================================================================== --- head/sys/boot/sparc64/boot1/boot1.c (revision 113582) +++ head/sys/boot/sparc64/boot1/boot1.c (revision 113583) @@ -1,666 +1,665 @@ /* * Copyright (c) 1998 Robert Nordier * All rights reserved. * Copyright (c) 2001 Robert Drehmel * All rights reserved. * * Redistribution and use in source and binary forms are freely * permitted provided that the above copyright notice and this * paragraph and the following disclaimer are duplicated in all * such forms. * * This software is provided "AS IS" and without any express or * implied warranties, including, without limitation, the implied * warranties of merchantability and fitness for a particular * purpose. * */ #include __FBSDID("$FreeBSD$"); #include -#include #include #include #include #define _PATH_LOADER "/boot/loader" #define _PATH_KERNEL "/boot/kernel/kernel" #define BSIZEMAX 16384 typedef int putc_func_t(int c, void *arg); typedef int32_t ofwh_t; struct sp_data { char *sp_buf; u_int sp_len; u_int sp_size; }; static const char digits[] = "0123456789abcdef"; static char bootpath[128]; static char bootargs[128]; static ofwh_t bootdev; static struct fs fs; static ino_t inomap; static char blkbuf[BSIZEMAX]; static unsigned int fsblks; static uint32_t fs_off; int main(int ac, char **av); static void exit(int) __dead2; static void load(const char *); static int dskread(void *, u_int64_t, int); static void usage(void); static void bcopy(const void *src, void *dst, size_t len); static void bzero(void *b, size_t len); static int mount(const char *device); static void panic(const char *fmt, ...) __dead2; static int printf(const char *fmt, ...); static int putchar(int c, void *arg); static int vprintf(const char *fmt, va_list ap); static int vsnprintf(char *str, size_t sz, const char *fmt, va_list ap); static int __printf(const char *fmt, putc_func_t *putc, void *arg, va_list ap); static int __putc(int c, void *arg); static int __puts(const char *s, putc_func_t *putc, void *arg); static int __sputc(int c, void *arg); static char *__uitoa(char *buf, u_int val, int base); static char *__ultoa(char *buf, u_long val, int base); /* * Open Firmware interface functions */ typedef u_int64_t ofwcell_t; typedef u_int32_t u_ofwh_t; typedef int (*ofwfp_t)(ofwcell_t []); ofwfp_t ofw; /* the prom Open Firmware entry */ void ofw_init(int, int, int, int, ofwfp_t); ofwh_t ofw_finddevice(const char *); ofwh_t ofw_open(const char *); int ofw_getprop(ofwh_t, const char *, void *, size_t); int ofw_read(ofwh_t, void *, size_t); int ofw_write(ofwh_t, const void *, size_t); int ofw_seek(ofwh_t, u_int64_t); void ofw_exit(void) __dead2; ofwh_t bootdevh; ofwh_t stdinh, stdouth; /* * This has to stay here, as the PROM seems to ignore the * entry point specified in the a.out header. (or elftoaout is broken) */ void ofw_init(int d, int d1, int d2, int d3, ofwfp_t ofwaddr) { ofwh_t chosenh; char *av[16]; char *p; int ac; ofw = ofwaddr; chosenh = ofw_finddevice("/chosen"); ofw_getprop(chosenh, "stdin", &stdinh, sizeof(stdinh)); ofw_getprop(chosenh, "stdout", &stdouth, sizeof(stdouth)); ofw_getprop(chosenh, "bootargs", bootargs, sizeof(bootargs)); ofw_getprop(chosenh, "bootpath", bootpath, sizeof(bootpath)); bootargs[sizeof(bootargs) - 1] = '\0'; bootpath[sizeof(bootpath) - 1] = '\0'; ac = 0; p = bootargs; for (;;) { while (*p == ' ' && *p != '\0') p++; if (*p == '\0' || ac >= 16) break; av[ac++] = p; while (*p != ' ' && *p != '\0') p++; if (*p != '\0') *p++ = '\0'; } exit(main(ac, av)); } ofwh_t ofw_finddevice(const char *name) { ofwcell_t args[] = { (ofwcell_t)"finddevice", 1, 1, (ofwcell_t)name, 0 }; if ((*ofw)(args)) { printf("ofw_finddevice: name=\"%s\"\n", name); return (1); } return (args[4]); } int ofw_getprop(ofwh_t ofwh, const char *name, void *buf, size_t len) { ofwcell_t args[] = { (ofwcell_t)"getprop", 4, 1, (u_ofwh_t)ofwh, (ofwcell_t)name, (ofwcell_t)buf, len, 0 }; if ((*ofw)(args)) { printf("ofw_getprop: ofwh=0x%x buf=%p len=%u\n", ofwh, buf, len); return (1); } return (0); } ofwh_t ofw_open(const char *path) { ofwcell_t args[] = { (ofwcell_t)"open", 1, 1, (ofwcell_t)path, 0 }; if ((*ofw)(args)) { printf("ofw_open: path=\"%s\"\n", path); return (-1); } return (args[4]); } int ofw_close(ofwh_t devh) { ofwcell_t args[] = { (ofwcell_t)"close", 1, 0, (u_ofwh_t)devh }; if ((*ofw)(args)) { printf("ofw_close: devh=0x%x\n", devh); return (1); } return (0); } int ofw_read(ofwh_t devh, void *buf, size_t len) { ofwcell_t args[] = { (ofwcell_t)"read", 4, 1, (u_ofwh_t)devh, (ofwcell_t)buf, len, 0 }; if ((*ofw)(args)) { printf("ofw_read: devh=0x%x buf=%p len=%u\n", devh, buf, len); return (1); } return (0); } int ofw_write(ofwh_t devh, const void *buf, size_t len) { ofwcell_t args[] = { (ofwcell_t)"write", 3, 1, (u_ofwh_t)devh, (ofwcell_t)buf, len, 0 }; if ((*ofw)(args)) { printf("ofw_write: devh=0x%x buf=%p len=%u\n", devh, buf, len); return (1); } return (0); } int ofw_seek(ofwh_t devh, u_int64_t off) { ofwcell_t args[] = { (ofwcell_t)"seek", 4, 1, (u_ofwh_t)devh, off >> 32, off, 0 }; if ((*ofw)(args)) { printf("ofw_seek: devh=0x%x off=0x%lx\n", devh, off); return (1); } return (0); } void ofw_exit(void) { ofwcell_t args[3]; args[0] = (ofwcell_t)"exit"; args[1] = 0; args[2] = 0; for (;;) (*ofw)(args); } static void bcopy(const void *src, void *dst, size_t len) { const char *s = src; char *d = dst; while (len-- != 0) *d++ = *s++; } static void memcpy(void *dst, const void *src, size_t len) { bcopy(src, dst, len); } static void bzero(void *b, size_t len) { char *p = b; while (len-- != 0) *p++ = 0; } static int strcmp(const char *s1, const char *s2) { for (; *s1 == *s2 && *s1; s1++, s2++) ; return ((u_char)*s1 - (u_char)*s2); } #include "ufsread.c" int main(int ac, char **av) { const char *path; int i; path = _PATH_LOADER; for (i = 0; i < ac; i++) { switch (av[i][0]) { case '-': switch (av[i][1]) { default: usage(); } break; default: path = av[i]; break; } } printf(" \n>> FreeBSD/sparc64 boot block\n" " Boot path: %s\n" " Boot loader: %s\n", bootpath, path); if (mount(bootpath) == -1) panic("mount"); load(path); return (1); } static void usage(void) { printf("usage: boot device [/path/to/loader]\n"); exit(1); } static void exit(int code) { ofw_exit(); } static struct dmadat __dmadat; static int mount(const char *device) { dmadat = &__dmadat; if ((bootdev = ofw_open(device)) == -1) { printf("mount: can't open device\n"); return (-1); } if (fsread(0, NULL, 0)) { printf("mount: can't read superblock\n"); return (-1); } return (0); } static void load(const char *fname) { Elf64_Ehdr eh; Elf64_Phdr ph; caddr_t p; ino_t ino; int i; if ((ino = lookup(fname)) == 0) { printf("File %s not found\n", fname); return; } if (fsread(ino, &eh, sizeof(eh)) != sizeof(eh)) { printf("Can't read elf header\n"); return; } if (!IS_ELF(eh)) { printf("Not an ELF file\n"); return; } for (i = 0; i < eh.e_phnum; i++) { fs_off = eh.e_phoff + i * eh.e_phentsize; if (fsread(ino, &ph, sizeof(ph)) != sizeof(ph)) { printf("Can't read program header %d\n", i); return; } if (ph.p_type != PT_LOAD) continue; fs_off = ph.p_offset; p = (caddr_t)ph.p_vaddr; if (fsread(ino, p, ph.p_filesz) != ph.p_filesz) { printf("Can't read content of section %d\n", i); return; } if (ph.p_filesz != ph.p_memsz) bzero(p + ph.p_filesz, ph.p_memsz - ph.p_filesz); } ofw_close(bootdev); (*(void (*)(int, int, int, int, ofwfp_t))eh.e_entry)(0, 0, 0, 0, ofw); } static int dskread(void *buf, u_int64_t lba, int nblk) { /* * The OpenFirmware should open the correct partition for us. * That means, if we read from offset zero on an open instance handle, * we should read from offset zero of that partition. */ ofw_seek(bootdev, lba * DEV_BSIZE); ofw_read(bootdev, buf, nblk * DEV_BSIZE); return (0); } static void panic(const char *fmt, ...) { char buf[128]; va_list ap; va_start(ap, fmt); vsnprintf(buf, sizeof buf, fmt, ap); printf("panic: %s\n", buf); va_end(ap); exit(1); } static int printf(const char *fmt, ...) { va_list ap; int ret; va_start(ap, fmt); ret = vprintf(fmt, ap); va_end(ap); return (ret); } static int putchar(int c, void *arg) { char buf; if (c == '\n') { buf = '\r'; ofw_write(stdouth, &buf, 1); } buf = c; ofw_write(stdouth, &buf, 1); return (1); } static int vprintf(const char *fmt, va_list ap) { int ret; ret = __printf(fmt, putchar, 0, ap); return (ret); } static int vsnprintf(char *str, size_t sz, const char *fmt, va_list ap) { struct sp_data sp; int ret; sp.sp_buf = str; sp.sp_len = 0; sp.sp_size = sz; ret = __printf(fmt, __sputc, &sp, ap); return (ret); } static int __printf(const char *fmt, putc_func_t *putc, void *arg, va_list ap) { char buf[(sizeof(long) * 8) + 1]; char *nbuf; u_long ul; u_int ui; int lflag; int sflag; char *s; int pad; int ret; int c; nbuf = &buf[sizeof buf - 1]; ret = 0; while ((c = *fmt++) != 0) { if (c != '%') { ret += putc(c, arg); continue; } lflag = 0; sflag = 0; pad = 0; reswitch: c = *fmt++; switch (c) { case '#': sflag = 1; goto reswitch; case '%': ret += putc('%', arg); break; case 'c': c = va_arg(ap, int); ret += putc(c, arg); break; case 'd': if (lflag == 0) { ui = (u_int)va_arg(ap, int); if (ui < (int)ui) { ui = -ui; ret += putc('-', arg); } s = __uitoa(nbuf, ui, 10); } else { ul = (u_long)va_arg(ap, long); if (ul < (long)ul) { ul = -ul; ret += putc('-', arg); } s = __ultoa(nbuf, ul, 10); } ret += __puts(s, putc, arg); break; case 'l': lflag = 1; goto reswitch; case 'o': if (lflag == 0) { ui = (u_int)va_arg(ap, u_int); s = __uitoa(nbuf, ui, 8); } else { ul = (u_long)va_arg(ap, u_long); s = __ultoa(nbuf, ul, 8); } ret += __puts(s, putc, arg); break; case 'p': ul = (u_long)va_arg(ap, void *); s = __ultoa(nbuf, ul, 16); ret += __puts("0x", putc, arg); ret += __puts(s, putc, arg); break; case 's': s = va_arg(ap, char *); ret += __puts(s, putc, arg); break; case 'u': if (lflag == 0) { ui = va_arg(ap, u_int); s = __uitoa(nbuf, ui, 10); } else { ul = va_arg(ap, u_long); s = __ultoa(nbuf, ul, 10); } ret += __puts(s, putc, arg); break; case 'x': if (lflag == 0) { ui = va_arg(ap, u_int); s = __uitoa(nbuf, ui, 16); } else { ul = va_arg(ap, u_long); s = __ultoa(nbuf, ul, 16); } if (sflag) ret += __puts("0x", putc, arg); ret += __puts(s, putc, arg); break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': pad = pad * 10 + c - '0'; goto reswitch; default: break; } } return (ret); } static int __sputc(int c, void *arg) { struct sp_data *sp; sp = arg; if (sp->sp_len < sp->sp_size) sp->sp_buf[sp->sp_len++] = c; sp->sp_buf[sp->sp_len] = '\0'; return (1); } static int __puts(const char *s, putc_func_t *putc, void *arg) { const char *p; int ret; ret = 0; for (p = s; *p != '\0'; p++) ret += putc(*p, arg); return (ret); } static char * __uitoa(char *buf, u_int ui, int base) { char *p; p = buf; *p = '\0'; do *--p = digits[ui % base]; while ((ui /= base) != 0); return (p); } static char * __ultoa(char *buf, u_long ul, int base) { char *p; p = buf; *p = '\0'; do *--p = digits[ul % base]; while ((ul /= base) != 0); return (p); }