aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorToomas Soome <tsoome@FreeBSD.org>2021-01-26 22:47:56 +0000
committerToomas Soome <tsoome@FreeBSD.org>2021-01-26 23:07:34 +0000
commit6c7a932d0b8baaaee16eca0ba061bfa6e0e57bfd (patch)
tree02c093a3e9eb9d6b83a429982a41f2da3e1468fd
parent93ebd6307efeb95a29bc614edd0c67c2af850e98 (diff)
downloadsrc-6c7a932d0b8baaaee16eca0ba061bfa6e0e57bfd.tar.gz
src-6c7a932d0b8baaaee16eca0ba061bfa6e0e57bfd.zip
loader: start kernel in text mode when there is no vbefb vt driver
If kernel is built without VT vbefb driver, make sure we start kernel in text mode.
-rw-r--r--stand/common/gfx_fb.h1
-rw-r--r--stand/common/load_elf.c63
-rw-r--r--stand/i386/libi386/bootinfo.c10
-rw-r--r--stand/loader.mk9
4 files changed, 74 insertions, 9 deletions
diff --git a/stand/common/gfx_fb.h b/stand/common/gfx_fb.h
index 1424b8223136..d046865604ea 100644
--- a/stand/common/gfx_fb.h
+++ b/stand/common/gfx_fb.h
@@ -204,6 +204,7 @@ typedef struct teken_gfx {
struct gen_fb tg_fb;
teken_funcs_t *tg_functions;
void *tg_private;
+ bool tg_kernel_supported; /* Loaded kernel is supported */
} teken_gfx_t;
extern font_list_t fonts;
diff --git a/stand/common/load_elf.c b/stand/common/load_elf.c
index cb542718fe2f..62fdb560ecff 100644
--- a/stand/common/load_elf.c
+++ b/stand/common/load_elf.c
@@ -39,6 +39,7 @@ __FBSDID("$FreeBSD$");
#include <stand.h>
#define FREEBSD_ELF
#include <sys/link_elf.h>
+#include <gfx_fb.h>
#include "bootstrap.h"
@@ -84,12 +85,14 @@ typedef struct elf_file {
static int __elfN(loadimage)(struct preloaded_file *mp, elf_file_t ef,
uint64_t loadaddr);
-static int __elfN(lookup_symbol)(struct preloaded_file *mp, elf_file_t ef,
- const char* name, Elf_Sym* sym);
+static int __elfN(lookup_symbol)(elf_file_t ef, const char* name,
+ Elf_Sym *sym, unsigned char type);
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,
Elf_Addr p_start, Elf_Addr p_end);
+static bool __elfN(parse_vt_drv_set)(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);
@@ -872,12 +875,24 @@ nosyms:
ef->buckets = ef->hashtab + 2;
ef->chains = ef->buckets + ef->nbuckets;
- if (__elfN(lookup_symbol)(fp, ef, "__start_set_modmetadata_set",
- &sym) != 0)
+ gfx_state.tg_kernel_supported = false;
+ if (__elfN(lookup_symbol)(ef, "__start_set_vt_drv_set", &sym,
+ STT_NOTYPE) == 0) {
+ p_start = sym.st_value + ef->off;
+ if (__elfN(lookup_symbol)(ef, "__stop_set_vt_drv_set", &sym,
+ STT_NOTYPE) == 0) {
+ p_end = sym.st_value + ef->off;
+ gfx_state.tg_kernel_supported =
+ __elfN(parse_vt_drv_set)(fp, ef, p_start, p_end);
+ }
+ }
+
+ if (__elfN(lookup_symbol)(ef, "__start_set_modmetadata_set", &sym,
+ STT_NOTYPE) != 0)
return 0;
p_start = sym.st_value + ef->off;
- if (__elfN(lookup_symbol)(fp, ef, "__stop_set_modmetadata_set",
- &sym) != 0)
+ if (__elfN(lookup_symbol)(ef, "__stop_set_modmetadata_set", &sym,
+ STT_NOTYPE) != 0)
return ENOENT;
p_end = sym.st_value + ef->off;
@@ -1072,6 +1087,36 @@ out:
return (err);
}
+/*
+ * Walk through vt_drv_set, each vt driver structure starts with
+ * static 16 chars for driver name. If we have "vbefb", return true.
+ */
+static bool
+__elfN(parse_vt_drv_set)(struct preloaded_file *fp, elf_file_t ef,
+ Elf_Addr p_start, Elf_Addr p_end)
+{
+ Elf_Addr v, p;
+ char vd_name[16];
+ int error;
+
+ 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)
+ v += ef->off;
+ else if (error != 0)
+ return (false);
+ COPYOUT(v, &vd_name, sizeof(vd_name));
+ if (strncmp(vd_name, "vbefb", sizeof(vd_name)) == 0)
+ return (true);
+ p += sizeof(Elf_Addr);
+ }
+
+ return (false);
+}
+
int
__elfN(parse_modmetadata)(struct preloaded_file *fp, elf_file_t ef,
Elf_Addr p_start, Elf_Addr p_end)
@@ -1185,8 +1230,8 @@ elf_hash(const char *name)
static const char __elfN(bad_symtable)[] = "elf" __XSTRING(__ELF_WORD_SIZE)
"_lookup_symbol: corrupt symbol table\n";
int
-__elfN(lookup_symbol)(struct preloaded_file *fp, elf_file_t ef,
- const char* name, Elf_Sym *symp)
+__elfN(lookup_symbol)(elf_file_t ef, const char* name, Elf_Sym *symp,
+ unsigned char type)
{
Elf_Hashelt symnum;
Elf_Sym sym;
@@ -1213,7 +1258,7 @@ __elfN(lookup_symbol)(struct preloaded_file *fp, elf_file_t ef,
free(strp);
if (sym.st_shndx != SHN_UNDEF ||
(sym.st_value != 0 &&
- ELF_ST_TYPE(sym.st_info) == STT_FUNC)) {
+ ELF_ST_TYPE(sym.st_info) == type)) {
*symp = sym;
return 0;
}
diff --git a/stand/i386/libi386/bootinfo.c b/stand/i386/libi386/bootinfo.c
index 71e07cfb9702..57f926b76589 100644
--- a/stand/i386/libi386/bootinfo.c
+++ b/stand/i386/libi386/bootinfo.c
@@ -41,6 +41,16 @@ __FBSDID("$FreeBSD$");
void
bi_load_vbe_data(struct preloaded_file *kfp)
{
+ if (!gfx_state.tg_kernel_supported) {
+ /*
+ * Loaded kernel does not have vt/vbe backend,
+ * switch console to text mode.
+ */
+ if (vbe_available())
+ bios_set_text_mode(VGA_TEXT_MODE);
+ return;
+ }
+
if (vbe_available()) {
file_addmetadata(kfp, MODINFOMD_VBE_FB,
sizeof(gfx_state.tg_fb), &gfx_state.tg_fb);
diff --git a/stand/loader.mk b/stand/loader.mk
index cde7a31dca7e..3a38a9bc9e63 100644
--- a/stand/loader.mk
+++ b/stand/loader.mk
@@ -17,23 +17,32 @@ CFLAGS.pnglite.c+= -DHAVE_MEMCPY -I${SRCTOP}/sys/contrib/zlib
.if ${MACHINE} == "i386" || ${MACHINE_CPUARCH} == "amd64"
SRCS+= load_elf32.c load_elf32_obj.c reloc_elf32.c
SRCS+= load_elf64.c load_elf64_obj.c reloc_elf64.c
+CFLAGS.load_elf32.c += -I$(SRCTOP)/sys/teken -I${SRCTOP}/contrib/pnglite
+CFLAGS.load_elf64.c += -I$(SRCTOP)/sys/teken -I${SRCTOP}/contrib/pnglite
.elif ${MACHINE_CPUARCH} == "aarch64"
SRCS+= load_elf64.c reloc_elf64.c
+CFLAGS.load_elf64.c += -I$(SRCTOP)/sys/teken -I${SRCTOP}/contrib/pnglite
.elif ${MACHINE_CPUARCH} == "arm"
SRCS+= load_elf32.c reloc_elf32.c
+CFLAGS.load_elf32.c += -I$(SRCTOP)/sys/teken -I${SRCTOP}/contrib/pnglite
.elif ${MACHINE_CPUARCH} == "powerpc"
SRCS+= load_elf32.c reloc_elf32.c
SRCS+= load_elf64.c reloc_elf64.c
SRCS+= metadata.c
+CFLAGS.load_elf32.c += -I$(SRCTOP)/sys/teken -I${SRCTOP}/contrib/pnglite
+CFLAGS.load_elf64.c += -I$(SRCTOP)/sys/teken -I${SRCTOP}/contrib/pnglite
.elif ${MACHINE_ARCH:Mmips64*} != ""
SRCS+= load_elf64.c reloc_elf64.c
SRCS+= metadata.c
+CFLAGS.load_elf64.c += -I$(SRCTOP)/sys/teken -I${SRCTOP}/contrib/pnglite
.elif ${MACHINE} == "mips"
SRCS+= load_elf32.c reloc_elf32.c
SRCS+= metadata.c
+CFLAGS.load_elf32.c += -I$(SRCTOP)/sys/teken -I${SRCTOP}/contrib/pnglite
.elif ${MACHINE_CPUARCH} == "riscv"
SRCS+= load_elf64.c reloc_elf64.c
SRCS+= metadata.c
+CFLAGS.load_elf64.c += -I$(SRCTOP)/sys/teken -I${SRCTOP}/contrib/pnglite
.endif
.if ${LOADER_DISK_SUPPORT:Uyes} == "yes"