Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,4 @@ jobs:
run: podman run --rm --read-only -v "$PWD:/workspace" -w /workspace dev make all
- name: test
timeout-minutes: 1
run: podman run --rm --read-only -v "$PWD:/workspace" -w /workspace dev make test_loader emu_test test uki_test kexec_test
run: podman run --rm --read-only -v "$PWD:/workspace" -w /workspace dev make test
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
bootloader_emu
busybox
busybox.tar.bz2
demo.img
demo_uki.img
demo.img
dependencies.make
disk
hello
Expand All @@ -19,5 +19,7 @@ kexec.cpio
mini_kexec
purgatory.h
serial.log
test_fat32
test_fat32_disk
test_loader
uki_disk
42 changes: 34 additions & 8 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
MAKEFLAGS += --no-builtin-rules
.SILENT:
.PHONY: all clean distclean test uki_test kexec_test
UNIT_TESTS := loader fat32
.PHONY: all clean distclean test unit_tests qemu_test uki_test kexec_test emu_test $(UNIT_TESTS:%=run_test_%)

CC := gcc
CC_X86 := x86_64-linux-gnu-gcc

CFLAGS := -std=c23 -Os -g -Wall -Wextra -Wdeclaration-after-statement -Werror -fpack-struct -fno-builtin
CFLAGS_USER := $(CFLAGS) -DNO_STATIC_INTERNALS
CFLAGS_M16 := $(CFLAGS) -m16 -march=i386 -nostdinc -ffreestanding -fno-pic -fno-stack-protector -fno-asynchronous-unwind-tables -fno-unwind-tables -fno-exceptions -ffunction-sections -fdata-sections

LD := ld
Expand All @@ -22,14 +24,18 @@ OBJDUMP_FLAGS_M16 := -m i8086 -M intel

all: disk uki.efi kexec.cpio bootloader_emu kernel

test: unit_tests emu_test qemu_test uki_test kexec_test

unit_tests: $(UNIT_TESTS:%=run_test_%)

clean:
git clean -e '!kernel' -e '!kernel.tar.xz' -e '!busybox.tar.bz2' -fX

distclean:
git clean -fX
rm -rf kernel_headers busybox

test: disk
qemu_test: disk
echo 'running $< in qemu'
./run_vm.sh -n '$<' | tee serial.log
grep -F 'Found GPT disk: 01234567-ABCD-0123-ABCD-0123456789AB' < serial.log > /dev/null
Expand Down Expand Up @@ -70,23 +76,37 @@ dependencies.make: *.c

include dependencies.make

bootloader.o: main.o io_buf.o lib.o gpt.o fat32.o loader.o linux.o
bootloader.o: main.emu.o io_buf.emu.o lib.emu.o gpt.emu.o fat32.emu.o loader.emu.o linux.emu.o
echo 'linking $^ -> $@'
$(LD) -r -o '$@' $^
$(OBJCOPY) --keep-global-symbol=init '$@'
$(OBJCOPY) --keep-global-symbol=bootloader_init '$@'
$(OBJDUMP) -h '$@'

bootloader_emu: bootloader.o bios_services_emu.o
echo 'linking $^ -> $@'
$(CC) -o '$@' $^

test_loader: lib.o gpt.o fat32.o io_buf.o
test_loader: lib.emu.o gpt.emu.o fat32.emu.o io_buf.emu.o loader.emu.o

test_fat32: lib.emu.o gpt.emu.o fat32.emu.o io_buf.emu.o

test_fat32_inputs := test_fat32_disk

test_fat32_disk: make_test_fat32_disk.sh
echo 'creating $@'
./$< '$@'

test_%: test_%.o
echo 'linking $^ -> $@'
$(CC) -o '$@' $^
echo 'running $@'
./'$@'

define UNIT_TEST_RULE
run_test_$(1): test_$(1) $$(test_$(1)_inputs)
echo 'running $$<'
./'$$<' $$(test_$(1)_inputs)
endef

$(foreach unit,$(UNIT_TESTS),$(eval $(call UNIT_TEST_RULE,$(unit))))

disk: make_disk.sh mbr.bin bootloader.bin kernel initrd.cpio
echo 'creating $@'
Expand Down Expand Up @@ -157,7 +177,13 @@ uki.efi: pe_inject.py uki_base.efi kernel_stub.bin pe_loader.bin

%.o:
echo 'compiling $< -> $@'
$(CC) $(CFLAGS) -c '$<' -o '$@'
$(CC) $(CFLAGS_USER) -c '$<' -o '$@'
$(OBJDUMP) -h '$@'

%.emu.o: %.o
echo 'prefixing $< -> $@'
$(OBJCOPY) --prefix-symbols=bootloader_ '$<' '$@'
$(OBJCOPY) --redefine-sym bootloader_memset=memset '$@'
$(OBJDUMP) -h '$@'

