diff options
author | Miod Vallat <miod@cvs.openbsd.org> | 2010-02-17 21:25:50 +0000 |
---|---|---|
committer | Miod Vallat <miod@cvs.openbsd.org> | 2010-02-17 21:25:50 +0000 |
commit | fab147de8183bc711673520efc974d172c1e2050 (patch) | |
tree | 68dc90043fdbae636bc6bdc0a580b97f85dcc70f | |
parent | f063e6044f09e58905b6d171b45e72679045f203 (diff) |
If PMON has loaded an initrd binary, and this binary looks like a valid
ELF image, assume it's the kernel and try to boot it immediately.
This allows a Gdium system with both the bootloader and the kernel image on
an ext2fs partition, with `al' pointing to the bootblocks and `rd' pointing
to the kernel in PMON environment, to boot a kernel with proper kernel
symbols, for the first time.
(please don't get me started on how reliable `load -k' is on the Gdium)
Bump bootblocks version to 0.2.
-rw-r--r-- | sys/arch/loongson/stand/boot/Makefile.inc | 4 | ||||
-rw-r--r-- | sys/arch/loongson/stand/boot/conf.c | 20 | ||||
-rw-r--r-- | sys/arch/loongson/stand/boot/libsa.h | 24 | ||||
-rw-r--r-- | sys/arch/loongson/stand/boot/machdep.c | 91 | ||||
-rw-r--r-- | sys/arch/loongson/stand/boot/rd.c | 133 |
5 files changed, 236 insertions, 36 deletions
diff --git a/sys/arch/loongson/stand/boot/Makefile.inc b/sys/arch/loongson/stand/boot/Makefile.inc index 751bf25a1df..804b2e456bf 100644 --- a/sys/arch/loongson/stand/boot/Makefile.inc +++ b/sys/arch/loongson/stand/boot/Makefile.inc @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile.inc,v 1.1 2010/02/17 19:51:30 miod Exp $ +# $OpenBSD: Makefile.inc,v 1.2 2010/02/17 21:25:49 miod Exp $ .include "${.CURDIR}/../Makefile.inc" @@ -18,7 +18,7 @@ AFLAGS+= ${SAABI} .PATH: ${BOOTDIR} SRCS= start.S -SRCS+= conf.c cons.c dev.c devopen.c exec.c machdep.c +SRCS+= conf.c cons.c dev.c devopen.c exec.c machdep.c rd.c .PATH: ${S}/arch/loongson/loongson SRCS+= pmon.c pmon32.S diff --git a/sys/arch/loongson/stand/boot/conf.c b/sys/arch/loongson/stand/boot/conf.c index 2562b38c4ec..32d41b78545 100644 --- a/sys/arch/loongson/stand/boot/conf.c +++ b/sys/arch/loongson/stand/boot/conf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: conf.c,v 1.2 2010/02/16 21:28:39 miod Exp $ */ +/* $OpenBSD: conf.c,v 1.3 2010/02/17 21:25:49 miod Exp $ */ /* * Copyright (c) 1982, 1986, 1990, 1993 @@ -39,7 +39,7 @@ #include <lib/libsa/ufs.h> #include <lib/libsa/cd9660.h> -const char version[] = "0.1"; +const char version[] = "0.2"; #if 0 /* network code not compiled in */ int debug = 0; #endif @@ -48,6 +48,9 @@ int debug = 0; * Device configuration */ struct devsw devsw[] = { + /* initrd */ + { "rd", rd_iostrategy, rd_ioopen, rd_ioclose, noioctl }, + /* ATA storage device */ { "wd", pmon_iostrategy, pmon_ioopen, pmon_ioclose, noioctl } }; int ndevs = NENTS(devsw); @@ -56,10 +59,15 @@ int ndevs = NENTS(devsw); * Filesystem configuration */ struct fs_ops file_system[] = { - { ufs_open, ufs_close, ufs_read, ufs_write, ufs_seek, - ufs_stat, ufs_readdir }, - { cd9660_open, cd9660_close, cd9660_read, cd9660_write, cd9660_seek, - cd9660_stat, cd9660_readdir } + /* initrd ``filesystem'' */ + { rdfs_open, rdfs_close, rdfs_read, rdfs_write, + rdfs_seek, rdfs_stat, rdfs_readdir }, + /* ufs filesystem */ + { ufs_open, ufs_close, ufs_read, ufs_write, + ufs_seek, ufs_stat, ufs_readdir }, + /* cd9660 filesystem - in case a cd image is dd'ed on non USB media */ + { cd9660_open, cd9660_close, cd9660_read, cd9660_write, + cd9660_seek, cd9660_stat, cd9660_readdir } }; int nfsys = NENTS(file_system); diff --git a/sys/arch/loongson/stand/boot/libsa.h b/sys/arch/loongson/stand/boot/libsa.h index f0f87ac873d..c727d7985e4 100644 --- a/sys/arch/loongson/stand/boot/libsa.h +++ b/sys/arch/loongson/stand/boot/libsa.h @@ -1,4 +1,4 @@ -/* $OpenBSD: libsa.h,v 1.2 2010/02/16 21:28:39 miod Exp $ */ +/* $OpenBSD: libsa.h,v 1.3 2010/02/17 21:25:49 miod Exp $ */ /* * Copyright (c) 2010 Miodrag Vallat. @@ -20,6 +20,9 @@ #define DEFAULT_KERNEL_ADDRESS 0 +/* where the initrd is loaded */ +#define INITRD_BASE PHYS_TO_CKSEG0(0x04000000) + /* * MD interfaces for MI boot(9) */ @@ -42,6 +45,25 @@ int pmon_iostrategy(void *, int, daddr_t, size_t, void *, size_t *); int pmon_ioopen(struct open_file *, ...); int pmon_ioclose(struct open_file *); +/* + * INITRD I/O + */ +int rd_iostrategy(void *, int, daddr_t, size_t, void *, size_t *); +int rd_ioopen(struct open_file *, ...); +int rd_ioclose(struct open_file *); +int rd_isvalid(void); + +/* + * INITRD ``filesystem'' + */ +int rdfs_open(char *path, struct open_file *f); +int rdfs_close(struct open_file *f); +int rdfs_read(struct open_file *f, void *buf, size_t size, size_t *resid); +int rdfs_write(struct open_file *f, void *buf, size_t size, size_t *resid); +off_t rdfs_seek(struct open_file *f, off_t offset, int where); +int rdfs_stat(struct open_file *f, struct stat *sb); +int rdfs_readdir(struct open_file *f, char *name); + extern int pmon_argc; extern int32_t *pmon_argv; extern int32_t *pmon_envp; diff --git a/sys/arch/loongson/stand/boot/machdep.c b/sys/arch/loongson/stand/boot/machdep.c index 46f529be831..05c74f5c0c2 100644 --- a/sys/arch/loongson/stand/boot/machdep.c +++ b/sys/arch/loongson/stand/boot/machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: machdep.c,v 1.2 2010/02/16 21:28:39 miod Exp $ */ +/* $OpenBSD: machdep.c,v 1.3 2010/02/17 21:25:49 miod Exp $ */ /* * Copyright (c) 2010 Miodrag Vallat. @@ -48,6 +48,13 @@ #include <machine/pmon.h> #include <stand/boot/cmd.h> +void gdium_abort(void); +int is_gdium; +int boot_rd; + +extern int bootprompt; +extern char *kernelfile; + /* * Console */ @@ -134,6 +141,15 @@ devboot(dev_t dev, char *path) int i; /* + * If we are booting the initrd image, things are easy... + */ + + if (dev != 0) { + strlcpy(path, "rd0a", BOOTDEVLEN); + return; + } + + /* * First, try to figure where we have been loaded from; we'll assume * the default device to load the kernel from is the same. * @@ -203,7 +219,7 @@ devboot(dev_t dev, char *path) } /* - * Ugly clock routines + * Ugly (lack of) clock routines */ time_t @@ -221,44 +237,65 @@ machdep() { const char *envvar; + /* + * Since we can't have non-blocking input, we will try to + * autoload the kernel pointed to by the `bsd' environment + * variable, and fallback to interactive mode if the variable + * is empty or the load fails. + */ + + if (boot_rd == 0) { + envvar = pmon_getenv("bsd"); + if (envvar != NULL) { + bootprompt = 0; + kernelfile = (char *)envvar; + } else { + if (is_gdium) + gdium_abort(); + } + } +} + +int +main() +{ + const char *envvar; + cninit(); /* * Figure out whether we are running on a Gdium system, which - * has an horribly castrated PMON. If we do, return immediately. + * has an horribly castrated PMON. If we do, the best we can do + * is boot an initrd image. */ envvar = pmon_getenv("Version"); - if (envvar != NULL && strncmp(envvar, "Gdium", 5) == 0) { - /* Here's a nickel, kid. Get yourself a better firmware */ - printf("\n\nSorry, OpenBSD boot blocks do not work on Gdium, " - "because of dire firmware limitations.\n" - "Also, the firmware has reset the USB controller so you " - "will need to power cycle.\n" - "We would apologize for this incovenience, but we have " - "no control about the firmware of your machine.\n\n"); - _rtt(); - } + if (envvar != NULL && strncmp(envvar, "Gdium", 5) == 0) + is_gdium = 1; /* - * Since we can't have non-blocking input, we will try to - * autoload the kernel pointed to by the `bsd' environment - * variable, and fallback to interactive mode if the variable - * is empty or the load fails. + * Check if we have a valid initrd loaded. */ - envvar = pmon_getenv("bsd"); - if (envvar != NULL) { - extern int bootprompt; - extern char *kernelfile; + envvar = pmon_getenv("rd"); + if (envvar != NULL && *envvar != '\0') + boot_rd = rd_isvalid(); + if (boot_rd != 0) bootprompt = 0; - kernelfile = (char *)envvar; - } + + boot(boot_rd); + return 0; } -int -main() +void +gdium_abort() { - boot(0); - return 0; + /* Here's a nickel, kid. Get yourself a better firmware */ + printf("\n\nSorry, OpenBSD boot blocks do not work on Gdium, " + "because of dire firmware limitations.\n" + "Also, the firmware has reset the USB controller so you " + "will need to power cycle.\n" + "We would apologize for this incovenience, but we have " + "no control about the firmware of your machine.\n\n"); + _rtt(); } diff --git a/sys/arch/loongson/stand/boot/rd.c b/sys/arch/loongson/stand/boot/rd.c new file mode 100644 index 00000000000..5a00bfd4b76 --- /dev/null +++ b/sys/arch/loongson/stand/boot/rd.c @@ -0,0 +1,133 @@ +/* $OpenBSD: rd.c,v 1.1 2010/02/17 21:25:49 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. + */ + +#include <sys/types.h> +#include "libsa.h" +#include <machine/cpu.h> +#include <machine/param.h> +#include <sys/exec_elf.h> + +static off_t rdoffs; + +/* + * INITRD I/O + */ + +int +rd_iostrategy(void *f, int rw, daddr_t dblk, size_t size, void *buf, + size_t *rsize) +{ + /* never invoked directly */ + return ENXIO; +} + +int +rd_ioopen(struct open_file *f, ...) +{ + return 0; +} + +int +rd_ioclose(struct open_file *f) +{ + return 0; +} + +int +rd_isvalid() +{ + Elf64_Ehdr *elf64 = (Elf64_Ehdr *)INITRD_BASE; + + if (memcmp(elf64->e_ident, ELFMAG, SELFMAG) != 0 || + elf64->e_ident[EI_CLASS] != ELFCLASS64 || + elf64->e_ident[EI_DATA] != ELFDATA2LSB || + elf64->e_type != ET_EXEC || elf64->e_machine != EM_MIPS) + return 0; + + return 1; +} + +/* + * INITRD filesystem + */ +int +rdfs_open(char *path, struct open_file *f) +{ + if (f->f_dev->dv_open == rd_ioopen) { + rdoffs = 0; + return 0; + } + + return EINVAL; +} + +int +rdfs_close(struct open_file *f) +{ + return 0; +} + +int +rdfs_read(struct open_file *f, void *buf, size_t size, size_t *resid) +{ + if (size != 0) { + bcopy((void *)(INITRD_BASE + rdoffs), buf, size); + rdoffs += size; + } + *resid = 0; + + return 0; +} + +int +rdfs_write(struct open_file *f, void *buf, size_t size, size_t *resid) +{ + return EIO; +} + +off_t +rdfs_seek(struct open_file *f, off_t offset, int where) +{ + switch (where) { + case 0: /* SEEK_SET */ + rdoffs = offset; + break; + case 1: /* SEEK_CUR */ + rdoffs += offset; + break; + default: + errno = EIO; + return -1; + } + + return rdoffs; +} + +int +rdfs_stat(struct open_file *f, struct stat *sb) +{ + return EIO; +} + +#ifndef NO_READDIR +int +rdfs_readdir(struct open_file *f, char *path) +{ + return EIO; +} +#endif |