Ninja-based buildsystem now building a running kernel!

This commit is contained in:
Justin C. Miller
2019-02-02 21:35:39 -08:00
parent acdca19f59
commit bc01a37452
8 changed files with 75 additions and 24 deletions

View File

@@ -5,7 +5,7 @@ from collections import namedtuple
library = namedtuple('library', ['path', 'deps']) library = namedtuple('library', ['path', 'deps'])
program = namedtuple('program', ['path', 'deps', 'output', 'targets']) program = namedtuple('program', ['path', 'deps', 'output', 'targets'])
source = namedtuple('source', ['name', 'input', 'output', 'action']) source = namedtuple('source', ['name', 'input', 'output', 'action'])
version = namedtuple('version', ['major', 'minor', 'patch', 'sha']) version = namedtuple('version', ['major', 'minor', 'patch', 'sha', 'dirty'])
MODULES = { MODULES = {
"elf": library('src/libraries/elf', ['kutil']), "elf": library('src/libraries/elf', ['kutil']),
@@ -45,7 +45,7 @@ def get_sources(path, srcroot):
source( source(
relpath(name, srcroot), relpath(name, srcroot),
abspath(name), abspath(name),
f + ".o", relpath(abspath(name), path) + ".o",
actions[ext])) actions[ext]))
return sources return sources
@@ -53,18 +53,24 @@ def get_sources(path, srcroot):
def get_git_version(): def get_git_version():
from subprocess import run from subprocess import run
cp = run(['git', 'describe', '--always'], cp = run(['git', 'describe', '--dirty', '--abbrev=7'],
check=True, capture_output=True) check=True, capture_output=True)
full_version = cp.stdout.decode('utf-8').strip() full_version = cp.stdout.decode('utf-8').strip()
dirty = False
parts1 = full_version.split('-') parts1 = full_version.split('-')
if parts1[-1] == "dirty":
dirty = True
parts1 = parts1[:-1]
parts2 = parts1[0].split('.') parts2 = parts1[0].split('.')
return version( return version(
parts2[0], parts2[0],
parts2[1], parts2[1],
parts2[2], parts2[2],
parts1[-1]) parts1[-1][1:],
dirty)
def main(buildroot): def main(buildroot):

22
qemu.sh Executable file
View File

@@ -0,0 +1,22 @@
#!/usr/bin/env bash
build=${1:-"$(dirname $0)/build"}
ninja -C $build
kvm=""
if [[ -f /dev/kvm ]]; then
kvm="--enable-kvm"
fi
exec qemu-system-x86_64 \
-drive "if=pflash,format=raw,file=${build}/flash.img" \
-drive "format=raw,file=${build}/popcorn.img" \
-smp 1 \
-m 512 \
-d mmu,int,guest_errors \
-D popcorn.log \
-cpu Broadwell \
-M q35 \
-no-reboot \
-nographic \
$kvm

View File

@@ -31,15 +31,16 @@ ccflags = $
-DVERSION_MAJOR={{ version.major }} $ -DVERSION_MAJOR={{ version.major }} $
-DVERSION_MINOR={{ version.minor }} $ -DVERSION_MINOR={{ version.minor }} $
-DVERSION_PATCH={{ version.patch }} $ -DVERSION_PATCH={{ version.patch }} $
-DVERSION_GITSHA=\"{{ version.sha }}\" $ -DVERSION_GITSHA=0x{% if version.dirty %}1{% else %}0{% endif %}{{ version.sha }} $
-DGIT_VERSION=\"{{ version.major }}.{{ version.minor }}.{{ version.patch }}-{{ version.sha }}\" $ -DGIT_VERSION=\"{{ version.major }}.{{ version.minor }}.{{ version.patch }}-{{ version.sha }}\" $
-DGIT_VERSION_WIDE=L\"{{ version.major }}.{{ version.minor }}.{{ version.patch }}-{{ version.sha }}\" $
$warnflags $warnflags
asflags = $ asflags = $
-DVERSION_MAJOR={{ version.major }} $ -DVERSION_MAJOR={{ version.major }} $
-DVERSION_MINOR={{ version.minor }} $ -DVERSION_MINOR={{ version.minor }} $
-DVERSION_PATCH={{ version.patch }} $ -DVERSION_PATCH={{ version.patch }} $
-DVERSION_GITSHA=\"{{ version.sha }}\" -DVERSION_GITSHA=0x{% if version.dirty %}1{% else %}0{% endif %}{{ version.sha }}
cflags = -std=c11 cflags = -std=c11
cxxflags = -std=c++14 cxxflags = -std=c++14
@@ -121,9 +122,6 @@ build $
build $builddir/flash.img : cp $srcroot/assets/ovmf/x64/OVMF.fd build $builddir/flash.img : cp $srcroot/assets/ovmf/x64/OVMF.fd
name = flash.img name = flash.img
build $builddir/popcorn.fat : cp $srcroot/assets/ovmf/x64/OVMF.fd
name = flash.img
build $builddir/fatroot/popcorn.elf : cp $builddir/host/popcorn.elf build $builddir/fatroot/popcorn.elf : cp $builddir/host/popcorn.elf
name = kernel to FAT image name = kernel to FAT image

