diff options
author | msmith <msmith@FreeBSD.org> | 1998-08-21 03:17:42 +0000 |
---|---|---|
committer | msmith <msmith@FreeBSD.org> | 1998-08-21 03:17:42 +0000 |
commit | fc79e25bdfb72a2d74aad83d33451c23b0aaf440 (patch) | |
tree | 3e0bb5e950da1db4ccdaf9ebb08680dead391076 | |
parent | e32cf4cb0475337c863f32898a295324b09c2106 (diff) | |
download | FreeBSD-src-fc79e25bdfb72a2d74aad83d33451c23b0aaf440.zip FreeBSD-src-fc79e25bdfb72a2d74aad83d33451c23b0aaf440.tar.gz |
This is the new unified bootstrap, sometimes known previously as the
'three-stage' bootstrap.
There are a number of caveats with the code in its current state:
- The i386 bootstrap only supports booting from a floppy.
- The kernel and kld do not yet know how to deal with the extended
information and module summary passed in.
- PnP-based autodetection and demand loading of modules is not implemented.
- i386 ELF kernel loading is not ready yet.
- The i386 bootstrap is loaded via an ugly blockmap.
On the alpha, both net- and disk-booting (SRM console machines only) is
supported. No blockmaps are used by this code.
Obtained from: Parts from the NetBSD/i386 standalone bootstrap.
-rw-r--r-- | sys/boot/i386/libi386/bootinfo32.c | 197 | ||||
-rw-r--r-- | sys/boot/i386/libi386/bootinfo64.c | 197 | ||||
-rw-r--r-- | sys/boot/ofw/libofw/devicename.c | 232 | ||||
-rw-r--r-- | sys/boot/ofw/libofw/ofw_console.c | 165 | ||||
-rw-r--r-- | sys/boot/ofw/libofw/ofw_module.c | 64 |
5 files changed, 855 insertions, 0 deletions
diff --git a/sys/boot/i386/libi386/bootinfo32.c b/sys/boot/i386/libi386/bootinfo32.c new file mode 100644 index 0000000..8554f2a --- /dev/null +++ b/sys/boot/i386/libi386/bootinfo32.c @@ -0,0 +1,197 @@ +/*- + * Copyright (c) 1998 Michael Smith <msmith@freebsd.org> + * 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. + * + * $Id$ + */ + +#include <sys/reboot.h> +#include <stand.h> +#include "bootstrap.h" + + +/* + * Return a 'boothowto' value corresponding to the kernel arguments in + * (kargs) and any relevant environment variables. + */ +static struct +{ + char *ev; + int mask; +} howto_names[] = { + {"boot_askname", RB_ASKNAME}, + {"boot_userconfig", RB_CONFIG}, + {"boot_ddb", RB_KDB}, + {"boot_gdb", RB_GDB}, + {"boot_single", RB_SINGLE}, + {"boot_verbose", RB_VERBOSE}, + {NULL, 0} +}; + +int +bi_getboothowto(char *kargs) +{ + char *cp; + int howto; + int active; + int i; + + howto = 0; + if (kargs != NULL) { + cp = kargs; + active = 0; + while (*cp != 0) { + if (!active && (*cp == '-')) { + active = 1; + } else if (active) + switch (*cp) { + case 'a': + howto |= RB_ASKNAME; + break; + case 'c': + howto |= RB_CONFIG; + break; + case 'd': + howto |= RB_KDB; + break; + case 'g': + howto |= RB_GDB; + break; + case 'h': + howto |= RB_SERIAL; + break; + case 'r': + howto |= RB_DFLTROOT; + break; + case 's': + howto |= RB_SINGLE; + break; + case 'v': + howto |= RB_VERBOSE; + break; + default: + active = 0; + break; + } + } + cp++; + } + for (i = 0; howto_names[i].ev != NULL; i++) + if (getenv(howto_names[i].ev) != NULL) + howto |= howto_names[i].mask; + if (!strcmp(getenv("console"), "comconsole")) + howto |= RB_SERIAL; + return(howto); +} + +/* + * Copy the environment into the load area starting at (addr). + * Each variable is formatted as <name>=<value>, with a single nul + * separating each variable, and a double nul terminating the environment. + */ +vm_offset_t +bi_copyenv(vm_offset_t addr) +{ + struct env_var *ep; + + /* traverse the environment */ + for (ep = environ; ep != NULL; ep = ep->ev_next) { + vpbcopy(ep->ev_name, addr, strlen(ep->ev_name)); + addr += strlen(ep->ev_name); + vpbcopy("=", addr, 1); + addr++; + if (ep->ev_value != NULL) { + vpbcopy(ep->ev_value, addr, strlen(ep->ev_value)); + addr += strlen(ep->ev_value); + } + vpbcopy("", addr, 1); + addr++; + } + vpbcopy("", addr, 1); + addr++; +} + +/* + * Copy module-related data into the load area, where it can be + * used as a directory for loaded modules. + * + * Module data is presented in a self-describing format. Each datum + * is preceeded by a 16-bit identifier and a 16-bit size field. + * + * Currently, the following data are saved: + * + * MOD_NAME (variable) module name (string) + * MOD_TYPE (variable) module type (string) + * MOD_ADDR sizeof(vm_offset_t) module load address + * MOD_SIZE sizeof(size_t) module size + * MOD_METADATA (variable) type-specific metadata + */ +#define MOD_STR(t, a, s) { \ + u_int32_t ident = (t << 16) + strlen(s) + 1; \ + vpbcopy(&ident, a, sizeof(ident)); \ + a += sizeof(ident); \ + vpbcopy(s, a, strlen(s) + 1); \ + a += strlen(s) + 1; \ +} + +#define MOD_NAME(a, s) MOD_STR(MODINFO_NAME, a, s) +#define MOD_TYPE(a, s) MOD_STR(MODINFO_TYPE, a, s) + +#define MOD_VAR(t, a, s) { \ + u_int32_t ident = (t << 16) + sizeof(s); \ + vpbcopy(&ident, a, sizeof(ident)); \ + a += sizeof(ident); \ + vpbcopy(&s, a, sizeof(s)); \ + a += sizeof(s); \ +} + +#define MOD_ADDR(a, s) MOD_VAR(MODINFO_ADDR, a, s) +#define MOD_SIZE(a, s) MOD_VAR(MODINFO_SIZE, a, s) + +#define MOD_METADATA(a, mm) { \ + u_int32_t ident = ((MODINFO_METADATA | mm->md_type) << 16) + mm->md_size; \ + vpbcopy(&ident, a, sizeof(ident)); \ + a += sizeof(ident); \ + vpbcopy(mm->md_data, a, mm->md_size); \ + a += mm->md_size; \ +} + +vm_offset_t +bi_copymodules(vm_offset_t addr) +{ + struct loaded_module *mp; + struct module_metadata *md; + + /* start with the first module on the list, should be the kernel */ + for (mp = mod_findmodule(NULL, NULL); mp != NULL; mp = mp->m_next) { + + MOD_NAME(addr, mp->m_name); + MOD_TYPE(addr, mp->m_type); + MOD_ADDR(addr, mp->m_addr); + MOD_SIZE(addr, mp->m_size); + for (md = mp->m_metadata; md != NULL; md = md->md_next) + MOD_METADATA(addr, md); + } + return(addr); +} diff --git a/sys/boot/i386/libi386/bootinfo64.c b/sys/boot/i386/libi386/bootinfo64.c new file mode 100644 index 0000000..8554f2a --- /dev/null +++ b/sys/boot/i386/libi386/bootinfo64.c @@ -0,0 +1,197 @@ +/*- + * Copyright (c) 1998 Michael Smith <msmith@freebsd.org> + * 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. + * + * $Id$ + */ + +#include <sys/reboot.h> +#include <stand.h> +#include "bootstrap.h" + + +/* + * Return a 'boothowto' value corresponding to the kernel arguments in + * (kargs) and any relevant environment variables. + */ +static struct +{ + char *ev; + int mask; +} howto_names[] = { + {"boot_askname", RB_ASKNAME}, + {"boot_userconfig", RB_CONFIG}, + {"boot_ddb", RB_KDB}, + {"boot_gdb", RB_GDB}, + {"boot_single", RB_SINGLE}, + {"boot_verbose", RB_VERBOSE}, + {NULL, 0} +}; + +int +bi_getboothowto(char *kargs) +{ + char *cp; + int howto; + int active; + int i; + + howto = 0; + if (kargs != NULL) { + cp = kargs; + active = 0; + while (*cp != 0) { + if (!active && (*cp == '-')) { + active = 1; + } else if (active) + switch (*cp) { + case 'a': + howto |= RB_ASKNAME; + break; + case 'c': + howto |= RB_CONFIG; + break; + case 'd': + howto |= RB_KDB; + break; + case 'g': + howto |= RB_GDB; + break; + case 'h': + howto |= RB_SERIAL; + break; + case 'r': + howto |= RB_DFLTROOT; + break; + case 's': + howto |= RB_SINGLE; + break; + case 'v': + howto |= RB_VERBOSE; + break; + default: + active = 0; + break; + } + } + cp++; + } + for (i = 0; howto_names[i].ev != NULL; i++) + if (getenv(howto_names[i].ev) != NULL) + howto |= howto_names[i].mask; + if (!strcmp(getenv("console"), "comconsole")) + howto |= RB_SERIAL; + return(howto); +} + +/* + * Copy the environment into the load area starting at (addr). + * Each variable is formatted as <name>=<value>, with a single nul + * separating each variable, and a double nul terminating the environment. + */ +vm_offset_t +bi_copyenv(vm_offset_t addr) +{ + struct env_var *ep; + + /* traverse the environment */ + for (ep = environ; ep != NULL; ep = ep->ev_next) { + vpbcopy(ep->ev_name, addr, strlen(ep->ev_name)); + addr += strlen(ep->ev_name); + vpbcopy("=", addr, 1); + addr++; + if (ep->ev_value != NULL) { + vpbcopy(ep->ev_value, addr, strlen(ep->ev_value)); + addr += strlen(ep->ev_value); + } + vpbcopy("", addr, 1); + addr++; + } + vpbcopy("", addr, 1); + addr++; +} + +/* + * Copy module-related data into the load area, where it can be + * used as a directory for loaded modules. + * + * Module data is presented in a self-describing format. Each datum + * is preceeded by a 16-bit identifier and a 16-bit size field. + * + * Currently, the following data are saved: + * + * MOD_NAME (variable) module name (string) + * MOD_TYPE (variable) module type (string) + * MOD_ADDR sizeof(vm_offset_t) module load address + * MOD_SIZE sizeof(size_t) module size + * MOD_METADATA (variable) type-specific metadata + */ +#define MOD_STR(t, a, s) { \ + u_int32_t ident = (t << 16) + strlen(s) + 1; \ + vpbcopy(&ident, a, sizeof(ident)); \ + a += sizeof(ident); \ + vpbcopy(s, a, strlen(s) + 1); \ + a += strlen(s) + 1; \ +} + +#define MOD_NAME(a, s) MOD_STR(MODINFO_NAME, a, s) +#define MOD_TYPE(a, s) MOD_STR(MODINFO_TYPE, a, s) + +#define MOD_VAR(t, a, s) { \ + u_int32_t ident = (t << 16) + sizeof(s); \ + vpbcopy(&ident, a, sizeof(ident)); \ + a += sizeof(ident); \ + vpbcopy(&s, a, sizeof(s)); \ + a += sizeof(s); \ +} + +#define MOD_ADDR(a, s) MOD_VAR(MODINFO_ADDR, a, s) +#define MOD_SIZE(a, s) MOD_VAR(MODINFO_SIZE, a, s) + +#define MOD_METADATA(a, mm) { \ + u_int32_t ident = ((MODINFO_METADATA | mm->md_type) << 16) + mm->md_size; \ + vpbcopy(&ident, a, sizeof(ident)); \ + a += sizeof(ident); \ + vpbcopy(mm->md_data, a, mm->md_size); \ + a += mm->md_size; \ +} + +vm_offset_t +bi_copymodules(vm_offset_t addr) +{ + struct loaded_module *mp; + struct module_metadata *md; + + /* start with the first module on the list, should be the kernel */ + for (mp = mod_findmodule(NULL, NULL); mp != NULL; mp = mp->m_next) { + + MOD_NAME(addr, mp->m_name); + MOD_TYPE(addr, mp->m_type); + MOD_ADDR(addr, mp->m_addr); + MOD_SIZE(addr, mp->m_size); + for (md = mp->m_metadata; md != NULL; md = md->md_next) + MOD_METADATA(addr, md); + } + return(addr); +} diff --git a/sys/boot/ofw/libofw/devicename.c b/sys/boot/ofw/libofw/devicename.c new file mode 100644 index 0000000..310bb94 --- /dev/null +++ b/sys/boot/ofw/libofw/devicename.c @@ -0,0 +1,232 @@ +/*- + * Copyright (c) 1998 Michael Smith <msmith@freebsd.org> + * 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. + * + * $Id$ + */ + +#include <stand.h> +#include <string.h> +#include <sys/disklabel.h> +#include "bootstrap.h" +#include "libalpha.h" + +static int alpha_parsedev(struct alpha_devdesc **dev, char *devspec, 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 +alpha_getdev(void **vdev, char *devspec, char **path) +{ + struct alpha_devdesc **dev = (struct alpha_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 = alpha_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(alpha_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<unit>[s<slice>][<partition>]: + * + */ +static int +alpha_parsedev(struct alpha_devdesc **dev, char *devspec, char **path) +{ + struct alpha_devdesc *idev; + struct devsw *dv; + int i, unit, slice, partition, err; + char *cp, *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 alpha_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.srmdisk.unit = unit; + idev->d_kind.srmdisk.slice = slice; + idev->d_kind.srmdisk.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) + *dev = idev; + return(0); + + fail: + free(idev); + return(err); +} + + +char * +alpha_fmtdev(void *vdev) +{ + struct alpha_devdesc *dev = (struct alpha_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.srmdisk.unit); + if (dev->d_kind.srmdisk.slice > 0) + cp += sprintf(cp, "s%d", dev->d_kind.srmdisk.slice); + if (dev->d_kind.srmdisk.partition >= 0) + cp += sprintf(cp, "%c", dev->d_kind.srmdisk.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 +alpha_setcurrdev(struct env_var *ev, int flags, void *value) +{ + struct alpha_devdesc *ncurr; + int rv; + + if ((rv = alpha_parsedev(&ncurr, value, NULL)) != 0) + return(rv); + free(ncurr); + env_setenv(ev->ev_name, flags | EV_NOHOOK, value, NULL, NULL); + return(0); +} + diff --git a/sys/boot/ofw/libofw/ofw_console.c b/sys/boot/ofw/libofw/ofw_console.c new file mode 100644 index 0000000..535ce31 --- /dev/null +++ b/sys/boot/ofw/libofw/ofw_console.c @@ -0,0 +1,165 @@ +/* $Id$ */ +/* $NetBSD: prom.c,v 1.3 1997/09/06 14:03:58 drochner Exp $ */ + +/* + * Mach Operating System + * Copyright (c) 1992 Carnegie Mellon University + * All Rights Reserved. + * + * 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 Mellon + * the rights to redistribute these changes. + */ + +#include <sys/types.h> + +#include <machine/prom.h> +#include <machine/rpb.h> + +#include "common.h" +#include "bootstrap.h" + +int console; + +static void prom_probe(struct console *cp); +static int prom_init(int); +void prom_putchar(int); +int prom_getchar(void); +static int prom_poll(void); + +struct console promconsole = { + "prom", + "SRM firmware console", + 0, + prom_probe, + prom_init, + prom_putchar, + prom_getchar, + prom_poll, +}; + +void +init_prom_calls() +{ + extern struct prom_vec prom_dispatch_v; + struct rpb *r; + struct crb *c; + char buf[4]; + + r = (struct rpb *)HWRPB_ADDR; + c = (struct crb *)((u_int8_t *)r + r->rpb_crb_off); + + prom_dispatch_v.routine_arg = c->crb_v_dispatch; + prom_dispatch_v.routine = c->crb_v_dispatch->entry_va; + + /* Look for console tty. */ + prom_getenv(PROM_E_TTY_DEV, buf, 4); + console = buf[0] - '0'; +} + +static void +prom_probe(struct console *cp) +{ + init_prom_calls(); + cp->c_flags |= C_PRESENTIN|C_PRESENTOUT; +} + +static int +prom_init(int arg) +{ + return 0; +} + +void +prom_putchar(int c) +{ + prom_return_t ret; + char cbuf; + + cbuf = c; + do { + ret.bits = prom_dispatch(PROM_R_PUTS, console, &cbuf, 1); + } while ((ret.u.retval & 1) == 0); +} + +static int saved_char = -1; + +int +prom_getchar() +{ + prom_return_t ret; + + if (saved_char != -1) { + int c = saved_char; + saved_char = -1; + return c; + } + + for (;;) { + ret.bits = prom_dispatch(PROM_R_GETC, console); + if (ret.u.status == 0 || ret.u.status == 1) + return (ret.u.retval); + } +} + +int +prom_poll() +{ + prom_return_t ret; + + if (saved_char != -1) + return 1; + + ret.bits = prom_dispatch(PROM_R_GETC, console); + if (ret.u.status == 0 || ret.u.status == 1) { + saved_char = ret.u.retval; + return 1; + } + + return 0; +} + +int +prom_getenv(id, buf, len) + int id, len; + char *buf; +{ + prom_return_t ret; + + ret.bits = prom_dispatch(PROM_R_GETENV, id, buf, len-1); + if (ret.u.status & 0x4) + ret.u.retval = 0; + buf[ret.u.retval] = '\0'; + + return (ret.u.retval); +} + +int +prom_open(dev, len) + char *dev; + int len; +{ + prom_return_t ret; + + ret.bits = prom_dispatch(PROM_R_OPEN, dev, len); + if (ret.u.status & 0x4) + return (-1); + else + return (ret.u.retval); +} diff --git a/sys/boot/ofw/libofw/ofw_module.c b/sys/boot/ofw/libofw/ofw_module.c new file mode 100644 index 0000000..a08fc85 --- /dev/null +++ b/sys/boot/ofw/libofw/ofw_module.c @@ -0,0 +1,64 @@ +/*- + * Copyright (c) 1998 Michael Smith <msmith@freebsd.org> + * 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. + * + * $Id$ + */ + +/* + * alpha-specific module functionality. + * + */ + +#include <stand.h> +#include <string.h> + +#include "bootstrap.h" +#include "libalpha.h" + +/* + * Look for a method and having found it, boot the kernel module. + */ +int +alpha_boot(void) +{ + int i; + + for (i = 0; module_formats[i] != NULL; i++) { + if (((loaded_modules->m_flags & MF_FORMATMASK) == module_formats[i]->l_format) && + (module_formats[i]->l_exec != NULL)) { + return((module_formats[i]->l_exec)(loaded_modules)); + } + } +} + +/* + * Use voodoo to load modules required by current hardware. + */ +int +alpha_autoload(void) +{ + /* XXX use PnP to locate stuff here */ + return(0); +} |