summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAda Christine <adachristine18@gmail.com>2022-03-18 12:24:48 +0000
committerAda Christine <adachristine18@gmail.com>2022-03-18 12:24:48 +0000
commit51cfcb98bde7e78b4817a9060885b25b6c3d354c (patch)
treea7ba8214cdfbc170dceded6e8deb883efd100ae4
parent5826f2045cca28b7c9ba8a5b65b4b4928eb6b461 (diff)
now using clang, native PE UEFI loader image. made an ugly hack to get
into the shim. it's probably ok.
-rw-r--r--.gitignore1
-rw-r--r--README.md4
-rw-r--r--api/loader/efi/shim.h13
-rw-r--r--defaults.mk10
-rw-r--r--efi.mk31
-rw-r--r--kc/boot/Makefile3
-rw-r--r--kc/core/Makefile2
-rw-r--r--kc/defaults.mk8
-rw-r--r--kc/dynamic_x86_64.c13
-rw-r--r--kc/entry_x86_64.S8
-rw-r--r--kc/kc.ld2
-rw-r--r--loader/Makefile16
-rw-r--r--loader/main_efi.c91
-rw-r--r--rules.mk8
14 files changed, 127 insertions, 83 deletions
diff --git a/.gitignore b/.gitignore
index 62b87a1..a2bec76 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,4 +6,5 @@
*.efi
*.log
*.kate-swp
+*.pdb
diff --git a/README.md b/README.md
index e68d251..203a4aa 100644
--- a/README.md
+++ b/README.md
@@ -9,10 +9,10 @@ whoever is outside my house yelling "comment your code!" i will never comment my
in order to use this you will require the following:
-- a gcc cross-compiler targeting x86\_64-elf. instructions [here](https://wiki.osdev.org/GCC_Cross-Compiler)
+- clang 9.0+
- qemu supporting x86\_64
- an OVMF installation usable as a firmware for qemu
-- gnu-efi
+- gnu-efi for EFI headers
generally it is only currently possible to build from a POSIX-like system.
this is not a rule, but i do not currently support any other means
diff --git a/api/loader/efi/shim.h b/api/loader/efi/shim.h
index 0255361..dcdf077 100644
--- a/api/loader/efi/shim.h
+++ b/api/loader/efi/shim.h
@@ -23,11 +23,14 @@ struct efi_loader_image
UINTN buffer_size;
};
-typedef EFI_STATUS (*efi_image_func)(struct efi_loader_image *image);
-typedef EFI_STATUS (*efi_page_alloc_func)(EFI_MEMORY_TYPE type,
+typedef EFI_STATUS (EFIAPI *efi_image_func)(struct efi_loader_image *image);
+typedef EFI_STATUS (EFIAPI *efi_page_alloc_func)(
+ EFI_MEMORY_TYPE type,
UINTN size,
EFI_PHYSICAL_ADDRESS *base);
-typedef EFI_STATUS (*efi_page_free_func)(EFI_PHYSICAL_ADDRESS base, UINTN size);
+typedef EFI_STATUS (EFIAPI *efi_page_free_func)(
+ EFI_PHYSICAL_ADDRESS base,
+ UINTN size);
struct efi_loader_interface
{
@@ -42,6 +45,6 @@ struct efi_loader_interface
efi_image_func image_load;
};
-typedef EFI_STATUS (*efi_shim_entry_func)(struct efi_loader_image *image,
- struct efi_loader_interface *interface);
+typedef EFI_STATUS
+(__attribute__((sysv_abi)) *efi_shim_entry_func)(struct efi_loader_interface *interface);
diff --git a/defaults.mk b/defaults.mk
index 16193f2..2cc7ac1 100644
--- a/defaults.mk
+++ b/defaults.mk
@@ -3,10 +3,10 @@
ARCH := x86_64
ABI := elf
TARGET := $(ARCH)-$(ABI)
-CC := $(TARGET)-gcc
-CXX := $(TARGET)-g++
-AS := $(TARGET)-as
-LD := $(TARGET)-ld
+CC := clang
+CXX := clang++
+AS := clang
+LD := ld.bfd
OBJCOPY := objcopy
CFLAGS += -ffreestanding -mno-red-zone -ggdb -std=c2x \
@@ -17,6 +17,4 @@ CXXFLAGS += -ffreestanding -mno-red-zone -ggdb \
-Wall -Wextra -Werror -fno-stack-protector
LDFLAGS += -nostdlib
-LIBDIRS += -L$(dir $(shell $(CC) -print-libgcc-file-name))
-LOADLIBES += -lgcc
diff --git a/efi.mk b/efi.mk
index 4067e44..60cf1d6 100644
--- a/efi.mk
+++ b/efi.mk
@@ -21,32 +21,7 @@ EFILDSCRIPT := $(EFILIBDIR)/elf_$(GNUEFIARCH)_efi.lds
CPPFLAGS += -I$(EFIAPIDIR) -I$(EFIAPIDIR)/protocol -I$(EFIAPIDIR)/$(GNUEFIARCH) \
-DGNU_EFI_USE_MS_ABI -DEFI_CALL_WRAPPER -DEFI_DEBUG
-CFLAGS += -fPIC -fshort-wchar -maccumulate-outgoing-args -mno-avx -mno-sse \
- -mno-mmx -funsigned-char -Wno-pointer-sign
-
-OBJCOPY.efi = $(OBJCOPY) -j .text -j .sdata -j .data -j .dynamic \
- -j .dynsm -j .rel -j .rela -j .reloc \
- --target=efi-app-$(GNUEFIARCH) $< $@
-
-OBJCOPY.debug.efi = $(OBJCOPY) -j .text -j .sdata -j .data -j .dynamic \
- -j .dynsym -j .rel -j .rela -j .reloc -j .debug_info \
- -j .debug_abbrev -j .debug_loc -j .debug_aranges \
- -j .debug_line -j .debug_macinfo -j .debug_str \
- --target=efi-app-$(GNUEFIARCH) $< $@
-
-LINK._efi.so = $(LD) $(LDFLAGS) -znocombreloc -Bsymbolic -shared --no-undefined \
- $(LIBDIRS) -L$(EFILIBDIR) -T $(EFILDSCRIPT) \
- $(filter %.o, $^) -lgnuefi -lefi $(LOADLIBES) -o $@
-
-%.efi: %_efi.so
- $(OBJCOPY.info)
- @$(OBJCOPY.efi)
-
-%.debug.efi: %_efi.so
- $(OBJCOPY.info)
- @$(OBJCOPY.debug.efi)
-
-%_efi.so: $(EFILDSCRIPT) $(EFICRT)
- $(LINK.info)
- @$(LINK._efi.so)
+%.efi:
+ $(CC.info)
+ @$(CC) $(LDFLAGS) -o $@ $^
diff --git a/kc/boot/Makefile b/kc/boot/Makefile
index 297b6df..b90f183 100644
--- a/kc/boot/Makefile
+++ b/kc/boot/Makefile
@@ -8,6 +8,9 @@ TARGET := efi.os
.DEFAULT: $(TARGET)
CPPFLAGS += -I../../api -I ../api -I../../lib
+
+CFLAGS += -fshort-wchar
+
OBJS := entry_x86_64.o reloc_x86_64.o dynamic_x86_64.o \
kc_main.o elf64.o memcmp.o memcpy.o \
memmove.o memset.o loader_paging.o
diff --git a/kc/core/Makefile b/kc/core/Makefile
index 4d373cd..394b2dc 100644
--- a/kc/core/Makefile
+++ b/kc/core/Makefile
@@ -19,7 +19,7 @@ IOBJS :=
# __attribute__((interrupt)) requires -mgeneral-regs-only
$(GOBJS): CFLAGS += -mgeneral-regs-only
-$(GOBJS): CFLAGS += -mcmodel=small -fPIC
+$(GOBJS): CFLAGS += -mcmodel=small
OBJS := $(SOBJS) $(GOBJS) $(IOBJS)
DEPS := $(patsubst %.o,%.d,$(OBJS))
diff --git a/kc/defaults.mk b/kc/defaults.mk
index 0b6c4ba..ec6dfd3 100644
--- a/kc/defaults.mk
+++ b/kc/defaults.mk
@@ -1,7 +1,9 @@
-LIBDIRS += -L$(dir $(shell $(CC) -print-libgcc-file-name))
LDSCRIPT := ../kc.ld
+
+CFLAGS += -fPIC -fvisibility=hidden -mgeneral-regs-only
+
LDFLAGS += -z max-page-size=4096 --export-dynamic -pic \
- -z separate-code -pie -Bsymbolic -shared
-LOADLIBES := -lgcc
+ -z separate-code -pie -Bsymbolic -shared \
+ -z execstack -g
diff --git a/kc/dynamic_x86_64.c b/kc/dynamic_x86_64.c
index 6b7abd7..a573283 100644
--- a/kc/dynamic_x86_64.c
+++ b/kc/dynamic_x86_64.c
@@ -9,10 +9,10 @@ void kc_dynamic_init(void *base, Elf64_Dyn *dyn)
size_t entsize;
};
- struct rela reladyn = {NULL,};
- struct rela relaplt = {NULL,};
+ struct rela reladyn = {NULL, 0, 0};
+ struct rela relaplt = {NULL, 0, 0};
- Elf64_Addr *gotplt;
+ Elf64_Addr *gotplt = NULL;
while (dyn && dyn->d_tag != DT_NULL)
{
@@ -46,8 +46,11 @@ void kc_dynamic_init(void *base, Elf64_Dyn *dyn)
// peform relocations
//
- gotplt[1] = (uintptr_t)NULL;
- gotplt[2] = (uintptr_t)kc_resolve_symbol;
+ if (gotplt)
+ {
+ gotplt[1] = (uintptr_t)NULL;
+ gotplt[2] = (uintptr_t)kc_resolve_symbol;
+ }
kc_reloc(base, relaplt.entries, relaplt.size, relaplt.entsize);
kc_reloc(base, reladyn.entries, reladyn.size, reladyn.entsize);
}
diff --git a/kc/entry_x86_64.S b/kc/entry_x86_64.S
index 8431044..c426335 100644
--- a/kc/entry_x86_64.S
+++ b/kc/entry_x86_64.S
@@ -6,14 +6,22 @@
.global kc_entry
.type kc_entry, @function
kc_entry:
+ push %rbp
push %rdi
push %rsi
+ mov %rsp, %rbp
+ and $-0x10, %rsp
lea kc_image_base(%rip), %rdi
lea _DYNAMIC(%rip), %rsi
call kc_dynamic_init
+ mov %rbp, %rsp
pop %rsi
pop %rdi
+ mov %rsp, %rbp
+ and $-0x10, %rsp
call kc_main
+ mov %rbp, %rsp
+ pop %rbp
ret
.size kc_entry, . - kc_entry
diff --git a/kc/kc.ld b/kc/kc.ld
index dbce342..97d6a2a 100644
--- a/kc/kc.ld
+++ b/kc/kc.ld
@@ -4,7 +4,7 @@ SECTIONS
{
PROVIDE_HIDDEN(kc_image_base = .);
- . = sizeof_headers;
+ . = SIZEOF_HEADERS;
.rela.plt :
{
diff --git a/loader/Makefile b/loader/Makefile
index 5e1c8ac..d273258 100644
--- a/loader/Makefile
+++ b/loader/Makefile
@@ -4,18 +4,22 @@ include ../efi.mk
VPATH := ../lib
IMAGE := loader.efi
-BUILD := $(IMAGE) $(IMAGE:.efi=.debug.efi)
CPPFLAGS += -I../api -I../lib
-all: $(BUILD)
+CFLAGS += --target=$(GNUEFIARCH)-unknown-windows -fshort-wchar -mno-avx \
+ -mno-sse -mno-mmx -funsigned-char -Wno-pointer-sign -ggdb
-OBJS := main_efi.o elf64.o memcmp.o memmove.o kprintf.o strtoull.o
+LDFLAGS := --target=$(GNUEFIARCH)-unknown-windows -nostdlib -ggdb \
+ -Wl,-entry:efi_main,-subsystem:efi_application -fuse-ld=lld-link
+
+all: $(IMAGE)
+
+OBJS := main_efi.o elf64.o memcmp.o memmove.o kprintf.o strtoull.o memset.o \
+ memcpy.o
DEPS := $(OBJS:.o=.d)
-IMAGE_SO := $(IMAGE:.efi=_efi.so)
-$(IMAGE_SO): $(OBJS)
-.INTERMEDIATE: $(IMAGE_SO)
+$(IMAGE): $(OBJS)
CLEANLIST := $(wildcard $(BUILD) $(OBJS))
DCLEANLIST := $(CLEANLIST) $(wildcard $(DEPS))
diff --git a/loader/main_efi.c b/loader/main_efi.c
index 0b7dc3b..3b50c36 100644
--- a/loader/main_efi.c
+++ b/loader/main_efi.c
@@ -32,6 +32,9 @@ static struct efi_loader_image shim_image =
.path = L"\\adasoft\\sophia\\efi.os"
};
+static CHAR16 *linebuf;
+static CHAR16 *linebuf_ptr;
+
static VOID *AllocatePool(UINTN size)
{
EFI_STATUS status;
@@ -65,16 +68,7 @@ static VOID FreePool(void *block)
}
}
-static struct efi_loader_interface loader_interface =
-{
- NULL,
- NULL,
- &alloc_page,
- &free_page,
- &open_image,
- &allocate_image,
- &load_image
-};
+static struct efi_loader_interface loader_interface;
static const CHAR16 *efi_status_strings[] =
{
@@ -129,14 +123,18 @@ static const CHAR16 *efi_warning_strings[] =
int kfputc(int c, FILE *f)
{
(void)f;
- CHAR16 s[2] = {0,};
- EFI_STATUS status;
+ EFI_STATUS status = EFI_SUCCESS;
if (loader_interface.system_table)
{
EFI_SIMPLE_TEXT_OUT_PROTOCOL *out = gST->ConOut;
- s[0] = c;
- status = out->OutputString(out, s);
+ *linebuf_ptr++ = c;
+ if (((linebuf_ptr - linebuf) == EFI_PAGE_SIZE - 2) || (c == L'\n'))
+ {
+ *linebuf_ptr++ = 0;
+ status = out->OutputString(out, linebuf);
+ linebuf_ptr = linebuf;
+ }
}
else
{
@@ -153,13 +151,54 @@ int kfputc(int c, FILE *f)
EFI_STATUS efi_main(EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *system_table)
{
+ loader_interface = (struct efi_loader_interface){
+ image_handle,
+ system_table,
+ alloc_page,
+ free_page,
+ open_image,
+ allocate_image,
+ load_image
+ };
+
gST = system_table;
gBS = system_table->BootServices;
- loader_interface.image_handle = image_handle;
- loader_interface.system_table = system_table;
EFI_STATUS status;
+ if EFI_ERROR((status = alloc_page(
+ EfiLoaderData,
+ EFI_PAGE_SIZE,
+ (EFI_PHYSICAL_ADDRESS *)&linebuf)))
+ {
+ gST->ConOut->OutputString(
+ gST->ConOut,
+ L"error allocating for line buffer");
+ return status;
+ }
+ else
+ {
+ gBS->SetMem(linebuf, EFI_PAGE_SIZE, 0);
+ linebuf_ptr = linebuf;
+ }
+
+ kprintf("loader interface %p\r\n"
+ "image_handle %p\r\n"
+ "system_table %p\r\n"
+ "page_alloc %p\r\n"
+ "page_free %p\r\n"
+ "image_open %p\r\n"
+ "image_alloc %p\r\n"
+ "image_load %p\r\n",
+ &loader_interface,
+ loader_interface.image_handle,
+ loader_interface.system_table,
+ loader_interface.page_alloc,
+ loader_interface.page_free,
+ loader_interface.image_open,
+ loader_interface.image_alloc,
+ loader_interface.image_load);
+
if (EFI_ERROR((status = open_image(&shim_image))))
{
kprintf("error opening shim image: %ls\r\n",
@@ -214,7 +253,7 @@ EFI_STATUS alloc_page(EFI_MEMORY_TYPE type,
EFI_STATUS free_page(EFI_PHYSICAL_ADDRESS base, UINTN size)
{
- return gBS->FreePages(base, size);
+ return gBS->FreePages(base, EFI_SIZE_TO_PAGES(size));
}
@@ -304,7 +343,6 @@ EFI_STATUS open_image(struct efi_loader_image *image)
{
phdrs_size = ehdr.e_phentsize * ehdr.e_phnum;
phdrs = AllocatePool(phdrs_size);
- ASSERT(phdrs);
}
else
{
@@ -366,8 +404,6 @@ static EFI_STATUS read_image(struct efi_loader_image *image,
EFI_STATUS status;
- ASSERT(buffer);
-
if (!EFI_ERROR((status = image->file->SetPosition(image->file, offset))))
{
*buffer = (void *)(image->buffer_base + offset);
@@ -425,12 +461,23 @@ EFI_STATUS load_image(struct efi_loader_image *image)
static EFI_STATUS enter_shim(void)
{
- EFI_STATUS status;
+ EFI_STATUS status = EFI_ABORTED;
Elf64_Ehdr *ehdr = (Elf64_Ehdr *)shim_image.buffer_base;
kc_entry_func entry;
entry = (kc_entry_func)(shim_image.buffer_base + ehdr->e_entry);
- status = entry(&loader_interface);
+ kprintf("entering shim @%p\r\n", entry);
+
+ __asm__ volatile
+ (
+ "mov %0, %%rax\n\t"
+ "lea %1, %%rdi\n\t"
+ "call *%%rax\n\t"
+ :
+ : "m"(entry), "m"(loader_interface)
+ : "%rax", "%rdi"
+ );
+
return status;
}
diff --git a/rules.mk b/rules.mk
index 2115028..756184e 100644
--- a/rules.mk
+++ b/rules.mk
@@ -15,7 +15,7 @@ COMPILE.info = $(info $$(CC) $@)
%.os:
$(LINK.info)
- @$(LINK.os)
+ $(LINK.os)
%.debug.os: %.os
$(OBJCOPY) --only-keep-debug $< $@
@@ -23,15 +23,15 @@ COMPILE.info = $(info $$(CC) $@)
%.o: %.c
$(COMPILE.info)
- @$(COMPILE.c) -MMD -MP
+ $(COMPILE.c) -MMD -MP
%.o: %.cpp
$(COMPILE.info)
- @$(COMPILE.cpp) -MMD -MP
+ $(COMPILE.cpp) -MMD -MP
%.o: %.S
$(COMPILE.info)
- @$(COMPILE.S) -MMD -MP
+ $(COMPILE.S) -MMD -MP
clean:
$(info $$(RM) $(CLEANLIST))