View File

@@ -11,30 +11,32 @@ objcopy = ${srcroot}/sysroot/bin/x86_64-elf-objcopy
{% block variables %} {% block variables %}
ccflags = $ccflags $ ccflags = $ccflags $
-D__ELF__ $
-D__POPCORN__ $
-nodefaultlibs $
-nostdinc $
-nostdlib $ -nostdlib $
-ffreestanding $ -ffreestanding $
-nodefaultlibs $
-fno-builtin $
-mno-sse $ -mno-sse $
-fno-omit-frame-pointer $ -fno-omit-frame-pointer $
-mno-red-zone $ -mno-red-zone $
-g $
-mcmodel=large $ -mcmodel=large $
-D__ELF__ $
-D__POPCORN__ $
-isystem${srcroot}/sysroot/include $ -isystem${srcroot}/sysroot/include $
--sysroot="${srcroot}/sysroot" --sysroot="${srcroot}/sysroot"
cxxflags = $cxxflags $ cxxflags = $cxxflags $
-nostdlibinc $
-isystem${srcroot}/sysroot/include/c++/v1 $
-fno-exceptions $ -fno-exceptions $
-fno-rtti -fno-rtti $
-isystem${srcroot}/sysroot/include/c++/v1
ldflags = $ldflags $ ldflags = $ldflags $
-g $ -g $
-nostdlib $ -nostdlib $
-nostartfiles $
-znocombreloc $ -znocombreloc $
-nostartfiles -Bsymbolic $
-nostartfiles $
-Bstatic
{% endblock %} {% endblock %}
# vim: et ts=4 sts=4 sw=4

View File

