[boot] Go back to loading symbol table in boot

The symbol table needs to be passed to the panic handler very early in
the kernel, loading it in init is far less useful. Return it to the boot
directory and remove it from the initrd.
This commit is contained in:
Justin C. Miller
2023-02-04 00:00:59 -08:00
parent 86d458fc6c
commit aba45b9b67
11 changed files with 50 additions and 79 deletions

View File

@@ -39,6 +39,8 @@ class Manifest:
self.flags = config.get("flags", tuple()) self.flags = config.get("flags", tuple())
self.symbols = ""
initrd = config.get("initrd", dict()) initrd = config.get("initrd", dict())
self.initrd = { self.initrd = {
"name": initrd.get("name", "initrd.dat"), "name": initrd.get("name", "initrd.dat"),
@@ -110,52 +112,7 @@ class Manifest:
write_ent(self.kernel) write_ent(self.kernel)
write_ent(self.init) write_ent(self.init)
write_path(self.initrd["name"]) write_path(self.initrd["name"])
write_path(self.symbols)
for p in self.panics: for p in self.panics:
write_ent(p) write_ent(p)
def write_init_config(self, path, modules):
from os.path import join
import struct
with open(path, 'wb') as outfile:
magic = "jsixinit".encode("utf-8") # magic string
version = 1
reserved = 0
string_data = bytearray()
outfile.write(struct.pack("<8s BBH HH",
magic,
version, reserved, len(self.services),
len(self.data), len(self.drivers)))
offset_ptr = outfile.tell()
outfile.write(struct.pack("<H", 0)) # filled in later
def write_str(s):
pos = len(string_data)
string_data.extend(s.encode("utf-8") + b"\0")
outfile.write(struct.pack("<H", pos))
def write_driver(ent):
write_str(ent.output)
drivers = modules[ent.module].drivers
outfile.write(struct.pack("<H", len(drivers)))
for driver in drivers:
write_str(driver)
for p in self.services:
write_str(p.output)
for p in self.data:
write_str(p.output)
for p in self.drivers:
write_driver(p)
offset = outfile.tell()
outfile.write(string_data)
outfile.seek(offset_ptr)
outfile.write(struct.pack("<H", offset))

View File

@@ -157,13 +157,16 @@ class Project:
syms = manifest.add_data("symbol_table.dat", syms = manifest.add_data("symbol_table.dat",
"Symbol table", ("symbols",)) "Symbol table", ("symbols",))
sym_out = f"${{build_root}}/symbol_table.dat" syms_file = "jsix.symbols"
syms_path = join(manifest.location, syms_file );
syms_out = join(fatroot, syms_path)
build.build( build.build(
rule = "makest", rule = "makest",
outputs = [sym_out], outputs = [syms_out],
inputs = [f"${{build_root}}/kernel/{modules['kernel'].output}"], inputs = [f"${{build_root}}/kernel/{modules['kernel'].output}"],
) )
add_initrd_content("jsix/data", "symbol_table.dat") fatroot_content.append(syms_out)
manifest.symbols = syms_file
bootloader = "${build_root}/fatroot/efi/boot/bootx64.efi" bootloader = "${build_root}/fatroot/efi/boot/bootx64.efi"
build.build( build.build(

View File

@@ -31,11 +31,11 @@ bootconfig::bootconfig(util::buffer data, uefi::boot_services *bs)
status_line status {L"Loading boot config"}; status_line status {L"Loading boot config"};
if (*util::read<uint64_t>(data) != jsixboot) if (*util::read<uint64_t>(data) != jsixboot)
error::raise(uefi::status::load_error, L"Bad header in jsix_boot.dat"); error::raise(uefi::status::load_error, L"Bad header in boot config");
const uint8_t version = *util::read<uint8_t>(data); const uint8_t version = *util::read<uint8_t>(data);
if (version != 1) if (version != 1)
error::raise(uefi::status::incompatible_version, L"Bad version in jsix_boot.dat"); error::raise(uefi::status::incompatible_version, L"Bad version in boot config");
uint8_t num_panics = *util::read<uint8_t>(data); uint8_t num_panics = *util::read<uint8_t>(data);
m_flags = *util::read<uint16_t>(data); m_flags = *util::read<uint16_t>(data);
@@ -43,6 +43,7 @@ bootconfig::bootconfig(util::buffer data, uefi::boot_services *bs)
read_descriptor(m_kernel, data); read_descriptor(m_kernel, data);
read_descriptor(m_init, data); read_descriptor(m_init, data);
m_initrd = read_string(data); m_initrd = read_string(data);
m_symbols = read_string(data);
m_panics.count = num_panics; m_panics.count = num_panics;
m_panics.pointer = new descriptor [num_panics]; m_panics.pointer = new descriptor [num_panics];

View File

@@ -31,6 +31,7 @@ public:
inline const descriptor & kernel() const { return m_kernel; } inline const descriptor & kernel() const { return m_kernel; }
inline const descriptor & init() const { return m_init; } inline const descriptor & init() const { return m_init; }
inline const wchar_t * initrd() const { return m_initrd; } inline const wchar_t * initrd() const { return m_initrd; }
inline const wchar_t * symbols() const { return m_symbols; }
inline const descriptors & panics() { return m_panics; } inline const descriptors & panics() { return m_panics; }
private: private:
@@ -39,6 +40,7 @@ private:
descriptor m_init; descriptor m_init;
descriptors m_panics; descriptors m_panics;
wchar_t const *m_initrd; wchar_t const *m_initrd;
wchar_t const *m_symbols;
}; };
} // namespace boot } // namespace boot

View File

@@ -72,7 +72,7 @@ load_program(
util::const_buffer data = load_file(disk, desc.path); util::const_buffer data = load_file(disk, desc.path);
elf::file program(data.pointer, data.count); elf::file program {data};
if (!program.valid()) { if (!program.valid()) {
auto *header = program.header(); auto *header = program.header();
console::print(L" progam size: %d\r\n", data.count); console::print(L" progam size: %d\r\n", data.count);
@@ -91,7 +91,7 @@ load_program(
verify_kernel_header(program, data); verify_kernel_header(program, data);
size_t num_sections = 0; size_t num_sections = 0;
for (auto &seg : program.programs()) { for (auto &seg : program.segments()) {
if (seg.type == elf::segment_type::load) if (seg.type == elf::segment_type::load)
++num_sections; ++num_sections;
} }
@@ -99,7 +99,7 @@ load_program(
bootproto::program_section *sections = new bootproto::program_section [num_sections]; bootproto::program_section *sections = new bootproto::program_section [num_sections];
size_t next_section = 0; size_t next_section = 0;
for (auto &seg : program.programs()) { for (auto &seg : program.segments()) {
if (seg.type != elf::segment_type::load) if (seg.type != elf::segment_type::load)
continue; continue;

View File

@@ -72,8 +72,8 @@ load_resources(bootproto::args *args, video::screen *screen, uefi::handle image,
status_line status {L"Loading programs"}; status_line status {L"Loading programs"};
fs::file disk = fs::get_boot_volume(image, bs); fs::file disk = fs::get_boot_volume(image, bs);
fs::file bc_data = disk.open(L"jsix\\boot.conf"); util::buffer bc_data = loader::load_file(disk, L"jsix\\boot.conf");
bootconfig bc {bc_data.load(), bs}; bootconfig bc {bc_data, bs};
args->kernel = loader::load_program(disk, L"kernel", bc.kernel(), true); args->kernel = loader::load_program(disk, L"kernel", bc.kernel(), true);
args->init = loader::load_program(disk, L"init server", bc.init()); args->init = loader::load_program(disk, L"init server", bc.init());
@@ -85,6 +85,8 @@ load_resources(bootproto::args *args, video::screen *screen, uefi::handle image,
namespace bits = util::bits; namespace bits = util::bits;
using bootproto::desc_flags; using bootproto::desc_flags;
bool has_panic = false;
if (screen) { if (screen) {
video::make_module(screen); video::make_module(screen);
@@ -93,19 +95,25 @@ load_resources(bootproto::args *args, video::screen *screen, uefi::handle image,
for (const descriptor &d : bc.panics()) { for (const descriptor &d : bc.panics()) {
if (bits::has(d.flags, desc_flags::graphical)) { if (bits::has(d.flags, desc_flags::graphical)) {
args->panic = loader::load_program(disk, L"panic handler", d); args->panic = loader::load_program(disk, L"panic handler", d);
has_panic = true;
break; break;
} }
} }
} }
if (!args->panic) { if (!has_panic) {
for (const descriptor &d : bc.panics()) { for (const descriptor &d : bc.panics()) {
if (!bits::has(d.flags, desc_flags::graphical)) { if (!bits::has(d.flags, desc_flags::graphical)) {
args->panic = loader::load_program(disk, L"panic handler", d); args->panic = loader::load_program(disk, L"panic handler", d);
has_panic = true;
break; break;
} }
} }
} }
const wchar_t *symbol_file = bc.symbols();
if (has_panic && symbol_file && *symbol_file)
args->symbol_table = loader::load_file(disk, symbol_file).pointer;
} }
memory::efi_mem_map memory::efi_mem_map

View File

@@ -158,6 +158,8 @@ status_line::do_fail(const wchar_t *message, uefi::status status)
void void
status_line::do_blank() status_line::do_blank()
{ {
m_level = level_ok; // Keep print_status_tag from happening in dtor
auto out = console::get().m_out; auto out = console::get().m_out;
int row = out->mode->cursor_row; int row = out->mode->cursor_row;

View File

@@ -2,12 +2,13 @@
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
#include <util/counted.h>
#include <util/pointers.h> #include <util/pointers.h>
namespace elf { namespace elf {
struct file_header; struct file_header;
struct program_header; struct segment_header;
struct section_header; struct section_header;
template <typename T> template <typename T>
@@ -37,9 +38,8 @@ class file
{ {
public: public:
/// Constructor: Create an elf object out of ELF data in memory /// Constructor: Create an elf object out of ELF data in memory
/// \arg data The ELF data to read /// \arg data A const_buffer pointing at the ELF data
/// \arg size Size of the ELF data, in bytes file(util::const_buffer data);
file(const void *data, size_t size);
/// Check the validity of the ELF data /// Check the validity of the ELF data
/// \returns true for valid ELF data /// \returns true for valid ELF data
@@ -51,25 +51,24 @@ public:
/// Get the base address of the program in memory /// Get the base address of the program in memory
inline uintptr_t base() const { inline uintptr_t base() const {
return reinterpret_cast<uintptr_t>(m_data); return reinterpret_cast<uintptr_t>(m_data.pointer);
} }
/// Get the ELF program headers /// Get the ELF segment headers
inline const subheaders<program_header> & programs() const { return m_programs; } inline const subheaders<segment_header> & segments() const { return m_segments; }
/// Get the ELF section headers /// Get the ELF section headers
inline const subheaders<section_header> & sections() const { return m_sections; } inline const subheaders<section_header> & sections() const { return m_sections; }
inline const file_header * header() const { inline const file_header * header() const {
return reinterpret_cast<const file_header *>(m_data); return reinterpret_cast<const file_header *>(m_data.pointer);
} }
private: private:
subheaders<program_header> m_programs; subheaders<segment_header> m_segments;
subheaders<section_header> m_sections; subheaders<section_header> m_sections;
const void *m_data; util::const_buffer m_data;
size_t m_size;
}; };
} }

View File

@@ -63,7 +63,7 @@ enum class segment_flags : uint32_t
}; };
is_bitfield(segment_flags); is_bitfield(segment_flags);
struct program_header struct segment_header
{ {
segment_type type; segment_type type;
segment_flags flags; segment_flags flags;

View File

@@ -5,25 +5,24 @@ static const uint32_t expected_magic = 0x464c457f; // "\x7f" "ELF"
namespace elf { namespace elf {
inline const file_header * fh(const void *data) { return reinterpret_cast<const file_header*>(data); } inline const file_header * fh(util::const_buffer data) { return reinterpret_cast<const file_header*>(data.pointer); }
template <typename T> template <typename T>
const T *convert(const void *data, size_t offset) { const T *convert(util::const_buffer data, size_t offset) {
return reinterpret_cast<const T*>(util::offset_pointer(data, offset)); return reinterpret_cast<const T*>(util::offset_pointer(data.pointer, offset));
} }
file::file(const void *data, size_t size) : file::file(util::const_buffer data) :
m_programs(convert<program_header>(data, fh(data)->ph_offset), fh(data)->ph_entsize, fh(data)->ph_num), m_segments(convert<segment_header>(data, fh(data)->ph_offset), fh(data)->ph_entsize, fh(data)->ph_num),
m_sections(convert<section_header>(data, fh(data)->sh_offset), fh(data)->sh_entsize, fh(data)->sh_num), m_sections(convert<section_header>(data, fh(data)->sh_offset), fh(data)->sh_entsize, fh(data)->sh_num),
m_data(data), m_data(data)
m_size(size)
{ {
} }
bool bool
file::valid() const file::valid() const
{ {
if (m_size < sizeof(file_header)) if (m_data.count < sizeof(file_header))
return false; return false;
const file_header *fheader = header(); const file_header *fheader = header();

View File

@@ -46,7 +46,7 @@ load_program(
{ {
uintptr_t base_address = reinterpret_cast<uintptr_t>(data.pointer); uintptr_t base_address = reinterpret_cast<uintptr_t>(data.pointer);
elf::file progelf {data.pointer, data.count}; elf::file progelf {data};
if (!progelf.valid()) { if (!progelf.valid()) {
sprintf(err_msg, " ** error loading program '%s': ELF is invalid", name); sprintf(err_msg, " ** error loading program '%s': ELF is invalid", name);
@@ -72,7 +72,7 @@ load_program(
return false; return false;
} }
for (auto &seg : progelf.programs()) { for (auto &seg : progelf.segments()) {
if (seg.type != elf::segment_type::load) if (seg.type != elf::segment_type::load)
continue; continue;