From 60a01a977aa968440c7cd562a37f80d2e879975c Mon Sep 17 00:00:00 2001 From: Tyler McGurrin Date: Mon, 16 Dec 2024 23:47:38 -0500 Subject: [PATCH] bully this crap code into working with GCC (and add GCC toolchain har har har) --- .gitignore | 5 +- Makefile | 30 ++- build_scripts/config.mk | 25 +++ build_scripts/toolchain.mk | 57 ++++++ src/bootloader/stage1/boot.asm | 4 +- src/bootloader/stage2/Makefile | 17 +- src/bootloader/stage2/ctype.c | 14 -- src/bootloader/stage2/ctype.h | 10 - src/bootloader/stage2/disk.c | 48 ----- src/bootloader/stage2/disk.h | 19 -- src/bootloader/stage2/entry.asm | 175 +++++++++++++++++ src/bootloader/stage2/fat.c | 322 ------------------------------ src/bootloader/stage2/fat.h | 51 ----- src/bootloader/stage2/linker.ld | 15 ++ src/bootloader/stage2/linker.lnk | 12 -- src/bootloader/stage2/main.asm | 28 --- src/bootloader/stage2/main.c | 99 +++++----- src/bootloader/stage2/memdefs.h | 24 --- src/bootloader/stage2/memory.c | 36 ---- src/bootloader/stage2/memory.h | 11 -- src/bootloader/stage2/stdint.h | 24 --- src/bootloader/stage2/stdio.c | 290 ++++++++++++++++++--------- src/bootloader/stage2/stdio.h | 5 +- src/bootloader/stage2/string.c | 49 ----- src/bootloader/stage2/string.h | 10 - src/bootloader/stage2/utility.c | 14 -- src/bootloader/stage2/utility.h | 9 - src/bootloader/stage2/x86.asm | 324 ++++++------------------------- src/bootloader/stage2/x86.h | 27 +-- 29 files changed, 611 insertions(+), 1143 deletions(-) create mode 100644 build_scripts/config.mk create mode 100644 build_scripts/toolchain.mk delete mode 100644 src/bootloader/stage2/ctype.c delete mode 100644 src/bootloader/stage2/ctype.h delete mode 100644 src/bootloader/stage2/disk.c delete mode 100644 src/bootloader/stage2/disk.h create mode 100644 src/bootloader/stage2/entry.asm delete mode 100644 src/bootloader/stage2/fat.c delete mode 100644 src/bootloader/stage2/fat.h create mode 100644 src/bootloader/stage2/linker.ld delete mode 100644 src/bootloader/stage2/linker.lnk delete mode 100644 src/bootloader/stage2/main.asm delete mode 100644 src/bootloader/stage2/memdefs.h delete mode 100644 src/bootloader/stage2/memory.c delete mode 100644 src/bootloader/stage2/memory.h delete mode 100644 src/bootloader/stage2/stdint.h delete mode 100644 src/bootloader/stage2/string.c delete mode 100644 src/bootloader/stage2/string.h delete mode 100644 src/bootloader/stage2/utility.c delete mode 100644 src/bootloader/stage2/utility.h diff --git a/.gitignore b/.gitignore index 608b1d4..615d0f9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,5 @@ .vscode/ -build/ \ No newline at end of file +build/ +toolchain/ +bx_enh_dbg.ini +src/bootloader/stage2_old \ No newline at end of file diff --git a/Makefile b/Makefile index d2a41bc..4b82d98 100644 --- a/Makefile +++ b/Makefile @@ -1,16 +1,12 @@ -ASM=nasm -CC=gcc -CC16=/opt/watcom/binl/wcc -LD16=/opt/watcom/binl/wlink - -SRC_DIR=src -TOOLS_DIR=tools -BUILD_DIR=build +include build_scripts/config.mk .PHONY: all floppy_image kernel bootloader clean always tools_fat all: floppy_image tools_fat +include build_scripts/toolchain.mk + + # # Floppy image # @@ -34,12 +30,12 @@ bootloader: stage1 stage2 stage1: $(BUILD_DIR)/stage1.bin $(BUILD_DIR)/stage1.bin: always - $(MAKE) -C $(SRC_DIR)/bootloader/stage1 BUILD_DIR=$(abspath $(BUILD_DIR)) + $(MAKE) -C src/bootloader/stage1 BUILD_DIR=$(abspath $(BUILD_DIR)) stage2: $(BUILD_DIR)/stage2.bin $(BUILD_DIR)/stage2.bin: always - $(MAKE) -C $(SRC_DIR)/bootloader/stage2 BUILD_DIR=$(abspath $(BUILD_DIR)) + $(MAKE) -C src/bootloader/stage2 BUILD_DIR=$(abspath $(BUILD_DIR)) # @@ -48,15 +44,15 @@ $(BUILD_DIR)/stage2.bin: always kernel: $(BUILD_DIR)/kernel.bin $(BUILD_DIR)/kernel.bin: always - $(MAKE) -C $(SRC_DIR)/kernel BUILD_DIR=$(abspath $(BUILD_DIR)) + $(MAKE) -C src/kernel BUILD_DIR=$(abspath $(BUILD_DIR)) # # Tools # tools_fat: $(BUILD_DIR)/tools/fat -$(BUILD_DIR)/tools/fat: always $(TOOLS_DIR)/fat/fat.c +$(BUILD_DIR)/tools/fat: always tools/fat/fat.c mkdir -p $(BUILD_DIR)/tools - $(CC) -g -o $(BUILD_DIR)/tools/fat $(TOOLS_DIR)/fat/fat.c + $(CC) -g -o $(BUILD_DIR)/tools/fat tools/fat/fat.c # # Always @@ -68,8 +64,8 @@ always: # Clean # clean: - $(MAKE) -C $(SRC_DIR)/bootloader/stage1 BUILD_DIR=$(abspath $(BUILD_DIR)) clean - $(MAKE) -C $(SRC_DIR)/bootloader/stage2 BUILD_DIR=$(abspath $(BUILD_DIR)) clean - $(MAKE) -C $(SRC_DIR)/kernel BUILD_DIR=$(abspath $(BUILD_DIR)) clean + $(MAKE) -C src/bootloader/stage1 BUILD_DIR=$(abspath $(BUILD_DIR)) clean + $(MAKE) -C src/bootloader/stage2 BUILD_DIR=$(abspath $(BUILD_DIR)) clean + $(MAKE) -C src/kernel BUILD_DIR=$(abspath $(BUILD_DIR)) clean rm -rf $(BUILD_DIR)/* - rm -rf $(SRC_DIR)/bootloader/stage2/*.err + rm -rf src/bootloader/stage2/*.err diff --git a/build_scripts/config.mk b/build_scripts/config.mk new file mode 100644 index 0000000..30934b9 --- /dev/null +++ b/build_scripts/config.mk @@ -0,0 +1,25 @@ +export CFLAGS = -std=c99 -g +export ASM = nasm +export ASMFLAGS = +export CC = gcc +export CXX = g++ +export LD = gcc +export LINKFLAGS = +export LIBS = + +export TARGET = i686-elf +export TARGET_ASM = nasm +export TARGET_ASMFLAGS = +export TARGET_CFLAGS = -std=c99 -g +export TARGET_CC = $(TARGET)-gcc +export TARGET_CXX = $(TARGET)-g++ +export TARGET_LD = $(TARGET)-gcc +export TARGET_LINKFLAGS = +export TARGET_LIBS = + +export BUILD_DIR = $(abspath build) + +BINUTILS_VERSION = 2.43.1 +BINUTILS_URL = https://ftp.gnu.org/gnu/binutils/binutils-$(BINUTILS_VERSION).tar.gz +GCC_VERSION = 14.2.0 +GCC_URL = https://ftp.gnu.org/gnu/gcc/gcc-$(GCC_VERSION)/gcc-$(GCC_VERSION).tar.gz \ No newline at end of file diff --git a/build_scripts/toolchain.mk b/build_scripts/toolchain.mk new file mode 100644 index 0000000..19e5bdf --- /dev/null +++ b/build_scripts/toolchain.mk @@ -0,0 +1,57 @@ + +TOOLCHAIN_PREFIX = $(abspath toolchain/$(TARGET)) +export PATH := $(TOOLCHAIN_PREFIX)/bin:$(PATH) + +toolchain: toolchain_binutils toolchain_gcc + +BINUTILS_SRC = toolchain/binutils-$(BINUTILS_VERSION) +BINUTILS_BUILD = toolchain/binutils-build-$(BINUTILS_VERSION) + +toolchain_binutils: $(BINUTILS_SRC).tar.gz + + cd toolchain && tar -xf binutils-$(BINUTILS_VERSION).tar.gz + mkdir -p $(BINUTILS_BUILD) + cd $(BINUTILS_BUILD) && ../binutils-$(BINUTILS_VERSION)/configure \ + --prefix="$(TOOLCHAIN_PREFIX)" \ + --target=$(TARGET) \ + --with-sysroot \ + --disable-nls \ + --disable-werror + $(MAKE) -j10 -C $(BINUTILS_BUILD) + $(MAKE) -C $(BINUTILS_BUILD) install + +$(BINUTILS_SRC).tar.gz: + mkdir -p toolchain + cd toolchain && wget $(BINUTILS_URL) + + +GCC_SRC = toolchain/gcc-$(GCC_VERSION) +GCC_BUILD = toolchain/gcc-build-$(GCC_VERSION) + +toolchain_gcc: toolchain_binutils $(GCC_SRC).tar.gz + cd toolchain && tar -xf gcc-$(GCC_VERSION).tar.gz + mkdir -p $(GCC_BUILD) + cd $(GCC_BUILD) && ../gcc-$(GCC_VERSION)/configure \ + --prefix="$(TOOLCHAIN_PREFIX)" \ + --target=$(TARGET) \ + --disable-nls \ + --enable-languages=c,c++ \ + --without-headers + $(MAKE) -j10 -C $(GCC_BUILD) all-gcc all-target-libgcc + $(MAKE) -C $(GCC_BUILD) install-gcc install-target-libgcc + +$(GCC_SRC).tar.gz: + mkdir -p toolchain + cd toolchain && wget $(GCC_URL) + + +# CLEAN +clean-toolchain: + rm -rf $(GCC_BUILD) $(GCC_SRC) $(BINUTILS_BUILD) $(BINUTILS_SRC) + +clean-toolchain-all: + rm -rf toolchain/* + + +.PHONY: toolchain toolchain_gcc toolchain_binutils + diff --git a/src/bootloader/stage1/boot.asm b/src/bootloader/stage1/boot.asm index e3b9ebf..409cf6b 100644 --- a/src/bootloader/stage1/boot.asm +++ b/src/bootloader/stage1/boot.asm @@ -373,8 +373,8 @@ msg_no_stage2: db 'Cant Find Stage 2!', ENDL, 0 file_stage2_bin: db 'STAGE2 BIN' stage2_cluster: dw 0 -STAGE2_LOAD_SEGMENT equ 0x2000 -STAGE2_LOAD_OFFSET equ 0 +STAGE2_LOAD_SEGMENT equ 0x0 +STAGE2_LOAD_OFFSET equ 0x500 times 510-($-$$) db 0 dw 0AA55h diff --git a/src/bootloader/stage2/Makefile b/src/bootloader/stage2/Makefile index 63a7455..0df9738 100644 --- a/src/bootloader/stage2/Makefile +++ b/src/bootloader/stage2/Makefile @@ -1,9 +1,8 @@ -BUILD_DIR?=build/ -ASM?=nasm -ASMFLAGS?=-f obj -CC16?=/usr/bin/watcom/binl/wcc -CFLAGS16?=-4 -d3 -s -wx -ms -zl -zq -za99 # -oneatxzh -LD16?=/usr/bin/watcom/binl/wlink +TARGET_ASMFLAGS += -f elf +TARGET_CFLAGS += -ffreestanding -nostdlib +TARGET_LIBS += -lgcc +TARGET_LINKFLAGS += -T linker.ld -nostdlib + SOURCES_C=$(wildcard *.c) SOURCES_ASM=$(wildcard *.asm) @@ -17,13 +16,13 @@ all: stage2 stage2: $(BUILD_DIR)/stage2.bin $(BUILD_DIR)/stage2.bin: $(OBJECTS_ASM) $(OBJECTS_C) - $(LD16) NAME $(BUILD_DIR)/stage2.bin FILE \{ $(OBJECTS_ASM) $(OBJECTS_C) \} OPTION MAP=$(BUILD_DIR)/stage2.map @linker.lnk + $(TARGET_LD) $(TARGET_LINKFLAGS) -Wl,-Map=$(BUILD_DIR)/stage2.map -o $@ $^ $(TARGET_LIBS) $(BUILD_DIR)/stage2/c/%.obj: %.c always - $(CC16) $(CFLAGS16) -fo=$@ $< + $(TARGET_CC) $(TARGET_CFLAGS) -c -o $@ $< $(BUILD_DIR)/stage2/asm/%.obj: %.asm always - $(ASM) $(ASMFLAGS) -o $@ $< + $(TARGET_ASM) $(TARGET_ASMFLAGS) -o $@ $< always: mkdir -p $(BUILD_DIR)/stage2/c diff --git a/src/bootloader/stage2/ctype.c b/src/bootloader/stage2/ctype.c deleted file mode 100644 index df73df5..0000000 --- a/src/bootloader/stage2/ctype.c +++ /dev/null @@ -1,14 +0,0 @@ -/*----------------*\ -|Nanite OS | -|Copyright (C) 2024| -|Tyler McGurrin | -\*----------------*/ -#include "ctype.h" - -bool islower(char chr) { - return chr >= 'a' && chr <= 'z'; -} - -char toupper(char chr) { - return islower(chr) ? (chr - 'a' + 'A') : chr; -} diff --git a/src/bootloader/stage2/ctype.h b/src/bootloader/stage2/ctype.h deleted file mode 100644 index 608fb73..0000000 --- a/src/bootloader/stage2/ctype.h +++ /dev/null @@ -1,10 +0,0 @@ -/*----------------*\ -|Nanite OS | -|Copyright (C) 2024| -|Tyler McGurrin | -\*----------------*/ -#pragma once -#include "stdint.h" - -bool islower(char chr); -char toupper(char chr); diff --git a/src/bootloader/stage2/disk.c b/src/bootloader/stage2/disk.c deleted file mode 100644 index e08531e..0000000 --- a/src/bootloader/stage2/disk.c +++ /dev/null @@ -1,48 +0,0 @@ -/*----------------*\ -|Nanite OS | -|Copyright (C) 2024| -|Tyler McGurrin | -\*----------------*/ -#include "disk.h" -#include "x86.h" -#include "stdio.h" - -bool DISK_Initialize(DISK* disk, uint8_t driveNumber) { - uint8_t driveType; - uint16_t cylinders, sectors, heads; - - if (!x86_Disk_GetDriveParams(disk->id, &driveType, &cylinders, §ors, &heads)) - return false; - - disk->id = driveNumber; - disk->cylinders = cylinders + 1; - disk->heads = heads + 1; - disk->sectors = sectors; - - return true; -} - -void DISK_LBA2CHS(DISK* disk, uint32_t lba, uint16_t* cylinderOut, uint16_t* sectorOut, uint16_t* headOut) { - // sector = (LBA % sectors per track + 1) - *sectorOut = lba % disk->sectors +1; - - // cylinder = (LBA / sects per track / heads) - *cylinderOut = (lba / disk->sectors) / disk->heads; - - // head = (LBA / sects per track % heads) - *headOut = (lba / disk->sectors) % disk->heads; -} - -bool DISK_ReadSectors(DISK* disk, uint32_t lba, uint8_t sectors, void far* dataOut) { - uint16_t cylinder, sector, head; - - DISK_LBA2CHS(disk, lba, &cylinder, §or, &head); - - for (int i = 0; i < 3; i++) { - if (x86_Disk_Read(disk->id, cylinder, sector, head, sectors, dataOut)) - return true; - x86_Disk_Reset(disk->id); - } - - return false; -} diff --git a/src/bootloader/stage2/disk.h b/src/bootloader/stage2/disk.h deleted file mode 100644 index 8b20239..0000000 --- a/src/bootloader/stage2/disk.h +++ /dev/null @@ -1,19 +0,0 @@ -/*----------------*\ -|Nanite OS | -|Copyright (C) 2024| -|Tyler McGurrin | -\*----------------*/ -#pragma once - -#include "stdint.h" - -typedef struct { - uint8_t id; - uint16_t cylinders; - uint16_t sectors; - uint16_t heads; -} DISK; - -bool DISK_Initialize(DISK* disk, uint8_t driveNumber); -bool DISK_ReadSectors(DISK* disk, uint32_t lba, uint8_t sectors, void far* dataOut); - diff --git a/src/bootloader/stage2/entry.asm b/src/bootloader/stage2/entry.asm new file mode 100644 index 0000000..52f72bb --- /dev/null +++ b/src/bootloader/stage2/entry.asm @@ -0,0 +1,175 @@ +;/////////////////////; +;Nanite OS ; +;COPYRIGHT (C) 2024 ; +;Tyler McGurrin ; +;/////////////////////; +bits 16 + +section .entry + +extern __bss_start +extern __end + +extern start +global entry + +entry: + cli + + ; save boot drive + mov [g_BootDrive], dl + + ; setup stack + mov ax, ds + mov ss, ax + mov sp, 0xFFF0 + mov bp, sp + + ; switch to PMODE + call EnableA20 + call LoadGDT + + ; set PMODE enable flag in CR0 + mov eax, CR0 + or al, 1 + mov cr0, eax + + ; far jmp into PMODE + jmp dword 08h:.pmode + +.pmode: + ; we are now in protected mode! + [bits 32] + + ; 6 - setup segment registers + mov ax, 0x10 + mov ds, ax + mov ss, ax + mov al, 0 + cld + rep stosb + + ; clear BSS (uninit data) + mov edi, __bss_start + mov ecx, __end + sub ecx, edi + + + xor edx, edx + mov dl, [g_BootDrive] + push edx + call start + + cli + hlt + + + +EnableA20: + [bits 16] + ; disable keyboard + call A20WaitInput + mov al, KbdControllerDisableKeyboard + out KbdControllerCommandPort, al + + ; read control output port + call A20WaitInput + mov al, KbdControllerReadCtrlOutputPort + out KbdControllerCommandPort, al + + call A20WaitOutput + in al, KbdControllerDataPort + push eax + + ; write control output port + call A20WaitInput + mov al, KbdControllerWriteCtrlOutputPort + out KbdControllerCommandPort, al + + call A20WaitInput + pop eax + or al, 2 ; bit 2 = A20 bit + out KbdControllerDataPort, al + + ; enable keyboard + call A20WaitInput + mov al, KbdControllerEnableKeyboard + out KbdControllerCommandPort, al + + call A20WaitInput + ret + + +A20WaitInput: + [bits 16] + ; wait until status bit 2 (input buffer) is 0 + ; by reading from command port, we read status byte + in al, KbdControllerCommandPort + test al, 2 + jnz A20WaitInput + ret + +A20WaitOutput: + [bits 16] + ; wait until status bit 1 (output buffer) is 1 so it can be read + in al, KbdControllerCommandPort + test al, 1 + jz A20WaitOutput + ret + + +LoadGDT: + [bits 16] + lgdt [g_GDTDesc] + ret + + + +KbdControllerDataPort equ 0x60 +KbdControllerCommandPort equ 0x64 +KbdControllerDisableKeyboard equ 0xAD +KbdControllerEnableKeyboard equ 0xAE +KbdControllerReadCtrlOutputPort equ 0xD0 +KbdControllerWriteCtrlOutputPort equ 0xD1 + +ScreenBuffer equ 0xB8000 + +g_GDT: ; NULL descriptor + dq 0 + + ; 32-bit code segment + dw 0FFFFh ; limit (bits 0-15) = 0xFFFFF for full 32-bit range + dw 0 ; base (bits 0-15) = 0x0 + db 0 ; base (bits 16-23) + db 10011010b ; access (present, ring 0, code segment, executable, direction 0, readable) + db 11001111b ; granularity (4k pages, 32-bit pmode) + limit (bits 16-19) + db 0 ; base high + + ; 32-bit data segment + dw 0FFFFh ; limit (bits 0-15) = 0xFFFFF for full 32-bit range + dw 0 ; base (bits 0-15) = 0x0 + db 0 ; base (bits 16-23) + db 10010010b ; access (present, ring 0, data segment, executable, direction 0, writable) + db 11001111b ; granularity (4k pages, 32-bit pmode) + limit (bits 16-19) + db 0 ; base high + + ; 16-bit code segment + dw 0FFFFh ; limit (bits 0-15) = 0xFFFFF + dw 0 ; base (bits 0-15) = 0x0 + db 0 ; base (bits 16-23) + db 10011010b ; access (present, ring 0, code segment, executable, direction 0, readable) + db 00001111b ; granularity (1b pages, 16-bit pmode) + limit (bits 16-19) + db 0 ; base high + + ; 16-bit data segment + dw 0FFFFh ; limit (bits 0-15) = 0xFFFFF + dw 0 ; base (bits 0-15) = 0x0 + db 0 ; base (bits 16-23) + db 10010010b ; access (present, ring 0, data segment, executable, direction 0, writable) + db 00001111b ; granularity (1b pages, 16-bit pmode) + limit (bits 16-19) + db 0 ; base high + +g_GDTDesc: dw g_GDTDesc - g_GDT - 1 ; limit = size of GDT + dd g_GDT ; address of GDT + +g_BootDrive: db 0 diff --git a/src/bootloader/stage2/fat.c b/src/bootloader/stage2/fat.c deleted file mode 100644 index 2e6e1ae..0000000 --- a/src/bootloader/stage2/fat.c +++ /dev/null @@ -1,322 +0,0 @@ -/*----------------*\ -|Nanite OS | -|Copyright (C) 2024| -|Tyler McGurrin | -\*----------------*/ -#include "fat.h" -#include "stdio.h" -#include "memdefs.h" -#include "utility.h" -#include "string.h" -#include "memory.h" -#include "ctype.h" - -#define SECTOR_SIZE 512 -#define MAX_PATH_SIZE 256 -#define MAX_FILE_HANDLES 10 -#define ROOT_DIRECTORY_HANDLE -1 - -#pragma pack(push,1) -typedef struct -{ - uint8_t BootJumpInstruction[3]; - uint8_t OemIdentifier[8]; - uint16_t BytesPerSector; - uint8_t SectorsPerCluster; - uint16_t ReservedSectors; - uint8_t FatCount; - uint16_t DirEntryCount; - uint16_t TotalSectors; - uint8_t MediaDescriptorType; - uint16_t SectorsPerFat; - uint16_t SectorsPerTrack; - uint16_t Heads; - uint32_t HiddenSectors; - uint32_t LargeSectorCount; - -//Extended Boot Record - uint8_t DriveNumber; - uint8_t _Reserved; - uint8_t Signature; - uint32_t VolumeId; //Serial Can be whatever - uint8_t VolumeLabel[11]; //11 Bytes MUST Be padded with spaces! - uint8_t SystemId[8]; //8 Bytes padded with spaces (use MSWIN4.1 for best compatibility!) - -} FAT_BootSector; -#pragma pack(pop) - -typedef struct { - FAT_File Public; - bool Opened; - uint32_t FirstCluster; - uint32_t CurrentCluster; - uint32_t CurrentSectorInCluster; - uint8_t Buffer[SECTOR_SIZE]; - -} FAT_FileData; - - -typedef struct { - union { - FAT_BootSector BootSector; - uint8_t BootSectorBytes[SECTOR_SIZE]; - } BS; - - FAT_FileData RootDirectory; - - FAT_FileData OpenedFiles[MAX_FILE_HANDLES]; - -} FAT_Data; - -static FAT_Data far* g_Data; -static uint8_t far* g_Fat = NULL; -static uint32_t g_DataSectionLba; - -bool FAT_ReadBootSector(DISK* disk) { - return DISK_ReadSectors(disk, 0, 1, &g_Data->BS.BootSectorBytes); -} - -bool FAT_ReadFat(DISK* disk) -{ - return DISK_ReadSectors(disk, g_Data->BS.BootSector.ReservedSectors, g_Data->BS.BootSector.SectorsPerFat, g_Fat); -} - -bool FAT_Initialize(DISK* disk) { - g_Data = (FAT_Data far*)MEMORY_FAT_ADDR; - - // read bootsector - if (!FAT_ReadBootSector(disk)) { - printf("FAT: Bootsector Read Failed!\r\n"); - return false; - } - - // read FAT - g_Fat = (uint8_t far*)(g_Data + sizeof(FAT_Data)); - uint32_t fatSize = g_Data->BS.BootSector.BytesPerSector * g_Data->BS.BootSector.SectorsPerFat; - if(sizeof(FAT_Data) + fatSize >= MEMORY_FAT_SIZE) { - printf("FAT: Not Enough Memory to Read FAT!\r\nNeeded %u, Only Have %u\r\n", sizeof(FAT_Data) + fatSize, MEMORY_FAT_SIZE); - return false; - } - - if (!FAT_ReadFat(disk)) { - printf("FAT: Failed to Read FAT!\r\n"); - return false; - } - - // open root dir - uint32_t rootDirLba = g_Data->BS.BootSector.ReservedSectors + g_Data->BS.BootSector.SectorsPerFat * g_Data->BS.BootSector.FatCount; - uint32_t rootDirSize = sizeof(FAT_DirectoryEntry) * g_Data->BS.BootSector.DirEntryCount; - - g_Data->RootDirectory.Public.Handle = ROOT_DIRECTORY_HANDLE; - g_Data->RootDirectory.Public.IsDirectory = true; - g_Data->RootDirectory.Public.Position = 0; - g_Data->RootDirectory.Public.Size = sizeof(FAT_DirectoryEntry) * g_Data->BS.BootSector.DirEntryCount; - g_Data->RootDirectory.Opened = true; - g_Data->RootDirectory.FirstCluster = rootDirLba; - g_Data->RootDirectory.CurrentCluster = 0; - g_Data->RootDirectory.CurrentSectorInCluster = 0; - - if (!DISK_ReadSectors(disk, rootDirLba, 1, g_Data->RootDirectory.Buffer)) { - printf("FAT: Failed to Read Root Directory!\r\n"); - return false; - } - //calculate data - uint32_t rootDirSectors = (rootDirSize + g_Data->BS.BootSector.BytesPerSector - 1) / g_Data->BS.BootSector.BytesPerSector; - g_DataSectionLba = rootDirLba + rootDirSectors; - - // reset opened files - for (int i = 0; i < MAX_FILE_HANDLES; i++) - g_Data->OpenedFiles[i].Opened = false; - - return true; -} - -uint32_t FAT_ClusterToLba(uint32_t cluster) { - return g_DataSectionLba + (cluster -2) * g_Data->BS.BootSector.SectorsPerCluster; -} - -FAT_File far* FAT_OpenEntry(DISK* disk, FAT_DirectoryEntry* entry) { - // find empty handle - int handle = -1; - for (int i = 0; i < MAX_FILE_HANDLES && handle < 0; i++) { - if (!g_Data->OpenedFiles[i].Opened) - handle = i; - } - // out of handles - if (handle < 0) { - printf("FAT: Out of File Handles!\r\n"); - return false; - } - - // setup vars - FAT_FileData far* fd = &g_Data->OpenedFiles[handle]; - fd->Public.Handle = handle; - fd->Public.IsDirectory = (entry->Attributes & FAT_ATTRIBUTE_DIRECTORY) != 0; - fd->Public.Position = 0; - fd->Public.Size = entry->Size; - fd->FirstCluster = entry->FirstClusterLow + ((uint32_t)entry->FirstClusterHigh << 16); - fd->CurrentCluster = fd->FirstCluster; - fd->CurrentSectorInCluster = 0; - - if (!DISK_ReadSectors(disk, FAT_ClusterToLba(fd->CurrentCluster), 1, fd->Buffer)) { - printf("FAT: Read Error!\r\n"); - return false; - } - - fd->Opened = true; - return &fd->Public; -} - -uint32_t FAT_NextCluster(uint32_t currentCluster) { - uint32_t fatIndex = currentCluster * 3 / 2; - if (currentCluster % 2 == 0) - return (*(uint16_t far*)(g_Fat + fatIndex)) & 0x0FFF; - else - return (*(uint16_t far*)(g_Fat + fatIndex)) >> 4; - -} - -uint32_t FAT_Read(DISK* disk, FAT_File far* file, uint32_t byteCount, void* dataOut) { - // get file data - FAT_FileData far* fd = (file->Handle == ROOT_DIRECTORY_HANDLE) - ? &g_Data->RootDirectory - : &g_Data->OpenedFiles[file->Handle]; - - uint8_t* u8DataOut = (uint8_t*)dataOut; - - // don't read past EOF - if (!fd->Public.IsDirectory) - byteCount = min(byteCount, fd->Public.Size - fd->Public.Position); - - while (byteCount > 0) { - uint32_t leftInBuffer = SECTOR_SIZE - (fd->Public.Position % SECTOR_SIZE); - uint32_t take = min(byteCount, leftInBuffer); - memcpy(u8DataOut, fd->Buffer + fd->Public.Position % SECTOR_SIZE, take); - u8DataOut += take; - fd->Public.Position += take; - byteCount -= take; - - // see if we need to read more data - if (leftInBuffer == take) { - // root dir handler - if (fd->Public.Handle == ROOT_DIRECTORY_HANDLE) { - ++fd->CurrentCluster; - // read next sect. - if (!DISK_ReadSectors(disk, fd->CurrentCluster, 1, fd->Buffer)) { - printf("FAT: Read Error!\r\n"); - break; - } - } - else { - // read next sect. - if (++fd->CurrentSectorInCluster >= g_Data->BS.BootSector.SectorsPerCluster) { - // calc next cluster & sect. to read - fd->CurrentSectorInCluster = 0; - fd->CurrentCluster = FAT_NextCluster; - } - if (fd->CurrentCluster >= 0x0FF8) { - // mark EOF - fd->Public.Size = fd.Public.Position; - break; - - } - - // read next sect. - if (!DISK_ReadSectors(disk, FAT_ClusterToLba(fd->CurrentCluster) + fd->CurrentSectorInCluster, 1, fd->Buffer)) { - printf("FAT: Read Error!\r\n"); - break; - } - } - } - } - - return u8DataOut - (uint8_t*)dataOut; -} -bool FAT_ReadEntry(DISK* disk, FAT_File far* file, FAT_DirectoryEntry* dirEntry) { - return FAT_Read(disk, file, sizeof(FAT_DirectoryEntry), dirEntry) == sizeof(FAT_DirectoryEntry); - -} -void FAT_Close(FAT_File far* file) { - if (file->Handle == ROOT_DIRECTORY_HANDLE) { - file->Position = 0; - g_Data->RootDirectory.CurrentCluster = g_Data->RootDirectory.FirstCluster; - } - else { - g_Data->OpenedFiles[file->Handle].Opened = false; - } -} - -bool FAT_FindFile(DISK* disk, FAT_File far* file, const char* name, FAT_DirectoryEntry* entryOut) { - char fatName[11]; - FAT_DirectoryEntry entry; - - // convert from name to fat name - memset(fatName, ' ', sizeof(fatName)); - const char* ext = strchr(name, '.'); - if (ext == NULL) - ext = name + 11; - for (int i = 0; i < 8 && name[i] && name + i < ext; i++) - fatName[i] = toupper(name[i]); - if (ext != NULL) { - for (int i = 0; i < 3 && ext[i + 1]; i++) - fatName[i + 8] = toupper(ext[i + 1]); - } - while (FAT_ReadEntry(disk, file, &entry)) { - if (memcmp(fatName, entry.Name, 11) == 0) { - *entryOut = entry; - return true; - } - } - - return false; -} - -FAT_File far* FAT_Open(DISK* disk, const char* path) { - char name[MAX_PATH_SIZE]; - - // ignore leading slash - if (path[0] == '/') - path++; - - FAT_File far* current = &g_Data->RootDirectory.Public; - - while (*path) { - // extract next file name from path - bool isLast = false; - const char* delim = strchr(path, '/'); - if (delim != NULL) { - memcpy(name, path, delim - path); - name[delim - path + 1] = '\0'; - path = delim + 1; - } - else { - unsigned len = strlen(path); - memcpy(name, path, len); - name[len + 1] = '\0'; - path += len; - bool isLast = true; - } - // find directory entry in current dir - FAT_DirectoryEntry entry; - if (FAT_FindFile(disk, current, name, &entry)) { - FAT_Close(current); - - // check if DIR - if (!isLast && entry.Attributes & FAT_ATTRIBUTE_DIRECTORY == 0) { - printf("FAT: %s is NOT a Directory!\r\n", name); - return NULL; - } - - // open new DIR entry - current = FAT_OpenEntry(disk, &entry); - } - else { - FAT_Close(current); - printf("FAT: %s NOT Found!", name); - return NULL; - } - - } - - return current; -} \ No newline at end of file diff --git a/src/bootloader/stage2/fat.h b/src/bootloader/stage2/fat.h deleted file mode 100644 index 1e13d41..0000000 --- a/src/bootloader/stage2/fat.h +++ /dev/null @@ -1,51 +0,0 @@ -/*----------------*\ -|Nanite OS | -|Copyright (C) 2024| -|Tyler McGurrin | -\*----------------*/ -#pragma once -#include "stdint.h" -#include "disk.h" - -#pragma pack(push, 1) -typedef struct -{ - uint8_t Name[11]; - uint8_t Attributes; - uint8_t _Reserved; - uint8_t CreatedTimeTenths; - uint16_t CreatedTime; - uint16_t CreatedDate; - uint16_t AccessedDate; - uint16_t FirstClusterHigh; - uint16_t ModifiedTime; - uint16_t ModifiedDate; - uint16_t FirstClusterLow; - uint32_t Size; - -} FAT_DirectoryEntry; -#pragma pack(pop) - -typedef struct { - int Handle; - bool IsDirectory; - uint32_t Position; - uint32_t Size; -} FAT_File; - -enum FAT_Attributes { - FAT_ATTRIBUTE_READ_ONLY = 0x01, - FAT_ATTRIBUTE_HIDDEN = 0x02, - FAT_ATTRIBUTE_SYSTEM = 0x04, - FAT_ATTRIBUTE_VOLUME_ID = 0x08, - FAT_ATTRIBUTE_DIRECTORY = 0x10, - FAT_ATTRIBUTE_ARCHIVE = 0x20, - FAT_ATTRIBUTE_LFN = FAT_ATTRIBUTE_READ_ONLY | FAT_ATTRIBUTE_HIDDEN | FAT_ATTRIBUTE_SYSTEM | FAT_ATTRIBUTE_VOLUME_ID -}; - - -bool FAT_Initialize(DISK* disk); -FAT_File far* FAT_Open(DISK* disk, const char* path); -uint32_t FAT_Read(DISK* disk, FAT_File far* file, uint32_t byteCount, void* dataOut); -bool FAT_ReadEntry(DISK* disk, FAT_File far* file, FAT_DirectoryEntry* dirEntry); -void FAT_Close(FAT_File far* file); \ No newline at end of file diff --git a/src/bootloader/stage2/linker.ld b/src/bootloader/stage2/linker.ld new file mode 100644 index 0000000..786ccbb --- /dev/null +++ b/src/bootloader/stage2/linker.ld @@ -0,0 +1,15 @@ +ENTRY(entry) +OUTPUT_FORMAT("binary") +phys = 0x00000500; + +SECTIONS { + . = phys; + + .entry : { __entry_start = .; *(.entry) } + .text : { __text_start = .; *(.text) } + .data : { __data_start = .; *(.data) } + .rodata : { __rodata_start = .; *(.rodata) } + .bss : { __bss_start = .; *(.bss) } + + __end = .; +} \ No newline at end of file diff --git a/src/bootloader/stage2/linker.lnk b/src/bootloader/stage2/linker.lnk deleted file mode 100644 index 9e70033..0000000 --- a/src/bootloader/stage2/linker.lnk +++ /dev/null @@ -1,12 +0,0 @@ -FORMAT RAW BIN -OPTION QUIET, - NODEFAULTLIBS, - START=entry, - VERBOSE, - OFFSET=0, - STACK=0x200 -ORDER - CLNAME CODE - SEGMENT _ENTRY - SEGMENT _TEXT - CLNAME DATA diff --git a/src/bootloader/stage2/main.asm b/src/bootloader/stage2/main.asm deleted file mode 100644 index 8646753..0000000 --- a/src/bootloader/stage2/main.asm +++ /dev/null @@ -1,28 +0,0 @@ -;/////////////////////; -;Nanite OS ; -;COPYRIGHT (C) 2024 ; -;Tyler McGurrin ; -;/////////////////////; -bits 16 - -section _ENTRY class=CODE - -extern _cstart_ -global entry - -entry: - cli - ; setup stack - mov ax, ds - mov ss, ax - mov sp, 0 - mov bp, sp - sti - - ; expect boot drive in dl, send it as argument to cstart function - xor dh, dh - push dx - call _cstart_ - - cli - hlt diff --git a/src/bootloader/stage2/main.c b/src/bootloader/stage2/main.c index 86112c3..5924576 100644 --- a/src/bootloader/stage2/main.c +++ b/src/bootloader/stage2/main.c @@ -3,64 +3,67 @@ |Copyright (C) 2024| |Tyler McGurrin | \*----------------*/ -#include "stdint.h" +#include #include "stdio.h" -#include "disk.h" -#include "fat.h" +// #include "disk.h" +// #include "fat.h" -void far* g_data = (void far*)0x00500200; -#define LOGO " _ _____ _ __________________\r\n / | / / | / | / / _/_ __/ ____/\r\n / |/ / /| | / |/ // / / / / __/ \r\n / /| / ___ |/ /| // / / / / /___ \r\n\\/_/ |_/_/ |_/_/ |_/___/ /_/ /_____/ \r\n" +// void far* g_data = (void far*)0x00500200; +#define LOGO " _ _____ _ __________________\n / | / / | / | / / _/_ __/ ____/\n / |/ / /| | / |/ // / / / / __/ \n / /| / ___ |/ /| // / / / / /___ \n\\/_/ |_/_/ |_/_/ |_/___/ /_/ /_____/ \n" #define VERSION "v0.0.1" -void _cdecl cstart_(uint16_t bootDrive) { + void __attribute__((cdecl)) start(uint16_t bootDrive) { + clrscr(); printf("%s", LOGO); - printf(" %s\r\n--------------------------------------\r\n", VERSION); + printf(" %s\n--------------------------------------\n", VERSION); + + for(;;); - printf("Initializing FAT Driver..."); - DISK disk; - if (!DISK_Initialize(&disk, bootDrive)) { - printf("Failed!\r\nDisk Initialization Error\r\n"); - goto end; - } +// printf("Initializing FAT Driver..."); +// DISK disk; +// if (!DISK_Initialize(&disk, bootDrive)) { +// printf("Failed!\nDisk Initialization Error\n"); +// goto end; +// } - DISK_ReadSectors(&disk, 19, 1, g_data); +// DISK_ReadSectors(&disk, 19, 1, g_data); - if (!FAT_Initialize(&disk)) { - printf("Failed!\r\nDisk Initialization Error\r\n"); - goto end; - } - printf("Done!\r\n"); - // printf("Listing Root DIR...\r\n"); - // // browse files in root - FAT_File far* fd = FAT_Open(&disk, "/"); - FAT_DirectoryEntry entry; - int i = 0; - // while (FAT_ReadEntry(&disk, fd, &entry) && i++ < 5) { - // printf(" "); - // for (int i = 0; i < 11; i++) - // putc(entry.Name[i]); - // printf("\r\n"); - // } - // FAT_Close(fd); +// if (!FAT_Initialize(&disk)) { +// printf("Failed!\nDisk Initialization Error\n"); +// goto end; +// } +// printf("Done!\n"); +// // printf("Listing Root DIR...\n"); +// // // browse files in root +// FAT_File far* fd = FAT_Open(&disk, "/"); +// FAT_DirectoryEntry entry; +// int i = 0; +// // while (FAT_ReadEntry(&disk, fd, &entry) && i++ < 5) { +// // printf(" "); +// // for (int i = 0; i < 11; i++) +// // putc(entry.Name[i]); +// // printf("\n"); +// // } +// // FAT_Close(fd); - printf("Testing FAT Driver..."); - // read test.txt - char buffer[100]; - uint32_t read; - fd = FAT_Open(&disk, "misc/test.txt"); - while ((read = FAT_Read(&disk, fd, sizeof(buffer), buffer))) - { - for (uint32_t i = 0; i < read; i++) - { - if (buffer[i] == '\n') - putc('\r'); - putc(buffer[i]); - } - } - FAT_Close(fd); +// printf("Testing FAT Driver..."); +// // read test.txt +// char buffer[100]; +// uint32_t read; +// fd = FAT_Open(&disk, "misc/test.txt"); +// while ((read = FAT_Read(&disk, fd, sizeof(buffer), buffer))) +// { +// for (uint32_t i = 0; i < read; i++) +// { +// if (buffer[i] == '\n') +// putc(''); +// putc(buffer[i]); +// } +// } +// FAT_Close(fd); -end: - for (;;); +// end: +// for (;;); } diff --git a/src/bootloader/stage2/memdefs.h b/src/bootloader/stage2/memdefs.h deleted file mode 100644 index 931fd7d..0000000 --- a/src/bootloader/stage2/memdefs.h +++ /dev/null @@ -1,24 +0,0 @@ -/*----------------*\ -|Nanite OS | -|Copyright (C) 2024| -|Tyler McGurrin | -\*----------------*/ -#pragma once - -// 0x00000000 - 0x000003FF - interrupt vector table -// 0x00000400 - 0x000004FF - BIOS data area - -#define MEMORY_MIN 0x00000500 -#define MEMORY_MAX 0x00080000 - -// 0x00000500 - 0x00010500 - FAT driver -#define MEMORY_FAT_ADDR ((void far*)0x00500000) // segment:offset (SSSSOOOO) -#define MEMORY_FAT_SIZE 0x00010000 - -// 0x00020000 - 0x00030000 - stage2 - -// 0x00030000 - 0x00080000 - free - -// 0x00080000 - 0x0009FFFF - Extended BIOS data area -// 0x000A0000 - 0x000C7FFF - Video -// 0x000C8000 - 0x000FFFFF - BIOS diff --git a/src/bootloader/stage2/memory.c b/src/bootloader/stage2/memory.c deleted file mode 100644 index a87ba47..0000000 --- a/src/bootloader/stage2/memory.c +++ /dev/null @@ -1,36 +0,0 @@ -/*----------------*\ -|Nanite OS | -|Copyright (C) 2024| -|Tyler McGurrin | -\*----------------*/ -#include "memory.h" - -void far* memcpy(void far* dst, const void far* src, uint16_t num) { - uint8_t far* u8Dst = (uint8_t far *)dst; - const uint8_t far* u8Src = (const uint8_t far *)src; - - for (uint16_t i = 0; i < num; i++) - u8Dst[i] = u8Src[i]; - - return dst; -} - -void far* memset (void far * ptr, int value, uint16_t num) { - uint8_t far* u8Ptr = (uint8_t far *)ptr; - - for (uint16_t i = 0; i < num; i++) - u8Ptr[i] = (uint8_t)value; - - return ptr; -} - -int memcmp(const void far* ptr1, const void far * ptr2, uint16_t num) { - const uint8_t far* u8Ptr1 = (const uint8_t far *)ptr1; - const uint8_t far* u8Ptr2 = (const uint8_t far *)ptr2; - - for (uint16_t i = 0; i < num; i++) - if (u8Ptr1[i] != u8Ptr2[i]) - return 1; - - return 0; -} diff --git a/src/bootloader/stage2/memory.h b/src/bootloader/stage2/memory.h deleted file mode 100644 index f2f03af..0000000 --- a/src/bootloader/stage2/memory.h +++ /dev/null @@ -1,11 +0,0 @@ -/*----------------*\ -|Nanite OS | -|Copyright (C) 2024| -|Tyler McGurrin | -\*----------------*/ -#pragma once -#include "stdint.h" - -void far* memcpy(void far* dst, const void far* src, uint16_t num); -void far* memset(void far* ptr, int value, uint16_t num); -int memcmp(const void far* ptr1, const void far * ptr2, uint16_t num); diff --git a/src/bootloader/stage2/stdint.h b/src/bootloader/stage2/stdint.h deleted file mode 100644 index 36d398b..0000000 --- a/src/bootloader/stage2/stdint.h +++ /dev/null @@ -1,24 +0,0 @@ -/*----------------*\ -|Nanite OS | -|Copyright (C) 2024| -|Tyler McGurrin | -\*----------------*/ -#pragma once - -typedef signed char int8_t; -typedef unsigned char uint8_t; -typedef signed short int16_t; -typedef unsigned short uint16_t; -typedef signed long int int32_t; -typedef unsigned long int uint32_t; -typedef signed long long int int64_t; -typedef unsigned long long int uint64_t; - -typedef uint8_t bool; - -#define false 0 -#define true 1 - -#define NULL ((void*)0) -#define min(a,b) ((a) < (b) ? (a) : (b)) -#define max(a,b) ((a) > (b) ? (a) : (b)) diff --git a/src/bootloader/stage2/stdio.c b/src/bootloader/stage2/stdio.c index 9ae959f..03ace46 100644 --- a/src/bootloader/stage2/stdio.c +++ b/src/bootloader/stage2/stdio.c @@ -5,10 +5,107 @@ \*----------------*/ #include "stdio.h" #include "x86.h" +#include +#include + +const unsigned SCREEN_WIDTH = 80; +const unsigned SCREEN_HEIGHT = 25; +const uint8_t DEFAULT_COLOUR = 0x7; + +uint8_t* g_ScreenBuffer = (uint8_t*)0xB8000; +int g_ScreenX = 0, g_ScreenY = 0; + +void putchr(int x, int y, char c) +{ + g_ScreenBuffer[2 * (y * SCREEN_WIDTH + x)] = c; +} + +void putcolour(int x, int y, uint8_t colour) +{ + g_ScreenBuffer[2 * (y * SCREEN_WIDTH + x) + 1] = colour; +} + +char getchr(int x, int y) +{ + return g_ScreenBuffer[2 * (y * SCREEN_WIDTH + x)]; +} + +uint8_t getcolour(int x, int y) +{ + return g_ScreenBuffer[2 * (y * SCREEN_WIDTH + x) + 1]; +} + +void setcursor(int x, int y) +{ + int pos = y * SCREEN_WIDTH + x; + + x86_outb(0x3D4, 0x0F); + x86_outb(0x3D5, (uint8_t)(pos & 0xFF)); + x86_outb(0x3D4, 0x0E); + x86_outb(0x3D5, (uint8_t)((pos >> 8) & 0xFF)); +} + +void clrscr() +{ + for (int y = 0; y < SCREEN_HEIGHT; y++) + for (int x = 0; x < SCREEN_WIDTH; x++) + { + putchr(x, y, '\0'); + putcolour(x, y, DEFAULT_COLOUR); + } + g_ScreenX =0; g_ScreenY = 0; + setcursor(g_ScreenX, g_ScreenY); +} + +void scrollback(int lines) +{ + for (int y = lines; y < SCREEN_HEIGHT; y++) + for (int x = 0; x < SCREEN_WIDTH; x++) + { + putchr(x, y - lines, getchr(x, y)); + putcolour(x, y - lines, getcolour(x, y)); + } + + for (int y= SCREEN_HEIGHT - lines; y < SCREEN_HEIGHT; y++) + for (int x = 0; x < SCREEN_WIDTH; x++) + { + putchr(x, y - lines, getchr(x, y)); + putcolour(x, y - lines, getcolour(x, y)); + } + g_ScreenY -= lines; +} void putc(char c) { - x86_Video_WriteCharTeletype(c, 0); + switch (c) + { + case '\n': + g_ScreenX = 0; + g_ScreenY++; + break; + case '\t': + for (int i = 0; i < 4 - (g_ScreenX % 4); i++) + putc(' '); + break; + case '\r': + g_ScreenX = 0; + break; + default: + putchr(g_ScreenX, g_ScreenY, c); + g_ScreenX++; + break; + } + + if (g_ScreenX >= SCREEN_WIDTH) + { + g_ScreenY++; + g_ScreenX = 0; + } + if (g_ScreenY >= SCREEN_HEIGHT) + scrollback(1); + + setcursor(g_ScreenX, g_ScreenY); + } void puts(const char* str) @@ -20,6 +117,39 @@ void puts(const char* str) } } +const char g_HexChars[] = "0123456789abcdef"; + + +void printf_unsigned(unsigned long long number, int radix) +{ + char buffer[32]; + int pos = 0; + + //number to ASCII conversion + do { + unsigned long long rem = number % radix; + number /= radix; + buffer[pos++] = g_HexChars[rem]; + } while (number > 0); + + //print number in reverse order + while (--pos >= 0) + putc(buffer[pos]); +} + +void printf_signed(long long number, int radix) +{ + if (number < 0) + { + putc('-'); + printf_unsigned(-number, radix); + } + else printf_unsigned(number, radix); + +} + + + #define PRINTF_STATE_NORMAL 0 #define PRINTF_STATE_LENGTH 1 #define PRINTF_STATE_LENGTH_SHORT 2 @@ -32,17 +162,15 @@ void puts(const char* str) #define PRINTF_LENGTH_LONG 3 #define PRINTF_LENGTH_LONG_LONG 4 +void printf(const char* fmt, ...) { + va_list args; + va_start(args, fmt); -int* printf_number(int* argp, int length, bool sign, int radix); - -void _cdecl printf(const char* fmt, ...) { - int* argp = (int*)&fmt; int state= PRINTF_STATE_NORMAL; int length = PRINTF_LENGTH_DEFAULT; int radix = 10; bool sign = false; - - argp++; + bool number = false; while (*fmt) { @@ -93,39 +221,72 @@ void _cdecl printf(const char* fmt, ...) { PRINTF_STATE_SPEC_: switch (*fmt) { - case 'c': putc((char)*argp); - argp++; + case 'c': putc((char)va_arg(args, int)); break; - case 's': puts(*(char***)argp); - argp++; + case 's': puts(va_arg(args, const char*)); break; case '%': putc('%'); break; case 'd': - case 'i': radix = 10; sign = true; - argp = printf_number(argp, length, sign, radix); + case 'i': radix = 10; + sign = true; + number = true; break; - case 'u': radix = 10; sign = false; - argp = printf_number(argp, length, sign, radix); + case 'u': radix = 10; sign = false; number = true; break; case 'X': case 'x': - case 'p': radix = 16; sign = false; - argp = printf_number(argp, length, sign, radix); + case 'p': radix = 16; sign = false; number = true; break; - case 'o': radix = 8; sign = false; - argp = printf_number(argp, length, sign, radix); + case 'o': radix = 8; sign = false; number = true; break; //ignore invalid specifiers (specs) default: break; } + if (number) + { + if (sign) + { + switch (length) + { + case PRINTF_LENGTH_SHORT_SHORT: + case PRINTF_LENGTH_SHORT: + case PRINTF_LENGTH_DEFAULT: + printf_signed(va_arg(args, int), radix); + break; + case PRINTF_LENGTH_LONG: + printf_signed(va_arg(args, long), radix); + break; + case PRINTF_LENGTH_LONG_LONG: + printf_signed(va_arg(args, long long), radix); + break; + } + } + else + { + switch (length) + { + case PRINTF_LENGTH_SHORT_SHORT: + case PRINTF_LENGTH_SHORT: + case PRINTF_LENGTH_DEFAULT: + printf_unsigned(va_arg(args, unsigned int), radix); + break; + case PRINTF_LENGTH_LONG: + printf_unsigned(va_arg(args, unsigned long), radix); + break; + case PRINTF_LENGTH_LONG_LONG: + printf_unsigned(va_arg(args, unsigned long long), radix); + break; + } + } + } //reset state state = PRINTF_STATE_NORMAL; @@ -137,86 +298,21 @@ void _cdecl printf(const char* fmt, ...) { fmt++; } + + va_end(args); } -const char g_HexChars[] = "0123456789abcdef"; -int* printf_number(int* argp, int length, bool sign, int radix) + +void print_buffer(const char* msg, const void* buffer, uint32_t count) { - char buffer[32]; - unsigned long long number; - int number_sign = 1; - int pos = 0; - - //process length - switch (length) - { - case PRINTF_LENGTH_SHORT_SHORT: - case PRINTF_LENGTH_SHORT: - case PRINTF_LENGTH_DEFAULT: - if (sign) - { - int n = *argp; - if (n < 0) { - n = -n; - number_sign = -1; - } - number = (unsigned long long)n; - } - else { - number = *(unsigned int*)argp; - } - argp++; - break; - - case PRINTF_LENGTH_LONG: - if (sign) - { - long int n = *(long int*)argp; - if (n < 0) { - n = -n; - number_sign = -1; - } - number = (unsigned long long)n; - } - else { - number = *(unsigned long int*)argp; - } - argp += 2; - break; - - case PRINTF_LENGTH_LONG_LONG: - if (sign) - { - long long int n = *(long long int*)argp; - if (n < 0) { - n = -n; - number_sign = -1; - } - number = (unsigned long long)n; - } - else { - number = *(unsigned long long*)argp; - } - argp += 4; - break; - } - - //number to ASCII conversion - do { - uint32_t rem; - x86_div64_32(number, radix, &number, &rem); - buffer[pos++] = g_HexChars[rem]; - } while (number > 0); - - //add sign - if (sign && number_sign < 0) { - buffer[pos++] = '-'; - } - - //print number in reverse order - while (--pos >= 0) - putc(buffer[pos]); - - return argp; + const uint8_t* u8Buffer = (const uint8_t*)buffer; + + puts(msg); + for (uint16_t i = 0; i < count; i++) + { + putc(g_HexChars[u8Buffer[i] >> 4]); + putc(g_HexChars[u8Buffer[i] & 0xF]); + } + puts("\n"); } diff --git a/src/bootloader/stage2/stdio.h b/src/bootloader/stage2/stdio.h index 1de4a82..10dcdb8 100644 --- a/src/bootloader/stage2/stdio.h +++ b/src/bootloader/stage2/stdio.h @@ -4,7 +4,10 @@ |Tyler McGurrin | \*----------------*/ #pragma once +#include +void clrscr(); void putc(char c); void puts(const char* str); -void _cdecl printf(const char* fmt, ...); +void printf(const char* fmt, ...); +void print_buffer(const char* msg, const void* buffer, uint32_t count); diff --git a/src/bootloader/stage2/string.c b/src/bootloader/stage2/string.c deleted file mode 100644 index 8361098..0000000 --- a/src/bootloader/stage2/string.c +++ /dev/null @@ -1,49 +0,0 @@ -/*----------------*\ -|Nanite OS | -|Copyright (C) 2024| -|Tyler McGurrin | -\*----------------*/ -#include "string.h" -#include "stdint.h" - -const char* strchr(const char* str, char chr) { - if (str == NULL) - return NULL; - - while (*str) { - if (*str == chr) - return str; - - ++str; - } - - return NULL; -} - -char* strcpy(char* dst, const char* src) { - char* origDst = dst; - - if (dst == NULL) - return NULL; - - if (src == NULL) { - *dst = '\0'; - return dst; - } - while (*src) { - *dst = *src; - ++src; - ++dst; - } - - *dst = '\0'; - return origDst; -} - -unsigned strlen(const char* str) { - unsigned len = 0; - while (*str) { - ++len; ++str; - } - return len; -} diff --git a/src/bootloader/stage2/string.h b/src/bootloader/stage2/string.h deleted file mode 100644 index 4f36582..0000000 --- a/src/bootloader/stage2/string.h +++ /dev/null @@ -1,10 +0,0 @@ -/*----------------*\ -|Nanite OS | -|Copyright (C) 2024| -|Tyler McGurrin | -\*----------------*/ -#pragma once - -const char* strchr(const char* str, char chr); -char* strcpy(char* dst, const char* src); -unsigned strlen(const char* str); diff --git a/src/bootloader/stage2/utility.c b/src/bootloader/stage2/utility.c deleted file mode 100644 index 00e44b9..0000000 --- a/src/bootloader/stage2/utility.c +++ /dev/null @@ -1,14 +0,0 @@ -/*----------------*\ -|Nanite OS | -|Copyright (C) 2024| -|Tyler McGurrin | -\*----------------*/ -#include "utility.h" - -uint32_t align(uint32_t number, uint32_t alignTo) { - if (alignTo == 0) - return number; - - uint32_t rem = number % alignTo; - return (rem > 0) ? (number + alignTo - rem) : number; -} diff --git a/src/bootloader/stage2/utility.h b/src/bootloader/stage2/utility.h deleted file mode 100644 index 741bc59..0000000 --- a/src/bootloader/stage2/utility.h +++ /dev/null @@ -1,9 +0,0 @@ -/*----------------*\ -|Nanite OS | -|Copyright (C) 2024| -|Tyler McGurrin | -\*----------------*/ -#pragma once -#include "stdint.h" - -uint32_t align(uint32_t number, uint32_t alignTo); diff --git a/src/bootloader/stage2/x86.asm b/src/bootloader/stage2/x86.asm index d1b2980..4de2f7e 100644 --- a/src/bootloader/stage2/x86.asm +++ b/src/bootloader/stage2/x86.asm @@ -1,279 +1,77 @@ -;/////////////////////; -;Nanite OS ; -;COPYRIGHT (C) 2024 ; -;Tyler McGurrin ; -;/////////////////////; -bits 16 +%macro x86_EnterRealMode 0 + [bits 32] + jmp work 18h:.pmode16 -section _TEXT class=CODE +.pmode16: + [bits 16] + mov eax, cr0 + and al, ~1 + mov cr0, eax + jmp word 00h:.rmode -; -; U4D -; -; Operation: Unsigned 4 byte divide -; Inputs: DX;AX Dividend -; CX;BX Divisor -; Outputs: DX;AX Quotient -; CX;BX Remainder -; Volatile: none -; -global __U4D -__U4D: - shl edx, 16 ; dx to upper half of edx - mov dx, ax ; edx - dividend - mov eax, edx ; eax - dividend - xor edx, edx +.rmode: + mov ax, 0 + mov ds, ax + mov ss, ax - shl ecx, 16 ; cx to upper half of ecx - mov cx, bx ; ecx - divisor + sti - div ecx ; eax - quot, edx - remainder - mov ebx, edx - mov ecx, edx - shr ecx, 16 +%endmacro - mov edx, eax - shr edx, 16 +%macro x86_EnterProtectedMode 0 + cli + ; set PMODE enable flag in CR0 + mov eax, CR0 + or al, 1 + mov cr0, eax - ret + ; far jmp into PMODE + jmp dword 08h:.pmode - -; -; U4M -; Operation: integer four byte multiply -; Inputs: DX;AX integer M1 -; CX;BX integer M2 -; Outputs: DX;AX product -; Volatile: CX, BX destroyed -; -global __U4M -__U4M: - shl edx, 16 ; dx to upper half of edx - mov dx, ax ; m1 in edx - mov eax, edx ; m1 in eax - - shl ecx, 16 ; cx to upper half of ecx - mov cx, bx ; m2 in ecx - - mul ecx ; result in edx:eax (we only need eax) - mov edx, eax ; move upper half to dx - shr edx, 16 - - ret - -; -; void _cdecl x86_div64_32(uint64_t dividend, uint32_t divisor, uint64_t* quotientOut, uint32_t* remainderOut); -; -global _x86_div64_32 -_x86_div64_32: - - ; make new call frame - push bp ; save old call frame - mov bp, sp ; initialize new call frame - - push bx - - ; divide upper 32 bits - mov eax, [bp + 8] ; eax <- upper 32 bits of dividend - mov ecx, [bp + 12] ; ecx <- divisor - xor edx, edx - div ecx ; eax - quot, edx - remainder - - ; store upper 32 bits of quotient - mov bx, [bp + 16] - mov [bx + 4], eax - - ; divide lower 32 bits - mov eax, [bp + 4] ; eax <- lower 32 bits of dividend - ; edx <- old remainder - div ecx - - ; store results - mov [bx], eax - mov bx, [bp + 18] - mov [bx], edx - - pop bx - - ; restore old call frame - mov sp, bp - pop bp - ret - -; -; int 10h ah=0Eh -; args: character, page -; -global _x86_Video_WriteCharTeletype -_x86_Video_WriteCharTeletype: +.pmode: + ; we are now in protected mode! + [bits 32] - ; make new call frame - push bp ; save old call frame - mov bp, sp ; initialize new call frame + ; 6 - setup segment registers + mov ax, 0x10 + mov ds, ax + mov ss, ax - ; save bx - push bx - ; [bp + 0] - old call frame - ; [bp + 2] - return address (small memory model => 2 bytes) - ; [bp + 4] - first argument (character) - ; [bp + 6] - second argument (page) - ; note: bytes are converted to words (you can't push a single byte on the stack) - mov ah, 0Eh - mov al, [bp + 4] - mov bh, [bp + 6] +%endmacro + +global x86_outb +x86_outb: + [bits 32] + mov dx, [esp + 4] + mov al, [esp + 8] + out dx, al + ret + +global x86_inb +x86_inb: + [bits 32] + mov dx, [esp + 4] + xor eax, eax + in al, dx + ret + +global x86_realmode_putc +x86_realmode_putc: + ; setup stack frame + push ebp + mov ebp, esp + + x86_EnterRealMode + + mov al, [sp + 8] + mov ah, 0xe int 10h - ; restore bx - pop bx + x86_EnterProtectedMode - ; restore old call frame - mov sp, bp - pop bp + mov esp, ebp + pop ebp ret - - -; -; bool _cdecl x86_Disk_Reset(uint8_t drive); -; -global _x86_Disk_Reset -_x86_Disk_Reset: - - ; make new call frame - push bp ; save old call frame - mov bp, sp ; initialize new call frame - - mov ah, 0 - mov dl, [bp + 4] ; dl - drive - stc - int 13h - - mov ax, 1 - sbb ax, 0 ; 1 on success, 0 on fail - - ; restore old call frame - mov sp, bp - pop bp - ret - - -; -; bool _cdecl x86_Disk_Read(uint8_t drive, -; uint16_t cylinder, -; uint16_t sector, -; uint16_t head, -; uint8_t count, -; void far * dataOut); -; -global _x86_Disk_Read -_x86_Disk_Read: - - ; make new call frame - push bp ; save old call frame - mov bp, sp ; initialize new call frame - - ; save modified regs - push bx - push es - - ; setup args - mov dl, [bp + 4] ; dl - drive - - mov ch, [bp + 6] ; ch - cylinder (lower 8 bits) - mov cl, [bp + 7] ; cl - cylinder to bits 6-7 - shl cl, 6 - - mov al, [bp + 8] ; cl - sector to bits 0-5 - and al, 3Fh - or cl, al - - mov dh, [bp + 10] ; dh - head - - mov al, [bp + 12] ; al - count - - mov bx, [bp + 16] ; es:bx - far pointer to data out - mov es, bx - mov bx, [bp + 14] - - ; call int13h - mov ah, 02h - stc - int 13h - - ; set return value - mov ax, 1 - sbb ax, 0 ; 1 on success, 0 on fail - - ; restore regs - pop es - pop bx - - ; restore old call frame - mov sp, bp - pop bp - ret - - -; -; bool _cdecl x86_Disk_GetDriveParams(uint8_t drive, -; uint8_t* driveTypeOut, -; uint16_t* cylindersOut, -; uint16_t* sectorsOut, -; uint16_t* headsOut); -; -global _x86_Disk_GetDriveParams -_x86_Disk_GetDriveParams: - - ; make new call frame - push bp ; save old call frame - mov bp, sp ; initialize new call frame - - ; save regs - push es - push bx - push si - push di - - ; call int13h - mov dl, [bp + 4] ; dl - disk drive - mov ah, 08h - mov di, 0 ; es:di - 0000:0000 - mov es, di - stc - int 13h - - ; return - mov ax, 1 - sbb ax, 0 - - ; out params - mov si, [bp + 6] ; drive type from bl - mov [si], bl - - mov bl, ch ; cylinders - lower bits in ch - mov bh, cl ; cylinders - upper bits in cl (6-7) - shr bh, 6 - mov si, [bp + 8] - mov [si], bx - - xor ch, ch ; sectors - lower 5 bits in cl - and cl, 3Fh - mov si, [bp + 10] - mov [si], cx - - mov cl, dh ; heads - dh - mov si, [bp + 12] - mov [si], cx - - ; restore regs - pop di - pop si - pop bx - pop es - - ; restore old call frame - mov sp, bp - pop bp - ret \ No newline at end of file diff --git a/src/bootloader/stage2/x86.h b/src/bootloader/stage2/x86.h index 994e3fd..731669c 100644 --- a/src/bootloader/stage2/x86.h +++ b/src/bootloader/stage2/x86.h @@ -1,26 +1,5 @@ -/*----------------*\ -|Nanite OS | -|Copyright (C) 2024| -|Tyler McGurrin | -\*----------------*/ #pragma once -#include "stdint.h" +#include -void _cdecl x86_div64_32(uint64_t dividend, uint32_t divisor, uint64_t* quotientOut, uint32_t* remainderOut); - -void _cdecl x86_Video_WriteCharTeletype(char c, uint8_t page); - -bool _cdecl x86_Disk_Reset(uint8_t drive); - -bool _cdecl x86_Disk_Read(uint8_t drive, - uint16_t cylinder, - uint16_t sector, - uint16_t head, - uint8_t count, - void far * dataOut); - -bool _cdecl x86_Disk_GetDriveParams(uint8_t drive, - uint8_t* driveTypeOut, - uint16_t* cylindersOut, - uint16_t* sectorsOut, - uint16_t* headsOut); +void __attribute__((cdecl)) x86_outb(uint16_t port, uint8_t value); +uint8_t __attribute__((cdecl)) x86_inb(uint16_t port); \ No newline at end of file