summaryrefslogtreecommitdiffstats
path: root/sys/boot
diff options
context:
space:
mode:
authorRenato Botelho <renato@netgate.com>2016-01-25 08:56:15 -0200
committerRenato Botelho <renato@netgate.com>2016-01-25 08:56:15 -0200
commiteb84e0723f3b4bc5e40024f66fe21c14b09e9ec4 (patch)
treefec6b99d018e13f1fccbe31478aaf29a28a55642 /sys/boot
parentc50df8e1b90c4f9b8bbffa592477c129854776ce (diff)
parent94b1bbbd44bd88b6db1c00d795cdf7675b3ae254 (diff)
downloadFreeBSD-src-eb84e0723f3b4bc5e40024f66fe21c14b09e9ec4.zip
FreeBSD-src-eb84e0723f3b4bc5e40024f66fe21c14b09e9ec4.tar.gz
Merge remote-tracking branch 'origin/stable/10' into devel
Diffstat (limited to 'sys/boot')
-rw-r--r--sys/boot/common/bootstrap.h7
-rw-r--r--sys/boot/common/load_elf.c265
-rw-r--r--sys/boot/common/load_elf_obj.c9
-rw-r--r--sys/boot/common/module.c11
-rw-r--r--sys/boot/efi/boot1/Makefile14
-rw-r--r--sys/boot/efi/boot1/boot1.c31
-rw-r--r--sys/boot/efi/include/efierr.h3
-rw-r--r--sys/boot/efi/libefi/Makefile1
-rw-r--r--sys/boot/efi/libefi/efi_console.c420
-rw-r--r--sys/boot/efi/loader/Makefile3
-rw-r--r--sys/boot/efi/loader/bootinfo.c7
-rw-r--r--sys/boot/efi/loader/copy.c2
-rw-r--r--sys/boot/efi/loader/main.c99
-rw-r--r--sys/boot/fdt/dts/arm/beaglebone-black.dts4
-rw-r--r--sys/boot/fdt/dts/arm/beaglebone.dts2
-rw-r--r--sys/boot/fdt/fdt_loader_cmd.c2
-rw-r--r--sys/boot/ficl/amd64/sysdep.c2
-rw-r--r--sys/boot/forth/beastie.4th6
-rw-r--r--sys/boot/forth/beastie.4th.85
-rw-r--r--sys/boot/forth/loader.4th3
-rw-r--r--sys/boot/forth/loader.conf.55
-rw-r--r--sys/boot/forth/support.4th27
-rw-r--r--sys/boot/i386/libi386/Makefile3
-rw-r--r--sys/boot/i386/libi386/bootinfo64.c45
-rw-r--r--sys/boot/i386/libi386/elf64_freebsd.c2
-rw-r--r--sys/boot/i386/libi386/libi386.h3
-rw-r--r--sys/boot/i386/libi386/multiboot.c425
-rw-r--r--sys/boot/i386/libi386/multiboot.h225
-rw-r--r--sys/boot/i386/libi386/multiboot_tramp.S51
-rw-r--r--sys/boot/i386/loader/conf.c4
-rw-r--r--sys/boot/i386/zfsboot/zfsboot.c6
-rw-r--r--sys/boot/ia64/efi/Makefile1
-rw-r--r--sys/boot/libstand32/Makefile4
-rw-r--r--sys/boot/pc98/boot2/boot2.c2
-rw-r--r--sys/boot/pc98/libpc98/biosdisk.c6
-rw-r--r--sys/boot/uboot/common/main.c55
-rw-r--r--sys/boot/uboot/lib/copy.c22
37 files changed, 1551 insertions, 231 deletions
diff --git a/sys/boot/common/bootstrap.h b/sys/boot/common/bootstrap.h
index c9bcc52..de77c7b 100644
--- a/sys/boot/common/bootstrap.h
+++ b/sys/boot/common/bootstrap.h
@@ -231,9 +231,9 @@ int mod_load(char *name, struct mod_depend *verinfo, int argc, char *argv[]);
int mod_loadkld(const char *name, int argc, char *argv[]);
struct preloaded_file *file_alloc(void);
-struct preloaded_file *file_findfile(char *name, char *type);
+struct preloaded_file *file_findfile(const char *name, const char *type);
struct file_metadata *file_findmetadata(struct preloaded_file *fp, int type);
-struct preloaded_file *file_loadraw(char *name, char *type);
+struct preloaded_file *file_loadraw(char *name, char *type, int insert);
void file_discard(struct preloaded_file *fp);
void file_addmetadata(struct preloaded_file *fp, int type, size_t size, void *p);
int file_addmodule(struct preloaded_file *fp, char *modname, int version,
@@ -257,6 +257,9 @@ int __elfN(obj_loadfile)(char *filename, u_int64_t dest,
int __elfN(reloc)(struct elf_file *ef, symaddr_fn *symaddr,
const void *reldata, int reltype, Elf_Addr relbase,
Elf_Addr dataaddr, void *data, size_t len);
+int __elfN(loadfile_raw)(char *filename, u_int64_t dest,
+ struct preloaded_file **result, int multiboot);
+int __elfN(load_modmetadata)(struct preloaded_file *fp, u_int64_t dest);
#endif
/*
diff --git a/sys/boot/common/load_elf.c b/sys/boot/common/load_elf.c
index edbad05..200a29c 100644
--- a/sys/boot/common/load_elf.c
+++ b/sys/boot/common/load_elf.c
@@ -76,7 +76,8 @@ static int __elfN(loadimage)(struct preloaded_file *mp, elf_file_t ef, u_int64_t
static int __elfN(lookup_symbol)(struct preloaded_file *mp, elf_file_t ef, const char* name, Elf_Sym* sym);
static int __elfN(reloc_ptr)(struct preloaded_file *mp, elf_file_t ef,
Elf_Addr p, void *val, size_t len);
-static int __elfN(parse_modmetadata)(struct preloaded_file *mp, elf_file_t ef);
+static int __elfN(parse_modmetadata)(struct preloaded_file *mp, elf_file_t ef,
+ Elf_Addr p_start, Elf_Addr p_end);
static symaddr_fn __elfN(symaddr);
static char *fake_modname(const char *name);
@@ -85,6 +86,61 @@ const char *__elfN(moduletype) = "elf module";
u_int64_t __elfN(relocation_offset) = 0;
+static int
+__elfN(load_elf_header)(char *filename, elf_file_t ef)
+{
+ ssize_t bytes_read;
+ Elf_Ehdr *ehdr;
+ int err;
+
+ /*
+ * Open the image, read and validate the ELF header
+ */
+ if (filename == NULL) /* can't handle nameless */
+ return (EFTYPE);
+ if ((ef->fd = open(filename, O_RDONLY)) == -1)
+ return (errno);
+ ef->firstpage = malloc(PAGE_SIZE);
+ if (ef->firstpage == NULL) {
+ close(ef->fd);
+ return (ENOMEM);
+ }
+ bytes_read = read(ef->fd, ef->firstpage, PAGE_SIZE);
+ ef->firstlen = (size_t)bytes_read;
+ if (bytes_read < 0 || ef->firstlen <= sizeof(Elf_Ehdr)) {
+ err = EFTYPE; /* could be EIO, but may be small file */
+ goto error;
+ }
+ ehdr = ef->ehdr = (Elf_Ehdr *)ef->firstpage;
+
+ /* Is it ELF? */
+ if (!IS_ELF(*ehdr)) {
+ err = EFTYPE;
+ goto error;
+ }
+ if (ehdr->e_ident[EI_CLASS] != ELF_TARG_CLASS || /* Layout ? */
+ ehdr->e_ident[EI_DATA] != ELF_TARG_DATA ||
+ ehdr->e_ident[EI_VERSION] != EV_CURRENT || /* Version ? */
+ ehdr->e_version != EV_CURRENT ||
+ ehdr->e_machine != ELF_TARG_MACH) { /* Machine ? */
+ err = EFTYPE;
+ goto error;
+ }
+
+ return (0);
+
+error:
+ if (ef->firstpage != NULL) {
+ free(ef->firstpage);
+ ef->firstpage = NULL;
+ }
+ if (ef->fd != -1) {
+ close(ef->fd);
+ ef->fd = -1;
+ }
+ return (err);
+}
+
/*
* Attempt to load the file (file) as an ELF module. It will be stored at
* (dest), and a pointer to a module structure describing the loaded object
@@ -93,54 +149,32 @@ u_int64_t __elfN(relocation_offset) = 0;
int
__elfN(loadfile)(char *filename, u_int64_t dest, struct preloaded_file **result)
{
+ return (__elfN(loadfile_raw)(filename, dest, result, 0));
+}
+
+int
+__elfN(loadfile_raw)(char *filename, u_int64_t dest,
+ struct preloaded_file **result, int multiboot)
+{
struct preloaded_file *fp, *kfp;
struct elf_file ef;
Elf_Ehdr *ehdr;
int err;
- ssize_t bytes_read;
fp = NULL;
bzero(&ef, sizeof(struct elf_file));
+ ef.fd = -1;
- /*
- * Open the image, read and validate the ELF header
- */
- if (filename == NULL) /* can't handle nameless */
- return(EFTYPE);
- if ((ef.fd = open(filename, O_RDONLY)) == -1)
- return(errno);
- ef.firstpage = malloc(PAGE_SIZE);
- if (ef.firstpage == NULL) {
- close(ef.fd);
- return(ENOMEM);
- }
- bytes_read = read(ef.fd, ef.firstpage, PAGE_SIZE);
- ef.firstlen = (size_t)bytes_read;
- if (bytes_read < 0 || ef.firstlen <= sizeof(Elf_Ehdr)) {
- err = EFTYPE; /* could be EIO, but may be small file */
- goto oerr;
- }
- ehdr = ef.ehdr = (Elf_Ehdr *)ef.firstpage;
-
- /* Is it ELF? */
- if (!IS_ELF(*ehdr)) {
- err = EFTYPE;
- goto oerr;
- }
- if (ehdr->e_ident[EI_CLASS] != ELF_TARG_CLASS || /* Layout ? */
- ehdr->e_ident[EI_DATA] != ELF_TARG_DATA ||
- ehdr->e_ident[EI_VERSION] != EV_CURRENT || /* Version ? */
- ehdr->e_version != EV_CURRENT ||
- ehdr->e_machine != ELF_TARG_MACH) { /* Machine ? */
- err = EFTYPE;
- goto oerr;
- }
+ err = __elfN(load_elf_header)(filename, &ef);
+ if (err != 0)
+ return (err);
+ ehdr = ef.ehdr;
/*
* Check to see what sort of module we are.
*/
- kfp = file_findfile(NULL, NULL);
+ kfp = file_findfile(NULL, __elfN(kerneltype));
#ifdef __powerpc__
/*
* Kernels can be ET_DYN, so just assume the first loaded object is the
@@ -177,6 +211,11 @@ __elfN(loadfile)(char *filename, u_int64_t dest, struct preloaded_file **result)
} else if (ehdr->e_type == ET_DYN) {
/* Looks like a kld module */
+ if (multiboot != 0) {
+ printf("elf" __XSTRING(__ELF_WORD_SIZE) "_loadfile: can't load module as multiboot\n");
+ err = EPERM;
+ goto oerr;
+ }
if (kfp == NULL) {
printf("elf" __XSTRING(__ELF_WORD_SIZE) "_loadfile: can't load module before kernel\n");
err = EPERM;
@@ -209,10 +248,14 @@ __elfN(loadfile)(char *filename, u_int64_t dest, struct preloaded_file **result)
err = EPERM;
goto out;
}
- if (ef.kernel)
+ if (ef.kernel == 1 && multiboot == 0)
setenv("kernelname", filename, 1);
fp->f_name = strdup(filename);
- fp->f_type = strdup(ef.kernel ? __elfN(kerneltype) : __elfN(moduletype));
+ if (multiboot == 0)
+ fp->f_type = strdup(ef.kernel ?
+ __elfN(kerneltype) : __elfN(moduletype));
+ else
+ fp->f_type = strdup("elf multiboot kernel");
#ifdef ELF_VERBOSE
if (ef.kernel)
@@ -240,7 +283,8 @@ __elfN(loadfile)(char *filename, u_int64_t dest, struct preloaded_file **result)
out:
if (ef.firstpage)
free(ef.firstpage);
- close(ef.fd);
+ if (ef.fd != -1)
+ close(ef.fd);
return(err);
}
@@ -269,6 +313,8 @@ __elfN(loadimage)(struct preloaded_file *fp, elf_file_t ef, u_int64_t off)
int symtabindex;
Elf_Size size;
u_int fpcopy;
+ Elf_Sym sym;
+ Elf_Addr p_start, p_end;
dp = NULL;
shdr = NULL;
@@ -571,7 +617,15 @@ nosyms:
COPYOUT(ef->hashtab + 1, &ef->nchains, sizeof(ef->nchains));
ef->buckets = ef->hashtab + 2;
ef->chains = ef->buckets + ef->nbuckets;
- if (__elfN(parse_modmetadata)(fp, ef) == 0)
+
+ if (__elfN(lookup_symbol)(fp, ef, "__start_set_modmetadata_set", &sym) != 0)
+ return 0;
+ p_start = sym.st_value + ef->off;
+ if (__elfN(lookup_symbol)(fp, ef, "__stop_set_modmetadata_set", &sym) != 0)
+ return ENOENT;
+ p_end = sym.st_value + ef->off;
+
+ if (__elfN(parse_modmetadata)(fp, ef, p_start, p_end) == 0)
goto out;
if (ef->kernel) /* kernel must not depend on anything */
@@ -634,7 +688,123 @@ struct mod_metadata32 {
#endif
int
-__elfN(parse_modmetadata)(struct preloaded_file *fp, elf_file_t ef)
+__elfN(load_modmetadata)(struct preloaded_file *fp, u_int64_t dest)
+{
+ struct elf_file ef;
+ int err, i, j;
+ Elf_Shdr *sh_meta, *shdr = NULL;
+ Elf_Shdr *sh_data[2];
+ char *shstrtab = NULL;
+ size_t size;
+ Elf_Addr p_start, p_end;
+
+ bzero(&ef, sizeof(struct elf_file));
+ ef.fd = -1;
+
+ err = __elfN(load_elf_header)(fp->f_name, &ef);
+ if (err != 0)
+ goto out;
+
+ if (ef.ehdr->e_type == ET_EXEC) {
+ ef.kernel = 1;
+ } else if (ef.ehdr->e_type != ET_DYN) {
+ err = EFTYPE;
+ goto out;
+ }
+
+ size = ef.ehdr->e_shnum * ef.ehdr->e_shentsize;
+ shdr = alloc_pread(ef.fd, ef.ehdr->e_shoff, size);
+ if (shdr == NULL) {
+ err = ENOMEM;
+ goto out;
+ }
+
+ /* Load shstrtab. */
+ shstrtab = alloc_pread(ef.fd, shdr[ef.ehdr->e_shstrndx].sh_offset,
+ shdr[ef.ehdr->e_shstrndx].sh_size);
+ if (shstrtab == NULL) {
+ printf("\nelf" __XSTRING(__ELF_WORD_SIZE)
+ "load_modmetadata: unable to load shstrtab\n");
+ err = EFTYPE;
+ goto out;
+ }
+
+ /* Find set_modmetadata_set and data sections. */
+ sh_data[0] = sh_data[1] = sh_meta = NULL;
+ for (i = 0, j = 0; i < ef.ehdr->e_shnum; i++) {
+ if (strcmp(&shstrtab[shdr[i].sh_name],
+ "set_modmetadata_set") == 0) {
+ sh_meta = &shdr[i];
+ }
+ if ((strcmp(&shstrtab[shdr[i].sh_name], ".data") == 0) ||
+ (strcmp(&shstrtab[shdr[i].sh_name], ".rodata") == 0)) {
+ sh_data[j++] = &shdr[i];
+ }
+ }
+ if (sh_meta == NULL || sh_data[0] == NULL || sh_data[1] == NULL) {
+ printf("\nelf" __XSTRING(__ELF_WORD_SIZE)
+ "load_modmetadata: unable to find set_modmetadata_set or data sections\n");
+ err = EFTYPE;
+ goto out;
+ }
+
+ /* Load set_modmetadata_set into memory */
+ err = kern_pread(ef.fd, dest, sh_meta->sh_size, sh_meta->sh_offset);
+ if (err != 0) {
+ printf("\nelf" __XSTRING(__ELF_WORD_SIZE)
+ "load_modmetadata: unable to load set_modmetadata_set: %d\n", err);
+ goto out;
+ }
+ p_start = dest;
+ p_end = dest + sh_meta->sh_size;
+ dest += sh_meta->sh_size;
+
+ /* Load data sections into memory. */
+ err = kern_pread(ef.fd, dest, sh_data[0]->sh_size,
+ sh_data[0]->sh_offset);
+ if (err != 0) {
+ printf("\nelf" __XSTRING(__ELF_WORD_SIZE)
+ "load_modmetadata: unable to load data: %d\n", err);
+ goto out;
+ }
+
+ /*
+ * We have to increment the dest, so that the offset is the same into
+ * both the .rodata and .data sections.
+ */
+ ef.off = -(sh_data[0]->sh_addr - dest);
+ dest += (sh_data[1]->sh_addr - sh_data[0]->sh_addr);
+
+ err = kern_pread(ef.fd, dest, sh_data[1]->sh_size,
+ sh_data[1]->sh_offset);
+ if (err != 0) {
+ printf("\nelf" __XSTRING(__ELF_WORD_SIZE)
+ "load_modmetadata: unable to load data: %d\n", err);
+ goto out;
+ }
+
+ err = __elfN(parse_modmetadata)(fp, &ef, p_start, p_end);
+ if (err != 0) {
+ printf("\nelf" __XSTRING(__ELF_WORD_SIZE)
+ "load_modmetadata: unable to parse metadata: %d\n", err);
+ goto out;
+ }
+
+out:
+ if (shstrtab != NULL)
+ free(shstrtab);
+ if (shdr != NULL)
+ free(shdr);
+ if (ef.firstpage != NULL)
+ free(ef.firstpage);
+ if (ef.fd != -1)
+ close(ef.fd);
+ return (err);
+}
+
+int
+__elfN(parse_modmetadata)(struct preloaded_file *fp, elf_file_t ef,
+ Elf_Addr p_start, Elf_Addr p_end)
{
struct mod_metadata md;
#if (defined(__i386__) || defined(__powerpc__)) && __ELF_WORD_SIZE == 64
@@ -644,20 +814,13 @@ __elfN(parse_modmetadata)(struct preloaded_file *fp, elf_file_t ef)
#endif
struct mod_depend *mdepend;
struct mod_version mver;
- Elf_Sym sym;
char *s;
int error, modcnt, minfolen;
- Elf_Addr v, p, p_stop;
-
- if (__elfN(lookup_symbol)(fp, ef, "__start_set_modmetadata_set", &sym) != 0)
- return 0;
- p = sym.st_value + ef->off;
- if (__elfN(lookup_symbol)(fp, ef, "__stop_set_modmetadata_set", &sym) != 0)
- return ENOENT;
- p_stop = sym.st_value + ef->off;
+ Elf_Addr v, p;
modcnt = 0;
- while (p < p_stop) {
+ p = p_start;
+ while (p < p_end) {
COPYOUT(p, &v, sizeof(v));
error = __elfN(reloc_ptr)(fp, ef, p, &v, sizeof(v));
if (error == EOPNOTSUPP)
diff --git a/sys/boot/common/load_elf_obj.c b/sys/boot/common/load_elf_obj.c
index 2c8e184..3d8b02a 100644
--- a/sys/boot/common/load_elf_obj.c
+++ b/sys/boot/common/load_elf_obj.c
@@ -129,20 +129,13 @@ __elfN(obj_loadfile)(char *filename, u_int64_t dest,
goto oerr;
}
- kfp = file_findfile(NULL, NULL);
+ kfp = file_findfile(NULL, __elfN(obj_kerneltype));
if (kfp == NULL) {
printf("elf" __XSTRING(__ELF_WORD_SIZE)
"_obj_loadfile: can't load module before kernel\n");
err = EPERM;
goto oerr;
}
- if (strcmp(__elfN(obj_kerneltype), kfp->f_type)) {
- printf("elf" __XSTRING(__ELF_WORD_SIZE)
- "_obj_loadfile: can't load module with kernel type '%s'\n",
- kfp->f_type);
- err = EPERM;
- goto oerr;
- }
if (archsw.arch_loadaddr != NULL)
dest = archsw.arch_loadaddr(LOAD_ELF, hdr, dest);
diff --git a/sys/boot/common/module.c b/sys/boot/common/module.c
index c7d19d1..2af9c20 100644
--- a/sys/boot/common/module.c
+++ b/sys/boot/common/module.c
@@ -138,7 +138,7 @@ command_load(int argc, char *argv[])
command_errmsg = "invalid load type";
return(CMD_ERROR);
}
- return(file_loadraw(argv[1], typestr) ? CMD_OK : CMD_ERROR);
+ return (file_loadraw(argv[1], typestr, 1) ? CMD_OK : CMD_ERROR);
}
/*
* Do we have explicit KLD load ?
@@ -193,7 +193,7 @@ command_load_geli(int argc, char *argv[])
argv += (optind - 1);
argc -= (optind - 1);
sprintf(typestr, "%s:geli_keyfile%d", argv[1], num);
- return(file_loadraw(argv[2], typestr) ? CMD_OK : CMD_ERROR);
+ return (file_loadraw(argv[2], typestr, 1) ? CMD_OK : CMD_ERROR);
}
COMMAND_SET(unload, "unload", "unload all modules", command_unload);
@@ -362,7 +362,7 @@ file_load_dependencies(struct preloaded_file *base_file)
* no arguments or anything.
*/
struct preloaded_file *
-file_loadraw(char *name, char *type)
+file_loadraw(char *name, char *type, int insert)
{
struct preloaded_file *fp;
char *cp;
@@ -421,7 +421,8 @@ file_loadraw(char *name, char *type)
loadaddr = laddr;
/* Add to the list of loaded files */
- file_insert_tail(fp);
+ if (insert != 0)
+ file_insert_tail(fp);
close(fd);
return(fp);
}
@@ -524,7 +525,7 @@ mod_loadkld(const char *kldname, int argc, char *argv[])
* NULL may be passed as a wildcard to either.
*/
struct preloaded_file *
-file_findfile(char *name, char *type)
+file_findfile(const char *name, const char *type)
{
struct preloaded_file *fp;
diff --git a/sys/boot/efi/boot1/Makefile b/sys/boot/efi/boot1/Makefile
index ddf3147..8cb6c62 100644
--- a/sys/boot/efi/boot1/Makefile
+++ b/sys/boot/efi/boot1/Makefile
@@ -9,7 +9,7 @@ MAN=
MK_SSP= no
-PROG= loader.sym
+PROG= boot1.sym
INTERNALPROG=
# architecture-specific loader code
@@ -38,7 +38,7 @@ LDFLAGS= -Wl,-T${LDSCRIPT} -Wl,-Bsymbolic -shared
LDFLAGS+= -Wl,-znocombreloc
.endif
-${PROG}: ${LDSCRIPT}
+DPADD+= ${LDSCRIPT}
OBJCOPY?= objcopy
OBJDUMP?= objdump
@@ -49,19 +49,19 @@ EFI_TARGET= efi-app-x86_64
EFI_TARGET= efi-app-ia32
.endif
-boot1.efi: loader.sym
+boot1.efi: ${PROG}
if [ `${OBJDUMP} -t ${.ALLSRC} | fgrep '*UND*' | wc -l` != 0 ]; then \
${OBJDUMP} -t ${.ALLSRC} | fgrep '*UND*'; \
exit 1; \
fi
${OBJCOPY} -j .text -j .sdata -j .data \
-j .dynamic -j .dynsym -j .rel.dyn \
- -j .rela.dyn -j .reloc -j .eh_frame -j set_Xcommand_set \
+ -j .rela.dyn -j .reloc -j .eh_frame \
--output-target=${EFI_TARGET} ${.ALLSRC} ${.TARGET}
boot1.o: ${.CURDIR}/../../common/ufsread.c
-# The following inserts out objects into a template FAT file system
+# The following inserts our objects into a template FAT file system
# created by generate-fat.sh
.include "${.CURDIR}/Makefile.fat"
@@ -73,7 +73,7 @@ boot1.efifat: boot1.efi
bzip2 -f -d ${.TARGET}.bz2
dd if=boot1.efi of=${.TARGET} seek=${BOOT1_OFFSET} conv=notrunc
-CLEANFILES= boot1.efifat
+CLEANFILES= boot1.efi boot1.efifat
.endif # ${COMPILER_TYPE} != "gcc"
@@ -82,7 +82,7 @@ CLEANFILES= boot1.efifat
.if ${MACHINE_CPUARCH} == "amd64" || ${MACHINE_CPUARCH} == "i386"
beforedepend ${OBJS}: machine x86
-CLEANFILES+= machine x86 boot1.efi
+CLEANFILES+= machine x86
machine:
ln -sf ${.CURDIR}/../../../amd64/include machine
diff --git a/sys/boot/efi/boot1/boot1.c b/sys/boot/efi/boot1/boot1.c
index e0c26da..1e3821b 100644
--- a/sys/boot/efi/boot1/boot1.c
+++ b/sys/boot/efi/boot1/boot1.c
@@ -30,7 +30,7 @@ __FBSDID("$FreeBSD$");
#define _PATH_LOADER "/boot/loader.efi"
#define _PATH_KERNEL "/boot/kernel/kernel"
-
+
#define BSIZEMAX 16384
typedef int putc_func_t(char c, void *arg);
@@ -40,7 +40,7 @@ struct sp_data {
u_int sp_len;
u_int sp_size;
};
-
+
static const char digits[] = "0123456789abcdef";
static void panic(const char *fmt, ...) __dead2;
@@ -62,7 +62,7 @@ static void load(const char *fname);
EFI_SYSTEM_TABLE *systab;
EFI_HANDLE *image;
-static void
+static void
bcopy(const void *src, void *dst, size_t len)
{
const char *s = src;
@@ -71,12 +71,12 @@ bcopy(const void *src, void *dst, size_t len)
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)
@@ -86,7 +86,7 @@ bzero(void *b, size_t len)
while (len-- != 0)
*p++ = 0;
}
-
+
static int
strcmp(const char *s1, const char *s2)
{
@@ -134,7 +134,7 @@ EFI_STATUS efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE* Xsystab)
for (i = 0; i < nparts; i++) {
status = systab->BootServices->HandleProtocol(handles[i],
- &DevicePathGUID, (void **)&devpath);
+ &DevicePathGUID, (void **)&devpath);
if (EFI_ERROR(status))
continue;
@@ -142,7 +142,7 @@ EFI_STATUS efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE* Xsystab)
devpath = NextDevicePathNode(devpath);
status = systab->BootServices->HandleProtocol(handles[i],
- &BlockIoProtocolGUID, (void **)&blkio);
+ &BlockIoProtocolGUID, (void **)&blkio);
if (EFI_ERROR(status))
continue;
@@ -158,7 +158,7 @@ EFI_STATUS efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE* Xsystab)
bootdevhandle = handles[i];
load(path);
-
+
panic("Load failed");
return EFI_SUCCESS;
@@ -266,7 +266,7 @@ fsstat(ufs_ino_t inode)
}
static struct dmadat __dmadat;
-
+
static int
domount(EFI_DEVICE_PATH *device, EFI_BLOCK_IO *blkio, int quiet)
{
@@ -278,7 +278,7 @@ domount(EFI_DEVICE_PATH *device, EFI_BLOCK_IO *blkio, int quiet)
if (!quiet)
printf("domount: can't read superblock\n");
return (-1);
- }
+ }
if (!quiet)
printf("Succesfully mounted UFS filesystem\n");
return (0);
@@ -303,26 +303,26 @@ load(const char *fname)
status = systab->BootServices->AllocatePool(EfiLoaderData,
bufsize, &buffer);
fsread(ino, buffer, bufsize);
-
+
/* XXX: For secure boot, we need our own loader here */
status = systab->BootServices->LoadImage(TRUE, image, bootdevpath,
buffer, bufsize, &loaderhandle);
if (EFI_ERROR(status))
printf("LoadImage failed with error %lu\n",
- status & ~EFI_ERROR_MASK);
+ EFI_ERROR_CODE(status));
status = systab->BootServices->HandleProtocol(loaderhandle,
&LoadedImageGUID, (VOID**)&loaded_image);
if (EFI_ERROR(status))
printf("HandleProtocol failed with error %lu\n",
- status & ~EFI_ERROR_MASK);
+ EFI_ERROR_CODE(status));
loaded_image->DeviceHandle = bootdevhandle;
status = systab->BootServices->StartImage(loaderhandle, NULL, NULL);
if (EFI_ERROR(status))
printf("StartImage failed with error %lu\n",
- status & ~EFI_ERROR_MASK);
+ EFI_ERROR_CODE(status));
}
static void
@@ -552,4 +552,3 @@ __ultoa(char *buf, u_long ul, int base)
while ((ul /= base) != 0);
return (p);
}
-
diff --git a/sys/boot/efi/include/efierr.h b/sys/boot/efi/include/efierr.h
index dc57f0e..921b297 100644
--- a/sys/boot/efi/include/efierr.h
+++ b/sys/boot/efi/include/efierr.h
@@ -30,7 +30,8 @@ Revision History
#define EFIWARN(a) (a)
-#define EFI_ERROR(a) (((INTN) a) < 0)
+#define EFI_ERROR(a) (((INTN) a) < 0)
+#define EFI_ERROR_CODE(a) (a & ~EFI_ERROR_MASK)
#define EFI_SUCCESS 0
diff --git a/sys/boot/efi/libefi/Makefile b/sys/boot/efi/libefi/Makefile
index 8180d9e..900b230 100644
--- a/sys/boot/efi/libefi/Makefile
+++ b/sys/boot/efi/libefi/Makefile
@@ -19,5 +19,6 @@ CFLAGS+= -I${.CURDIR}/../../common
# Suppress warning from clang for FreeBSD %b and %D formats
CFLAGS+= -fformat-extensions
+CFLAGS+= -DTERM_EMU
.include <bsd.lib.mk>
diff --git a/sys/boot/efi/libefi/efi_console.c b/sys/boot/efi/libefi/efi_console.c
index 3538994..52a3725 100644
--- a/sys/boot/efi/libefi/efi_console.c
+++ b/sys/boot/efi/libefi/efi_console.c
@@ -35,6 +35,69 @@ __FBSDID("$FreeBSD$");
static SIMPLE_TEXT_OUTPUT_INTERFACE *conout;
static SIMPLE_INPUT_INTERFACE *conin;
+#ifdef TERM_EMU
+#define DEFAULT_FGCOLOR EFI_LIGHTGRAY
+#define DEFAULT_BGCOLOR EFI_BLACK
+
+#define MAXARGS 8
+static int args[MAXARGS], argc;
+static int fg_c, bg_c, curx, cury;
+static int esc;
+
+void get_pos(int *x, int *y);
+void curs_move(int *_x, int *_y, int x, int y);
+static void CL(int);
+#endif
+
+static void efi_cons_probe(struct console *);
+static int efi_cons_init(int);
+void efi_cons_putchar(int);
+int efi_cons_getchar(void);
+void efi_cons_efiputchar(int);
+int efi_cons_poll(void);
+
+struct console efi_console = {
+ "efi",
+ "EFI console",
+ 0,
+ efi_cons_probe,
+ efi_cons_init,
+ efi_cons_putchar,
+ efi_cons_getchar,
+ efi_cons_poll
+};
+
+#ifdef TERM_EMU
+
+/* Get cursor position. */
+void
+get_pos(int *x, int *y)
+{
+ *x = conout->Mode->CursorColumn;
+ *y = conout->Mode->CursorRow;
+}
+
+/* Move cursor to x rows and y cols (0-based). */
+void
+curs_move(int *_x, int *_y, int x, int y)
+{
+ conout->SetCursorPosition(conout, x, y);
+ if (_x != NULL)
+ *_x = conout->Mode->CursorColumn;
+ if (_y != NULL)
+ *_y = conout->Mode->CursorRow;
+}
+
+/* Clear internal state of the terminal emulation code. */
+void
+end_term(void)
+{
+ esc = 0;
+ argc = -1;
+}
+
+#endif
+
static void
efi_cons_probe(struct console *cp)
{
@@ -46,22 +109,314 @@ efi_cons_probe(struct console *cp)
static int
efi_cons_init(int arg)
{
- conout->SetAttribute(conout, EFI_TEXT_ATTR(EFI_LIGHTGRAY, EFI_BLACK));
+ conout->SetAttribute(conout, EFI_TEXT_ATTR(DEFAULT_FGCOLOR,
+ DEFAULT_BGCOLOR));
+#ifdef TERM_EMU
+ end_term();
+ get_pos(&curx, &cury);
+ curs_move(&curx, &cury, curx, cury);
+ fg_c = DEFAULT_FGCOLOR;
+ bg_c = DEFAULT_BGCOLOR;
+#endif
+ conout->EnableCursor(conout, TRUE);
return 0;
}
+static void
+efi_cons_rawputchar(int c)
+{
+ int i;
+ UINTN x, y;
+ conout->QueryMode(conout, conout->Mode->Mode, &x, &y);
+
+ if (c == '\t')
+ /* XXX lame tab expansion */
+ for (i = 0; i < 8; i++)
+ efi_cons_rawputchar(' ');
+ else {
+#ifndef TERM_EMU
+ if (c == '\n')
+ efi_cons_efiputchar('\r');
+ else
+ efi_cons_efiputchar(c);
+#else
+ switch (c) {
+ case '\r':
+ curx = 0;
+ curs_move(&curx, &cury, curx, cury);
+ return;
+ case '\n':
+ cury++;
+ if (cury >= y) {
+ efi_cons_efiputchar('\n');
+ cury--;
+ } else
+ curs_move(&curx, &cury, curx, cury);
+ return;
+ case '\b':
+ if (curx > 0) {
+ curx--;
+ curs_move(&curx, &cury, curx, cury);
+ }
+ return;
+ default:
+ efi_cons_efiputchar(c);
+ curx++;
+ if (curx > x-1) {
+ curx = 0;
+ cury++;
+ }
+ if (cury > y-1) {
+ curx = 0;
+ cury--;
+ }
+ }
+ curs_move(&curx, &cury, curx, cury);
+#endif
+ }
+}
+
+/* Gracefully exit ESC-sequence processing in case of misunderstanding. */
+static void
+bail_out(int c)
+{
+ char buf[16], *ch;
+ int i;
+
+ if (esc) {
+ efi_cons_rawputchar('\033');
+ if (esc != '\033')
+ efi_cons_rawputchar(esc);
+ for (i = 0; i <= argc; ++i) {
+ sprintf(buf, "%d", args[i]);
+ ch = buf;
+ while (*ch)
+ efi_cons_rawputchar(*ch++);
+ }
+ }
+ efi_cons_rawputchar(c);
+ end_term();
+}
+
+/* Clear display from current position to end of screen. */
+static void
+CD(void) {
+ int i;
+ UINTN x, y;
+
+ get_pos(&curx, &cury);
+ if (curx == 0 && cury == 0) {
+ conout->ClearScreen(conout);
+ end_term();
+ return;
+ }
+
+ conout->QueryMode(conout, conout->Mode->Mode, &x, &y);
+ CL(0); /* clear current line from cursor to end */
+ for (i = cury + 1; i < y-1; i++) {
+ curs_move(NULL, NULL, 0, i);
+ CL(0);
+ }
+ curs_move(NULL, NULL, curx, cury);
+ end_term();
+}
+
+/*
+ * Absolute cursor move to args[0] rows and args[1] columns
+ * (the coordinates are 1-based).
+ */
+static void
+CM(void)
+{
+ if (args[0] > 0)
+ args[0]--;
+ if (args[1] > 0)
+ args[1]--;
+ curs_move(&curx, &cury, args[1], args[0]);
+ end_term();
+}
+
+/* Home cursor (left top corner), also called from mode command. */
void
-efi_cons_putchar(int c)
+HO(void)
{
- CHAR16 buf[2];
+ argc = 1;
+ args[0] = args[1] = 1;
+ CM();
+}
- if (c == '\n')
- efi_cons_putchar('\r');
+/* Clear line from current position to end of line */
+static void
+CL(int direction)
+{
+ int i, len;
+ UINTN x, y;
+ CHAR16 *line;
- buf[0] = c;
- buf[1] = 0;
+ conout->QueryMode(conout, conout->Mode->Mode, &x, &y);
+ switch (direction) {
+ case 0: /* from cursor to end */
+ len = x - curx + 1;
+ break;
+ case 1: /* from beginning to cursor */
+ len = curx;
+ break;
+ case 2: /* entire line */
+ len = x;
+ break;
+ }
- conout->OutputString(conout, buf);
+ if (cury == y - 1)
+ len--;
+
+ line = malloc(len * sizeof (CHAR16));
+ if (line == NULL) {
+ printf("out of memory\n");
+ return;
+ }
+ for (i = 0; i < len; i++)
+ line[i] = ' ';
+ line[len-1] = 0;
+
+ if (direction != 0)
+ curs_move(NULL, NULL, 0, cury);
+
+ conout->OutputString(conout, line);
+ /* restore cursor position */
+ curs_move(NULL, NULL, curx, cury);
+ free(line);
+ end_term();
+}
+
+static void
+get_arg(int c)
+{
+ if (argc < 0)
+ argc = 0;
+ args[argc] *= 10;
+ args[argc] += c - '0';
+}
+
+/* Emulate basic capabilities of cons25 terminal */
+static void
+efi_term_emu(int c)
+{
+ static int ansi_col[] = {
+ 0, 4, 2, 6, 1, 5, 3, 7
+ };
+ int t, i;
+
+ switch (esc) {
+ case 0:
+ switch (c) {
+ case '\033':
+ esc = c;
+ break;
+ default:
+ efi_cons_rawputchar(c);
+ break;
+ }
+ break;
+ case '\033':
+ switch (c) {
+ case '[':
+ esc = c;
+ args[0] = 0;
+ argc = -1;
+ break;
+ default:
+ bail_out(c);
+ break;
+ }
+ break;
+ case '[':
+ switch (c) {
+ case ';':
+ if (argc < 0)
+ argc = 0;
+ else if (argc + 1 >= MAXARGS)
+ bail_out(c);
+ else
+ args[++argc] = 0;
+ break;
+ case 'H': /* ho = \E[H */
+ if (argc < 0)
+ HO();
+ else if (argc == 1)
+ CM();
+ else
+ bail_out(c);
+ break;
+ case 'J': /* cd = \E[J */
+ if (argc < 0)
+ CD();
+ else
+ bail_out(c);
+ break;
+ case 'm':
+ if (argc < 0) {
+ fg_c = DEFAULT_FGCOLOR;
+ bg_c = DEFAULT_BGCOLOR;
+ }
+ for (i = 0; i <= argc; ++i) {
+ switch (args[i]) {
+ case 0: /* back to normal */
+ fg_c = DEFAULT_FGCOLOR;
+ bg_c = DEFAULT_BGCOLOR;
+ break;
+ case 1: /* bold */
+ fg_c |= 0x8;
+ break;
+ case 4: /* underline */
+ case 5: /* blink */
+ bg_c |= 0x8;
+ break;
+ case 7: /* reverse */
+ t = fg_c;
+ fg_c = bg_c;
+ bg_c = t;
+ break;
+ case 30: case 31: case 32: case 33:
+ case 34: case 35: case 36: case 37:
+ fg_c = ansi_col[args[i] - 30];
+ break;
+ case 39: /* normal */
+ fg_c = DEFAULT_FGCOLOR;
+ break;
+ case 40: case 41: case 42: case 43:
+ case 44: case 45: case 46: case 47:
+ bg_c = ansi_col[args[i] - 40];
+ break;
+ case 49: /* normal */
+ bg_c = DEFAULT_BGCOLOR;
+ break;
+ }
+ }
+ conout->SetAttribute(conout, EFI_TEXT_ATTR(fg_c, bg_c));
+ end_term();
+ break;
+ default:
+ if (isdigit(c))
+ get_arg(c);
+ else
+ bail_out(c);
+ break;
+ }
+ break;
+ default:
+ bail_out(c);
+ break;
+ }
+}
+
+void
+efi_cons_putchar(int c)
+{
+#ifdef TERM_EMU
+ efi_term_emu(c);
+#else
+ efi_cons_rawputchar(c);
+#endif
}
int
@@ -77,6 +432,12 @@ efi_cons_getchar()
BS->WaitForEvent(1, &conin->WaitForKey, &junk);
status = conin->ReadKeyStroke(conin, &key);
}
+ switch (key.ScanCode) {
+ case 0x17: /* ESC */
+ return (0x1b); /* esc */
+ }
+
+ /* this can return */
return (key.UnicodeChar);
}
@@ -87,13 +448,36 @@ efi_cons_poll()
return (BS->CheckEvent(conin->WaitForKey) == EFI_SUCCESS);
}
-struct console efi_console = {
- "efi",
- "EFI console",
- 0,
- efi_cons_probe,
- efi_cons_init,
- efi_cons_putchar,
- efi_cons_getchar,
- efi_cons_poll
-};
+/* Plain direct access to EFI OutputString(). */
+void
+efi_cons_efiputchar(int c)
+{
+ CHAR16 buf[2];
+
+ /*
+ * translate box chars to unicode
+ */
+ switch (c) {
+ /* single frame */
+ case 0xb3: buf[0] = BOXDRAW_VERTICAL; break;
+ case 0xbf: buf[0] = BOXDRAW_DOWN_LEFT; break;
+ case 0xc0: buf[0] = BOXDRAW_UP_RIGHT; break;
+ case 0xc4: buf[0] = BOXDRAW_HORIZONTAL; break;
+ case 0xda: buf[0] = BOXDRAW_DOWN_RIGHT; break;
+ case 0xd9: buf[0] = BOXDRAW_UP_LEFT; break;
+
+ /* double frame */
+ case 0xba: buf[0] = BOXDRAW_DOUBLE_VERTICAL; break;
+ case 0xbb: buf[0] = BOXDRAW_DOUBLE_DOWN_LEFT; break;
+ case 0xbc: buf[0] = BOXDRAW_DOUBLE_UP_LEFT; break;
+ case 0xc8: buf[0] = BOXDRAW_DOUBLE_UP_RIGHT; break;
+ case 0xc9: buf[0] = BOXDRAW_DOUBLE_DOWN_RIGHT; break;
+ case 0xcd: buf[0] = BOXDRAW_DOUBLE_HORIZONTAL; break;
+
+ default:
+ buf[0] = c;
+ }
+ buf[1] = 0; /* terminate string */
+
+ conout->OutputString(conout, buf);
+}
diff --git a/sys/boot/efi/loader/Makefile b/sys/boot/efi/loader/Makefile
index 8d3fe87..268edce 100644
--- a/sys/boot/efi/loader/Makefile
+++ b/sys/boot/efi/loader/Makefile
@@ -12,7 +12,6 @@ MK_SSP= no
PROG= loader.sym
INTERNALPROG=
-.PATH: ${.CURDIR}/../../efi/loader
# architecture-specific loader code
SRCS= autoload.c \
bootinfo.c \
@@ -80,7 +79,7 @@ EFI_TARGET= efi-app-x86_64
EFI_TARGET= efi-app-ia32
.endif
-loader.efi: loader.sym
+loader.efi: ${PROG}
if [ `${OBJDUMP} -t ${.ALLSRC} | fgrep '*UND*' | wc -l` != 0 ]; then \
${OBJDUMP} -t ${.ALLSRC} | fgrep '*UND*'; \
exit 1; \
diff --git a/sys/boot/efi/loader/bootinfo.c b/sys/boot/efi/loader/bootinfo.c
index f3bb9cc..18837f8 100644
--- a/sys/boot/efi/loader/bootinfo.c
+++ b/sys/boot/efi/loader/bootinfo.c
@@ -275,7 +275,7 @@ bi_load_efi_data(struct preloaded_file *kfp)
pages, &addr);
if (EFI_ERROR(status)) {
printf("%s: AllocatePages error %lu\n", __func__,
- (unsigned long)(status & ~EFI_ERROR_MASK));
+ EFI_ERROR_CODE(status));
return (ENOMEM);
}
@@ -291,7 +291,7 @@ bi_load_efi_data(struct preloaded_file *kfp)
status = BS->GetMemoryMap(&sz, mm, &efi_mapkey, &mmsz, &mmver);
if (EFI_ERROR(status)) {
printf("%s: GetMemoryMap error %lu\n", __func__,
- (unsigned long)(status & ~EFI_ERROR_MASK));
+ EFI_ERROR_CODE(status));
return (EINVAL);
}
status = BS->ExitBootServices(IH, efi_mapkey);
@@ -305,8 +305,7 @@ bi_load_efi_data(struct preloaded_file *kfp)
}
BS->FreePages(addr, pages);
}
- printf("ExitBootServices error %lu\n",
- (unsigned long)(status & ~EFI_ERROR_MASK));
+ printf("ExitBootServices error %lu\n", EFI_ERROR_CODE(status));
return (EINVAL);
}
diff --git a/sys/boot/efi/loader/copy.c b/sys/boot/efi/loader/copy.c
index a7d6bf1..363d95d 100644
--- a/sys/boot/efi/loader/copy.c
+++ b/sys/boot/efi/loader/copy.c
@@ -56,7 +56,7 @@ efi_copy_init(void)
STAGE_PAGES, &staging);
if (EFI_ERROR(status)) {
printf("failed to allocate staging area: %lu\n",
- (unsigned long)(status & EFI_ERROR_MASK));
+ EFI_ERROR_CODE(status));
return (status);
}
staging_end = staging + STAGE_PAGES * EFI_PAGE_SIZE;
diff --git a/sys/boot/efi/loader/main.c b/sys/boot/efi/loader/main.c
index e6e13f1..ec9f9af 100644
--- a/sys/boot/efi/loader/main.c
+++ b/sys/boot/efi/loader/main.c
@@ -63,10 +63,10 @@ EFI_GUID debugimg = DEBUG_IMAGE_INFO_TABLE_GUID;
EFI_STATUS
main(int argc, CHAR16 *argv[])
{
- char vendor[128];
+ char var[128];
EFI_LOADED_IMAGE *img;
EFI_GUID *guid;
- int i;
+ int i, j, vargood;
/*
* XXX Chicken-and-egg problem; we want to have console output
@@ -76,6 +76,29 @@ main(int argc, CHAR16 *argv[])
*/
cons_probe();
+ /*
+ * Loop through the args, and for each one that contains an '=' that is
+ * not the first character, add it to the environment. This allows
+ * loader and kernel env vars to be passed on the command line. Convert
+ * args from UCS-2 to ASCII (16 to 8 bit) as they are copied.
+ */
+ for (i = 1; i < argc; i++) {
+ vargood = 0;
+ for (j = 0; argv[i][j] != 0; j++) {
+ if (j == sizeof(var)) {
+ vargood = 0;
+ break;
+ }
+ if (j > 0 && argv[i][j] == '=')
+ vargood = 1;
+ var[j] = (char)argv[i][j];
+ }
+ if (vargood) {
+ var[j] = 0;
+ putenv(var);
+ }
+ }
+
if (efi_copy_init()) {
printf("failed to allocate staging area\n");
return (EFI_BUFFER_TOO_SMALL);
@@ -203,50 +226,47 @@ command_memmap(int argc, char *argv[])
status = BS->GetMemoryMap(&sz, 0, &key, &dsz, &dver);
if (status != EFI_BUFFER_TOO_SMALL) {
printf("Can't determine memory map size\n");
- return CMD_ERROR;
+ return (CMD_ERROR);
}
map = malloc(sz);
status = BS->GetMemoryMap(&sz, map, &key, &dsz, &dver);
if (EFI_ERROR(status)) {
printf("Can't read memory map\n");
- return CMD_ERROR;
+ return (CMD_ERROR);
}
ndesc = sz / dsz;
printf("%23s %12s %12s %8s %4s\n",
- "Type", "Physical", "Virtual", "#Pages", "Attr");
+ "Type", "Physical", "Virtual", "#Pages", "Attr");
for (i = 0, p = map; i < ndesc;
i++, p = NextMemoryDescriptor(p, dsz)) {
- printf("%23s %012lx %012lx %08lx ",
- types[p->Type],
- p->PhysicalStart,
- p->VirtualStart,
- p->NumberOfPages);
- if (p->Attribute & EFI_MEMORY_UC)
- printf("UC ");
- if (p->Attribute & EFI_MEMORY_WC)
- printf("WC ");
- if (p->Attribute & EFI_MEMORY_WT)
- printf("WT ");
- if (p->Attribute & EFI_MEMORY_WB)
- printf("WB ");
- if (p->Attribute & EFI_MEMORY_UCE)
- printf("UCE ");
- if (p->Attribute & EFI_MEMORY_WP)
- printf("WP ");
- if (p->Attribute & EFI_MEMORY_RP)
- printf("RP ");
- if (p->Attribute & EFI_MEMORY_XP)
- printf("XP ");
- printf("\n");
+ printf("%23s %012lx %012lx %08lx ", types[p->Type],
+ p->PhysicalStart, p->VirtualStart, p->NumberOfPages);
+ if (p->Attribute & EFI_MEMORY_UC)
+ printf("UC ");
+ if (p->Attribute & EFI_MEMORY_WC)
+ printf("WC ");
+ if (p->Attribute & EFI_MEMORY_WT)
+ printf("WT ");
+ if (p->Attribute & EFI_MEMORY_WB)
+ printf("WB ");
+ if (p->Attribute & EFI_MEMORY_UCE)
+ printf("UCE ");
+ if (p->Attribute & EFI_MEMORY_WP)
+ printf("WP ");
+ if (p->Attribute & EFI_MEMORY_RP)
+ printf("RP ");
+ if (p->Attribute & EFI_MEMORY_XP)
+ printf("XP ");
+ printf("\n");
}
- return CMD_OK;
+ return (CMD_OK);
}
-COMMAND_SET(configuration, "configuration",
- "print configuration tables", command_configuration);
+COMMAND_SET(configuration, "configuration", "print configuration tables",
+ command_configuration);
static const char *
guid_to_string(EFI_GUID *guid)
@@ -292,7 +312,7 @@ command_configuration(int argc, char *argv[])
printf(" at %p\n", ST->ConfigurationTable[i].VendorTable);
}
- return CMD_OK;
+ return (CMD_OK);
}
@@ -308,6 +328,7 @@ command_mode(int argc, char *argv[])
char rowenv[8];
EFI_STATUS status;
SIMPLE_TEXT_OUTPUT_INTERFACE *conout;
+ extern void HO(void);
conout = ST->ConOut;
@@ -329,14 +350,15 @@ command_mode(int argc, char *argv[])
}
sprintf(rowenv, "%u", (unsigned)rows);
setenv("LINES", rowenv, 1);
-
+ HO(); /* set cursor */
return (CMD_OK);
}
- for (i = 0; ; i++) {
+ printf("Current mode: %d\n", conout->Mode->Mode);
+ for (i = 0; i <= conout->Mode->MaxMode; i++) {
status = conout->QueryMode(conout, i, &cols, &rows);
if (EFI_ERROR(status))
- break;
+ continue;
printf("Mode %d: %u columns, %u rows\n", i, (unsigned)cols,
(unsigned)rows);
}
@@ -367,20 +389,17 @@ command_nvram(int argc, char *argv[])
status = RS->GetNextVariableName(&varsz, NULL, NULL);
for (; status != EFI_NOT_FOUND; ) {
- status = RS->GetNextVariableName(&varsz, var,
- &varguid);
+ status = RS->GetNextVariableName(&varsz, var, &varguid);
//if (EFI_ERROR(status))
//break;
conout->OutputString(conout, var);
printf("=");
datasz = 0;
- status = RS->GetVariable(var, &varguid, NULL, &datasz,
- NULL);
+ status = RS->GetVariable(var, &varguid, NULL, &datasz, NULL);
/* XXX: check status */
data = malloc(datasz);
- status = RS->GetVariable(var, &varguid, NULL, &datasz,
- data);
+ status = RS->GetVariable(var, &varguid, NULL, &datasz, data);
if (EFI_ERROR(status))
printf("<error retrieving variable>");
else {
diff --git a/sys/boot/fdt/dts/arm/beaglebone-black.dts b/sys/boot/fdt/dts/arm/beaglebone-black.dts
index ff25f9d..0e35a7a 100644
--- a/sys/boot/fdt/dts/arm/beaglebone-black.dts
+++ b/sys/boot/fdt/dts/arm/beaglebone-black.dts
@@ -146,9 +146,9 @@
};
i2c@44e0b000 {
- pmic@48 {
+ pmic@24 {
compatible = "ti,am335x-pmic";
- reg = <0x48>;
+ reg = <0x24>;
};
};
};
diff --git a/sys/boot/fdt/dts/arm/beaglebone.dts b/sys/boot/fdt/dts/arm/beaglebone.dts
index 83b948f..3f8e022 100644
--- a/sys/boot/fdt/dts/arm/beaglebone.dts
+++ b/sys/boot/fdt/dts/arm/beaglebone.dts
@@ -133,7 +133,7 @@
i2c@44e0b000 {
pmic@24 {
compatible = "ti,am335x-pmic";
- reg = <0x48>;
+ reg = <0x24>;
};
};
};
diff --git a/sys/boot/fdt/fdt_loader_cmd.c b/sys/boot/fdt/fdt_loader_cmd.c
index 0f63776..98a0388 100644
--- a/sys/boot/fdt/fdt_loader_cmd.c
+++ b/sys/boot/fdt/fdt_loader_cmd.c
@@ -261,7 +261,7 @@ fdt_load_dtb_file(const char * filename)
oldbfp = file_findfile(NULL, "dtb");
/* Attempt to load and validate a new dtb from a file. */
- if ((bfp = file_loadraw(filename, "dtb")) == NULL) {
+ if ((bfp = file_loadraw(filename, "dtb", 1)) == NULL) {
sprintf(command_errbuf, "failed to load file '%s'", filename);
return (1);
}
diff --git a/sys/boot/ficl/amd64/sysdep.c b/sys/boot/ficl/amd64/sysdep.c
index 00b0d4a..6031094 100644
--- a/sys/boot/ficl/amd64/sysdep.c
+++ b/sys/boot/ficl/amd64/sysdep.c
@@ -55,7 +55,7 @@ void ficlTextOut(FICL_VM *pVM, char *msg, int fNewline)
IGNORE(pVM);
while(*msg != 0)
- putchar(*(msg++));
+ putchar((unsigned char)*(msg++));
if (fNewline)
putchar('\n');
diff --git a/sys/boot/forth/beastie.4th b/sys/boot/forth/beastie.4th
index 9ede592..752cce2 100644
--- a/sys/boot/forth/beastie.4th
+++ b/sys/boot/forth/beastie.4th
@@ -85,14 +85,10 @@ variable logoY
also support-functions
: beastie-start ( -- ) \ starts the menu
- s" console" getenv dup -1 <> if
- s" efi" 2swap contains? if
- s" set beastie_disable=YES" evaluate
- then
- else drop then
s" beastie_disable" getenv dup -1 <> if
s" YES" compare-insensitive 0= if
any_conf_read? if
+ load_xen_throw
load_kernel
load_modules
then
diff --git a/sys/boot/forth/beastie.4th.8 b/sys/boot/forth/beastie.4th.8
index 534a60c..70d8694 100644
--- a/sys/boot/forth/beastie.4th.8
+++ b/sys/boot/forth/beastie.4th.8
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd April 27, 2014
+.Dd January 20, 2016
.Dt BEASTIE.4TH 8
.Os
.Sh NAME
@@ -119,8 +119,7 @@ Sets the desired row position of the logo. Default is 4.
If set to
.Dq YES ,
the beastie boot menu will be skipped.
-The beastie boot menu is always skipped if booting UEFI or running non-x86
-hardware.
+The beastie boot menu is always skipped if running non-x86 hardware.
.It Va loader_delay
If set to a number higher than zero, introduces a delay before starting the
beastie boot menu. During the delay the user can press either Ctrl-C to skip
diff --git a/sys/boot/forth/loader.4th b/sys/boot/forth/loader.4th
index 43d2a8e..ad4042e 100644
--- a/sys/boot/forth/loader.4th
+++ b/sys/boot/forth/loader.4th
@@ -147,13 +147,14 @@ only forth definitions also support-functions
\ was succesfully loaded!
any_conf_read? if
s" loader_delay" getenv -1 = if
+ load_xen_throw
load_kernel
load_modules
else
drop
." Loading Kernel and Modules (Ctrl-C to Abort)" cr
s" also support-functions" evaluate
- s" set delay_command='load_kernel load_modules'" evaluate
+ s" set delay_command='load_xen_throw load_kernel load_modules'" evaluate
s" set delay_showdots" evaluate
delay_execute
then
diff --git a/sys/boot/forth/loader.conf.5 b/sys/boot/forth/loader.conf.5
index 3c1ce1d..c574a92 100644
--- a/sys/boot/forth/loader.conf.5
+++ b/sys/boot/forth/loader.conf.5
@@ -23,7 +23,7 @@
.\" SUCH DAMAGE.
.\"
.\" $FreeBSD$
-.Dd April 27, 2014
+.Dd January 20, 2016
.Dt LOADER.CONF 5
.Os
.Sh NAME
@@ -236,8 +236,7 @@ be displayed.
If set to
.Dq YES ,
the beastie boot menu will be skipped.
-The beastie boot menu is always skipped if booting UEFI or running non-x86
-hardware.
+The beastie boot menu is always skipped if running non-x86 hardware.
.It Va loader_logo Pq Dq Li orbbw
Selects a desired logo in the beastie boot menu.
Possible values are:
diff --git a/sys/boot/forth/support.4th b/sys/boot/forth/support.4th
index 1acef70..3d9990d 100644
--- a/sys/boot/forth/support.4th
+++ b/sys/boot/forth/support.4th
@@ -1460,6 +1460,20 @@ also builtins
abort" Unable to load a kernel!"
;
+: load_xen ( -- )
+ s" xen_kernel" getenv dup -1 <> if
+ 1 1 load
+ else
+ drop
+ 0
+ then
+;
+
+: load_xen_throw ( -- ) ( throws: abort )
+ load_xen
+ abort" Unable to load Xen!"
+;
+
: set_defaultoptions ( -- )
s" kernel_options" getenv dup -1 = if
drop
@@ -1578,12 +1592,15 @@ also builtins
else
drop
then
- r> if ( a path was passed )
- load_directory_or_file
- else
- standard_kernel_search
+ load_xen
+ ?dup 0= if ( success )
+ r> if ( a path was passed )
+ load_directory_or_file
+ else
+ standard_kernel_search
+ then
+ ?dup 0= if ['] load_modules catch then
then
- ?dup 0= if ['] load_modules catch then
;
only forth definitions
diff --git a/sys/boot/i386/libi386/Makefile b/sys/boot/i386/libi386/Makefile
index 1c4f049..d4fea80 100644
--- a/sys/boot/i386/libi386/Makefile
+++ b/sys/boot/i386/libi386/Makefile
@@ -6,7 +6,7 @@ INTERNALLIB=
SRCS= biosacpi.c bioscd.c biosdisk.c biosmem.c biospnp.c \
biospci.c biossmap.c bootinfo.c bootinfo32.c bootinfo64.c \
comconsole.c devicename.c elf32_freebsd.c \
- elf64_freebsd.c \
+ elf64_freebsd.c multiboot.c multiboot_tramp.S \
i386_copy.c i386_module.c nullconsole.c pxe.c pxetramp.s \
smbios.c time.c vidconsole.c amd64_tramp.S spinconsole.c
.PATH: ${.CURDIR}/../../zfs
@@ -65,6 +65,7 @@ machine:
# XXX: clang integrated-as doesn't grok .codeNN directives yet
CFLAGS.amd64_tramp.S= ${CLANG_NO_IAS}
+CFLAGS.multiboot_tramp.S= ${CLANG_NO_IAS}
CFLAGS+= ${CFLAGS.${.IMPSRC:T}}
.if ${MACHINE_CPUARCH} == "amd64"
diff --git a/sys/boot/i386/libi386/bootinfo64.c b/sys/boot/i386/libi386/bootinfo64.c
index 617414e..751e806 100644
--- a/sys/boot/i386/libi386/bootinfo64.c
+++ b/sys/boot/i386/libi386/bootinfo64.c
@@ -33,6 +33,7 @@ __FBSDID("$FreeBSD$");
#include <sys/linker.h>
#include <machine/bootinfo.h>
#include <machine/cpufunc.h>
+#include <machine/metadata.h>
#include <machine/psl.h>
#include <machine/specialreg.h>
#include "bootstrap.h"
@@ -176,14 +177,15 @@ bi_checkcpu(void)
* - Module metadata are formatted and placed in kernel space.
*/
int
-bi_load64(char *args, vm_offset_t *modulep, vm_offset_t *kernendp)
+bi_load64(char *args, vm_offset_t addr, vm_offset_t *modulep,
+ vm_offset_t *kernendp, int add_smap)
{
struct preloaded_file *xp, *kfp;
struct i386_devdesc *rootdev;
struct file_metadata *md;
- vm_offset_t addr;
u_int64_t kernend;
u_int64_t envp;
+ u_int64_t module;
vm_offset_t size;
char *rootdevname;
int howto;
@@ -210,21 +212,18 @@ bi_load64(char *args, vm_offset_t *modulep, vm_offset_t *kernendp)
/* Try reading the /etc/fstab file to select the root device */
getrootmount(i386_fmtdev((void *)rootdev));
- /* find the last module in the chain */
- addr = 0;
- for (xp = file_findfile(NULL, NULL); xp != NULL; xp = xp->f_next) {
- if (addr < (xp->f_addr + xp->f_size))
- addr = xp->f_addr + xp->f_size;
+ if (addr == 0) {
+ /* find the last module in the chain */
+ for (xp = file_findfile(NULL, NULL); xp != NULL; xp = xp->f_next) {
+ if (addr < (xp->f_addr + xp->f_size))
+ addr = xp->f_addr + xp->f_size;
+ }
}
/* pad to a page boundary */
addr = roundup(addr, PAGE_SIZE);
- /* copy our environment */
- envp = addr;
- addr = bi_copyenv(addr);
-
- /* pad to a page boundary */
- addr = roundup(addr, PAGE_SIZE);
+ /* place the metadata before anything */
+ module = *modulep = addr;
kfp = file_findfile(NULL, "elf kernel");
if (kfp == NULL)
@@ -235,20 +234,30 @@ bi_load64(char *args, vm_offset_t *modulep, vm_offset_t *kernendp)
file_addmetadata(kfp, MODINFOMD_HOWTO, sizeof howto, &howto);
file_addmetadata(kfp, MODINFOMD_ENVP, sizeof envp, &envp);
file_addmetadata(kfp, MODINFOMD_KERNEND, sizeof kernend, &kernend);
- bios_addsmapdata(kfp);
+ file_addmetadata(kfp, MODINFOMD_MODULEP, sizeof module, &module);
+ if (add_smap != 0)
+ bios_addsmapdata(kfp);
- /* Figure out the size and location of the metadata */
- *modulep = addr;
size = bi_copymodules64(0);
- kernend = roundup(addr + size, PAGE_SIZE);
+
+ /* copy our environment */
+ envp = roundup(addr + size, PAGE_SIZE);
+ addr = bi_copyenv(envp);
+
+ /* set kernend */
+ kernend = roundup(addr, PAGE_SIZE);
*kernendp = kernend;
/* patch MODINFOMD_KERNEND */
md = file_findmetadata(kfp, MODINFOMD_KERNEND);
bcopy(&kernend, md->md_data, sizeof kernend);
+ /* patch MODINFOMD_ENVP */
+ md = file_findmetadata(kfp, MODINFOMD_ENVP);
+ bcopy(&envp, md->md_data, sizeof envp);
+
/* copy module list and metadata */
- (void)bi_copymodules64(addr);
+ (void)bi_copymodules64(*modulep);
return(0);
}
diff --git a/sys/boot/i386/libi386/elf64_freebsd.c b/sys/boot/i386/libi386/elf64_freebsd.c
index 627d416..338a745 100644
--- a/sys/boot/i386/libi386/elf64_freebsd.c
+++ b/sys/boot/i386/libi386/elf64_freebsd.c
@@ -81,7 +81,7 @@ elf64_exec(struct preloaded_file *fp)
return(EFTYPE);
ehdr = (Elf_Ehdr *)&(md->md_data);
- err = bi_load64(fp->f_args, &modulep, &kernend);
+ err = bi_load64(fp->f_args, 0, &modulep, &kernend, 1);
if (err != 0)
return(err);
diff --git a/sys/boot/i386/libi386/libi386.h b/sys/boot/i386/libi386/libi386.h
index 357b8fd..e8bdf65 100644
--- a/sys/boot/i386/libi386/libi386.h
+++ b/sys/boot/i386/libi386/libi386.h
@@ -117,6 +117,7 @@ void bi_setboothowto(int howto);
vm_offset_t bi_copyenv(vm_offset_t addr);
int bi_load32(char *args, int *howtop, int *bootdevp, vm_offset_t *bip,
vm_offset_t *modulep, vm_offset_t *kernend);
-int bi_load64(char *args, vm_offset_t *modulep, vm_offset_t *kernend);
+int bi_load64(char *args, vm_offset_t addr, vm_offset_t *modulep,
+ vm_offset_t *kernend, int add_smap);
void pxe_enable(void *pxeinfo);
diff --git a/sys/boot/i386/libi386/multiboot.c b/sys/boot/i386/libi386/multiboot.c
new file mode 100644
index 0000000..00e36f2
--- /dev/null
+++ b/sys/boot/i386/libi386/multiboot.c
@@ -0,0 +1,425 @@
+/*-
+ * Copyright (c) 2014 Roger Pau Monné <royger@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.
+ */
+
+/*
+ * This multiboot implementation only implements a subset of the full
+ * multiboot specification in order to be able to boot Xen and a
+ * FreeBSD Dom0. Trying to use it to boot other multiboot compliant
+ * kernels will most surely fail.
+ *
+ * The full multiboot specification can be found here:
+ * http://www.gnu.org/software/grub/manual/multiboot/multiboot.html
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/exec.h>
+#include <sys/linker.h>
+#include <sys/module.h>
+#include <sys/stdint.h>
+#define _MACHINE_ELF_WANT_32BIT
+#include <machine/elf.h>
+#include <string.h>
+#include <stand.h>
+
+#include "bootstrap.h"
+#include "multiboot.h"
+#include "../i386/libi386/libi386.h"
+#include "../i386/btx/lib/btxv86.h"
+
+#define MULTIBOOT_SUPPORTED_FLAGS \
+ (MULTIBOOT_PAGE_ALIGN|MULTIBOOT_MEMORY_INFO)
+#define NUM_MODULES 2
+#define METADATA_FIXED_SIZE (PAGE_SIZE*4)
+#define METADATA_MODULE_SIZE PAGE_SIZE
+
+#define METADATA_RESV_SIZE(mod_num) \
+ roundup(METADATA_FIXED_SIZE + METADATA_MODULE_SIZE * mod_num, PAGE_SIZE)
+
+extern int elf32_loadfile_raw(char *filename, u_int64_t dest,
+ struct preloaded_file **result, int multiboot);
+extern int elf64_load_modmetadata(struct preloaded_file *fp, u_int64_t dest);
+extern int elf64_obj_loadfile(char *filename, u_int64_t dest,
+ struct preloaded_file **result);
+
+static int multiboot_loadfile(char *, u_int64_t, struct preloaded_file **);
+static int multiboot_exec(struct preloaded_file *);
+
+static int multiboot_obj_loadfile(char *, u_int64_t, struct preloaded_file **);
+static int multiboot_obj_exec(struct preloaded_file *fp);
+
+struct file_format multiboot = { multiboot_loadfile, multiboot_exec };
+struct file_format multiboot_obj =
+ { multiboot_obj_loadfile, multiboot_obj_exec };
+
+extern void multiboot_tramp();
+
+static const char mbl_name[] = "FreeBSD Loader";
+
+static int
+num_modules(struct preloaded_file *kfp)
+{
+ struct kernel_module *kmp;
+ int mod_num = 0;
+
+ for (kmp = kfp->f_modules; kmp != NULL; kmp = kmp->m_next)
+ mod_num++;
+
+ return (mod_num);
+}
+
+static vm_offset_t
+max_addr(void)
+{
+ struct preloaded_file *fp;
+ vm_offset_t addr = 0;
+
+ for (fp = file_findfile(NULL, NULL); fp != NULL; fp = fp->f_next) {
+ if (addr < (fp->f_addr + fp->f_size))
+ addr = fp->f_addr + fp->f_size;
+ }
+
+ return (addr);
+}
+
+static int
+multiboot_loadfile(char *filename, u_int64_t dest,
+ struct preloaded_file **result)
+{
+ uint32_t *magic;
+ int i, error;
+ caddr_t header_search;
+ ssize_t search_size;
+ int fd;
+ struct multiboot_header *header;
+ char *cmdline;
+
+ /*
+ * Read MULTIBOOT_SEARCH size in order to search for the
+ * multiboot magic header.
+ */
+ if (filename == NULL)
+ return (EFTYPE);
+ if ((fd = open(filename, O_RDONLY)) == -1)
+ return (errno);
+ header_search = malloc(MULTIBOOT_SEARCH);
+ if (header_search == NULL) {
+ close(fd);
+ return (ENOMEM);
+ }
+ search_size = read(fd, header_search, MULTIBOOT_SEARCH);
+ magic = (uint32_t *)header_search;
+
+ header = NULL;
+ for (i = 0; i < (search_size / sizeof(uint32_t)); i++) {
+ if (magic[i] == MULTIBOOT_HEADER_MAGIC) {
+ header = (struct multiboot_header *)&magic[i];
+ break;
+ }
+ }
+
+ if (header == NULL) {
+ error = EFTYPE;
+ goto out;
+ }
+
+ /* Valid multiboot header has been found, validate checksum */
+ if (header->magic + header->flags + header->checksum != 0) {
+ printf(
+ "Multiboot checksum failed, magic: 0x%x flags: 0x%x checksum: 0x%x\n",
+ header->magic, header->flags, header->checksum);
+ error = EFTYPE;
+ goto out;
+ }
+
+ if ((header->flags & ~MULTIBOOT_SUPPORTED_FLAGS) != 0) {
+ printf("Unsupported multiboot flags found: 0x%x\n",
+ header->flags);
+ error = EFTYPE;
+ goto out;
+ }
+
+ error = elf32_loadfile_raw(filename, dest, result, 1);
+ if (error != 0) {
+ printf(
+ "elf32_loadfile_raw failed: %d unable to load multiboot kernel\n",
+ error);
+ goto out;
+ }
+
+ /*
+ * f_addr is already aligned to PAGE_SIZE, make sure
+ * f_size it's also aligned so when the modules are loaded
+ * they are aligned to PAGE_SIZE.
+ */
+ (*result)->f_size = roundup((*result)->f_size, PAGE_SIZE);
+
+out:
+ free(header_search);
+ close(fd);
+ return (error);
+}
+
+static int
+multiboot_exec(struct preloaded_file *fp)
+{
+ vm_offset_t module_start, last_addr, metadata_size;
+ vm_offset_t modulep, kernend, entry;
+ struct file_metadata *md;
+ Elf_Ehdr *ehdr;
+ struct multiboot_info *mb_info = NULL;
+ struct multiboot_mod_list *mb_mod = NULL;
+ char *cmdline = NULL;
+ size_t len;
+ int error, mod_num;
+
+ /*
+ * Don't pass the memory size found by the bootloader, the memory
+ * available to Dom0 will be lower than that.
+ */
+ unsetenv("smbios.memory.enabled");
+
+ /* Allocate the multiboot struct and fill the basic details. */
+ mb_info = malloc(sizeof(struct multiboot_info));
+ if (mb_info == NULL) {
+ error = ENOMEM;
+ goto error;
+ }
+ bzero(mb_info, sizeof(struct multiboot_info));
+ mb_info->flags = MULTIBOOT_INFO_MEMORY|MULTIBOOT_INFO_BOOT_LOADER_NAME;
+ mb_info->mem_lower = bios_basemem / 1024;
+ mb_info->mem_upper = bios_extmem / 1024;
+ mb_info->boot_loader_name = VTOP(mbl_name);
+
+ /* Set the Xen command line. */
+ if (fp->f_args == NULL) {
+ /* Add the Xen command line if it is set. */
+ cmdline = getenv("xen_cmdline");
+ if (cmdline != NULL) {
+ fp->f_args = strdup(cmdline);
+ if (fp->f_args == NULL) {
+ error = ENOMEM;
+ goto error;
+ }
+ }
+ }
+ if (fp->f_args != NULL) {
+ len = strlen(fp->f_name) + 1 + strlen(fp->f_args) + 1;
+ cmdline = malloc(len);
+ if (cmdline == NULL) {
+ error = ENOMEM;
+ goto error;
+ }
+ snprintf(cmdline, len, "%s %s", fp->f_name, fp->f_args);
+ mb_info->cmdline = VTOP(cmdline);
+ mb_info->flags |= MULTIBOOT_INFO_CMDLINE;
+ }
+
+ /* Find the entry point of the Xen kernel and save it for later */
+ if ((md = file_findmetadata(fp, MODINFOMD_ELFHDR)) == NULL) {
+ printf("Unable to find %s entry point\n", fp->f_name);
+ error = EINVAL;
+ goto error;
+ }
+ ehdr = (Elf_Ehdr *)&(md->md_data);
+ entry = ehdr->e_entry & 0xffffff;
+
+ /*
+ * Prepare the multiboot module list, Xen assumes the first
+ * module is the Dom0 kernel, and the second one is the initramfs.
+ * This is not optimal for FreeBSD, that doesn't have a initramfs
+ * but instead loads modules dynamically and creates the metadata
+ * info on-the-fly.
+ *
+ * As expected, the first multiboot module is going to be the
+ * FreeBSD kernel loaded as a raw file. The second module is going
+ * to contain the metadata info and the loaded modules.
+ *
+ * On native FreeBSD loads all the modules and then places the
+ * metadata info at the end, but this is painful when running on Xen,
+ * because it relocates the second multiboot module wherever it
+ * likes. In order to workaround this limitation the metadata
+ * information is placed at the start of the second module and
+ * the original modulep value is saved together with the other
+ * metadata, so we can relocate everything.
+ */
+ fp = file_findfile(NULL, "elf kernel");
+ if (fp == NULL) {
+ printf("No FreeBSD kernel provided, aborting\n");
+ error = EINVAL;
+ goto error;
+ }
+
+ mb_mod = malloc(sizeof(struct multiboot_mod_list) * NUM_MODULES);
+ if (mb_mod == NULL) {
+ error = ENOMEM;
+ goto error;
+ }
+
+ bzero(mb_mod, sizeof(struct multiboot_mod_list) * NUM_MODULES);
+
+ /*
+ * Calculate how much memory is needed for the metatdata. We did
+ * an approximation of the maximum size when loading the kernel,
+ * but now we know the exact size, so we can release some of this
+ * preallocated memory if not needed.
+ */
+ last_addr = roundup(max_addr(), PAGE_SIZE);
+ mod_num = num_modules(fp);
+
+ /*
+ * Place the metadata after the last used address in order to
+ * calculate it's size, this will not be used.
+ */
+ error = bi_load64(fp->f_args, last_addr, &modulep, &kernend, 0);
+ if (error != 0) {
+ printf("bi_load64 failed: %d\n", error);
+ goto error;
+ }
+ metadata_size = roundup(kernend - last_addr, PAGE_SIZE);
+
+ /* Check that the size is not greater than what we have reserved */
+ if (metadata_size > METADATA_RESV_SIZE(mod_num)) {
+ printf("Required memory for metadata is greater than reserved "
+ "space, please increase METADATA_FIXED_SIZE and "
+ "METADATA_MODULE_SIZE and rebuild the loader\n");
+ error = ENOMEM;
+ goto error;
+ }
+
+ /*
+ * This is the position where the second multiboot module
+ * will be placed.
+ */
+ module_start = fp->f_addr + fp->f_size - metadata_size;
+
+ error = bi_load64(fp->f_args, module_start, &modulep, &kernend, 0);
+ if (error != 0) {
+ printf("bi_load64 failed: %d\n", error);
+ goto error;
+ }
+
+ mb_mod[0].mod_start = fp->f_addr;
+ mb_mod[0].mod_end = fp->f_addr + fp->f_size;
+ mb_mod[0].mod_end -= METADATA_RESV_SIZE(mod_num);
+
+ mb_mod[1].mod_start = module_start;
+ mb_mod[1].mod_end = last_addr;
+
+ mb_info->mods_count = NUM_MODULES;
+ mb_info->mods_addr = VTOP(mb_mod);
+ mb_info->flags |= MULTIBOOT_INFO_MODS;
+
+ dev_cleanup();
+ __exec((void *)VTOP(multiboot_tramp), (void *)entry,
+ (void *)VTOP(mb_info));
+
+ panic("exec returned");
+
+error:
+ if (mb_mod)
+ free(mb_mod);
+ if (mb_info)
+ free(mb_info);
+ if (cmdline)
+ free(cmdline);
+ return (error);
+}
+
+static int
+multiboot_obj_loadfile(char *filename, u_int64_t dest,
+ struct preloaded_file **result)
+{
+ struct preloaded_file *mfp, *kfp, *rfp;
+ struct kernel_module *kmp;
+ int error, mod_num;
+
+ /* See if there's a multiboot kernel loaded */
+ mfp = file_findfile(NULL, "elf multiboot kernel");
+ if (mfp == NULL)
+ return (EFTYPE);
+
+ /*
+ * We have a multiboot kernel loaded, see if there's a FreeBSD
+ * kernel loaded also.
+ */
+ kfp = file_findfile(NULL, "elf kernel");
+ if (kfp == NULL) {
+ /*
+ * No kernel loaded, this must be it. The kernel has to
+ * be loaded as a raw file, it will be processed by
+ * Xen and correctly loaded as an ELF file.
+ */
+ rfp = file_loadraw(filename, "elf kernel", 0);
+ if (rfp == NULL) {
+ printf(
+ "Unable to load %s as a multiboot payload kernel\n",
+ filename);
+ return (EINVAL);
+ }
+
+ /* Load kernel metadata... */
+ setenv("kernelname", filename, 1);
+ error = elf64_load_modmetadata(rfp, rfp->f_addr + rfp->f_size);
+ if (error) {
+ printf("Unable to load kernel %s metadata error: %d\n",
+ rfp->f_name, error);
+ return (EINVAL);
+ }
+
+ /*
+ * Save space at the end of the kernel in order to place
+ * the metadata information. We do an approximation of the
+ * max metadata size, this is not optimal but it's probably
+ * the best we can do at this point. Once all modules are
+ * loaded and the size of the metadata is known this
+ * space will be recovered if not used.
+ */
+ mod_num = num_modules(rfp);
+ rfp->f_size = roundup(rfp->f_size, PAGE_SIZE);
+ rfp->f_size += METADATA_RESV_SIZE(mod_num);
+ *result = rfp;
+ } else {
+ /* The rest should be loaded as regular modules */
+ error = elf64_obj_loadfile(filename, dest, result);
+ if (error != 0) {
+ printf("Unable to load %s as an object file, error: %d",
+ filename, error);
+ return (error);
+ }
+ }
+
+ return (0);
+}
+
+static int
+multiboot_obj_exec(struct preloaded_file *fp)
+{
+
+ return (EFTYPE);
+}
diff --git a/sys/boot/i386/libi386/multiboot.h b/sys/boot/i386/libi386/multiboot.h
new file mode 100644
index 0000000..819fa2e
--- /dev/null
+++ b/sys/boot/i386/libi386/multiboot.h
@@ -0,0 +1,225 @@
+/* multiboot.h - Multiboot header file. */
+/* Copyright (C) 1999,2003,2007,2008,2009 Free Software Foundation, Inc.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy
+* of this software and associated documentation files (the "Software"), to
+* deal in the Software without restriction, including without limitation the
+* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+* sell copies of the Software, and to permit persons to whom the Software is
+* furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ANY
+* DEVELOPER OR DISTRIBUTOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+* IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*
+* $FreeBSD$
+*/
+
+#ifndef MULTIBOOT_HEADER
+#define MULTIBOOT_HEADER 1
+
+/* How many bytes from the start of the file we search for the header. */
+#define MULTIBOOT_SEARCH 8192
+
+/* The magic field should contain this. */
+#define MULTIBOOT_HEADER_MAGIC 0x1BADB002
+
+/* This should be in %eax. */
+#define MULTIBOOT_BOOTLOADER_MAGIC 0x2BADB002
+
+/* The bits in the required part of flags field we don't support. */
+#define MULTIBOOT_UNSUPPORTED 0x0000fffc
+
+/* Alignment of multiboot modules. */
+#define MULTIBOOT_MOD_ALIGN 0x00001000
+
+/* Alignment of the multiboot info structure. */
+#define MULTIBOOT_INFO_ALIGN 0x00000004
+
+/* Flags set in the 'flags' member of the multiboot header. */
+
+/* Align all boot modules on i386 page (4KB) boundaries. */
+#define MULTIBOOT_PAGE_ALIGN 0x00000001
+
+/* Must pass memory information to OS. */
+#define MULTIBOOT_MEMORY_INFO 0x00000002
+
+/* Must pass video information to OS. */
+#define MULTIBOOT_VIDEO_MODE 0x00000004
+
+/* This flag indicates the use of the address fields in the header. */
+#define MULTIBOOT_AOUT_KLUDGE 0x00010000
+
+/* Flags to be set in the 'flags' member of the multiboot info structure. */
+
+/* is there basic lower/upper memory information? */
+#define MULTIBOOT_INFO_MEMORY 0x00000001
+/* is there a boot device set? */
+#define MULTIBOOT_INFO_BOOTDEV 0x00000002
+/* is the command-line defined? */
+#define MULTIBOOT_INFO_CMDLINE 0x00000004
+/* are there modules to do something with? */
+#define MULTIBOOT_INFO_MODS 0x00000008
+
+/* These next two are mutually exclusive */
+
+/* is there a symbol table loaded? */
+#define MULTIBOOT_INFO_AOUT_SYMS 0x00000010
+/* is there an ELF section header table? */
+#define MULTIBOOT_INFO_ELF_SHDR 0X00000020
+
+/* is there a full memory map? */
+#define MULTIBOOT_INFO_MEM_MAP 0x00000040
+
+/* Is there drive info? */
+#define MULTIBOOT_INFO_DRIVE_INFO 0x00000080
+
+/* Is there a config table? */
+#define MULTIBOOT_INFO_CONFIG_TABLE 0x00000100
+
+/* Is there a boot loader name? */
+#define MULTIBOOT_INFO_BOOT_LOADER_NAME 0x00000200
+
+/* Is there a APM table? */
+#define MULTIBOOT_INFO_APM_TABLE 0x00000400
+
+/* Is there video information? */
+#define MULTIBOOT_INFO_VIDEO_INFO 0x00000800
+
+#ifndef ASM_FILE
+
+typedef unsigned short multiboot_uint16_t;
+typedef unsigned int multiboot_uint32_t;
+typedef unsigned long long multiboot_uint64_t;
+
+struct multiboot_header
+{
+/* Must be MULTIBOOT_MAGIC - see above. */
+ multiboot_uint32_t magic;
+
+/* Feature flags. */
+ multiboot_uint32_t flags;
+
+/* The above fields plus this one must equal 0 mod 2^32. */
+ multiboot_uint32_t checksum;
+
+/* These are only valid if MULTIBOOT_AOUT_KLUDGE is set. */
+ multiboot_uint32_t header_addr;
+ multiboot_uint32_t load_addr;
+ multiboot_uint32_t load_end_addr;
+ multiboot_uint32_t bss_end_addr;
+ multiboot_uint32_t entry_addr;
+
+/* These are only valid if MULTIBOOT_VIDEO_MODE is set. */
+ multiboot_uint32_t mode_type;
+ multiboot_uint32_t width;
+ multiboot_uint32_t height;
+ multiboot_uint32_t depth;
+};
+
+/* The symbol table for a.out. */
+struct multiboot_aout_symbol_table
+{
+ multiboot_uint32_t tabsize;
+ multiboot_uint32_t strsize;
+ multiboot_uint32_t addr;
+ multiboot_uint32_t reserved;
+};
+typedef struct multiboot_aout_symbol_table multiboot_aout_symbol_table_t;
+
+/* The section header table for ELF. */
+struct multiboot_elf_section_header_table
+{
+ multiboot_uint32_t num;
+ multiboot_uint32_t size;
+ multiboot_uint32_t addr;
+ multiboot_uint32_t shndx;
+};
+typedef struct multiboot_elf_section_header_table multiboot_elf_section_header_table_t;
+
+struct multiboot_info
+{
+/* Multiboot info version number */
+ multiboot_uint32_t flags;
+
+/* Available memory from BIOS */
+ multiboot_uint32_t mem_lower;
+ multiboot_uint32_t mem_upper;
+
+/* "root" partition */
+ multiboot_uint32_t boot_device;
+
+/* Kernel command line */
+ multiboot_uint32_t cmdline;
+
+/* Boot-Module list */
+ multiboot_uint32_t mods_count;
+ multiboot_uint32_t mods_addr;
+
+ union
+ {
+ multiboot_aout_symbol_table_t aout_sym;
+ multiboot_elf_section_header_table_t elf_sec;
+ } u;
+
+/* Memory Mapping buffer */
+ multiboot_uint32_t mmap_length;
+ multiboot_uint32_t mmap_addr;
+
+/* Drive Info buffer */
+ multiboot_uint32_t drives_length;
+ multiboot_uint32_t drives_addr;
+
+/* ROM configuration table */
+ multiboot_uint32_t config_table;
+
+/* Boot Loader Name */
+ multiboot_uint32_t boot_loader_name;
+
+/* APM table */
+ multiboot_uint32_t apm_table;
+
+/* Video */
+ multiboot_uint32_t vbe_control_info;
+ multiboot_uint32_t vbe_mode_info;
+ multiboot_uint16_t vbe_mode;
+ multiboot_uint16_t vbe_interface_seg;
+ multiboot_uint16_t vbe_interface_off;
+ multiboot_uint16_t vbe_interface_len;
+};
+typedef struct multiboot_info multiboot_info_t;
+
+struct multiboot_mmap_entry
+{
+ multiboot_uint32_t size;
+ multiboot_uint64_t addr;
+ multiboot_uint64_t len;
+#define MULTIBOOT_MEMORY_AVAILABLE 1
+#define MULTIBOOT_MEMORY_RESERVED 2
+ multiboot_uint32_t type;
+} __attribute__((packed));
+typedef struct multiboot_mmap_entry multiboot_memory_map_t;
+
+struct multiboot_mod_list
+{
+/* the memory used goes from bytes 'mod_start' to 'mod_end-1' inclusive */
+ multiboot_uint32_t mod_start;
+ multiboot_uint32_t mod_end;
+
+/* Module command line */
+ multiboot_uint32_t cmdline;
+
+/* padding to take it to 16 bytes (must be zero) */
+ multiboot_uint32_t pad;
+};
+typedef struct multiboot_mod_list multiboot_module_t;
+
+#endif /* ! ASM_FILE */
+
+#endif /* ! MULTIBOOT_HEADER */
diff --git a/sys/boot/i386/libi386/multiboot_tramp.S b/sys/boot/i386/libi386/multiboot_tramp.S
new file mode 100644
index 0000000..0bd6043
--- /dev/null
+++ b/sys/boot/i386/libi386/multiboot_tramp.S
@@ -0,0 +1,51 @@
+/*-
+ * Copyright (c) 2014 Roger Pau Monné <royger@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.
+ *
+ * $FreeBSD$
+ */
+
+#define ASM_FILE
+#include "multiboot.h"
+
+/*
+ * The multiboot specification requires the executable to be launched
+ * with %cs set to a flat read/execute segment with offset 0 and limit
+ * 0xFFFFFFFF, and the rest of the segment registers (%ds, %es, %fs,
+ * %gs, %ss) to flat read/write segments with the same offset and limit.
+ * This is already done by the BTX code before calling multiboot_tramp,
+ * so there is no need to do anything here.
+ */
+
+ .globl multiboot_tramp
+multiboot_tramp:
+ /* Be sure that interrupts are disabled. */
+ cli
+
+ movl $MULTIBOOT_BOOTLOADER_MAGIC, %eax
+ /* Get the entry point and address of the multiboot_info parameter. */
+ movl 8(%esp), %ebx
+ movl 4(%esp), %ecx
+
+ call *%ecx
diff --git a/sys/boot/i386/loader/conf.c b/sys/boot/i386/loader/conf.c
index fda6fd2..38df74d 100644
--- a/sys/boot/i386/loader/conf.c
+++ b/sys/boot/i386/loader/conf.c
@@ -107,8 +107,12 @@ extern struct file_format i386_elf;
extern struct file_format i386_elf_obj;
extern struct file_format amd64_elf;
extern struct file_format amd64_elf_obj;
+extern struct file_format multiboot;
+extern struct file_format multiboot_obj;
struct file_format *file_formats[] = {
+ &multiboot,
+ &multiboot_obj,
#ifdef LOADER_PREFER_AMD64
&amd64_elf,
&amd64_elf_obj,
diff --git a/sys/boot/i386/zfsboot/zfsboot.c b/sys/boot/i386/zfsboot/zfsboot.c
index afb77b2..ca82c63 100644
--- a/sys/boot/i386/zfsboot/zfsboot.c
+++ b/sys/boot/i386/zfsboot/zfsboot.c
@@ -238,7 +238,7 @@ bios_getmem(void)
v86.es = VTOPSEG(&smap);
v86.edi = VTOPOFF(&smap);
v86int();
- if ((v86.efl & 1) || (v86.eax != SMAP_SIG))
+ if (V86_CY(v86.efl) || (v86.eax != SMAP_SIG))
break;
/* look for a low-memory segment that's large enough */
if ((smap.type == SMAP_TYPE_MEMORY) && (smap.base == 0) &&
@@ -285,7 +285,7 @@ bios_getmem(void)
v86.addr = 0x15; /* int 0x15 function 0xe801*/
v86.eax = 0xe801;
v86int();
- if (!(v86.efl & 1)) {
+ if (!V86_CY(v86.efl)) {
bios_extmem = ((v86.ecx & 0xffff) + ((v86.edx & 0xffff) * 64)) * 1024;
}
}
@@ -320,7 +320,7 @@ int13probe(int drive)
v86.edx = drive;
v86int();
- if (!(v86.efl & 0x1) && /* carry clear */
+ if (!V86_CY(v86.efl) && /* carry clear */
((v86.edx & 0xff) != (drive & DRV_MASK))) { /* unit # OK */
if ((v86.ecx & 0x3f) == 0) { /* absurd sector size */
return(0); /* skip device */
diff --git a/sys/boot/ia64/efi/Makefile b/sys/boot/ia64/efi/Makefile
index 6bb53b5..18b6d3a 100644
--- a/sys/boot/ia64/efi/Makefile
+++ b/sys/boot/ia64/efi/Makefile
@@ -37,7 +37,6 @@ FILESMODE_loader.efi= ${BINMODE}
loader.efi: loader.sym
if [ `${OBJDUMP} -t ${.ALLSRC} | fgrep '*UND*' | wc -l` != 0 ]; then \
${OBJDUMP} -t ${.ALLSRC} | fgrep '*UND*'; \
- rm ${.ALLSRC}; \
exit 1; \
fi
${OBJCOPY} -j .data -j .dynamic -j .dynstr -j .dynsym -j .hash \
diff --git a/sys/boot/libstand32/Makefile b/sys/boot/libstand32/Makefile
index 1fc04a2..4ee8690 100644
--- a/sys/boot/libstand32/Makefile
+++ b/sys/boot/libstand32/Makefile
@@ -63,8 +63,8 @@ SRCS+= ntoh.c
.if ${MACHINE_CPUARCH} != "ia64"
SRCS+= bcmp.c bcopy.c bzero.c ffs.c memccpy.c memchr.c memcmp.c memcpy.c \
memmove.c memset.c qdivrem.c strcat.c strchr.c strcmp.c strcpy.c \
- strcspn.c strlen.c strncat.c strncmp.c strncpy.c strpbrk.c \
- strrchr.c strsep.c strspn.c strstr.c strtok.c swab.c
+ strcspn.c strlcat.c strlcpy.c strlen.c strncat.c strncmp.c strncpy.c \
+ strpbrk.c strrchr.c strsep.c strspn.c strstr.c strtok.c swab.c
.endif
.if ${MACHINE_CPUARCH} == "arm"
.PATH: ${LIBC}/arm/gen
diff --git a/sys/boot/pc98/boot2/boot2.c b/sys/boot/pc98/boot2/boot2.c
index 69a422e..72aae7d 100644
--- a/sys/boot/pc98/boot2/boot2.c
+++ b/sys/boot/pc98/boot2/boot2.c
@@ -326,7 +326,7 @@ bd_getbigeom(int bunit)
v86.addr = 0x1b;
v86.eax = 0x8400 | unit;
v86int();
- if (v86.efl & 0x1)
+ if (V86_CY(v86.efl))
return 0x4F020F; /* 1200KB FD C:80 H:2 S:15 */
return ((v86.ecx & 0xffff) << 16) | (v86.edx & 0xffff);
}
diff --git a/sys/boot/pc98/libpc98/biosdisk.c b/sys/boot/pc98/libpc98/biosdisk.c
index 96dbd1f..b777d25 100644
--- a/sys/boot/pc98/libpc98/biosdisk.c
+++ b/sys/boot/pc98/libpc98/biosdisk.c
@@ -824,7 +824,7 @@ bd_chs_io(struct open_disk *od, daddr_t dblk, int blks, caddr_t dest, int write)
v86.es = VTOPSEG(dest);
v86.ebp = VTOPOFF(dest);
v86int();
- return (v86.efl & 0x1);
+ return (V86_CY(v86.efl));
}
static int
@@ -959,7 +959,7 @@ bd_getgeom(struct open_disk *od)
od->od_cyl = v86.ecx;
od->od_hds = (v86.edx >> 8) & 0xff;
od->od_sec = v86.edx & 0xff;
- if (v86.efl & 0x1)
+ if (V86_CY(v86.efl))
return(1);
}
@@ -1010,7 +1010,7 @@ bd_getbigeom(int bunit)
v86.addr = 0x1b;
v86.eax = 0x8400 | unit;
v86int();
- if (v86.efl & 0x1)
+ if (V86_CY(v86.efl))
return 0x4F020F; /* 1200KB FD C:80 H:2 S:15 */
return ((v86.ecx & 0xffff) << 16) | (v86.edx & 0xffff);
}
diff --git a/sys/boot/uboot/common/main.c b/sys/boot/uboot/common/main.c
index b830354..d860d97 100644
--- a/sys/boot/uboot/common/main.c
+++ b/sys/boot/uboot/common/main.c
@@ -315,7 +315,7 @@ print_disk_probe_info()
else
strcpy(slice, "<auto>");
- if (currdev.d_disk.partition > 0)
+ if (currdev.d_disk.partition >= 0)
sprintf(partition, "%d", currdev.d_disk.partition);
else
strcpy(partition, "<auto>");
@@ -382,7 +382,7 @@ probe_disks(int devidx, int load_type, int load_unit, int load_slice,
printf("\n");
}
- printf(" Requested disk type/unit not found\n");
+ printf(" Requested disk type/unit/slice/partition not found\n");
return (-1);
}
@@ -392,7 +392,7 @@ main(void)
struct api_signature *sig = NULL;
int load_type, load_unit, load_slice, load_partition;
int i;
- const char * loaderdev;
+ const char *ldev;
/*
* If we can't find the magic signature and related info, exit with a
@@ -485,10 +485,10 @@ main(void)
return (0xbadef1ce);
}
- env_setenv("currdev", EV_VOLATILE, uboot_fmtdev(&currdev),
- uboot_setcurrdev, env_nounset);
- env_setenv("loaddev", EV_VOLATILE, uboot_fmtdev(&currdev),
- env_noset, env_nounset);
+ ldev = uboot_fmtdev(&currdev);
+ env_setenv("currdev", EV_VOLATILE, ldev, uboot_setcurrdev, env_nounset);
+ env_setenv("loaddev", EV_VOLATILE, ldev, env_noset, env_nounset);
+ printf("Booting from %s\n", ldev);
setenv("LINES", "24", 1); /* optional */
setenv("prompt", "loader>", 1);
@@ -573,17 +573,47 @@ enum ubenv_action {
static void
handle_uboot_env_var(enum ubenv_action action, const char * var)
{
- const char * val;
- char ubv[128];
+ char ldvar[128];
+ const char *val;
+ char *wrk;
+ int len;
+
+ /*
+ * On an import with the variable name formatted as ldname=ubname,
+ * import the uboot variable ubname into the loader variable ldname,
+ * otherwise the historical behavior is to import to uboot.ubname.
+ */
+ if (action == UBENV_IMPORT) {
+ len = strcspn(var, "=");
+ if (len == 0) {
+ printf("name cannot start with '=': '%s'\n", var);
+ return;
+ }
+ if (var[len] == 0) {
+ strcpy(ldvar, "uboot.");
+ strncat(ldvar, var, sizeof(ldvar) - 7);
+ } else {
+ len = MIN(len, sizeof(ldvar) - 1);
+ strncpy(ldvar, var, len);
+ ldvar[len] = 0;
+ var = &var[len + 1];
+ }
+ }
/*
* If the user prepended "uboot." (which is how they usually see these
* names) strip it off as a convenience.
*/
if (strncmp(var, "uboot.", 6) == 0) {
- snprintf(ubv, sizeof(ubv), "%s", &var[6]);
- var = ubv;
+ var = &var[6];
}
+
+ /* If there is no variable name left, punt. */
+ if (var[0] == 0) {
+ printf("empty variable name\n");
+ return;
+ }
+
val = ub_env_get(var);
if (action == UBENV_SHOW) {
if (val == NULL)
@@ -592,8 +622,7 @@ handle_uboot_env_var(enum ubenv_action action, const char * var)
printf("uboot.%s=%s\n", var, val);
} else if (action == UBENV_IMPORT) {
if (val != NULL) {
- snprintf(ubv, sizeof(ubv), "uboot.%s", var);
- setenv(ubv, val, 1);
+ setenv(ldvar, val, 1);
}
}
}
diff --git a/sys/boot/uboot/lib/copy.c b/sys/boot/uboot/lib/copy.c
index bb658e3..76f2faf 100644
--- a/sys/boot/uboot/lib/copy.c
+++ b/sys/boot/uboot/lib/copy.c
@@ -69,11 +69,11 @@ uint64_t
uboot_loadaddr(u_int type, void *data, uint64_t addr)
{
struct sys_info *si;
- uintptr_t sblock, eblock, subldr, eubldr;
- uintptr_t biggest_block, this_block;
- size_t biggest_size, this_size;
+ uint64_t sblock, eblock, subldr, eubldr;
+ uint64_t biggest_block, this_block;
+ uint64_t biggest_size, this_size;
int i;
- char * envstr;
+ char *envstr;
if (addr == 0) {
/*
@@ -101,13 +101,14 @@ uboot_loadaddr(u_int type, void *data, uint64_t addr)
biggest_block = 0;
biggest_size = 0;
subldr = rounddown2((uintptr_t)_start, KERN_ALIGN);
- eubldr = roundup2(uboot_heap_end, KERN_ALIGN);
+ eubldr = roundup2((uint64_t)uboot_heap_end, KERN_ALIGN);
for (i = 0; i < si->mr_no; i++) {
if (si->mr[i].flags != MR_ATTR_DRAM)
continue;
- sblock = roundup2(si->mr[i].start, KERN_ALIGN);
- eblock = rounddown2(si->mr[i].start + si->mr[i].size,
+ sblock = roundup2((uint64_t)si->mr[i].start,
KERN_ALIGN);
+ eblock = rounddown2((uint64_t)si->mr[i].start +
+ si->mr[i].size, KERN_ALIGN);
if (biggest_size == 0)
sblock += KERN_MINADDR;
if (subldr >= sblock && subldr < eblock) {
@@ -127,9 +128,10 @@ uboot_loadaddr(u_int type, void *data, uint64_t addr)
if (biggest_size == 0)
panic("Not enough DRAM to load kernel\n");
#if 0
- printf("Loading kernel into region 0x%08x-0x%08x (%u MiB)\n",
- biggest_block, biggest_block + biggest_size - 1,
- biggest_size / 1024 / 1024);
+ printf("Loading kernel into region 0x%08jx-0x%08jx (%ju MiB)\n",
+ (uintmax_t)biggest_block,
+ (uintmax_t)biggest_block + biggest_size - 1,
+ (uintmax_t)biggest_size / 1024 / 1024);
#endif
return (biggest_block);
}
OpenPOWER on IntegriCloud