Begin KERNEL
This commit is contained in:
parent
d1083b4afe
commit
a0325af23a
3
Makefile
3
Makefile
@ -17,7 +17,8 @@ $(BUILD_DIR)/main_floppy.img: bootloader kernel
|
|||||||
mkfs.fat -F 12 -n "NANITE" $(BUILD_DIR)/main_floppy.img
|
mkfs.fat -F 12 -n "NANITE" $(BUILD_DIR)/main_floppy.img
|
||||||
dd if=$(BUILD_DIR)/stage1.bin of=$(BUILD_DIR)/main_floppy.img conv=notrunc
|
dd if=$(BUILD_DIR)/stage1.bin of=$(BUILD_DIR)/main_floppy.img conv=notrunc
|
||||||
mcopy -i $(BUILD_DIR)/main_floppy.img $(BUILD_DIR)/stage2.bin "::stage2.bin"
|
mcopy -i $(BUILD_DIR)/main_floppy.img $(BUILD_DIR)/stage2.bin "::stage2.bin"
|
||||||
mcopy -i $(BUILD_DIR)/main_floppy.img $(BUILD_DIR)/kernel.bin "::kernel.bin"
|
mmd -i $(BUILD_DIR)/main_floppy.img "::boot"
|
||||||
|
mcopy -i $(BUILD_DIR)/main_floppy.img $(BUILD_DIR)/kernel.bin "::boot/kernel.bin"
|
||||||
mmd -i $(BUILD_DIR)/main_floppy.img "::misc"
|
mmd -i $(BUILD_DIR)/main_floppy.img "::misc"
|
||||||
mcopy -i $(BUILD_DIR)/main_floppy.img test.txt "::misc/test.txt"
|
mcopy -i $(BUILD_DIR)/main_floppy.img test.txt "::misc/test.txt"
|
||||||
|
|
||||||
|
|||||||
@ -15,8 +15,8 @@ bool DISK_Initialize(DISK* disk, uint8_t driveNumber) {
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
disk->id = driveNumber;
|
disk->id = driveNumber;
|
||||||
disk->cylinders = cylinders + 1;
|
disk->cylinders = cylinders;
|
||||||
disk->heads = heads + 1;
|
disk->heads = heads;
|
||||||
disk->sectors = sectors;
|
disk->sectors = sectors;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -31,6 +31,8 @@ void DISK_LBA2CHS(DISK* disk, uint32_t lba, uint16_t* cylinderOut, uint16_t* sec
|
|||||||
|
|
||||||
// head = (LBA / sects per track % heads)
|
// head = (LBA / sects per track % heads)
|
||||||
*headOut = (lba / disk->sectors) % disk->heads;
|
*headOut = (lba / disk->sectors) % disk->heads;
|
||||||
|
|
||||||
|
// printf("LBA2CHS: lba=%u sect=%u cyl=%u head=%u disk_sectors=%u disk_heads=%u\n", lba, *sectorOut, *cylinderOut, *headOut, disk->sectors, disk->heads);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DISK_ReadSectors(DISK* disk, uint32_t lba, uint8_t sectors, void* dataOut) {
|
bool DISK_ReadSectors(DISK* disk, uint32_t lba, uint8_t sectors, void* dataOut) {
|
||||||
@ -38,9 +40,11 @@ bool DISK_ReadSectors(DISK* disk, uint32_t lba, uint8_t sectors, void* dataOut)
|
|||||||
|
|
||||||
DISK_LBA2CHS(disk, lba, &cylinder, §or, &head);
|
DISK_LBA2CHS(disk, lba, &cylinder, §or, &head);
|
||||||
|
|
||||||
for (int i = 0; i < 3; i++) {
|
for (int i = 0; i < 3; i++)
|
||||||
|
{
|
||||||
if (x86_Disk_Read(disk->id, cylinder, sector, head, sectors, dataOut))
|
if (x86_Disk_Read(disk->id, cylinder, sector, head, sectors, dataOut))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
x86_Disk_Reset(disk->id);
|
x86_Disk_Reset(disk->id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -19,51 +19,56 @@
|
|||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
uint8_t BootJumpInstruction[3];
|
uint8_t BootJumpInstruction[3];
|
||||||
uint8_t OemIdentifier[8];
|
uint8_t OemIdentifier[8];
|
||||||
uint16_t BytesPerSector;
|
uint16_t BytesPerSector;
|
||||||
uint8_t SectorsPerCluster;
|
uint8_t SectorsPerCluster;
|
||||||
uint16_t ReservedSectors;
|
uint16_t ReservedSectors;
|
||||||
uint8_t FatCount;
|
uint8_t FatCount;
|
||||||
uint16_t DirEntryCount;
|
uint16_t DirEntryCount;
|
||||||
uint16_t TotalSectors;
|
uint16_t TotalSectors;
|
||||||
uint8_t MediaDescriptorType;
|
uint8_t MediaDescriptorType;
|
||||||
uint16_t SectorsPerFat;
|
uint16_t SectorsPerFat;
|
||||||
uint16_t SectorsPerTrack;
|
uint16_t SectorsPerTrack;
|
||||||
uint16_t Heads;
|
uint16_t Heads;
|
||||||
uint32_t HiddenSectors;
|
uint32_t HiddenSectors;
|
||||||
uint32_t LargeSectorCount;
|
uint32_t LargeSectorCount;
|
||||||
|
|
||||||
//Extended Boot Record
|
// extended boot record
|
||||||
uint8_t DriveNumber;
|
uint8_t DriveNumber;
|
||||||
uint8_t _Reserved;
|
uint8_t _Reserved;
|
||||||
uint8_t Signature;
|
uint8_t Signature;
|
||||||
uint32_t VolumeId; //Serial Can be whatever
|
uint32_t VolumeId; // serial number, value doesn't matter
|
||||||
uint8_t VolumeLabel[11]; //11 Bytes MUST Be padded with spaces!
|
uint8_t VolumeLabel[11]; // 11 bytes, padded with spaces
|
||||||
uint8_t SystemId[8]; //8 Bytes padded with spaces (use MSWIN4.1 for best compatibility!)
|
uint8_t SystemId[8];
|
||||||
|
|
||||||
|
// ... we don't care about code ...
|
||||||
|
|
||||||
} __attribute__((packed)) FAT_BootSector;
|
} __attribute__((packed)) FAT_BootSector;
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
FAT_File Public;
|
|
||||||
bool Opened;
|
|
||||||
uint32_t FirstCluster;
|
|
||||||
uint32_t CurrentCluster;
|
|
||||||
uint32_t CurrentSectorInCluster;
|
|
||||||
uint8_t Buffer[SECTOR_SIZE];
|
|
||||||
|
|
||||||
} __attribute__((packed)) FAT_FileData;
|
typedef struct
|
||||||
|
{
|
||||||
|
uint8_t Buffer[SECTOR_SIZE];
|
||||||
|
FAT_File Public;
|
||||||
|
bool Opened;
|
||||||
|
uint32_t FirstCluster;
|
||||||
|
uint32_t CurrentCluster;
|
||||||
|
uint32_t CurrentSectorInCluster;
|
||||||
|
|
||||||
|
} FAT_FileData;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct
|
||||||
union {
|
{
|
||||||
FAT_BootSector BootSector;
|
union
|
||||||
uint8_t BootSectorBytes[SECTOR_SIZE];
|
{
|
||||||
} BS;
|
FAT_BootSector BootSector;
|
||||||
|
uint8_t BootSectorBytes[SECTOR_SIZE];
|
||||||
|
} BS;
|
||||||
|
|
||||||
FAT_FileData RootDirectory;
|
FAT_FileData RootDirectory;
|
||||||
|
|
||||||
FAT_FileData OpenedFiles[MAX_FILE_HANDLES];
|
FAT_FileData OpenedFiles[MAX_FILE_HANDLES];
|
||||||
|
|
||||||
} FAT_Data;
|
} FAT_Data;
|
||||||
|
|
||||||
@ -131,7 +136,7 @@ bool FAT_Initialize(DISK* disk) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint32_t FAT_ClusterToLba(uint32_t cluster) {
|
uint32_t FAT_ClusterToLba(uint32_t cluster) {
|
||||||
return g_DataSectionLba + (cluster -2) * g_Data->BS.BootSector.SectorsPerCluster;
|
return g_DataSectionLba + (cluster - 2) * g_Data->BS.BootSector.SectorsPerCluster;
|
||||||
}
|
}
|
||||||
|
|
||||||
FAT_File* FAT_OpenEntry(DISK* disk, FAT_DirectoryEntry* entry) {
|
FAT_File* FAT_OpenEntry(DISK* disk, FAT_DirectoryEntry* entry) {
|
||||||
@ -158,7 +163,10 @@ FAT_File* FAT_OpenEntry(DISK* disk, FAT_DirectoryEntry* entry) {
|
|||||||
fd->CurrentSectorInCluster = 0;
|
fd->CurrentSectorInCluster = 0;
|
||||||
|
|
||||||
if (!DISK_ReadSectors(disk, FAT_ClusterToLba(fd->CurrentCluster), 1, fd->Buffer)) {
|
if (!DISK_ReadSectors(disk, FAT_ClusterToLba(fd->CurrentCluster), 1, fd->Buffer)) {
|
||||||
printf("FAT: Read Error!\r\n");
|
printf("FAT: Failed to Open Entry, Read Error!\nCluster Is: %u\n", fd->CurrentCluster);
|
||||||
|
for (int i = 0; i < 11; i++)
|
||||||
|
printf("%c", entry->Name[i]);
|
||||||
|
printf("\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -184,7 +192,7 @@ uint32_t FAT_Read(DISK* disk, FAT_File* file, uint32_t byteCount, void* dataOut)
|
|||||||
uint8_t* u8DataOut = (uint8_t*)dataOut;
|
uint8_t* u8DataOut = (uint8_t*)dataOut;
|
||||||
|
|
||||||
// don't read past EOF
|
// don't read past EOF
|
||||||
if (!fd->Public.IsDirectory)
|
if (!fd->Public.IsDirectory || (fd->Public.IsDirectory && fd->Public.Size != 0))
|
||||||
byteCount = min(byteCount, fd->Public.Size - fd->Public.Position);
|
byteCount = min(byteCount, fd->Public.Size - fd->Public.Position);
|
||||||
|
|
||||||
while (byteCount > 0) {
|
while (byteCount > 0) {
|
||||||
@ -211,7 +219,7 @@ uint32_t FAT_Read(DISK* disk, FAT_File* file, uint32_t byteCount, void* dataOut)
|
|||||||
if (++fd->CurrentSectorInCluster >= g_Data->BS.BootSector.SectorsPerCluster) {
|
if (++fd->CurrentSectorInCluster >= g_Data->BS.BootSector.SectorsPerCluster) {
|
||||||
// calc next cluster & sect. to read
|
// calc next cluster & sect. to read
|
||||||
fd->CurrentSectorInCluster = 0;
|
fd->CurrentSectorInCluster = 0;
|
||||||
fd->CurrentCluster = FAT_NextCluster;
|
fd->CurrentCluster = FAT_NextCluster(fd->CurrentCluster);
|
||||||
}
|
}
|
||||||
if (fd->CurrentCluster >= 0x0FF8) {
|
if (fd->CurrentCluster >= 0x0FF8) {
|
||||||
// mark EOF
|
// mark EOF
|
||||||
@ -251,16 +259,23 @@ bool FAT_FindFile(DISK* disk, FAT_File* file, const char* name, FAT_DirectoryEnt
|
|||||||
|
|
||||||
// convert from name to fat name
|
// convert from name to fat name
|
||||||
memset(fatName, ' ', sizeof(fatName));
|
memset(fatName, ' ', sizeof(fatName));
|
||||||
|
fatName[11] + '\0';
|
||||||
|
|
||||||
const char* ext = strchr(name, '.');
|
const char* ext = strchr(name, '.');
|
||||||
if (ext == NULL)
|
if (ext == NULL)
|
||||||
ext = name + 11;
|
ext = name + 11;
|
||||||
for (int i = 0; i < 8 && name[i] && name + i < ext; i++)
|
for (int i = 0; i < 8 && name[i] && name + i < ext; i++)
|
||||||
fatName[i] = toupper(name[i]);
|
fatName[i] = toupper(name[i]);
|
||||||
if (ext != NULL) {
|
if (ext != name + 11) {
|
||||||
for (int i = 0; i < 3 && ext[i + 1]; i++)
|
for (int i = 0; i < 3 && ext[i + 1]; i++)
|
||||||
fatName[i + 8] = toupper(ext[i + 1]);
|
fatName[i + 8] = toupper(ext[i + 1]);
|
||||||
}
|
}
|
||||||
while (FAT_ReadEntry(disk, file, &entry)) {
|
while (FAT_ReadEntry(disk, file, &entry)) {
|
||||||
|
// for (int i = 0; i < 11; i++)
|
||||||
|
// printf("%c", fatName);
|
||||||
|
|
||||||
|
// for (int i = 0; i < 11; i++)
|
||||||
|
// printf("%c", entry.Name[i]);
|
||||||
if (memcmp(fatName, entry.Name, 11) == 0) {
|
if (memcmp(fatName, entry.Name, 11) == 0) {
|
||||||
*entryOut = entry;
|
*entryOut = entry;
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@ -7,9 +7,9 @@
|
|||||||
#include "stdio.h"
|
#include "stdio.h"
|
||||||
#include "x86.h"
|
#include "x86.h"
|
||||||
#include "disk.h"
|
#include "disk.h"
|
||||||
// #include "fat.h"
|
#include "fat.h"
|
||||||
|
|
||||||
#define LOGO " _ _____ _ __________________\n / | / / | / | / / _/_ __/ ____/\n / |/ / /| | / |/ // / / / / __/ \n / /| / ___ |/ /| // / / / / /___ \n\\/_/ |_/_/ |_/_/ |_/___/ /_/ /_____/ \n"
|
#define LOGO " _ _____ _ __________________\n / | / / | / | / / _/_ __/ ____/\n / |/ / /| | / |/ // / / / / __/ \n / /| / ___ |/ /| // / / / / /___ \n/_/ |_/_/ |_/_/ |_/___/ /_/ /_____/ \n"
|
||||||
#define VERSION "v0.0.1"
|
#define VERSION "v0.0.1"
|
||||||
|
|
||||||
void* g_data = (void*)0x20000;
|
void* g_data = (void*)0x20000;
|
||||||
@ -25,7 +25,7 @@ void* g_data = (void*)0x20000;
|
|||||||
// Clear screen and Print Startup logo
|
// Clear screen and Print Startup logo
|
||||||
clrscr();
|
clrscr();
|
||||||
printf("%s", LOGO);
|
printf("%s", LOGO);
|
||||||
printf(" %s\n--------------------------------------\n", VERSION);
|
printf("The Nano OS %s\n-------------------------------------\n", VERSION);
|
||||||
|
|
||||||
// Test Real Mode
|
// Test Real Mode
|
||||||
printf("Testing Real Mode...");
|
printf("Testing Real Mode...");
|
||||||
@ -44,47 +44,49 @@ void* g_data = (void*)0x20000;
|
|||||||
printf("Initializing Disk...");
|
printf("Initializing Disk...");
|
||||||
DISK disk;
|
DISK disk;
|
||||||
if (!DISK_Initialize(&disk, bootDrive)) {
|
if (!DISK_Initialize(&disk, bootDrive)) {
|
||||||
printf("Failed!\nDisk Initialization Error\n");
|
printf("Failed!\nDisk Initialization Error!\n");
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
printf("Done!\n");
|
printf("Done!\n");
|
||||||
DISK_ReadSectors(&disk, 0, 1, g_data);
|
DISK_ReadSectors(&disk, 0, 1, g_data);
|
||||||
print_buffer("> Boot Sector Data: ", g_data, 512);
|
// print_buffer("> Boot Sector Data: ", g_data, 512);
|
||||||
|
|
||||||
// printf("Initializing FAT Driver...");
|
printf("Initializing FAT Driver...");
|
||||||
// if (!FAT_Initialize(&disk)) {
|
if (!FAT_Initialize(&disk)) {
|
||||||
// printf("Failed!\nDisk Initialization Error\n");
|
printf("Failed!\nDisk Initialization Error!\n");
|
||||||
// goto end;
|
goto end;
|
||||||
// }
|
}
|
||||||
// printf("Done!\n");
|
printf("Done!\n");
|
||||||
// // printf("Listing Root DIR...\n");
|
// printf("Listing Root DIR...\n");
|
||||||
// // // browse files in root
|
// // browse files in root
|
||||||
// FAT_File far* fd = FAT_Open(&disk, "/");
|
FAT_File* fd = FAT_Open(&disk, "/");
|
||||||
// FAT_DirectoryEntry entry;
|
FAT_DirectoryEntry entry;
|
||||||
// int i = 0;
|
int i = 0;
|
||||||
// // while (FAT_ReadEntry(&disk, fd, &entry) && i++ < 5) {
|
// while (FAT_ReadEntry(&disk, fd, &entry) && i++ < 5) {
|
||||||
// // printf(" ");
|
// printf(" ");
|
||||||
// // for (int i = 0; i < 11; i++)
|
// for (int i = 0; i < 11; i++)
|
||||||
// // putc(entry.Name[i]);
|
// putc(entry.Name[i]);
|
||||||
// // printf("\n");
|
// printf("\n");
|
||||||
// // }
|
// }
|
||||||
// // FAT_Close(fd);
|
// FAT_Close(fd);
|
||||||
|
|
||||||
// printf("Testing FAT Driver...");
|
printf("Testing FAT Driver...");
|
||||||
// // read test.txt
|
// read test.txt
|
||||||
// char buffer[100];
|
char buffer[100];
|
||||||
// uint32_t read;
|
uint32_t read;
|
||||||
// fd = FAT_Open(&disk, "misc/test.txt");
|
fd = FAT_Open(&disk, "misc/test.txt");
|
||||||
// while ((read = FAT_Read(&disk, fd, sizeof(buffer), buffer)))
|
while ((read = FAT_Read(&disk, fd, sizeof(buffer), buffer)))
|
||||||
// {
|
{
|
||||||
// for (uint32_t i = 0; i < read; i++)
|
for (uint32_t i = 0; i < read; i++)
|
||||||
// {
|
{
|
||||||
// if (buffer[i] == '\n')
|
if (buffer[i] == '\n')
|
||||||
// putc('');
|
putc('\r');
|
||||||
// putc(buffer[i]);
|
putc(buffer[i]);
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
// FAT_Close(fd);
|
FAT_Close(fd);
|
||||||
|
|
||||||
|
printf("Loading Kernel...");
|
||||||
|
|
||||||
end:
|
end:
|
||||||
for (;;);
|
for (;;);
|
||||||
|
|||||||
@ -1,14 +1,32 @@
|
|||||||
BUILD_DIR?=build/
|
TARGET_ASMFLAGS += -f elf
|
||||||
ASM?=nasm
|
TARGET_CFLAGS += -ffreestanding -nostdlib
|
||||||
|
TARGET_LIBS += -lgcc
|
||||||
|
TARGET_LINKFLAGS += -T linker.ld -nostdlib
|
||||||
|
|
||||||
.PHONY: all kernel clean
|
|
||||||
|
SOURCES_C=$(wildcard *.c)
|
||||||
|
SOURCES_ASM=$(wildcard *.asm)
|
||||||
|
OBJECTS_C=$(patsubst %.c, $(BUILD_DIR)/kernel/c/%.obj, $(SOURCES_C))
|
||||||
|
OBJECTS_ASM=$(patsubst %.asm, $(BUILD_DIR)/kernel/asm/%.obj, $(SOURCES_ASM))
|
||||||
|
|
||||||
|
.PHONY: all kernel clean always
|
||||||
|
|
||||||
all: kernel
|
all: kernel
|
||||||
|
|
||||||
kernel: $(BUILD_DIR)/kernel.bin
|
kernel: $(BUILD_DIR)/kernel.bin
|
||||||
|
|
||||||
$(BUILD_DIR)/kernel.bin:
|
$(BUILD_DIR)/kernel.bin: $(OBJECTS_ASM) $(OBJECTS_C)
|
||||||
$(ASM) main.asm -f bin -o $(BUILD_DIR)/kernel.bin
|
$(TARGET_LD) $(TARGET_LINKFLAGS) -Wl,-Map=$(BUILD_DIR)/kernel.map -o $@ $^ $(TARGET_LIBS)
|
||||||
|
|
||||||
|
$(BUILD_DIR)/kernel/c/%.obj: %.c always
|
||||||
|
$(TARGET_CC) $(TARGET_CFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
|
$(BUILD_DIR)/kernel/asm/%.obj: %.asm always
|
||||||
|
$(TARGET_ASM) $(TARGET_ASMFLAGS) -o $@ $<
|
||||||
|
|
||||||
|
always:
|
||||||
|
mkdir -p $(BUILD_DIR)/kernel/c
|
||||||
|
mkdir -p $(BUILD_DIR)/kernel/asm
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f $(BUILD_DIR)/kernel.bin
|
rm -f $(BUILD_DIR)/kernel.bin
|
||||||
15
src/kernel/linker.ld
Normal file
15
src/kernel/linker.ld
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
ENTRY(entry)
|
||||||
|
OUTPUT_FORMAT("binary")
|
||||||
|
phys = 0x000100000;
|
||||||
|
|
||||||
|
SECTIONS {
|
||||||
|
. = phys;
|
||||||
|
|
||||||
|
.entry : { __entry_start = .; *(.entry) }
|
||||||
|
.text : { __text_start = .; *(.text) }
|
||||||
|
.data : { __data_start = .; *(.data) }
|
||||||
|
.rodata : { __rodata_start = .; *(.rodata) }
|
||||||
|
.bss : { __bss_start = .; *(.bss) }
|
||||||
|
|
||||||
|
__end = .;
|
||||||
|
}
|
||||||
@ -1,50 +0,0 @@
|
|||||||
;/////////////////////;
|
|
||||||
;Nanite OS ;
|
|
||||||
;COPYRIGHT (C) 2024 ;
|
|
||||||
;Tyler McGurrin ;
|
|
||||||
;/////////////////////;
|
|
||||||
org 0x0
|
|
||||||
bits 16
|
|
||||||
|
|
||||||
|
|
||||||
%define ENDL 0x0D, 0x0A
|
|
||||||
|
|
||||||
|
|
||||||
start:
|
|
||||||
; print hello world message
|
|
||||||
mov si, msg_hello
|
|
||||||
call puts
|
|
||||||
|
|
||||||
.halt:
|
|
||||||
cli
|
|
||||||
hlt
|
|
||||||
|
|
||||||
;
|
|
||||||
; Prints a string to the screen
|
|
||||||
; Params:
|
|
||||||
; - ds:si points to string
|
|
||||||
;
|
|
||||||
puts:
|
|
||||||
; save registers we will modify
|
|
||||||
push si
|
|
||||||
push ax
|
|
||||||
push bx
|
|
||||||
|
|
||||||
.loop:
|
|
||||||
lodsb ; loads next character in al
|
|
||||||
or al, al ; verify if next character is null?
|
|
||||||
jz .done
|
|
||||||
|
|
||||||
mov ah, 0x0E ; call bios interrupt
|
|
||||||
mov bh, 0 ; set page number to 0
|
|
||||||
int 0x10
|
|
||||||
|
|
||||||
jmp .loop
|
|
||||||
|
|
||||||
.done:
|
|
||||||
pop bx
|
|
||||||
pop ax
|
|
||||||
pop si
|
|
||||||
ret
|
|
||||||
|
|
||||||
msg_hello: db 'Loading Kernel...', ENDL, 0
|
|
||||||
31
src/kernel/main.c
Normal file
31
src/kernel/main.c
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
/*----------------*\
|
||||||
|
|Nanite OS |
|
||||||
|
|Copyright (C) 2024|
|
||||||
|
|Tyler McGurrin |
|
||||||
|
\*----------------*/
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "stdio.h"
|
||||||
|
#include "x86.h"
|
||||||
|
#include "disk.h"
|
||||||
|
#include "fat.h"
|
||||||
|
|
||||||
|
#define LOGO " _ _____ _ __________________\n / | / / | / | / / _/_ __/ ____/\n / |/ / /| | / |/ // / / / / __/ \n / /| / ___ |/ /| // / / / / /___ \n/_/ |_/_/ |_/_/ |_/___/ /_/ /_____/ \n"
|
||||||
|
#define VERSION "v0.0.1"
|
||||||
|
|
||||||
|
void* g_data = (void*)0x20000;
|
||||||
|
|
||||||
|
void puts_realmode(const char* str) {
|
||||||
|
while (*str) {
|
||||||
|
x86_realmode_putc(*str);
|
||||||
|
++str;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void __attribute__((cdecl)) start(uint16_t bootDrive) {
|
||||||
|
printf("Done!\n"); // done msg for load kernel (LEAVE HERE)
|
||||||
|
|
||||||
|
end:
|
||||||
|
for (;;);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
318
src/kernel/stdio.c
Normal file
318
src/kernel/stdio.c
Normal file
@ -0,0 +1,318 @@
|
|||||||
|
/*----------------*\
|
||||||
|
|Nanite OS |
|
||||||
|
|Copyright (C) 2024|
|
||||||
|
|Tyler McGurrin |
|
||||||
|
\*----------------*/
|
||||||
|
#include "stdio.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)
|
||||||
|
{
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
while(*str)
|
||||||
|
{
|
||||||
|
putc(*str);
|
||||||
|
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
|
||||||
|
#define PRINTF_STATE_LENGTH_LONG 3
|
||||||
|
#define PRINTF_STATE_SPEC 4
|
||||||
|
|
||||||
|
#define PRINTF_LENGTH_DEFAULT 0
|
||||||
|
#define PRINTF_LENGTH_SHORT_SHORT 1
|
||||||
|
#define PRINTF_LENGTH_SHORT 2
|
||||||
|
#define PRINTF_LENGTH_LONG 3
|
||||||
|
#define PRINTF_LENGTH_LONG_LONG 4
|
||||||
|
|
||||||
|
void printf(const char* fmt, ...) {
|
||||||
|
va_list args;
|
||||||
|
va_start(args, fmt);
|
||||||
|
|
||||||
|
int state= PRINTF_STATE_NORMAL;
|
||||||
|
int length = PRINTF_LENGTH_DEFAULT;
|
||||||
|
int radix = 10;
|
||||||
|
bool sign = false;
|
||||||
|
bool number = false;
|
||||||
|
|
||||||
|
while (*fmt)
|
||||||
|
{
|
||||||
|
switch (state)
|
||||||
|
{
|
||||||
|
case PRINTF_STATE_NORMAL:
|
||||||
|
switch (*fmt)
|
||||||
|
{
|
||||||
|
case '%': state = PRINTF_STATE_LENGTH;
|
||||||
|
break;
|
||||||
|
default: putc(*fmt);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PRINTF_STATE_LENGTH:
|
||||||
|
switch (*fmt)
|
||||||
|
{
|
||||||
|
case 'h': length = PRINTF_LENGTH_SHORT;
|
||||||
|
state = PRINTF_STATE_LENGTH_SHORT;
|
||||||
|
break;
|
||||||
|
case 'l': length = PRINTF_LENGTH_LONG;
|
||||||
|
state = PRINTF_STATE_LENGTH_LONG;
|
||||||
|
break;
|
||||||
|
default: goto PRINTF_STATE_SPEC_;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PRINTF_STATE_LENGTH_SHORT:
|
||||||
|
if (*fmt == 'h')
|
||||||
|
{
|
||||||
|
length = PRINTF_LENGTH_SHORT_SHORT;
|
||||||
|
state = PRINTF_STATE_SPEC;
|
||||||
|
}
|
||||||
|
else goto PRINTF_STATE_SPEC_;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PRINTF_STATE_LENGTH_LONG:
|
||||||
|
if (*fmt == 'h')
|
||||||
|
{
|
||||||
|
length = PRINTF_LENGTH_LONG_LONG;
|
||||||
|
state = PRINTF_STATE_SPEC;
|
||||||
|
}
|
||||||
|
else goto PRINTF_STATE_SPEC_;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PRINTF_STATE_SPEC:
|
||||||
|
PRINTF_STATE_SPEC_:
|
||||||
|
switch (*fmt)
|
||||||
|
{
|
||||||
|
case 'c': putc((char)va_arg(args, int));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 's': puts(va_arg(args, const char*));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '%': putc('%');
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'd':
|
||||||
|
case 'i': radix = 10;
|
||||||
|
sign = true;
|
||||||
|
number = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'u': radix = 10; sign = false; number = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'X':
|
||||||
|
case 'x':
|
||||||
|
case 'p': radix = 16; sign = false; number = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
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;
|
||||||
|
length = PRINTF_LENGTH_DEFAULT;
|
||||||
|
radix = 10;
|
||||||
|
sign = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt++;
|
||||||
|
}
|
||||||
|
|
||||||
|
va_end(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void print_buffer(const char* msg, const void* buffer, uint32_t count)
|
||||||
|
{
|
||||||
|
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");
|
||||||
|
}
|
||||||
13
src/kernel/stdio.h
Normal file
13
src/kernel/stdio.h
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
/*----------------*\
|
||||||
|
|Nanite OS |
|
||||||
|
|Copyright (C) 2024|
|
||||||
|
|Tyler McGurrin |
|
||||||
|
\*----------------*/
|
||||||
|
#pragma once
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
void clrscr();
|
||||||
|
void putc(char c);
|
||||||
|
void puts(const char* str);
|
||||||
|
void printf(const char* fmt, ...);
|
||||||
|
void print_buffer(const char* msg, const void* buffer, uint32_t count);
|
||||||
Loading…
x
Reference in New Issue
Block a user