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 | 8adeb775c43d4c2ae76cce40837a3953af6abc83 (patch) | |
tree | ec778e5f3903abe2dbb59959c0fd8398c99c145b /sys/boot/alpha/common | |
parent | 335c4be5b17816baac6b70d4d0b3132925de858d (diff) | |
download | FreeBSD-src-8adeb775c43d4c2ae76cce40837a3953af6abc83.zip FreeBSD-src-8adeb775c43d4c2ae76cce40837a3953af6abc83.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.
Diffstat (limited to 'sys/boot/alpha/common')
-rw-r--r-- | sys/boot/alpha/common/gensetdefs.c | 313 | ||||
-rw-r--r-- | sys/boot/alpha/common/main.c | 178 | ||||
-rw-r--r-- | sys/boot/alpha/common/setdef0.c | 49 | ||||
-rw-r--r-- | sys/boot/alpha/common/setdef1.c | 41 |
4 files changed, 581 insertions, 0 deletions
diff --git a/sys/boot/alpha/common/gensetdefs.c b/sys/boot/alpha/common/gensetdefs.c new file mode 100644 index 0000000..b72f78b --- /dev/null +++ b/sys/boot/alpha/common/gensetdefs.c @@ -0,0 +1,313 @@ +/*- + * Copyright (c) 1997 John D. Polstra. + * 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: gensetdefs.c,v 1.2 1998/06/14 13:44:44 dfr Exp $ + */ + +#include <sys/types.h> +#include <elf.h> + +#include <err.h> +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#define HASHSIZE 1009u /* Number of hash chains. */ +#define PREFIX ".set." /* Section name prefix for linker sets. */ + +/* One entry in the hash table. */ +typedef struct hashent { + struct hashent *next; /* Next entry with the same hash. */ + char *name; /* Name of the linker set. */ + size_t size; /* Size in bytes. */ +} hashent; + +/* Allocate storage for "count" objects of type "type". */ +#define NEW(type, count) ((type *) xmalloc((count) * sizeof(type))) + +static hashent *hashtab[HASHSIZE]; /* Hash chain heads. */ + +static void enter(const char *, size_t); +static int enter_sets(const char *); +static unsigned int hash(const char *); +static hashent *merge(void); +static int my_byte_order(void); +static void *xmalloc(size_t); +static char *xstrdup(const char *); + +/* + * This is a special-purpose program to generate the linker set definitions + * needed when building an ELF kernel. Its arguments are the names of + * ELF object files. It scans the section names of the object files, + * building a table of those that begin with ".set.", which represent + * linker sets. Finally, for each set "foo" with "count" elements, it + * writes a line "DEFINE_SET(foo, count);" to the standard output. + */ +int +main(int argc, char **argv) +{ + int i; + int status = EXIT_SUCCESS; + hashent *list; + + for (i = 1; i < argc; i++) + if (enter_sets(argv[i]) == -1) + status = EXIT_FAILURE; + + list = merge(); + while (list != NULL) { + hashent *next; + + printf("DEFINE_SET(%s, %lu);\n", list->name, + (unsigned long) (list->size / sizeof (void *))); + next = list->next; + free(list->name); + free(list); + list = next; + } + + return (status); +} + +/* + * Enter the given string into the hash table, if it is not already there. + * Each hash chain is kept sorted, so that it will be easy to merge the + * chains to get a single sorted list. + */ +static void +enter(const char *name, size_t size) +{ + int c = 0; + hashent *entp; + hashent **linkp; + hashent *newp; + + linkp = &hashtab[hash(name) % HASHSIZE]; + while ((entp = *linkp) != NULL && (c = strcmp(name, entp->name)) > 0) + linkp = &entp->next; + + if (entp == NULL || c != 0) { /* Not found; create a new entry. */ + newp = NEW(hashent, 1); + newp->name = xstrdup(name); + newp->size = 0; + newp->next = entp; + *linkp = newp; + entp = newp; + } + + entp->size += size; +} + +/* + * Return a hash value for the given string. + */ +static unsigned int +hash(const char *s) +{ + unsigned char ch; + unsigned int h = 0; + + while((ch = *s) != '\0') { + h = 9*h + ch; + s++; + } + return (h); +} + +/* + * Enter the linker sets from the given ELF object file. Returns 0 on + * success, or -1 if an error occurred. + */ +static int +enter_sets(const char *filename) +{ + int i; + FILE *iop; + Elf64_Shdr *shdr; + char *shstr; + Elf64_Ehdr ehdr; + + if ((iop = fopen(filename, "rb")) == NULL) { + warn("%s", filename); + return (-1); + } + if (fread(&ehdr, sizeof ehdr, 1, iop) != 1 || + ehdr.e_ident[EI_MAG0] != ELFMAG0 || + ehdr.e_ident[EI_MAG1] != ELFMAG1 || + ehdr.e_ident[EI_MAG2] != ELFMAG2 || + ehdr.e_ident[EI_MAG3] != ELFMAG3) { + warnx("%s: not an ELF file", filename); + fclose(iop); + return (-1); + } + if (ehdr.e_ident[EI_VERSION] != EV_CURRENT) { + warnx("%s: unsupported ELF version", filename); + fclose(iop); + return (-1); + } + if (ehdr.e_ident[EI_DATA] != my_byte_order()) { + warnx("%s: unsupported byte order", filename); + fclose(iop); + return (-1); + } + if (ehdr.e_shoff == 0) { + warnx("%s: no section table", filename); + fclose(iop); + return (-1); + } + if (ehdr.e_shstrndx == SHN_UNDEF) { + warnx("%s: no section name string table", filename); + fclose(iop); + return (-1); + } + + shdr = NEW(Elf64_Shdr, ehdr.e_shnum); + if (fseek(iop, ehdr.e_shoff, SEEK_SET) == -1) { + warn("%s", filename); + free(shdr); + fclose(iop); + return (-1); + } + if (fread(shdr, sizeof *shdr, ehdr.e_shnum, iop) != ehdr.e_shnum) { + warnx("%s: truncated section table", filename); + free(shdr); + fclose(iop); + return (-1); + } + + shstr = NEW(char, shdr[ehdr.e_shstrndx].sh_size); + if (fseek(iop, shdr[ehdr.e_shstrndx].sh_offset, SEEK_SET) == -1) { + warn("%s", filename); + free(shstr); + free(shdr); + fclose(iop); + return (-1); + } + if (fread(shstr, sizeof *shstr, shdr[ehdr.e_shstrndx].sh_size, iop) != + shdr[ehdr.e_shstrndx].sh_size) { + warnx("%s: truncated section name string table", filename); + free(shstr); + free(shdr); + fclose(iop); + return (-1); + } + + for (i = 1; i < ehdr.e_shnum; i++) { + const char *name = shstr + shdr[i].sh_name; + + if (strncmp(name, PREFIX, sizeof (PREFIX) - 1) == 0) + enter(name + sizeof (PREFIX) - 1, shdr[i].sh_size); + } + + free(shstr); + free(shdr); + fclose(iop); + return (0); +} + +/* + * Destructively merge all the sorted hash chains into a single sorted + * list, and return a pointer to its first element. + */ +static hashent * +merge(void) +{ + unsigned int numchains = HASHSIZE; + + while (numchains > 1) { /* More merging to do. */ + unsigned int lo = 0; + /* + * Merge chains pairwise from the outside in, halving the + * number of chains. + */ + while (numchains - lo >= 2) { + hashent **linkp = &hashtab[lo]; + hashent *l1 = hashtab[lo++]; + hashent *l2 = hashtab[--numchains]; + + while (l1 != NULL && l2 != NULL) { + if (strcmp(l1->name, l2->name) < 0) { + *linkp = l1; + linkp = &l1->next; + l1 = l1->next; + } else { + *linkp = l2; + linkp = &l2->next; + l2 = l2->next; + } + } + *linkp = l1==NULL ? l2 : l1; + } + } + + return (hashtab[0]); +} + +/* + * Determine the host byte order. + */ +static int +my_byte_order(void) +{ + static unsigned short s = 0xbbaa; + int byte0; + + byte0 = *(unsigned char *)&s; + if (byte0 == 0xaa) + return (ELFDATA2LSB); + else if (byte0 == 0xbb) + return (ELFDATA2MSB); + else + return (ELFDATANONE); +} + +/* + * Allocate a chunk of memory and return a pointer to it. Die if the + * malloc fails. + */ +static void * +xmalloc(size_t size) +{ + void *p; + + p = malloc(size); + if (p == NULL) + err(EXIT_FAILURE, "malloc"); + return (p); +} + +/* + * Duplicate a string and return a pointer to the copy. Die if there is + * not enough memory. + */ +static char * +xstrdup(const char *s) +{ + int size; + + size = strlen(s) + 1; + return (memcpy(xmalloc(size), s, size)); +} diff --git a/sys/boot/alpha/common/main.c b/sys/boot/alpha/common/main.c new file mode 100644 index 0000000..c4d8d71 --- /dev/null +++ b/sys/boot/alpha/common/main.c @@ -0,0 +1,178 @@ +/*- + * Copyright (c) 1998 Michael Smith <msmith@freebsd.org> + * Copyright (c) 1998 Doug Rabson <dfr@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/param.h> +#include <machine/rpb.h> +#include <machine/prom.h> +#include "bootstrap.h" +#include "libalpha/libalpha.h" + +extern char bootprog_name[], bootprog_rev[], bootprog_date[], bootprog_maker[]; + +struct alpha_devdesc currdev; /* our current device */ +struct arch_switch archsw; /* MI/MD interface boundary */ + +extern char end[]; +extern void OSFpal(void); +extern void halt(void); + +unsigned long +memsize() +{ + struct rpb *hwrpb = (struct rpb *)HWRPB_ADDR; + struct mddt *mddtp; + struct mddt_cluster *memc; + int i; + unsigned long total = 0; + + mddtp = (struct mddt *)(((caddr_t)hwrpb) + hwrpb->rpb_memdat_off); + for (i = 0; i < mddtp->mddt_cluster_cnt; i++) { + memc = &mddtp->mddt_clusters[i]; + total += memc->mddt_pg_cnt << PAGE_SHIFT; + } + return total; +} + +void +main(void) +{ + int i; + char bootfile[128]; + + /* + * Initialise the heap as early as possible. Once this is done, alloc() is usable. + * The stack is buried inside us, so this is safe + */ + setheap((void *)end, (void *)0x20040000); + + + /* + * XXX Chicken-and-egg problem; we want to have console output early, but some + * console attributes may depend on reading from eg. the boot device, which we + * can't do yet. + * + * We can use printf() etc. once this is done. + */ + cons_probe(); + + /* switch to OSF pal code. */ + OSFpal(); + + /* + * March through the device switch probing for things. + */ + for (i = 0; devsw[i] != NULL; i++) + if (devsw[i]->dv_init != NULL) + (devsw[i]->dv_init)(); + + printf("\n"); + printf(">> %s, Revision %s\n", bootprog_name, bootprog_rev); + printf(">> (%s, %s)\n", bootprog_maker, bootprog_date); + printf(">> Memory: %ld k\n", memsize() / 1024); + + /* We're booting from an SRM disk, try to spiff this */ + currdev.d_dev = devsw[0]; /* XXX presumes that biosdisk is first in devsw */ + currdev.d_type = currdev.d_dev->dv_type; + currdev.d_kind.srmdisk.unit = 0; + currdev.d_kind.srmdisk.slice = -1; /* XXX should be able to detect this, default to autoprobe */ + currdev.d_kind.srmdisk.partition = 0; /* default to 'a' */ + + /* Create alpha-specific variables */ + prom_getenv(PROM_E_BOOTED_FILE, bootfile, sizeof(bootfile)); + if (bootfile[0]) + setenv("bootfile", bootfile, 1); + env_setenv("currdev", EV_VOLATILE, alpha_fmtdev(&currdev), alpha_setcurrdev, env_nounset); + env_setenv("loaddev", EV_VOLATILE, alpha_fmtdev(&currdev), env_noset, env_nounset); + setenv("LINES", "24", 1); /* optional */ + + archsw.arch_autoload = alpha_autoload; + archsw.arch_boot = alpha_boot; + archsw.arch_getdev = alpha_getdev; + + /* + * XXX should these be in the MI source? + */ + source("/boot/boot.config"); + interact(); /* doesn't return */ +} + +COMMAND_SET(reboot, "reboot", "reboot the system", command_reboot); + +static int +command_reboot(int argc, char *argv[]) +{ + + printf("Rebooting...\n"); + delay(1000000); + reboot(); + /* Note: we shouldn't get to this point! */ + panic("Reboot failed!"); + exit(0); +} + +COMMAND_SET(halt, "halt", "halt the system", command_halt); + +static int +command_halt(int argc, char *argv[]) +{ + halt(); /* never returns */ + return(CMD_OK); +} + +#if 0 + +COMMAND_SET(stack, "stack", "show stack usage", command_stack); + +static int +command_stack(int argc, char *argv[]) +{ + char *cp; + + for (cp = &stackbase; cp < &stacktop; cp++) + if (*cp != 0) + break; + + printf("%d bytes of stack used\n", &stacktop - cp); + return(CMD_OK); +} + +#endif + +COMMAND_SET(heap, "heap", "show heap usage", command_heap); + +static int +command_heap(int argc, char *argv[]) +{ + printf("heap base at %p, top at %p, used %ld\n", end, sbrk(0), sbrk(0) - end); + return(CMD_OK); +} diff --git a/sys/boot/alpha/common/setdef0.c b/sys/boot/alpha/common/setdef0.c new file mode 100644 index 0000000..b41276d --- /dev/null +++ b/sys/boot/alpha/common/setdef0.c @@ -0,0 +1,49 @@ +/*- + * Copyright (c) 1997 John D. Polstra + * 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: setdef0.c,v 1.1 1998/06/10 10:53:12 dfr Exp $ + */ + +#ifdef __ELF__ + +#include <sys/param.h> +#include <sys/kernel.h> + +/* + * DEFINE_SET creates the section and label for a set, and emits the + * count word at the front of it. + */ +#define DEFINE_SET(set, count) \ + __asm__(".section .set." #set ",\"aw\""); \ + __asm__(".globl " #set); \ + __asm__(".type " #set ",@object"); \ + __asm__(".p2align 3"); \ + __asm__(#set ":"); \ + __asm__(".quad " #count); \ + __asm__(".previous") + +#include "setdefs.h" /* Contains a `DEFINE_SET' for each set */ + +#endif /* __ELF__ */ diff --git a/sys/boot/alpha/common/setdef1.c b/sys/boot/alpha/common/setdef1.c new file mode 100644 index 0000000..659618a --- /dev/null +++ b/sys/boot/alpha/common/setdef1.c @@ -0,0 +1,41 @@ +/*- + * Copyright (c) 1997 John D. Polstra + * 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: setdef1.c,v 1.1 1998/06/10 10:53:13 dfr Exp $ + */ + +#ifdef __ELF__ + +/* + * DEFINE_SET emits the NULL terminator for a set. + */ +#define DEFINE_SET(set, count) \ + __asm__(".section .set." #set ",\"aw\""); \ + __asm__(".quad 0"); \ + __asm__(".previous") + +#include "setdefs.h" /* Contains a `DEFINE_SET' for each set */ + +#endif /* __ELF__ */ |