@@ -27,7 +27,7 @@ SECTIONS
*(.note.*) *(.note.*)
} }
.bss ALIGN(0x1000) : { .bss ALIGN(16) : {
__bss_start = .; __bss_start = .;
*(.bss) *(.bss)
__bss_end = .; __bss_end = .;

View File

@@ -87,6 +87,8 @@ loader_load_elf(
{ {
EFI_STATUS status; EFI_STATUS status;
con_debug(L"Opening kernel file %s\r\n", (CHAR16 *)kernel_name);
EFI_FILE_PROTOCOL *file = NULL; EFI_FILE_PROTOCOL *file = NULL;
status = root->Open(root, &file, (CHAR16 *)kernel_name, EFI_FILE_MODE_READ, status = root->Open(root, &file, (CHAR16 *)kernel_name, EFI_FILE_MODE_READ,
EFI_FILE_READ_ONLY | EFI_FILE_HIDDEN | EFI_FILE_SYSTEM); EFI_FILE_READ_ONLY | EFI_FILE_HIDDEN | EFI_FILE_SYSTEM);
@@ -107,6 +109,8 @@ loader_load_elf(
status = file->Read(file, &length, &header); status = file->Read(file, &length, &header);
CHECK_EFI_STATUS_OR_RETURN(status, L"Reading ELF header"); CHECK_EFI_STATUS_OR_RETURN(status, L"Reading ELF header");
con_debug(L"Read %u bytes of ELF header\r\n", length);
if (length < sizeof(struct elf_header)) if (length < sizeof(struct elf_header))
CHECK_EFI_STATUS_OR_RETURN(EFI_LOAD_ERROR, L"Incomplete read of ELF header"); CHECK_EFI_STATUS_OR_RETURN(EFI_LOAD_ERROR, L"Incomplete read of ELF header");
@@ -131,10 +135,14 @@ loader_load_elf(
header.machine != 0x3e) header.machine != 0x3e)
CHECK_EFI_STATUS_OR_RETURN(EFI_LOAD_ERROR, L"ELF load error: wrong machine architecture"); CHECK_EFI_STATUS_OR_RETURN(EFI_LOAD_ERROR, L"ELF load error: wrong machine architecture");
con_debug(L"ELF is valid, entrypoint %lu\r\n", header.entrypoint);
data->kernel_entry = (void *)header.entrypoint; data->kernel_entry = (void *)header.entrypoint;
struct elf_program_header prog_header; struct elf_program_header prog_header;
for (int i = 0; i < header.ph_num; ++i) { for (int i = 0; i < header.ph_num; ++i) {
con_debug(L"Reading ELF program header %d\r\n", i);
status = file->SetPosition(file, header.ph_offset + i * header.ph_entsize); status = file->SetPosition(file, header.ph_offset + i * header.ph_entsize);
CHECK_EFI_STATUS_OR_RETURN(status, L"Setting ELF file position"); CHECK_EFI_STATUS_OR_RETURN(status, L"Setting ELF file position");
@@ -156,6 +164,8 @@ loader_load_elf(
struct elf_section_header sec_header; struct elf_section_header sec_header;
for (int i = 0; i < header.sh_num; ++i) { for (int i = 0; i < header.sh_num; ++i) {
con_debug(L"Reading ELF section header %d ", i);
status = file->SetPosition(file, header.sh_offset + i * header.sh_entsize); status = file->SetPosition(file, header.sh_offset + i * header.sh_entsize);
CHECK_EFI_STATUS_OR_RETURN(status, L"Setting ELF file position"); CHECK_EFI_STATUS_OR_RETURN(status, L"Setting ELF file position");
@@ -163,11 +173,15 @@ loader_load_elf(
status = file->Read(file, &length, &sec_header); status = file->Read(file, &length, &sec_header);
CHECK_EFI_STATUS_OR_RETURN(status, L"Reading ELF section header"); CHECK_EFI_STATUS_OR_RETURN(status, L"Reading ELF section header");
if ((sec_header.flags & ELF_SHF_ALLOC) == 0) continue; if ((sec_header.flags & ELF_SHF_ALLOC) == 0) {
con_debug(L"SHF_ALLOC section\r\n");
continue;
}
void *addr = (void *)(sec_header.addr - KERNEL_VIRT_ADDRESS); void *addr = (void *)(sec_header.addr - KERNEL_VIRT_ADDRESS);
if (sec_header.type == ELF_ST_PROGBITS) { if (sec_header.type == ELF_ST_PROGBITS) {
con_debug(L"PROGBITS section\r\n");
status = file->SetPosition(file, sec_header.offset); status = file->SetPosition(file, sec_header.offset);
CHECK_EFI_STATUS_OR_RETURN(status, L"Setting ELF file position"); CHECK_EFI_STATUS_OR_RETURN(status, L"Setting ELF file position");
@@ -175,7 +189,10 @@ loader_load_elf(
status = file->Read(file, &length, addr); status = file->Read(file, &length, addr);
CHECK_EFI_STATUS_OR_RETURN(status, L"Reading file"); CHECK_EFI_STATUS_OR_RETURN(status, L"Reading file");
} else if (sec_header.type == ELF_ST_NOBITS) { } else if (sec_header.type == ELF_ST_NOBITS) {
con_debug(L"NOBITS section\r\n");
bootsvc->SetMem(addr, sec_header.size, 0); bootsvc->SetMem(addr, sec_header.size, 0);
} else {
con_debug(L"other section\r\n");
} }
} }

View File

@@ -32,3 +32,9 @@ const CHAR16 *util_error_message(EFI_STATUS status);
: "r"((uint64_t)s), "r"((uint64_t)d), "r"((uint64_t)__LINE__) \ : "r"((uint64_t)s), "r"((uint64_t)d), "r"((uint64_t)__LINE__) \
: "rax", "rdx", "r8", "r9", "r10"); \ : "rax", "rdx", "r8", "r9", "r10"); \
} }
#ifdef BOOTLOADER_DEBUG
#define con_debug(...) con_printf(L"DEBUG: " __VA_ARGS__)
#else
#define con_debug(...)
#endif

View File

@@ -3,17 +3,17 @@ extern g_gdtr
global idt_write global idt_write
idt_write: idt_write:
lidt [g_idtr] lidt [rel g_idtr]
ret ret
global idt_load global idt_load
idt_load: idt_load:
sidt [g_idtr] sidt [rel g_idtr]
ret ret
global gdt_write global gdt_write
gdt_write: gdt_write:
lgdt [g_gdtr] lgdt [rel g_gdtr]
mov ax, si ; second arg is data segment mov ax, si ; second arg is data segment
mov ds, ax mov ds, ax
mov es, ax mov es, ax
@@ -30,6 +30,6 @@ gdt_write:
global gdt_load global gdt_load
gdt_load: gdt_load:
sgdt [g_gdtr] sgdt [rel g_gdtr]
ret ret