diff --git a/build.sh b/build.sh index 0e17b5b..7771e67 100755 --- a/build.sh +++ b/build.sh @@ -11,7 +11,7 @@ case $yn in echo Removing Old Build Files...; echo ---------------------------; - sudo make clean; + make clean; echo -----; echo Done!; echo -----; @@ -26,7 +26,7 @@ echo ------------ echo COMPILING OS echo ------------ -sudo make -s +make -s echo --------- echo Finished! @@ -38,7 +38,7 @@ case $yn in echo ------------- echo STARTING QEMU echo ------------- - sudo qemu-system-i386 -fda build/main_floppy.img + qemu-system-i386 -fda build/main_floppy.img echo -------- echo Finshed! echo -------- diff --git a/src/bootloader/stage2/disk.c b/src/bootloader/stage2/disk.c new file mode 100644 index 0000000..d81b78a --- /dev/null +++ b/src/bootloader/stage2/disk.c @@ -0,0 +1,48 @@ +/*----------------*\ +|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* dataOut) { + uint16_t cylinder, sector, head; + + DISK_LBA2CHS(disk, lba, &cylinder, §or, &head); + + for (int i = 0; i < 3; i++) { + if (x86_Disk_Read(disk->id, cylinder, sector, head, sectors, dataOut)) + return true; + x86_Disk_Reset(disk->id); + } + + return false; +} diff --git a/src/bootloader/stage2/disk.h b/src/bootloader/stage2/disk.h new file mode 100644 index 0000000..876cf39 --- /dev/null +++ b/src/bootloader/stage2/disk.h @@ -0,0 +1,20 @@ +/*----------------*\ +|Nanite OS | +|Copyright (C) 2024| +|Tyler McGurrin | +\*----------------*/ +#pragma once + +#include "stdint.h" +#include + +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* lowerDataOut); + diff --git a/src/bootloader/stage2/main.c b/src/bootloader/stage2/main.c index 5924576..d784dbd 100644 --- a/src/bootloader/stage2/main.c +++ b/src/bootloader/stage2/main.c @@ -5,29 +5,53 @@ \*----------------*/ #include #include "stdio.h" -// #include "disk.h" +#include "x86.h" +#include "disk.h" // #include "fat.h" -// void far* g_data = (void far*)0x00500200; #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) { + // Clear screen and Print Startup logo clrscr(); printf("%s", LOGO); printf(" %s\n--------------------------------------\n", VERSION); - for(;;); - + // Test Real Mode + printf("Testing Real Mode..."); + puts_realmode(" "); + printf("Ok!\n"); + + // get drive params (Test for Disk driver) + printf("Getting Drive Params..."); + uint8_t driveType; + uint16_t cyls, sects, heads; + x86_Disk_GetDriveParams(bootDrive, &driveType, &cyls, §s, &heads); + printf("Done!\n"); + printf("> Drive Type: %u\n> Cylinders: %u\n> Sectors: %u\n> Heads: %u\n", driveType, cyls, sects, heads); + + // init disk + printf("Initializing Disk..."); + DISK disk; + if (!DISK_Initialize(&disk, bootDrive)) { + 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); + // printf("Initializing FAT Driver..."); -// DISK disk; -// if (!DISK_Initialize(&disk, bootDrive)) { -// printf("Failed!\nDisk Initialization Error\n"); -// goto end; -// } - -// DISK_ReadSectors(&disk, 19, 1, g_data); - // if (!FAT_Initialize(&disk)) { // printf("Failed!\nDisk Initialization Error\n"); // goto end; @@ -62,8 +86,8 @@ // } // FAT_Close(fd); -// end: -// for (;;); +end: + for (;;); } diff --git a/src/bootloader/stage2/x86.asm b/src/bootloader/stage2/x86.asm index 4de2f7e..f76cfa3 100644 --- a/src/bootloader/stage2/x86.asm +++ b/src/bootloader/stage2/x86.asm @@ -1,20 +1,24 @@ %macro x86_EnterRealMode 0 [bits 32] - jmp work 18h:.pmode16 + jmp word 18h:.pmode16 ; 1 - jump to 16-bit protected mode segment .pmode16: [bits 16] + ; 2 - disable protected mode bit in cr0 mov eax, cr0 and al, ~1 mov cr0, eax + ; 3 - jump to real mode jmp word 00h:.rmode .rmode: + ; 4 - setup segments mov ax, 0 mov ds, ax mov ss, ax + ; 5 - enable interrupts sti %endmacro @@ -41,6 +45,23 @@ %endmacro +; Convert linear ADDR to seg:offset addr +; Args: +; 1 - linear addr +; 2 - (OUT) target seg (ex. ES) +; 3 - target 32 bit reg to use (ex. EAX) +; 4 - target lower 16 bit half of 3 (ex. AX) + +%macro LinearToSegOffset 4 + + mov %3, %1 ;linear addr to EAX + shr %3, 4 + mov %2, %4 + mov %3, %1 ;linear addr to EAX + and %3, 0xF + +%endmacro + global x86_outb x86_outb: @@ -58,6 +79,183 @@ x86_inb: in al, dx 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: + [bits 32] + + ; make new call frame + push ebp ; save old call frame + mov ebp, esp ; initialize new call frame + + x86_EnterRealMode + + [bits 16] + + ; save regs + push es + push bx + push esi + push di + + ; call int13h + mov dl, [bp + 8] ; dl - disk drive + mov ah, 08h + mov di, 0 ; es:di - 0000:0000 + mov es, di + stc + int 13h + + ; out params + mov eax, 1 + sbb eax, 0 + + ; drive type from bl + LinearToSegOffset [bp + 12], es, esi, si + mov [es:si], bl + + ; cylinders + mov bl, ch ; cylinders - lower bits in ch + mov bh, cl ; cylinders - upper bits in cl (6-7) + shr bh, 6 + inc bx + + LinearToSegOffset [bp + 16], es, esi, si + mov [es:si], bx + + ; sectors + xor ch, ch ; sectors - lower 5 bits in cl + and cl, 3Fh + + LinearToSegOffset [bp + 20], es, esi, si + mov [es:si], cx + + ; heads + mov cl, dh ; heads - dh + inc cx + + LinearToSegOffset [bp + 24], es, esi, si + mov [es:si], cx + + ; restore regs + pop di + pop esi + pop bx + pop es + + ; return + + push eax + + x86_EnterProtectedMode + + [bits 32] + + pop eax + + ; restore old call frame + mov esp, ebp + pop ebp + ret + +global x86_Disk_Reset +x86_Disk_Reset: + + ; make new call frame + push ebp ; save old call frame + mov ebp, esp ; initialize new call frame + + x86_EnterRealMode + + mov ah, 0 + mov dl, [bp + 8] ; dl - drive + stc + int 13h + + mov eax, 1 + sbb eax, 0 ; 1 on success, 0 on fail + + push eax + + x86_EnterProtectedMode + + pop eax + + ; restore old call frame + mov esp, ebp + pop ebp + 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 ebp ; save old call frame + mov ebp, esp ; initialize new call frame + + x86_EnterRealMode + + ; save modified regs + push ebx + push es + + ; setup args + mov dl, [bp + 8] ; dl - drive + + mov ch, [bp + 12] ; ch - cylinder (lower 8 bits) + mov cl, [bp + 13] ; cl - cylinder to bits 6-7 + shl cl, 6 + + mov al, [bp + 16] ; cl - sector to bits 0-5 + and al, 3Fh + or cl, al + + mov dh, [bp + 20] ; dh - head + + mov al, [bp + 24] ; al - count + + LinearToSegOffset [bp + 28], es, ebx, bx + + ; call int13h + mov ah, 02h + stc + int 13h + + ; set return value + mov eax, 1 + sbb eax, 0 ; 1 on success, 0 on fail + + ; restore regs + pop es + pop ebx + + push eax + + x86_EnterProtectedMode + + pop eax + + ; restore old call frame + mov esp, ebp + pop ebp + ret + + +; Testing Function global x86_realmode_putc x86_realmode_putc: ; setup stack frame @@ -66,7 +264,7 @@ x86_realmode_putc: x86_EnterRealMode - mov al, [sp + 8] + mov al, [bp + 8] mov ah, 0xe int 10h diff --git a/src/bootloader/stage2/x86.h b/src/bootloader/stage2/x86.h index 731669c..07c0bc6 100644 --- a/src/bootloader/stage2/x86.h +++ b/src/bootloader/stage2/x86.h @@ -1,5 +1,23 @@ #pragma once #include +#include void __attribute__((cdecl)) x86_outb(uint16_t port, uint8_t value); -uint8_t __attribute__((cdecl)) x86_inb(uint16_t port); \ No newline at end of file +uint8_t __attribute__((cdecl)) x86_inb(uint16_t port); + +void __attribute__((cdecl)) x86_realmode_putc(char c); + +bool __attribute__((cdecl)) x86_Disk_GetDriveParams(uint8_t drive, + uint8_t* driveTypeOut, + uint16_t* cylindersOut, + uint16_t* sectorsOut, + uint16_t* headsOut); + +bool __attribute__((cdecl)) x86_Disk_Reset(uint8_t drive); + +bool __attribute__((cdecl)) x86_Disk_Read(uint8_t drive, + uint16_t cylinder, + uint16_t sector, + uint16_t head, + uint8_t count, + void* lowerDataOut); \ No newline at end of file diff --git a/write.sh b/write.sh index d307b57..9e32ff6 100755 --- a/write.sh +++ b/write.sh @@ -2,7 +2,7 @@ echo ------------ echo COMPILING OS echo ------------ -sudo make +make echo --------- echo Finished!