diff --git a/host/CMakeLists.txt b/host/CMakeLists.txt index 4bac132..dde319c 100644 --- a/host/CMakeLists.txt +++ b/host/CMakeLists.txt @@ -1,8 +1,9 @@ cmake_minimum_required(VERSION 3.21) -project(os3_host C) +project(os3_host C CXX) add_subdirectory(../libfat ${CMAKE_CURRENT_BINARY_DIR}/libfat) add_subdirectory(libhost) add_subdirectory(mbrcopy) -add_subdirectory(kernelcopy) \ No newline at end of file +add_subdirectory(kernelcopy) +add_subdirectory(gdtCreator) \ No newline at end of file diff --git a/host/gdtCreator/CMakeLists.txt b/host/gdtCreator/CMakeLists.txt new file mode 100644 index 0000000..5a2d7bd --- /dev/null +++ b/host/gdtCreator/CMakeLists.txt @@ -0,0 +1 @@ +add_executable(gdtCreator gdtCreator.cpp) \ No newline at end of file diff --git a/host/gdtCreator/gdtCreator.cpp b/host/gdtCreator/gdtCreator.cpp new file mode 100644 index 0000000..074ee30 --- /dev/null +++ b/host/gdtCreator/gdtCreator.cpp @@ -0,0 +1,51 @@ +// +// Created by John Stefanelli on 13/01/23. +// + +#include + +uint64_t makeEntry(uint32_t base, uint16_t limit, bool present, unsigned char dpl, bool executable, bool exec_write) { + uint64_t value = 0x0; + //auto* target = (uint8_t*) &value; + + uint8_t access_byte = (present ? 0x80 : 0x00) + ((dpl & 0x3) << 5) + 16 + (executable ? 8 : 0) + (exec_write ? 2 : 0); + uint8_t flags = 0xC; + + value |= limit & 0xFFFF; //Low 16 bits of limit + value |= (base & 0xFFFFFF) << 16; //Low 24 bits of base + + value |= ((uint64_t) access_byte) << 40; + value |= ((uint64_t) limit & 0xF0000) << 32; + value |= ((uint64_t) flags) << 52; + value |= ((uint64_t) base & 0xFF000000) << 32; + + + /* + // Encode the limit + target[0] = limit & 0xFF; + target[1] = (limit >> 8) & 0xFF; + target[6] = (limit >> 16) & 0x0F; + + // Encode the base + target[2] = base & 0xFF; + target[3] = (base >> 8) & 0xFF; + target[4] = (base >> 16) & 0xFF; + target[7] = (base >> 24) & 0xFF; + + // Encode the access byte + target[5] = access_byte; + + // Encode the flags + target[6] |= (flags << 4); + */ + + return value; +} + +int main(int argc, char** argv) { + std::cout << std::hex << "Code: " << makeEntry(0, 0xFFFF, true, 0x0, true, true) << std::endl; + std::cout << std::hex << "Data: " << makeEntry(0, 0xFFFF, true, 0x0, false, true) << std::endl; + std::cout << std::hex << "User Code: " << makeEntry(0, 0xFFFF, true, 0x3, true, true) << std::endl; + std::cout << std::hex << "User Data: " << makeEntry(0, 0xFFFF, true, 0x3, false, true) << std::endl; + return 0; +} \ No newline at end of file diff --git a/host/kernelcopy/kernelcopy.c b/host/kernelcopy/kernelcopy.c index da46d6f..0c094ef 100644 --- a/host/kernelcopy/kernelcopy.c +++ b/host/kernelcopy/kernelcopy.c @@ -19,12 +19,27 @@ typedef struct _MBR_BuildSettings { } OS_PACK_MID MBR_BuildSettings; OS_PACK_END +OS_PACK_START +typedef struct _MBR_ReadPacket { + os_u16 sig_0; + os_u8 packet_size; //Fixed 10h + os_u8 reserved; + os_u16 blocks; + os_u16 buffer_offset; + os_u16 buffer_segment; + os_u64 lba; + os_u16 sig_1; +} OS_PACK_MID MBR_ReadPacket; +OS_PACK_END + #define MBR_SETTINGS_SIG_0 ((os_u16)0x4952) #define MBR_SETTINGS_SIG_1 ((os_u16)0x4953) +#define MBR_PACKET_SIG_0 ((os_u16) 0x4954) +#define MBR_PACKET_SIG_1 ((os_u16) 0x4955) int main(int argc, char** argv) { if (argc < 3) { - fprintf(stderr, "Not enough arguments.\n"); + fprintf(stderr, "Not enough arguments. Usage: kernelcopy \n"); return 1; } @@ -97,7 +112,7 @@ int main(int argc, char** argv) { } kernel_size += read; } while(read > 0); - printf("Kernel copy OK."); + printf("Kernel copy OK.\n"); free(buffer); fclose(kernel); @@ -109,6 +124,9 @@ int main(int argc, char** argv) { return 1; } + printf("Bytes per sector: %d\n", fat.header.base.bytes_per_sector); + printf("Kernel offset: %d, difference from bytes per sector: %d\n", kernel_offset, kernel_offset % fat.header.base.bytes_per_sector); + fflush(stdout); if (kernel_offset % fat.header.base.bytes_per_sector != 0) { fprintf(stderr, "Error: STAGE1 not aligned to sector\n"); return 1; @@ -131,10 +149,32 @@ int main(int argc, char** argv) { ptr++; } - if (found == OS_FALSE) { - fprintf(stderr, "Error: could not find BUILD_SETTINGS markers\n"); - return 1; - } + + if (found == OS_FALSE) { + fprintf(stderr, "Error: could not find BUILD_SETTINGS markers\n"); + return 1; + } + + found = OS_FALSE; + + ptr = mbr; + for (int i = 0; i < 512 - sizeof(MBR_ReadPacket); i++) { + MBR_ReadPacket * packet = (MBR_ReadPacket*)ptr; + if(packet->sig_0 == MBR_PACKET_SIG_0 && packet->sig_1 == MBR_PACKET_SIG_1) { + packet->lba = kernel_offset / fat.header.base.bytes_per_sector; + packet->blocks = (kernel_size / fat.header.base.bytes_per_sector) + ((kernel_size % fat.header.base.bytes_per_sector) == 0 ? 0 : 1); + packet->buffer_offset = 0x0000; + packet->buffer_segment = 0x0100; + found = OS_TRUE; + break; + } + ptr++; + } + + if (found == OS_FALSE) { + fprintf(stderr, "Error: could not find READ_PACKET markers\n"); + return 1; + } fseek(image, 0, SEEK_SET); fwrite(mbr, 1, 512, image); diff --git a/host/libhost/CMakeLists.txt b/host/libhost/CMakeLists.txt index 2646770..86dc20f 100644 --- a/host/libhost/CMakeLists.txt +++ b/host/libhost/CMakeLists.txt @@ -1,3 +1,3 @@ -add_library(host libhost.c include/libhost.h) +add_library(host libhost.c include/libhost.h ../gdtCreator/gdtCreator.cpp) target_link_libraries(host libfat) target_include_directories(host PUBLIC ${CMAKE_CURRENT_LIST_DIR}/include) \ No newline at end of file diff --git a/libfat/libfat.c b/libfat/libfat.c index 2e9d0ab..36f2a85 100644 --- a/libfat/libfat.c +++ b/libfat/libfat.c @@ -51,9 +51,6 @@ os_bool libfat_load_fat_cluster(LFControlBlock* fat, os_u32 target_cluster, os_b return OS_FALSE; } - os_u32 base_cluster = target_cluster - (target_cluster % fat->loaded_fat_cluster_amount); - os_u32 final_offset = fat_offset + (base_cluster * sizeof(os_u32)); - fat->handle.read(fat->loaded_fat_cluster_amount * sizeof(os_u32), (void*)fat->loaded_fat_segment, fat->handle.user_data); return OS_TRUE; } @@ -581,7 +578,6 @@ os_u32 libfat_write(LFFile* f, void* buffer, os_u32 buffer_size) { return 0; } - os_u32 start_position = f->position; os_u32 written = 0; while (buffer_size > 0) { @@ -622,7 +618,7 @@ os_u32 libfat_get_true_entry_offset(LFControlBlock* fat, LFDirectoryEntry* entry os_u32 cluster_size = fat->header.base.bytes_per_sector * fat->header.base.sectors_per_cluster; os_u32 data_offset = (fat->header.base.reserved_sectors + (fat->header.sectors_per_fat_32 * fat->header.base.number_of_fats)) * fat->header.base.bytes_per_sector; - return data_offset + (cluster_size * FAT_ENTRY_CLUSTER(entry->entry) - 2); + return data_offset + (cluster_size * (FAT_ENTRY_CLUSTER(entry->entry) - 2)); } os_bool libfat_test_mbr(LFFileHandle* mbr) { diff --git a/mbr/mbr.asm b/mbr/mbr.asm index 068665e..3432353 100644 --- a/mbr/mbr.asm +++ b/mbr/mbr.asm @@ -16,9 +16,7 @@ fat_header: ; Uses INT 13h AH=42h from: http://www.ctyme.com/intr/rb-0708.htm ; Stack Parameters (in order of PUSH): ; - BYTE: Drive number -; - WORD: Number of blocks to transfer -; - DWORD: Transfer buffer -; - DWORD: Partial LBA of first block to transfer +; - WORD: Address of packet ; - WORD: RETURN ADDRESS ; Returns: ; AX: 0 = Ok, Other = Error @@ -28,29 +26,18 @@ fat_header: ; SP + 2: Old SI ; SP + 4: Old DX ; SP + 6: return address -; SP + 8: LBA -; SP + 12: Transfer buffer -; SP + 16: Block -; SP + 18: Drive number +; SP + 8: Address of packet +; SP + 10: Drive number read_sectors_extended: PUSH DX ; save DX PUSH SI ; save SI PUSH BP ; save BP MOV BP, SP ; estabilish stack frame - MOV AX, [BP + 10] ; load first part of LBA address - MOV [packet_lba], AX ; write fist part of LBA to packet - MOV AX, [BP + 8] ; load second part of LBA to packet - MOV [packet_lba + 2], AX ; write second part of LBA to packet - MOV AX, [BP + 14] ; load first part of transfer buffer - MOV [packet_buffer], AX ; write first part of transfer buffer - MOV AX, [BP + 12] ; load second part of transfer buffer - MOV [packet_buffer + 2], AX ; write second part of transfer buffer - MOV AX, [BP + 16] ; load number of blocks - MOV [packet_blocks], AX ; write number of blocks MOV DX, 0 ; zero-out DX - MOV DL, [BP + 18] ; load drive number - MOV SI, read_sectors_packet ; load address of packet - MOV AX, 4200h ; set AH to 42h, AL to 0h + MOV DL, [BP + 10] ; load drive number + MOV SI, [BP + 8] ; load address of packet + MOV AH, 42h ; set AH to 42h + MOV AL, 0h ; set AL to 0h INT 13h ; call interrupt 13H, AH=42h JNC read_sectors_extended_exit ; exit if no error read_sectors_extended_error: ; save error if it happened @@ -60,6 +47,7 @@ read_sectors_extended_exit: ; leave function POP BP ; restore BP POP SI ; restore SI POP DX ; restore DX + RET ; return ; function PRINT: teletype to display @@ -192,7 +180,7 @@ entry: ; Set up stack and segments MOV AX, 0 ; set up stack segment MOV SS, AX ; ^^^ - MOV SP, 0x7C00 ; set up stack pointer (0x6c00-0x7BFF) + MOV SP, 0x7bFF ; set up stack pointer (0x6c00-0x7BFE) ; Sp HAS TO be set in the instruction after settings SS ; as setting SS disables interrupts for the next instruction ; Not doing this may cause an interrupt to use an old SP and new SS @@ -201,22 +189,31 @@ entry: MOV FS, AX ; ^^^ MOV GS, AX ; ^^^ - PUSH DX ; save drive number (DL) + PUSH DX ; save drive number (DL) + + ; Load kernel image + MOV BX, packet_blocks ; Load address of packet_blocks + MOV AX, [BX] ; Load value of packet_blocks + CMP AX, 0 ; See if amount of packets to read is 0 + JE endless_loop ; if no packets are to be loaded, the kernel is not present. Loop endlessly + POP AX ; load 'drive number' + PUSH AX ; pushing it twice to keep it saved, CBA to mess with SP, BP and stuff right now + PUSH AX ; push parameter 'drive number' + MOV AX, read_sectors_packet ; load 'packet address' + PUSH AX ; push parameter 'packet address' + CALL read_sectors_extended ; try to read these damned sectors + ADD SP, 4 ; clear previous call parameters - ; Load drive parameters - MOV AX, 4800h ; load AH=48h, AL=0h - MOV SI, disk_info_packet ; load address of Disk_Info_Packet - INT 13H ; INT 14h AH=48h: get drive parameters ; Print message MOV AX, msg ; load address of msg PUSH AX ; push parameter 'address of string' - MOV AX, 12 ; load size of msg + MOV AX, 14 ; load size of msg PUSH AX ; push parameter 'size of string' CALL print ; call function 'print' - SUB SP, 4 ; clear previous call parameters + ADD SP, 4 ; clear previous call parameters ; Enable A20 CALL check_a20 ; call check_a20. Result in Ax @@ -231,36 +228,45 @@ entry: MOV AX, a20_msg ; load address of 'a20_msg' PUSH AX ; push parameter 'address of string' - MOV AX, 6 ; load size of 'a20_msg' + MOV AX, 8 ; load size of 'a20_msg' PUSH AX ; push parameter 'size of string' CALL print ; print 'a20_msg' - JMP endless_loop ; loop endlessly + after_a20: + + ; load GDT + CLI ; disable interrupts + MOV AX, gdt ; load address of GDT + MOV [gdt_ptr_base], AX ; save address of GDT to gdt_ptr_base + LGDT [gdt_ptr_base] ; load GDT + + + ; print message + MOV AX, gdt_msg ; load address of 'gdt_ms' + PUSH AX ; push parameter 'address of string' + MOV AX, 8 ; load size of 'gdt_msg' + PUSH AX ; push parameter 'size of string' + CALL print ; print 'gdt_msg' + + JMP endless_loop ; loop endlessly endless_loop: JMP endless_loop ; loop endlessly section .data -info_marker dw 0x4950 -disk_info_packet: -info_size dw 0x1A -info_flags dw 0x0 -info_cyls dd 0x0 -info_heads dd 0x0 -info_sectors dd 0x0 -info_total_sec dq 0x0 -info_bps dw 0x0 -info_end dw 0x4951 +packet_sig_0 dw 0x4954 read_sectors_packet: -packet_size db 10h -packet_reserved db 0h -packet_blocks dw 0h -packet_buffer dd 0h -packet_lba dq 0h +packet_size db 10h +packet_reserved db 0h +packet_blocks dw 0h +packet_buffer_off dw 0h +packet_buffer_seg dw 0h +packet_lba dq 0h +packet_sig_1 dw 0x4955 build_settings: build_settings_magic_0 dw 0x4952 @@ -268,5 +274,17 @@ build_settings_offset dw 0x0 build_settings_size dw 0x0 build_settings_magic_1 dw 0x4953 -msg db "OS3_BOOT_OK!" -a20_msg db "NO_A20" \ No newline at end of file +msg db "OS3_KRNL_OK!", 10, 13 +a20_msg db "NO_A20", 10, 13 +gdt_msg db "GDT_OK", 10, 13 + +gdt: +null_sec dq 0x0 +kernel_code dq 0xc09a000000ffff +kernel_data dq 0xc092000000ffff +user_code dq 0xc0fa000000ffff +user_data dq 0xc0f2000000ffff + +gdt_ptr: +gdt_ptr_limit dw 40 +gdt_ptr_base dd 0 \ No newline at end of file diff --git a/rawimg/CMakeLists.txt b/rawimg/CMakeLists.txt index 28e362e..4944051 100644 --- a/rawimg/CMakeLists.txt +++ b/rawimg/CMakeLists.txt @@ -7,10 +7,16 @@ set(IMAGE_GEN_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/mkimg_linux.sh) endif (CMAKE_HOST_APPLE) cmake_path(SET MBR_BIN_PATH NORMALIZE "${CMAKE_CURRENT_BINARY_DIR}/../mbr/mbr.bin") -add_custom_command(OUTPUT ${MBR_BIN_PATH} COMMAND ${OS3_OBJCOPY_EXE} -O binary -g -S -R .eh_frame $ ${MBR_BIN_PATH} COMMAND ${OS3_OBJCOPY_EXE} --only-keep-debug $ ${MBR_BIN_PATH}.sym COMMAND echo "Building .bin file" DEPENDS mbr BYPRODUCTS ${MBR_BIN_PATH}.sym) +cmake_path(SET ST1_BIN_PATH NORMALIZE "${CMAKE_CURRENT_BINARY_DIR}/../stage1/stage1.bin") + +add_custom_command(OUTPUT ${MBR_BIN_PATH} COMMAND ${OS3_OBJCOPY_EXE} -O binary -g -S -R .eh_frame $ ${MBR_BIN_PATH} COMMAND ${OS3_OBJCOPY_EXE} --only-keep-debug $ ${MBR_BIN_PATH}.sym DEPENDS mbr BYPRODUCTS ${MBR_BIN_PATH}.sym) cmake_path(SET MBR_IMAGE_TARGET "${CMAKE_CURRENT_BINARY_DIR}/mbr.img") +cmake_path(SET KERNEL_IMAGE_TARGET "${CMAKE_CURRENT_BINARY_DIR}/kernel.img") add_custom_command(OUTPUT ${IMAGE_TARGET} COMMAND sh ${IMAGE_GEN_SCRIPT} ${IMAGE_TARGET}) add_custom_command(OUTPUT ${MBR_IMAGE_TARGET} COMMAND sh ${CMAKE_CURRENT_SOURCE_DIR}/mkmbrimg.sh ${IMAGE_TARGET} ${MBR_BIN_PATH} ${MBR_IMAGE_TARGET} DEPENDS ${IMAGE_TARGET} ${MBR_BIN_PATH}) -add_custom_target(image DEPENDS ${MBR_IMAGE_TARGET}) \ No newline at end of file + +add_custom_command(OUTPUT ${ST1_BIN_PATH} COMMAND ${OS3_OBJCOPY_EXE} -O binary -g -S -R .eh_frame $ ${ST1_BIN_PATH} COMMAND ${OS3_OBJCOPY_EXE} --only-keep-debug $ ${ST1_BIN_PATH}.sym DEPENDS stage1 BYPRODUCTS ${ST1_BIN_PATH}.sym) +add_custom_command(OUTPUT ${KERNEL_IMAGE_TARGET} COMMAND sh ${CMAKE_CURRENT_SOURCE_DIR}/mkkernelimg.sh ${MBR_IMAGE_TARGET} ${ST1_BIN_PATH} ${KERNEL_IMAGE_TARGET} DEPENDS ${MBR_IMAGE_TARGET} ${ST1_BIN_PATH}) +add_custom_target(image DEPENDS ${KERNEL_IMAGE_TARGET}) \ No newline at end of file diff --git a/rawimg/mkkernelimg.sh b/rawimg/mkkernelimg.sh new file mode 100644 index 0000000..fea1e20 --- /dev/null +++ b/rawimg/mkkernelimg.sh @@ -0,0 +1,5 @@ +#!/bin/sh + +BASEDIR=$(dirname "$0") +cp "$1" "$3" +"${BASEDIR}/../build/host/kernelcopy/kernelcopy" "$3" "$2" \ No newline at end of file diff --git a/stage1/CMakeLists.txt b/stage1/CMakeLists.txt index 2d1a682..2328fd7 100644 --- a/stage1/CMakeLists.txt +++ b/stage1/CMakeLists.txt @@ -1,2 +1,5 @@ add_executable(stage1 stage1.c) +target_compile_options(stage1 PUBLIC -ffreestanding) +set_target_properties(stage1 PROPERTIES LINK_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/linker.ld) +target_link_options(stage1 PRIVATE -T${CMAKE_CURRENT_SOURCE_DIR}/linker.ld) target_link_libraries(stage1 libfat) \ No newline at end of file diff --git a/stage1/linker.ld b/stage1/linker.ld new file mode 100644 index 0000000..420f618 --- /dev/null +++ b/stage1/linker.ld @@ -0,0 +1,17 @@ +ENTRY(main) +SECTIONS +{ + . = 0x10000; + .text : AT(0x10000){ + *.o(.text); + } + .data : { + *.o(.data); + } + .rodata : { + *.o(.rodata); + } + .bss : { + *.o(.bss); + } +} \ No newline at end of file diff --git a/stage1/stage1.c b/stage1/stage1.c index 1d69fc1..9d5fae3 100644 --- a/stage1/stage1.c +++ b/stage1/stage1.c @@ -2,7 +2,10 @@ // Created by barba on 06/10/2022. // - int main() { + while(1) { + + }; + return 0; } \ No newline at end of file