diff --git a/Makefile b/Makefile index 4b82d98..a467caf 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,8 @@ $(BUILD_DIR)/main_floppy.img: bootloader kernel 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 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" mcopy -i $(BUILD_DIR)/main_floppy.img test.txt "::misc/test.txt" diff --git a/src/bootloader/stage2/disk.c b/src/bootloader/stage2/disk.c index d81b78a..50c94b6 100644 --- a/src/bootloader/stage2/disk.c +++ b/src/bootloader/stage2/disk.c @@ -15,8 +15,8 @@ bool DISK_Initialize(DISK* disk, uint8_t driveNumber) { return false; disk->id = driveNumber; - disk->cylinders = cylinders + 1; - disk->heads = heads + 1; + disk->cylinders = cylinders; + disk->heads = heads; disk->sectors = sectors; 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) *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) { @@ -38,9 +40,11 @@ bool DISK_ReadSectors(DISK* disk, uint32_t lba, uint8_t sectors, void* dataOut) 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)) return true; + x86_Disk_Reset(disk->id); } diff --git a/src/bootloader/stage2/fat.c b/src/bootloader/stage2/fat.c index 130b8c1..300c8e2 100644 --- a/src/bootloader/stage2/fat.c +++ b/src/bootloader/stage2/fat.c @@ -17,53 +17,58 @@ #define MAX_FILE_HANDLES 10 #define ROOT_DIRECTORY_HANDLE -1 -typedef struct +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!) - + 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 number, value doesn't matter + uint8_t VolumeLabel[11]; // 11 bytes, padded with spaces + uint8_t SystemId[8]; + + // ... we don't care about code ... + } __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 { - union { - FAT_BootSector BootSector; - uint8_t BootSectorBytes[SECTOR_SIZE]; - } BS; +typedef struct +{ + union + { + 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; @@ -131,7 +136,7 @@ bool FAT_Initialize(DISK* disk) { } 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) { @@ -158,7 +163,10 @@ FAT_File* FAT_OpenEntry(DISK* disk, FAT_DirectoryEntry* entry) { fd->CurrentSectorInCluster = 0; 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; } @@ -184,7 +192,7 @@ uint32_t FAT_Read(DISK* disk, FAT_File* file, uint32_t byteCount, void* dataOut) uint8_t* u8DataOut = (uint8_t*)dataOut; // 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); 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) { // calc next cluster & sect. to read fd->CurrentSectorInCluster = 0; - fd->CurrentCluster = FAT_NextCluster; + fd->CurrentCluster = FAT_NextCluster(fd->CurrentCluster); } if (fd->CurrentCluster >= 0x0FF8) { // 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 memset(fatName, ' ', sizeof(fatName)); + fatName[11] + '\0'; + 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) { + if (ext != name + 11) { for (int i = 0; i < 3 && ext[i + 1]; i++) fatName[i + 8] = toupper(ext[i + 1]); } 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) { *entryOut = entry; return true; diff --git a/src/bootloader/stage2/main.c b/src/bootloader/stage2/main.c index d784dbd..0b13089 100644 --- a/src/bootloader/stage2/main.c +++ b/src/bootloader/stage2/main.c @@ -7,9 +7,9 @@ #include "stdio.h" #include "x86.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" void* g_data = (void*)0x20000; @@ -25,7 +25,7 @@ void* g_data = (void*)0x20000; // Clear screen and Print Startup logo clrscr(); printf("%s", LOGO); - printf(" %s\n--------------------------------------\n", VERSION); + printf("The Nano OS %s\n-------------------------------------\n", VERSION); // Test Real Mode printf("Testing Real Mode..."); @@ -44,47 +44,49 @@ void* g_data = (void*)0x20000; printf("Initializing Disk..."); DISK disk; if (!DISK_Initialize(&disk, bootDrive)) { - printf("Failed!\nDisk Initialization Error\n"); + printf("Failed!\nDisk Initialization Error!\n"); goto end; } printf("Done!\n"); 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..."); -// 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("Initializing FAT Driver..."); + 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* 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(''); -// 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('\r'); + putc(buffer[i]); + } + } + FAT_Close(fd); + + printf("Loading Kernel..."); end: for (;;); diff --git a/src/kernel/Makefile b/src/kernel/Makefile index f47f9fd..0f31d9b 100644 --- a/src/kernel/Makefile +++ b/src/kernel/Makefile @@ -1,14 +1,32 @@ -BUILD_DIR?=build/ -ASM?=nasm +TARGET_ASMFLAGS += -f elf +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 kernel: $(BUILD_DIR)/kernel.bin -$(BUILD_DIR)/kernel.bin: - $(ASM) main.asm -f bin -o $(BUILD_DIR)/kernel.bin +$(BUILD_DIR)/kernel.bin: $(OBJECTS_ASM) $(OBJECTS_C) + $(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: - rm -f $(BUILD_DIR)/kernel.bin + rm -f $(BUILD_DIR)/kernel.bin \ No newline at end of file diff --git a/src/kernel/linker.ld b/src/kernel/linker.ld new file mode 100644 index 0000000..e827302 --- /dev/null +++ b/src/kernel/linker.ld @@ -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 = .; +} \ No newline at end of file diff --git a/src/kernel/main.asm b/src/kernel/main.asm deleted file mode 100644 index eaf316f..0000000 --- a/src/kernel/main.asm +++ /dev/null @@ -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 diff --git a/src/kernel/main.c b/src/kernel/main.c new file mode 100644 index 0000000..aa77c14 --- /dev/null +++ b/src/kernel/main.c @@ -0,0 +1,31 @@ +/*----------------*\ +|Nanite OS | +|Copyright (C) 2024| +|Tyler McGurrin | +\*----------------*/ +#include +#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 (;;); +} + + diff --git a/src/kernel/stdio.c b/src/kernel/stdio.c new file mode 100644 index 0000000..03ace46 --- /dev/null +++ b/src/kernel/stdio.c @@ -0,0 +1,318 @@ +/*----------------*\ +|Nanite OS | +|Copyright (C) 2024| +|Tyler McGurrin | +\*----------------*/ +#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) +{ + 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"); +} diff --git a/src/kernel/stdio.h b/src/kernel/stdio.h new file mode 100644 index 0000000..10dcdb8 --- /dev/null +++ b/src/kernel/stdio.h @@ -0,0 +1,13 @@ +/*----------------*\ +|Nanite OS | +|Copyright (C) 2024| +|Tyler McGurrin | +\*----------------*/ +#pragma once +#include + +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); diff --git a/test.txt b/test.txt index 76f5a5a..e1786c8 100644 --- a/test.txt +++ b/test.txt @@ -1 +1 @@ -Done! +Ok!