mirror of
https://github.com/justinian/jsix.git
synced 2025-12-10 08:24:32 -08:00
Ninja-based buildsystem now building a running kernel!
This commit is contained in:
@@ -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
22
qemu.sh
Executable 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
|
||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ SECTIONS
|
|||||||
*(.note.*)
|
*(.note.*)
|
||||||
}
|
}
|
||||||
|
|
||||||
.bss ALIGN(0x1000) : {
|
.bss ALIGN(16) : {
|
||||||
__bss_start = .;
|
__bss_start = .;
|
||||||
*(.bss)
|
*(.bss)
|
||||||
__bss_end = .;
|
__bss_end = .;
|
||||||
|
|||||||
@@ -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");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user