%.m16.o:
Expand Down
40 changes: 40 additions & 0 deletions bios_services.c
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,46 @@ int16 disk_read(uint8 *buffer, uint16 sectors, uint32 lba)
return 0;
}

int16 disk_write(const uint8 *buffer, uint16 sectors, uint32 lba)
{
static struct disk_address_packet disk_address_packet;

uint8 result;
uint8 error;
uint16 offset;
uint16 segment;

if (sectors > 64) return -1;

if ((uint32) buffer > 0x000fffff) return -1;
offset = ((uint32) buffer & 0x0000ffff);
segment = ((uint32) buffer & 0x000f0000) >> 4;

disk_address_packet = (struct disk_address_packet) {
.size = 0x10,
.reserved = 0x00,
.sectors = sectors,
.buffer_offset = offset,
.buffer_segment = segment,
.lba_low = lba,
.lba_high = 0x00000000
};

__asm__ __volatile__ ( "int $0x13\nsetb %[res]\nmov %%ah, %[err]"
: [res] "=r" (result), [err] "=r" (error)
: "a" (0x4300), "d" (0x0080), "S" (&disk_address_packet)
: );

if (result != 0) {
print_str("disk write failed with ERR ");
print_hex_be(&error, 0x0001);
print_str("\r\n");
return -1;
}

return 0;
}

int16 mem_move(uint8 *dst, const uint8 *src, uint32 len)
{
static struct global_descriptor_table global_descriptor_table[6];
Expand Down
17 changes: 11 additions & 6 deletions bios_services.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
void halt();
void reset();
void print_char(char c);
int16 disk_read(uint8 *buffer, uint16 sectors, uint32 lba);
int16 mem_move(uint8 *dst, const uint8 *src, uint32 len);
void exec_kernel();
#pragma once

#include "prefix.h"

void PREFIX(halt)();
void PREFIX(reset)();
void PREFIX(print_char)(char c);
int16 PREFIX(disk_read)(uint8 *buffer, uint16 sectors, uint32 lba);
int16 PREFIX(disk_write)(const uint8 *buffer, uint16 sectors, uint32 lba);
int16 PREFIX(mem_move)(uint8 *dst, const uint8 *src, uint32 len);
void PREFIX(exec_kernel)();
52 changes: 43 additions & 9 deletions bios_services_emu.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
#include <unistd.h>
#include <fcntl.h>

#define PREFIX(name) bootloader_##name

#include "types.h"
#include "bios_services.h"

Expand All @@ -15,7 +17,7 @@
static int debug = 0;
static int disk_fd = -1;

void init();
void bootloader_init();

int main(int argc, char **argv)
{
Expand All @@ -29,34 +31,34 @@ int main(int argc, char **argv)
exit(1);
}

disk_fd = open(argv[1], O_RDONLY);
disk_fd = open(argv[1], O_RDWR);
if (disk_fd == -1) {
perror("open");
exit(1);
}

init();
bootloader_init();
}

void halt()
void bootloader_halt()
{
debug_printf();
while (1) pause();
}

void reset()
void bootloader_reset()
{
debug_printf();
exit(0);
}

void print_char(char c)
void bootloader_print_char(char c)
{
if (c != 0) fputc(c, stdout);
else fflush(stdout);
}

int16 disk_read(uint8 *buffer, uint16 sectors, uint32 lba)
int16 bootloader_disk_read(uint8 *buffer, uint16 sectors, uint32 lba)
{
uint32 len;
uint32 offset;
Expand Down Expand Up @@ -88,13 +90,45 @@ int16 disk_read(uint8 *buffer, uint16 sectors, uint32 lba)
return 0;
}

int16 mem_move(uint8 *dst, const uint8 *src, uint32 len)
int16 bootloader_disk_write(const uint8 *buffer, uint16 sectors, uint32 lba)
{
uint32 len;
uint32 offset;
ssize_t len_written;

debug_printf("buffer=0x%08lx, sectors=%u, lba=%u)", (size_t) buffer, sectors, lba);

if (sectors > 64) return -1;

len = sectors * 0x0200;
offset = lba * 0x0200;

while (len) {
len_written = pwrite(disk_fd, buffer, len, offset);

if (len_written == -1) {
perror("pwrite");
return -1;
} else if (len_written == 0) {
fprintf(stderr, "unexpected zero-length write\n");
return -1;
}

len -= len_written;
offset += len_written;
buffer += len_written;
}

return 0;
}

int16 bootloader_mem_move(uint8 *dst, const uint8 *src, uint32 len)
{
debug_printf("dst=0x%08lx, src=0x%08lx, len=%u)", (size_t) dst, (size_t) src, len);
return 0;
}

void exec_kernel()
void bootloader_exec_kernel()
{
debug_printf();
exit(0);
Expand Down
Loading
Loading