bully this crap code into working with GCC (and add GCC toolchain har har har)
This commit is contained in:
parent
ebaffb85ad
commit
60a01a977a
3
.gitignore
vendored
3
.gitignore
vendored
@ -1,2 +1,5 @@
|
|||||||
.vscode/
|
.vscode/
|
||||||
build/
|
build/
|
||||||
|
toolchain/
|
||||||
|
bx_enh_dbg.ini
|
||||||
|
src/bootloader/stage2_old
|
||||||
30
Makefile
30
Makefile
@ -1,16 +1,12 @@
|
|||||||
ASM=nasm
|
include build_scripts/config.mk
|
||||||
CC=gcc
|
|
||||||
CC16=/opt/watcom/binl/wcc
|
|
||||||
LD16=/opt/watcom/binl/wlink
|
|
||||||
|
|
||||||
SRC_DIR=src
|
|
||||||
TOOLS_DIR=tools
|
|
||||||
BUILD_DIR=build
|
|
||||||
|
|
||||||
.PHONY: all floppy_image kernel bootloader clean always tools_fat
|
.PHONY: all floppy_image kernel bootloader clean always tools_fat
|
||||||
|
|
||||||
all: floppy_image tools_fat
|
all: floppy_image tools_fat
|
||||||
|
|
||||||
|
include build_scripts/toolchain.mk
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Floppy image
|
# Floppy image
|
||||||
#
|
#
|
||||||
@ -34,12 +30,12 @@ bootloader: stage1 stage2
|
|||||||
stage1: $(BUILD_DIR)/stage1.bin
|
stage1: $(BUILD_DIR)/stage1.bin
|
||||||
|
|
||||||
$(BUILD_DIR)/stage1.bin: always
|
$(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
|
stage2: $(BUILD_DIR)/stage2.bin
|
||||||
|
|
||||||
$(BUILD_DIR)/stage2.bin: always
|
$(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
|
kernel: $(BUILD_DIR)/kernel.bin
|
||||||
|
|
||||||
$(BUILD_DIR)/kernel.bin: always
|
$(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
|
||||||
#
|
#
|
||||||
tools_fat: $(BUILD_DIR)/tools/fat
|
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
|
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
|
# Always
|
||||||
@ -68,8 +64,8 @@ always:
|
|||||||
# Clean
|
# Clean
|
||||||
#
|
#
|
||||||
clean:
|
clean:
|
||||||
$(MAKE) -C $(SRC_DIR)/bootloader/stage1 BUILD_DIR=$(abspath $(BUILD_DIR)) clean
|
$(MAKE) -C src/bootloader/stage1 BUILD_DIR=$(abspath $(BUILD_DIR)) clean
|
||||||
$(MAKE) -C $(SRC_DIR)/bootloader/stage2 BUILD_DIR=$(abspath $(BUILD_DIR)) clean
|
$(MAKE) -C src/bootloader/stage2 BUILD_DIR=$(abspath $(BUILD_DIR)) clean
|
||||||
$(MAKE) -C $(SRC_DIR)/kernel BUILD_DIR=$(abspath $(BUILD_DIR)) clean
|
$(MAKE) -C src/kernel BUILD_DIR=$(abspath $(BUILD_DIR)) clean
|
||||||
rm -rf $(BUILD_DIR)/*
|
rm -rf $(BUILD_DIR)/*
|
||||||
rm -rf $(SRC_DIR)/bootloader/stage2/*.err
|
rm -rf src/bootloader/stage2/*.err
|
||||||
|
|||||||
25
build_scripts/config.mk
Normal file
25
build_scripts/config.mk
Normal file
@ -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
|
||||||
57
build_scripts/toolchain.mk
Normal file
57
build_scripts/toolchain.mk
Normal file
@ -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
|
||||||
|
|
||||||
@ -373,8 +373,8 @@ msg_no_stage2: db 'Cant Find Stage 2!', ENDL, 0
|
|||||||
file_stage2_bin: db 'STAGE2 BIN'
|
file_stage2_bin: db 'STAGE2 BIN'
|
||||||
stage2_cluster: dw 0
|
stage2_cluster: dw 0
|
||||||
|
|
||||||
STAGE2_LOAD_SEGMENT equ 0x2000
|
STAGE2_LOAD_SEGMENT equ 0x0
|
||||||
STAGE2_LOAD_OFFSET equ 0
|
STAGE2_LOAD_OFFSET equ 0x500
|
||||||
|
|
||||||
times 510-($-$$) db 0
|
times 510-($-$$) db 0
|
||||||
dw 0AA55h
|
dw 0AA55h
|
||||||
|
|||||||
@ -1,9 +1,8 @@
|
|||||||
BUILD_DIR?=build/
|
TARGET_ASMFLAGS += -f elf
|
||||||
ASM?=nasm
|
TARGET_CFLAGS += -ffreestanding -nostdlib
|
||||||
ASMFLAGS?=-f obj
|
TARGET_LIBS += -lgcc
|
||||||
CC16?=/usr/bin/watcom/binl/wcc
|
TARGET_LINKFLAGS += -T linker.ld -nostdlib
|
||||||
CFLAGS16?=-4 -d3 -s -wx -ms -zl -zq -za99 # -oneatxzh
|
|
||||||
LD16?=/usr/bin/watcom/binl/wlink
|
|
||||||
|
|
||||||
SOURCES_C=$(wildcard *.c)
|
SOURCES_C=$(wildcard *.c)
|
||||||
SOURCES_ASM=$(wildcard *.asm)
|
SOURCES_ASM=$(wildcard *.asm)
|
||||||
@ -17,13 +16,13 @@ all: stage2
|
|||||||
stage2: $(BUILD_DIR)/stage2.bin
|
stage2: $(BUILD_DIR)/stage2.bin
|
||||||
|
|
||||||
$(BUILD_DIR)/stage2.bin: $(OBJECTS_ASM) $(OBJECTS_C)
|
$(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
|
$(BUILD_DIR)/stage2/c/%.obj: %.c always
|
||||||
$(CC16) $(CFLAGS16) -fo=$@ $<
|
$(TARGET_CC) $(TARGET_CFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
$(BUILD_DIR)/stage2/asm/%.obj: %.asm always
|
$(BUILD_DIR)/stage2/asm/%.obj: %.asm always
|
||||||
$(ASM) $(ASMFLAGS) -o $@ $<
|
$(TARGET_ASM) $(TARGET_ASMFLAGS) -o $@ $<
|
||||||
|
|
||||||
always:
|
always:
|
||||||
mkdir -p $(BUILD_DIR)/stage2/c
|
mkdir -p $(BUILD_DIR)/stage2/c
|
||||||
|
|||||||
@ -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;
|
|
||||||
}
|
|
||||||
@ -1,10 +0,0 @@
|
|||||||
/*----------------*\
|
|
||||||
|Nanite OS |
|
|
||||||
|Copyright (C) 2024|
|
|
||||||
|Tyler McGurrin |
|
|
||||||
\*----------------*/
|
|
||||||
#pragma once
|
|
||||||
#include "stdint.h"
|
|
||||||
|
|
||||||
bool islower(char chr);
|
|
||||||
char toupper(char chr);
|
|
||||||
@ -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;
|
|
||||||
}
|
|
||||||
@ -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);
|
|
||||||
|
|
||||||
175
src/bootloader/stage2/entry.asm
Normal file
175
src/bootloader/stage2/entry.asm
Normal file
@ -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
|
||||||
@ -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;
|
|
||||||
}
|
|
||||||
@ -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);
|
|
||||||
15
src/bootloader/stage2/linker.ld
Normal file
15
src/bootloader/stage2/linker.ld
Normal file
@ -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 = .;
|
||||||
|
}
|
||||||
@ -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
|
|
||||||
@ -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
|
|
||||||
@ -3,64 +3,67 @@
|
|||||||
|Copyright (C) 2024|
|
|Copyright (C) 2024|
|
||||||
|Tyler McGurrin |
|
|Tyler McGurrin |
|
||||||
\*----------------*/
|
\*----------------*/
|
||||||
#include "stdint.h"
|
#include <stdint.h>
|
||||||
#include "stdio.h"
|
#include "stdio.h"
|
||||||
#include "disk.h"
|
// #include "disk.h"
|
||||||
#include "fat.h"
|
// #include "fat.h"
|
||||||
|
|
||||||
void far* g_data = (void far*)0x00500200;
|
// void far* g_data = (void far*)0x00500200;
|
||||||
#define LOGO " _ _____ _ __________________\r\n / | / / | / | / / _/_ __/ ____/\r\n / |/ / /| | / |/ // / / / / __/ \r\n / /| / ___ |/ /| // / / / / /___ \r\n\\/_/ |_/_/ |_/_/ |_/___/ /_/ /_____/ \r\n"
|
#define LOGO " _ _____ _ __________________\n / | / / | / | / / _/_ __/ ____/\n / |/ / /| | / |/ // / / / / __/ \n / /| / ___ |/ /| // / / / / /___ \n\\/_/ |_/_/ |_/_/ |_/___/ /_/ /_____/ \n"
|
||||||
#define VERSION "v0.0.1"
|
#define VERSION "v0.0.1"
|
||||||
|
|
||||||
void _cdecl cstart_(uint16_t bootDrive) {
|
void __attribute__((cdecl)) start(uint16_t bootDrive) {
|
||||||
|
clrscr();
|
||||||
printf("%s", LOGO);
|
printf("%s", LOGO);
|
||||||
printf(" %s\r\n--------------------------------------\r\n", VERSION);
|
printf(" %s\n--------------------------------------\n", VERSION);
|
||||||
|
|
||||||
printf("Initializing FAT Driver...");
|
for(;;);
|
||||||
DISK disk;
|
|
||||||
if (!DISK_Initialize(&disk, bootDrive)) {
|
|
||||||
printf("Failed!\r\nDisk Initialization Error\r\n");
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
|
|
||||||
DISK_ReadSectors(&disk, 19, 1, g_data);
|
// printf("Initializing FAT Driver...");
|
||||||
|
// DISK disk;
|
||||||
|
// if (!DISK_Initialize(&disk, bootDrive)) {
|
||||||
|
// printf("Failed!\nDisk Initialization Error\n");
|
||||||
|
// goto end;
|
||||||
|
// }
|
||||||
|
|
||||||
if (!FAT_Initialize(&disk)) {
|
// DISK_ReadSectors(&disk, 19, 1, g_data);
|
||||||
printf("Failed!\r\nDisk Initialization Error\r\n");
|
|
||||||
goto end;
|
// if (!FAT_Initialize(&disk)) {
|
||||||
}
|
// printf("Failed!\nDisk Initialization Error\n");
|
||||||
printf("Done!\r\n");
|
// goto end;
|
||||||
// printf("Listing Root DIR...\r\n");
|
// }
|
||||||
// // browse files in root
|
// printf("Done!\n");
|
||||||
FAT_File far* fd = FAT_Open(&disk, "/");
|
// // printf("Listing Root DIR...\n");
|
||||||
FAT_DirectoryEntry entry;
|
// // // browse files in root
|
||||||
int i = 0;
|
// FAT_File far* fd = FAT_Open(&disk, "/");
|
||||||
// while (FAT_ReadEntry(&disk, fd, &entry) && i++ < 5) {
|
// FAT_DirectoryEntry entry;
|
||||||
// printf(" ");
|
// int i = 0;
|
||||||
// for (int i = 0; i < 11; i++)
|
// // while (FAT_ReadEntry(&disk, fd, &entry) && i++ < 5) {
|
||||||
// putc(entry.Name[i]);
|
// // printf(" ");
|
||||||
// printf("\r\n");
|
// // 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('');
|
||||||
|
// putc(buffer[i]);
|
||||||
|
// }
|
||||||
// }
|
// }
|
||||||
// FAT_Close(fd);
|
// FAT_Close(fd);
|
||||||
|
|
||||||
printf("Testing FAT Driver...");
|
// end:
|
||||||
// read test.txt
|
// for (;;);
|
||||||
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);
|
|
||||||
|
|
||||||
end:
|
|
||||||
for (;;);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -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
|
|
||||||
@ -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;
|
|
||||||
}
|
|
||||||
@ -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);
|
|
||||||
@ -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))
|
|
||||||
@ -5,10 +5,107 @@
|
|||||||
\*----------------*/
|
\*----------------*/
|
||||||
#include "stdio.h"
|
#include "stdio.h"
|
||||||
#include "x86.h"
|
#include "x86.h"
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
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)
|
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)
|
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_NORMAL 0
|
||||||
#define PRINTF_STATE_LENGTH 1
|
#define PRINTF_STATE_LENGTH 1
|
||||||
#define PRINTF_STATE_LENGTH_SHORT 2
|
#define PRINTF_STATE_LENGTH_SHORT 2
|
||||||
@ -32,17 +162,15 @@ void puts(const char* str)
|
|||||||
#define PRINTF_LENGTH_LONG 3
|
#define PRINTF_LENGTH_LONG 3
|
||||||
#define PRINTF_LENGTH_LONG_LONG 4
|
#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 state= PRINTF_STATE_NORMAL;
|
||||||
int length = PRINTF_LENGTH_DEFAULT;
|
int length = PRINTF_LENGTH_DEFAULT;
|
||||||
int radix = 10;
|
int radix = 10;
|
||||||
bool sign = false;
|
bool sign = false;
|
||||||
|
bool number = false;
|
||||||
argp++;
|
|
||||||
|
|
||||||
while (*fmt)
|
while (*fmt)
|
||||||
{
|
{
|
||||||
@ -93,39 +221,72 @@ void _cdecl printf(const char* fmt, ...) {
|
|||||||
PRINTF_STATE_SPEC_:
|
PRINTF_STATE_SPEC_:
|
||||||
switch (*fmt)
|
switch (*fmt)
|
||||||
{
|
{
|
||||||
case 'c': putc((char)*argp);
|
case 'c': putc((char)va_arg(args, int));
|
||||||
argp++;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 's': puts(*(char***)argp);
|
case 's': puts(va_arg(args, const char*));
|
||||||
argp++;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '%': putc('%');
|
case '%': putc('%');
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'd':
|
case 'd':
|
||||||
case 'i': radix = 10; sign = true;
|
case 'i': radix = 10;
|
||||||
argp = printf_number(argp, length, sign, radix);
|
sign = true;
|
||||||
|
number = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'u': radix = 10; sign = false;
|
case 'u': radix = 10; sign = false; number = true;
|
||||||
argp = printf_number(argp, length, sign, radix);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'X':
|
case 'X':
|
||||||
case 'x':
|
case 'x':
|
||||||
case 'p': radix = 16; sign = false;
|
case 'p': radix = 16; sign = false; number = true;
|
||||||
argp = printf_number(argp, length, sign, radix);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'o': radix = 8; sign = false;
|
case 'o': radix = 8; sign = false; number = true;
|
||||||
argp = printf_number(argp, length, sign, radix);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
//ignore invalid specifiers (specs)
|
//ignore invalid specifiers (specs)
|
||||||
default: break;
|
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
|
//reset state
|
||||||
state = PRINTF_STATE_NORMAL;
|
state = PRINTF_STATE_NORMAL;
|
||||||
@ -137,86 +298,21 @@ void _cdecl printf(const char* fmt, ...) {
|
|||||||
|
|
||||||
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];
|
const uint8_t* u8Buffer = (const uint8_t*)buffer;
|
||||||
unsigned long long number;
|
|
||||||
int number_sign = 1;
|
|
||||||
int pos = 0;
|
|
||||||
|
|
||||||
//process length
|
puts(msg);
|
||||||
switch (length)
|
for (uint16_t i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
case PRINTF_LENGTH_SHORT_SHORT:
|
putc(g_HexChars[u8Buffer[i] >> 4]);
|
||||||
case PRINTF_LENGTH_SHORT:
|
putc(g_HexChars[u8Buffer[i] & 0xF]);
|
||||||
case PRINTF_LENGTH_DEFAULT:
|
|
||||||
if (sign)
|
|
||||||
{
|
|
||||||
int n = *argp;
|
|
||||||
if (n < 0) {
|
|
||||||
n = -n;
|
|
||||||
number_sign = -1;
|
|
||||||
}
|
}
|
||||||
number = (unsigned long long)n;
|
puts("\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;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,7 +4,10 @@
|
|||||||
|Tyler McGurrin |
|
|Tyler McGurrin |
|
||||||
\*----------------*/
|
\*----------------*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
void clrscr();
|
||||||
void putc(char c);
|
void putc(char c);
|
||||||
void puts(const char* str);
|
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);
|
||||||
|
|||||||
@ -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;
|
|
||||||
}
|
|
||||||
@ -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);
|
|
||||||
@ -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;
|
|
||||||
}
|
|
||||||
@ -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);
|
|
||||||
@ -1,279 +1,77 @@
|
|||||||
;/////////////////////;
|
%macro x86_EnterRealMode 0
|
||||||
;Nanite OS ;
|
[bits 32]
|
||||||
;COPYRIGHT (C) 2024 ;
|
jmp work 18h:.pmode16
|
||||||
;Tyler McGurrin ;
|
|
||||||
;/////////////////////;
|
|
||||||
bits 16
|
|
||||||
|
|
||||||
section _TEXT class=CODE
|
.pmode16:
|
||||||
|
[bits 16]
|
||||||
|
mov eax, cr0
|
||||||
|
and al, ~1
|
||||||
|
mov cr0, eax
|
||||||
|
|
||||||
|
jmp word 00h:.rmode
|
||||||
|
|
||||||
|
.rmode:
|
||||||
|
mov ax, 0
|
||||||
|
mov ds, ax
|
||||||
|
mov ss, ax
|
||||||
|
|
||||||
|
sti
|
||||||
|
|
||||||
|
%endmacro
|
||||||
|
|
||||||
|
%macro x86_EnterProtectedMode 0
|
||||||
|
cli
|
||||||
|
; 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
|
||||||
|
|
||||||
|
|
||||||
;
|
%endmacro
|
||||||
; 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
|
|
||||||
|
|
||||||
shl ecx, 16 ; cx to upper half of ecx
|
|
||||||
mov cx, bx ; ecx - divisor
|
|
||||||
|
|
||||||
div ecx ; eax - quot, edx - remainder
|
|
||||||
mov ebx, edx
|
|
||||||
mov ecx, edx
|
|
||||||
shr ecx, 16
|
|
||||||
|
|
||||||
mov edx, eax
|
|
||||||
shr edx, 16
|
|
||||||
|
|
||||||
|
global x86_outb
|
||||||
|
x86_outb:
|
||||||
|
[bits 32]
|
||||||
|
mov dx, [esp + 4]
|
||||||
|
mov al, [esp + 8]
|
||||||
|
out dx, al
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
global x86_inb
|
||||||
;
|
x86_inb:
|
||||||
; U4M
|
[bits 32]
|
||||||
; Operation: integer four byte multiply
|
mov dx, [esp + 4]
|
||||||
; Inputs: DX;AX integer M1
|
xor eax, eax
|
||||||
; CX;BX integer M2
|
in al, dx
|
||||||
; 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
|
ret
|
||||||
|
|
||||||
;
|
global x86_realmode_putc
|
||||||
; void _cdecl x86_div64_32(uint64_t dividend, uint32_t divisor, uint64_t* quotientOut, uint32_t* remainderOut);
|
x86_realmode_putc:
|
||||||
;
|
; setup stack frame
|
||||||
global _x86_div64_32
|
push ebp
|
||||||
_x86_div64_32:
|
mov ebp, esp
|
||||||
|
|
||||||
; make new call frame
|
x86_EnterRealMode
|
||||||
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:
|
|
||||||
|
|
||||||
; make new call frame
|
|
||||||
push bp ; save old call frame
|
|
||||||
mov bp, sp ; initialize new call frame
|
|
||||||
|
|
||||||
; 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]
|
|
||||||
|
|
||||||
|
mov al, [sp + 8]
|
||||||
|
mov ah, 0xe
|
||||||
int 10h
|
int 10h
|
||||||
|
|
||||||
; restore bx
|
x86_EnterProtectedMode
|
||||||
pop bx
|
|
||||||
|
|
||||||
; restore old call frame
|
mov esp, ebp
|
||||||
mov sp, bp
|
pop ebp
|
||||||
pop bp
|
|
||||||
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
|
ret
|
||||||
@ -1,26 +1,5 @@
|
|||||||
/*----------------*\
|
|
||||||
|Nanite OS |
|
|
||||||
|Copyright (C) 2024|
|
|
||||||
|Tyler McGurrin |
|
|
||||||
\*----------------*/
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "stdint.h"
|
#include <stdint.h>
|
||||||
|
|
||||||
void _cdecl x86_div64_32(uint64_t dividend, uint32_t divisor, uint64_t* quotientOut, uint32_t* remainderOut);
|
void __attribute__((cdecl)) x86_outb(uint16_t port, uint8_t value);
|
||||||
|
uint8_t __attribute__((cdecl)) x86_inb(uint16_t port);
|
||||||
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);
|
|
||||||
Loading…
x
Reference in New Issue
Block a user