boot.img
kernel.efi
tags
+BOOTX64.EFI
-TARGET = kernel.efi
-OVMF = /usr/share/qemu/OVMF.fd
-#OVMF = /usr/share/edk2-ovmf/OVMF_CODE.fd
+ARCH = x86_64
+EFIARCH = efi-app-$(ARCH)
+TARGET = BOOTX64.EFI
-include uefi/Makefile
+CC = gcc
+LD = ld
+OBJCOPY = objcopy
+AR = ar
-.PHONY: all run clean
+CFLAGS = \
+ -fshort-wchar \
+ -fno-strict-aliasing \
+ -ffreestanding \
+ -fno-stack-protector \
+ -fno-stack-check \
+ -mno-red-zone \
+ -maccumulate-outgoing-args \
+ -Wno-builtin-declaration-mismatch \
+ -fpic \
+ -fPIC
-all: boot.img
+CPPFLAGS = \
+ -I./core/ \
+ -I./uefi \
+ -I/usr/include \
+ -D__$(ARCH)__ \
+ -DHAVE_USE_MS_ABI
+
+LDFLAGS = \
+ -nostdlib \
+ -shared \
+ -Bsymbolic \
+ -Luefi
+
+LIBS = \
+ -o $(TARGET).so \
+ -T uefi/elf_$(ARCH)_efi.lds
+
+# get source files, generate object names
+SRCS = $(wildcard core/*.c uefi/*.c)
+OBJS = $(SRCS:.c=.o)
+
+.PHONY: all clean run
+
+all: $(TARGET)
clean:
find -name '*.o' -delete
rm -f kernel.efi uefi/libuefi.a boot.img
run: boot.img
- qemu-system-x86_64 -bios $(OVMF) -cpu qemu64 boot.img
+ qemu-system-$(ARCH) -bios $(OVMF) -cpu qemu64 boot.img
boot.img: $(TARGET)
dd if=/dev/zero of=boot.img bs=1k count=1440
mformat -i boot.img -f 1440 ::
mmd -i boot.img ::/EFI
mmd -i boot.img ::/EFI/BOOT
- mcopy -i boot.img kernel.efi ::/EFI/BOOT/BOOTX64.EFI
+ mcopy -i boot.img BOOTX64.EFI ::/EFI/BOOT/BOOTX64.EFI
+
+$(TARGET): $(TARGET).so
+ $(OBJCOPY) -j .text -j .sdata -j .data -j .dynamic -j .dynsym -j .rel -j .rela -j .rel.* -j .rela.* -j .reloc --target $(EFIARCH) --subsystem=10 $^ $@ || echo target: $(EFIARCH)
+ rm $(TARGET).so
+
+$(TARGET).so: $(OBJS)
+ $(LD) $(LDFLAGS) $^ $(LIBS)
+ @rm *.lib 2>/dev/null || true
+
+%.o: %.c
+ $(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@
+
+%.o: %.S
+ $(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@
-#include <uefi.h>
+#include <platform.h>
+#include <kernel.h>
uint8_t Font[4096] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--- /dev/null
+/*
+ Graphics Support
+*/
+#define FONT_WIDTH 8
+#define FONT_HEIGHT 16
+extern uint8_t Font[];
+
+void Video_PutGlyph(int x, int y, char c);
+
+static inline void Video_PutPixel(int x, int y, uint32_t pixel)
+{
+ int offset = (sizeof(pixel) * Video.stride * y) + (sizeof(pixel) * x);
+ *(Video.buffer + offset) = pixel;
+}
+
+/*
+ Terminal/Console Driver
+*/
+void Term_Clear(void);
+void Term_PutChar(int c);
+void Term_PutString(char* s);
+void Term_PutInt(int64_t val);
+void Term_PutHex(uint64_t val);
+void Term_PutHex8(uint8_t val);
+void Term_PutHex16(uint16_t val);
+void Term_PutHex32(uint32_t val);
+void Term_PutHex64(uint64_t val);
+void Term_PutNewline(void);
\ No newline at end of file
--- /dev/null
+#include <platform.h>
+
+int main (int argc, char** argv)
+{
+
+ /* loop forever */
+ for (;;)
+ {
+// BS->Stall(1000000);
+ }
+
+ return 0;
+}
-#include <uefi.h>
+#include <platform.h>
+#include <kernel.h>
static char* Digits = "0123456789abcdef";
+static void PutGlyph(int x, int y, char c)
+{
+ char* glyph = &Font[c * FONT_HEIGHT];
+ for (int row = 0; row < 16; row++)
+ {
+ char piece = glyph[row];
+ for (int col = 0; col < 8; col++, piece <<= 1)
+ {
+ Video_PutPixel(
+ (x * FONT_WIDTH) + col,
+ (y * FONT_HEIGHT) + row,
+ (piece & 0x80) ? 0xFFFFFFFF : 0x00000000);
+ }
+ }
+}
+
+
void Term_PutChar(int c)
{
- wchar_t tmp[2] = { (wchar_t)c, 0 };
- ST->ConOut->OutputString(ST->ConOut, (c == '\n' ? (wchar_t*)L"\r\n" : tmp));
+// wchar_t tmp[2] = { (wchar_t)c, 0 };
+// ST->ConOut->OutputString(ST->ConOut, (c == '\n' ? (wchar_t*)L"\r\n" : tmp));
}
void Term_PutString(char* s)
--- /dev/null
+#include <platform.h>
+
+++ /dev/null
-#include <uefi.h>
-
-static void PutIntField(char* label, int val)
-{
- Term_PutString(label);
- Term_PutInt(val);
- Term_PutNewline();
-}
-
-int main (int argc, char** argv)
-{
- Video_Init();
-//
-// char glyph = 0;
-// for (int y = 0; y < 16; y++)
-// {
-// for (int x = 0; x < 16; x++)
-// {
-// Video_PutGlyph(
-// x,
-// y,
-// glyph++
-// );
-// }
-// }
-
- /* loop forever */
- for (;;)
- {
- BS->Stall(1000000);
- }
-
- return 0;
-}
# detect architecture
-MYARCH = $(shell uname -m | sed s,i[3456789]86,ia32,)
+HOST_ARCH = $(shell uname -m | sed s,i[3456789]86,ia32,)
ifeq ($(ARCH),)
-ARCH = $(MYARCH)
+ ARCH = $(HOST_ARCH)
endif
# get source files, generate object names
LIBOBJS = $(TMP:.S=.o)
# detect toolchain
-ifeq ($(wildcard /usr/bin/clang),)
-USE_GCC = 1
-endif
-ifneq ($(USE_GCC),)
+
ifeq ($(ARCH),x86_64)
-CFLAGS += -maccumulate-outgoing-args
+ CFLAGS += -maccumulate-outgoing-args
endif
+
CFLAGS += -Wno-builtin-declaration-mismatch -fpic -fPIC
LDFLAGS += -nostdlib -shared -Bsymbolic -Luefi uefi/crt_$(ARCH).o
LIBS += -o $(TARGET).so -luefi -T uefi/elf_$(ARCH)_efi.lds
+
# see if we're cross-compiling
-ifneq ($(ARCH),$(MYARCH))
-CC = $(ARCH)-elf-gcc
-LD = $(ARCH)-elf-ld
-OBJCOPY ?= $(ARCH)-elf-objcopy
+ifneq ($(ARCH),$(HOST_ARCH))
+ CC = $(ARCH)-elf-gcc
+ LD = $(ARCH)-elf-ld
+ OBJCOPY ?= $(ARCH)-elf-objcopy
else
-CC = gcc
-LD = ld
-OBJCOPY ?= objcopy
+ CC = gcc
+ LD = ld
+ OBJCOPY ?= objcopy
endif
+
ifeq ($(ARCH),aarch64)
-EFIARCH = pei-aarch64-little
+ EFIARCH = pei-aarch64-little
else
-EFIARCH = efi-app-$(ARCH)
+ EFIARCH = efi-app-$(ARCH)
endif
AR ?= ar
-else
-CFLAGS += --target=$(ARCH)-pc-win32-coff -Wno-builtin-requires-header -Wno-incompatible-library-redeclaration -Wno-long-long
-LDFLAGS += -subsystem:efi_application -nodefaultlib -dll -entry:uefi_init uefi/*.o
-LIBS = -out:$(TARGET)
-CC = clang
-LD = lld-link
-OBJCOPY = true
-endif
# recipies
ifeq ($(wildcard uefi/Makefile),)
-ALLTARGETS = crt_$(ARCH).o libuefi.a build
+ ALLTARGETS = crt_$(ARCH).o libuefi.a build
else
-ALLTARGETS = uefi/crt_$(ARCH).o uefi/libuefi.a $(OBJS) $(TARGET)
+ ALLTARGETS = uefi/crt_$(ARCH).o uefi/libuefi.a $(OBJS) $(TARGET)
endif
all: $(ALLTARGETS) $(EXTRA)
%.o: %.S
$(CC) $(CFLAGS) -c $< -o $@
+
+dump:
+ @echo CFLAGS = $(CFLAGS)
\ No newline at end of file
-/*
- * crt_x86_64.c
- *
- * Copyright (C) 2021 bzt (bztsrc@gitlab)
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * This file is part of the POSIX-UEFI package.
- * @brief C runtime, bootstraps an EFI application to call standard main()
- *
- * Simplified by Mike Lowis 2021.
- */
-
+#include <platform.h>
#include <uefi.h>
/* this is implemented by the application */
efi_runtime_services_t *RT = NULL;
efi_loaded_image_protocol_t *LIP = NULL;
-#if USE_UTF8
-char *__argvutf8 = NULL;
-#endif
+/* platform specific globals */
+VideoConfig Video = {0};
-/* we only need one .o file, so use inline Assembly here */
-void bootstrap()
+static void video_init(void)
{
- __asm__ __volatile__ (
- /* call init in C */
- " .align 4\n"
-#ifndef __clang__
- " .globl _start\n"
- "_start:\n"
- " lea ImageBase(%rip), %rdi\n"
- " lea _DYNAMIC(%rip), %rsi\n"
- " call uefi_init\n"
- " ret\n"
+ /* get a handle to the graphics protocol */
+ efi_gop_t *gop = NULL;
+ efi_guid_t gopGuid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
+ BS->LocateProtocol(&gopGuid, NULL, (void**)&gop);
- /* fake a relocation record, so that EFI won't complain */
- " .data\n"
- "dummy: .long 0\n"
- " .section .reloc, \"a\"\n"
- "label1:\n"
- " .long dummy-label1\n"
- " .long 10\n"
- " .word 0\n"
- ".text\n"
-#else
- " .globl __chkstk\n"
- "__chkstk:\n"
- " ret\n"
-#endif
- );
+ /* query mode 0 to see if mode needs to be set first */
+ uintn_t info_size = 0;
+ efi_gop_mode_info_t *info = NULL;
+ uintn_t status = gop->QueryMode(gop, 0, &info_size, &info);
+
+ /* some machines need mode set explicitly first */
+ if (status == EFI_NOT_STARTED)
+ {
+ status = gop->SetMode(gop, 0);
+ }
+
+ /*
+ OK, now we have real info for possible modes, pick the max mode.
+ We assume this one is the best resolution.
+ */
+ if (status == EFI_SUCCESS)
+ {
+ status = gop->SetMode(gop, 17); /* pick a smaller resolution for QEMU */
+// status = gop->SetMode(gop, gop->Mode->MaxMode-1);
+ }
+
+ /*
+ Now let's save off the info we need to draw pixels and glyphs.
+ The code in this file assumes 32 bits per pixel.
+ */
+ Video.buffer = (uint32_t*)(gop->Mode->FrameBufferBase);
+ Video.stride = gop->Mode->Information->PixelsPerScanLine;
}
-/**
- * Initialize POSIX-UEFI and call the application's main() function
+/*
+ * crt_x86_64.c : bootstrap() and uefi_init()
+ *
+ * Copyright (C) 2021 bzt (bztsrc@gitlab)
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * This file is part of the POSIX-UEFI package.
+ * @brief C runtime, bootstraps an EFI application to call standard main()
+ *
*/
-int uefi_init (
-#ifndef __clang__
- uintptr_t ldbase, Elf64_Dyn *dyn, efi_system_table_t *systab, efi_handle_t image
-#else
- efi_handle_t image, efi_system_table_t *systab
-#endif
-) {
+
+int uefi_init(uintptr_t ldbase, Elf64_Dyn *dyn, efi_system_table_t *systab, efi_handle_t image)
+{
efi_guid_t shpGuid = EFI_SHELL_PARAMETERS_PROTOCOL_GUID;
efi_shell_parameters_protocol_t *shp = NULL;
efi_guid_t shiGuid = SHELL_INTERFACE_PROTOCOL_GUID;
efi_guid_t lipGuid = EFI_LOADED_IMAGE_PROTOCOL_GUID;
efi_guid_t gopGuid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
efi_status_t status;
-#ifndef __clang__
+
long relsz = 0, relent = 0;
Elf64_Rel *rel = 0;
uintptr_t *addr;
if (rel && relent) {
while (relsz > 0) {
if(ELF64_R_TYPE (rel->r_info) == R_X86_64_RELATIVE)
- { addr = (unsigned long *)(ldbase + rel->r_offset); *addr += ldbase; break; }
+ { addr = (uintptr_t*)(ldbase + rel->r_offset); *addr += ldbase; break; }
rel = (Elf64_Rel*) ((char *) rel + relent);
relsz -= relent;
}
}
-#else
- (void)i;
-#endif
/* make sure SSE is enabled, because some say there are buggy firmware in the wild not doing that */
__asm__ __volatile__ (
" orw $3 << 9, %ax\n"
" mov %rax, %cr4\n"
);
+
/* save EFI pointers and loaded image into globals */
IM = image;
ST = systab;
BS = systab->BootServices;
RT = systab->RuntimeServices;
BS->HandleProtocol(image, &lipGuid, (void **)&LIP);
+
+ /* perform some initialization for the kernel */
+ video_init();
+
return main(0, 0);
}
+
+/* we only need one .o file, so use inline Assembly here */
+void bootstrap()
+{
+ __asm__ __volatile__ (
+ /* call init in C */
+ " .align 4\n"
+ " .globl _start\n"
+ "_start:\n"
+ " lea ImageBase(%rip), %rdi\n"
+ " lea _DYNAMIC(%rip), %rsi\n"
+ " call uefi_init\n"
+ " ret\n"
+
+ /* fake a relocation record, so that EFI won't complain */
+ " .data\n"
+ "dummy: .long 0\n"
+ " .section .reloc, \"a\"\n"
+ "label1:\n"
+ " .long dummy-label1\n"
+ " .long 10\n"
+ " .word 0\n"
+ ".text\n"
+ );
+}
--- /dev/null
+/* define standard type definitions */
+typedef char int8_t;
+typedef unsigned char uint8_t;
+typedef short int16_t;
+typedef unsigned short uint16_t;
+typedef int int32_t;
+typedef unsigned int uint32_t;
+typedef long long int64_t;
+typedef unsigned long long uint64_t;
+typedef long long intptr_t;
+typedef unsigned long long uintptr_t;
+
+/* sanity check type definitions */
+extern char check_u16[sizeof(uint16_t) == 2 ? 1 : -1];
+extern char check_u32[sizeof(uint32_t) == 4 ? 1 : -1];
+extern char check_u64[sizeof(uint64_t) == 8 ? 1 : -1];
+extern char check_uptr[sizeof(uintptr_t) == 8 ? 1 : -1];
+
+#define NULL ((void*)0)
+
+/* video memory configuration info */
+typedef struct {
+ uint32_t* buffer;
+ uint32_t stride;
+ uint32_t width;
+ uint32_t height;
+} VideoConfig;
+
+extern VideoConfig Video;
\ No newline at end of file
/* comment out this if you want to use wchar_t in your application */
#define USE_UTF8 1
-/* get these from the compiler */
-#ifndef _STDINT_H
-#define _STDINT_H
-typedef char int8_t;
-typedef unsigned char uint8_t;
-typedef short int16_t;
-typedef unsigned short uint16_t;
-typedef int int32_t;
-typedef unsigned int uint32_t;
-#ifndef __clang__
-typedef long int int64_t;
-typedef unsigned long int uint64_t;
-typedef unsigned long int uintptr_t;
-#else
-typedef long long int64_t;
-typedef unsigned long long uint64_t;
-typedef unsigned long long uintptr_t;
-#endif
-#endif
-extern char c_assert1[sizeof(uint32_t) == 4 ? 1 : -1];
-extern char c_assert2[sizeof(uint64_t) == 8 ? 1 : -1];
-extern char c_assert3[sizeof(uintptr_t) == 8 ? 1 : -1];
-
-#ifndef NULL
-#define NULL ((void*)0)
-#endif
/*** common defines and typedefs ***/
typedef int64_t intn_t;
typedef uint8_t boolean_t;
#define min(x,y) ((x)<(y)?(x):(y))
#define max(x,y) ((x)>(y)?(x):(y))
-#define FONT_WIDTH 8
-#define FONT_HEIGHT 16
-extern uint8_t Font[];
-
-extern uint32_t* VideoMem;
-extern uint32_t VideoStride;
-
-void Video_Init(void);
-void Video_PutGlyph(int x, int y, char c);
-
-static inline void Video_PutPixel(int x, int y, uint32_t pixel)
-{
- int offset = (sizeof(pixel) * VideoStride * y) + (sizeof(pixel) * x);
- *(VideoMem + offset) = pixel;
-}
-
-void Term_Clear(void);
-void Term_PutChar(int c);
-void Term_PutString(char* s);
-void Term_PutInt(int64_t val);
-void Term_PutHex(uint64_t val);
-void Term_PutHex8(uint8_t val);
-void Term_PutHex16(uint16_t val);
-void Term_PutHex32(uint32_t val);
-void Term_PutHex64(uint64_t val);
-void Term_PutNewline(void);
-
#ifdef __cplusplus
}
#endif
+++ /dev/null
-#include <uefi.h>
-
-uint32_t* VideoMem = NULL;
-uint32_t VideoStride = 0;
-
-void Video_Init(void)
-{
- /* get a handle to the graphics protocol */
- efi_gop_t *gop = NULL;
- efi_guid_t gopGuid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
- BS->LocateProtocol(&gopGuid, NULL, (void**)&gop);
-
- /* query mode 0 to see if mode needs to be set first */
- uintn_t info_size = 0;
- efi_gop_mode_info_t *info = NULL;
- uintn_t status = gop->QueryMode(gop, 0, &info_size, &info);
-
- /* some machines need mode set explicitly first */
- if (status == EFI_NOT_STARTED)
- {
- status = gop->SetMode(gop, 0);
- }
-
- /*
- OK, now we have real info for possible modes, pick the max mode.
- We assume this one is the best resolution.
- */
- if (status == EFI_SUCCESS)
- {
- status = gop->SetMode(gop, 17); /* pick a smaller resolution for QEMU */
-// status = gop->SetMode(gop, gop->Mode->MaxMode-1);
- }
-
- /*
- Now let's save off the info we need to draw pixels and glyphs.
- The code in this file assumes 32 bits per pixel.
- */
- VideoMem = (uint32_t*)(gop->Mode->FrameBufferBase);
- VideoStride = gop->Mode->Information->PixelsPerScanLine;
-}
-
-void Video_PutGlyph(int x, int y, char c)
-{
- char* glyph = &Font[c * FONT_HEIGHT];
- for (int row = 0; row < 16; row++)
- {
- char piece = glyph[row];
- for (int col = 0; col < 8; col++, piece <<= 1)
- {
- Video_PutPixel(
- (x * FONT_WIDTH) + col,
- (y * FONT_HEIGHT) + row,
- (piece & 0x80) ? 0xFFFFFFFF : 0x00000000);
- }
- }
-}