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.
This commit is contained in:
Toomas Soome 2021-01-27 00:47:56 +02:00
parent 93ebd6307e
commit 6c7a932d0b
4 changed files with 74 additions and 9 deletions

View File

@ -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;

View File

@ -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 @@ __elfN(loadimage)(struct preloaded_file *fp, elf_file_t ef, uint64_t off)
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 @@ __elfN(load_modmetadata)(struct preloaded_file *fp, uint64_t dest)
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;
}

View File

@ -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);

View File

@ -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"