From 94e9aced542ae8dcd52c62c468fdaf19b446bbe5 Mon Sep 17 00:00:00 2001 From: Joshua Goins Date: Mon, 6 Jun 2022 21:36:25 -0400 Subject: [PATCH] Separate stivale tty code --- Makefile | 11 +-- src/boot/stivale/stivale.c | 140 +++++++++++++++++++++++++++++++++++++ src/kernel.c | 134 ++--------------------------------- src/tty.h | 2 + 4 files changed, 153 insertions(+), 134 deletions(-) create mode 100644 src/boot/stivale/stivale.c create mode 100644 src/tty.h diff --git a/Makefile b/Makefile index 30131b6..4fc4b20 100644 --- a/Makefile +++ b/Makefile @@ -43,10 +43,12 @@ INTERNALLDFLAGS := \ -nostdlib \ -zmax-page-size=0x1000 \ -static - -CFILES := $(wildcard $(SRC_DIR)/*.c) -OBJ := $(BUILD_DIR)/$(notdir $(CFILES:.c=.o)) -HEADER_DEPS := $(BUILD_DIR)/$(notdir $(CFILES:.c=.d)) + +rwildcard=$(foreach d,$(wildcard $(1:=/*)),$(call rwildcard,$d,$2) $(filter $(subst *,%,$2),$d)) + +CFILES := $(shell find ./$(SRC_DIR) -type f -name '*.c') +OBJ := $(subst $(SRC_DIR),$(BUILD_DIR),$(CFILES:.c=.o)) +HEADER_DEPS := $(OBJ:.o=.d)) .PHONY: all all: $(KERNEL) @@ -56,6 +58,7 @@ $(KERNEL): $(OBJ) | $(BIN_DIR) -include $(HEADER_DEPS) $(BUILD_DIR)/%.o: $(SRC_DIR)/%.c | $(BUILD_DIR) + @mkdir -p $(@D) $(CC) $(CFLAGS) $(INTERNALCFLAGS) -c $< -o $@ # create directories if they don't exist diff --git a/src/boot/stivale/stivale.c b/src/boot/stivale/stivale.c new file mode 100644 index 0000000..4b22f01 --- /dev/null +++ b/src/boot/stivale/stivale.c @@ -0,0 +1,140 @@ +#include +#include +#include + +// We need to tell the stivale bootloader where we want our stack to be. +// We are going to allocate our stack as an array in .bss. +static uint8_t stack[8192]; + +// stivale2 uses a linked list of tags for both communicating TO the +// bootloader, or receiving info FROM it. More information about these tags +// is found in the stivale2 specification. + +// stivale2 offers a runtime terminal service which can be ditched at any +// time, but it provides an easy way to print out to graphical terminal, +// especially during early boot. +// Read the notes about the requirements for using this feature below this +// code block. +static struct stivale2_header_tag_terminal terminal_hdr_tag = { + // All tags need to begin with an identifier and a pointer to the next tag. + .tag = { + // Identification constant defined in stivale2.h and the specification. + .identifier = STIVALE2_HEADER_TAG_TERMINAL_ID, + // If next is 0, it marks the end of the linked list of header tags. + .next = 0 + }, + // The terminal header tag possesses a flags field, leave it as 0 for now + // as it is unused. + .flags = 0 +}; + +// We are now going to define a framebuffer header tag. +// This tag tells the bootloader that we want a graphical framebuffer instead +// of a CGA-compatible text mode. Omitting this tag will make the bootloader +// default to text mode, if available. +static struct stivale2_header_tag_framebuffer framebuffer_hdr_tag = { + // Same as above. + .tag = { + .identifier = STIVALE2_HEADER_TAG_FRAMEBUFFER_ID, + // Instead of 0, we now point to the previous header tag. The order in + // which header tags are linked does not matter. + .next = (uint64_t)&terminal_hdr_tag + }, + // We set all the framebuffer specifics to 0 as we want the bootloader + // to pick the best it can. + .framebuffer_width = 0, + .framebuffer_height = 0, + .framebuffer_bpp = 0 +}; + +// The stivale2 specification says we need to define a "header structure". +// This structure needs to reside in the .stivale2hdr ELF section in order +// for the bootloader to find it. We use this __attribute__ directive to +// tell the compiler to put the following structure in said section. +__attribute__((section(".stivale2hdr"), used)) +static struct stivale2_header stivale_hdr = { + // The entry_point member is used to specify an alternative entry + // point that the bootloader should jump to instead of the executable's + // ELF entry point. We do not care about that so we leave it zeroed. + .entry_point = 0, + // Let's tell the bootloader where our stack is. + // We need to add the sizeof(stack) since in x86(_64) the stack grows + // downwards. + .stack = (uintptr_t)stack + sizeof(stack), + // Bit 1, if set, causes the bootloader to return to us pointers in the + // higher half, which we likely want since this is a higher half kernel. + // Bit 2, if set, tells the bootloader to enable protected memory ranges, + // that is, to respect the ELF PHDR mandated permissions for the executable's + // segments. + // Bit 3, if set, enables fully virtual kernel mappings, which we want as + // they allow the bootloader to pick whichever *physical* memory address is + // available to load the kernel, rather than relying on us telling it where + // to load it. + // Bit 4 disables a deprecated feature and should always be set. + .flags = (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4), + // This header structure is the root of the linked list of header tags and + // points to the first one in the linked list. + .tags = (uintptr_t)&framebuffer_hdr_tag +}; + +// We will now write a helper function which will allow us to scan for tags +// that we want FROM the bootloader (structure tags). +void *stivale2_get_tag(struct stivale2_struct *stivale2_struct, uint64_t id) { + struct stivale2_tag *current_tag = (void *)stivale2_struct->tags; + for (;;) { + // If the tag pointer is NULL (end of linked list), we did not find + // the tag. Return NULL to signal this. + if (current_tag == NULL) { + return NULL; + } + + // Check whether the identifier matches. If it does, return a pointer + // to the matching tag. + if (current_tag->identifier == id) { + return current_tag; + } + + // Get a pointer to the next tag in the linked list and repeat. + current_tag = (void *)current_tag->next; + } +} + +struct stivale2_struct_tag_terminal *term_str_tag = NULL; +void *term_write_ptr = NULL; +void (*term_write)(const char *string, size_t length) = NULL; + +// The following will be our kernel's entry point. +void _start(struct stivale2_struct *stivale2_struct) { + // Let's get the terminal structure tag from the bootloader. + term_str_tag = stivale2_get_tag(stivale2_struct, STIVALE2_STRUCT_TAG_TERMINAL_ID); + + // Check if the tag was actually found. + if (term_str_tag == NULL) { + // It wasn't found, just hang... + for (;;) { + asm ("hlt"); + } + } + + kernel_main(); + + // We're done, just hang... + for (;;) { + asm ("hlt"); + } +} + +void terminal_initialize() { + // stub for stivale + // Let's get the address of the terminal write function. + term_write_ptr = (void *)term_str_tag->term_write; + + // Now, let's assign this pointer to a function pointer which + // matches the prototype described in the stivale2 specification for + // the stivale2_term_write function. + term_write = term_write_ptr; +} + +void tty_print(const char* str, int length) { + term_write(str, length); +} diff --git a/src/kernel.c b/src/kernel.c index fc940d5..4e856c9 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -1,132 +1,6 @@ -#include -#include -#include +#include -// We need to tell the stivale bootloader where we want our stack to be. -// We are going to allocate our stack as an array in .bss. -static uint8_t stack[8192]; - -// stivale2 uses a linked list of tags for both communicating TO the -// bootloader, or receiving info FROM it. More information about these tags -// is found in the stivale2 specification. - -// stivale2 offers a runtime terminal service which can be ditched at any -// time, but it provides an easy way to print out to graphical terminal, -// especially during early boot. -// Read the notes about the requirements for using this feature below this -// code block. -static struct stivale2_header_tag_terminal terminal_hdr_tag = { - // All tags need to begin with an identifier and a pointer to the next tag. - .tag = { - // Identification constant defined in stivale2.h and the specification. - .identifier = STIVALE2_HEADER_TAG_TERMINAL_ID, - // If next is 0, it marks the end of the linked list of header tags. - .next = 0 - }, - // The terminal header tag possesses a flags field, leave it as 0 for now - // as it is unused. - .flags = 0 -}; - -// We are now going to define a framebuffer header tag. -// This tag tells the bootloader that we want a graphical framebuffer instead -// of a CGA-compatible text mode. Omitting this tag will make the bootloader -// default to text mode, if available. -static struct stivale2_header_tag_framebuffer framebuffer_hdr_tag = { - // Same as above. - .tag = { - .identifier = STIVALE2_HEADER_TAG_FRAMEBUFFER_ID, - // Instead of 0, we now point to the previous header tag. The order in - // which header tags are linked does not matter. - .next = (uint64_t)&terminal_hdr_tag - }, - // We set all the framebuffer specifics to 0 as we want the bootloader - // to pick the best it can. - .framebuffer_width = 0, - .framebuffer_height = 0, - .framebuffer_bpp = 0 -}; - -// The stivale2 specification says we need to define a "header structure". -// This structure needs to reside in the .stivale2hdr ELF section in order -// for the bootloader to find it. We use this __attribute__ directive to -// tell the compiler to put the following structure in said section. -__attribute__((section(".stivale2hdr"), used)) -static struct stivale2_header stivale_hdr = { - // The entry_point member is used to specify an alternative entry - // point that the bootloader should jump to instead of the executable's - // ELF entry point. We do not care about that so we leave it zeroed. - .entry_point = 0, - // Let's tell the bootloader where our stack is. - // We need to add the sizeof(stack) since in x86(_64) the stack grows - // downwards. - .stack = (uintptr_t)stack + sizeof(stack), - // Bit 1, if set, causes the bootloader to return to us pointers in the - // higher half, which we likely want since this is a higher half kernel. - // Bit 2, if set, tells the bootloader to enable protected memory ranges, - // that is, to respect the ELF PHDR mandated permissions for the executable's - // segments. - // Bit 3, if set, enables fully virtual kernel mappings, which we want as - // they allow the bootloader to pick whichever *physical* memory address is - // available to load the kernel, rather than relying on us telling it where - // to load it. - // Bit 4 disables a deprecated feature and should always be set. - .flags = (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4), - // This header structure is the root of the linked list of header tags and - // points to the first one in the linked list. - .tags = (uintptr_t)&framebuffer_hdr_tag -}; - -// We will now write a helper function which will allow us to scan for tags -// that we want FROM the bootloader (structure tags). -void *stivale2_get_tag(struct stivale2_struct *stivale2_struct, uint64_t id) { - struct stivale2_tag *current_tag = (void *)stivale2_struct->tags; - for (;;) { - // If the tag pointer is NULL (end of linked list), we did not find - // the tag. Return NULL to signal this. - if (current_tag == NULL) { - return NULL; - } - - // Check whether the identifier matches. If it does, return a pointer - // to the matching tag. - if (current_tag->identifier == id) { - return current_tag; - } - - // Get a pointer to the next tag in the linked list and repeat. - current_tag = (void *)current_tag->next; - } -} - -// The following will be our kernel's entry point. -void _start(struct stivale2_struct *stivale2_struct) { - // Let's get the terminal structure tag from the bootloader. - struct stivale2_struct_tag_terminal *term_str_tag; - term_str_tag = stivale2_get_tag(stivale2_struct, STIVALE2_STRUCT_TAG_TERMINAL_ID); - - // Check if the tag was actually found. - if (term_str_tag == NULL) { - // It wasn't found, just hang... - for (;;) { - asm ("hlt"); - } - } - - // Let's get the address of the terminal write function. - void *term_write_ptr = (void *)term_str_tag->term_write; - - // Now, let's assign this pointer to a function pointer which - // matches the prototype described in the stivale2 specification for - // the stivale2_term_write function. - void (*term_write)(const char *string, size_t length) = term_write_ptr; - - // We should now be able to call the above function pointer to print out - // a simple "Hello World" to screen. - term_write("Hello World", 11); - - // We're done, just hang... - for (;;) { - asm ("hlt"); - } +void kernel_main(void) { + terminal_initialize(); + tty_print("Hello, world!", 12); } diff --git a/src/tty.h b/src/tty.h new file mode 100644 index 0000000..78d4d83 --- /dev/null +++ b/src/tty.h @@ -0,0 +1,2 @@ +void terminal_initialize(); +void tty_print(const char*, int length);