From 58de4d6c325c7839e3971ee64456ef228e01cb51 Mon Sep 17 00:00:00 2001 From: John Stefanelli Date: Sat, 24 Sep 2022 22:30:25 -0400 Subject: [PATCH] Initial commit --- .DS_Store | Bin 0 -> 6148 bytes .gitignore | 2 + .vscode/settings.json | 5 + CMakeLists.txt | 8 ++ CMakeToolchain.txt | 30 ++++ host/CMakeLists.txt | 6 + host/mbrcopy/CMakeLists.txt | 2 + host/mbrcopy/mbrcopy.c | 96 +++++++++++++ libfat/CMakeLists.txt | 3 + libfat/include/libfat.h | 147 +++++++++++++++++++ libfat/libfat.c | 272 ++++++++++++++++++++++++++++++++++++ mbr/CMakeLists.txt | 3 + mbr/linker.ld | 16 +++ mbr/mbr.asm | 125 +++++++++++++++++ os3_common/datatypes.h | 17 +++ os3_common/packing.h | 13 ++ rawimg/CMakeLists.txt | 9 ++ rawimg/mkimg_macos.sh | 6 + 18 files changed, 760 insertions(+) create mode 100644 .DS_Store create mode 100644 .gitignore create mode 100644 .vscode/settings.json create mode 100644 CMakeLists.txt create mode 100644 CMakeToolchain.txt create mode 100644 host/CMakeLists.txt create mode 100644 host/mbrcopy/CMakeLists.txt create mode 100644 host/mbrcopy/mbrcopy.c create mode 100644 libfat/CMakeLists.txt create mode 100644 libfat/include/libfat.h create mode 100644 libfat/libfat.c create mode 100644 mbr/CMakeLists.txt create mode 100644 mbr/linker.ld create mode 100644 mbr/mbr.asm create mode 100644 os3_common/datatypes.h create mode 100644 os3_common/packing.h create mode 100644 rawimg/CMakeLists.txt create mode 100644 rawimg/mkimg_macos.sh diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..9d1c245c2c5188de0cd34803353a6b3ae2f53ce6 GIT binary patch literal 6148 zcmeHKL2uJA6nUv*oYG(CVP_3 -o ") +set(CMAKE_CXX_LINK_EXECUTABLE "i686-elf-ld -o ") +set(CMAKE_ASM_NASM_LINK_EXECUTABLE "i686-elf-ld -o ") + +# Set language flags +set(CMAKE_C_FLAGS "-Wall -mtune=i386 -gdwarf -m32 -oS") +set(CMAKE_ASM_FLAGS "-felf32 -F dwarf -g") +set(CMAKE_ASM_NASM_OBJECT_FORMAT elf32) +set(CMAKE_STATIC_LINKER_FLAGS "") +set(CMAKE_EXE_LINKER_FLAGS "-m elf_i386 --nmagic -nostdlib") + +# Locate i686 sysroot? +set(CMAKE_FIND_ROOT_PATH $ENV{I686_CROSS_ROOT}) + +# adjust the default behavior of the FIND_XXX() commands: +# search programs in the host environment +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) + +# search headers and libraries in the target environment +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) + diff --git a/host/CMakeLists.txt b/host/CMakeLists.txt new file mode 100644 index 0000000..c7d08e8 --- /dev/null +++ b/host/CMakeLists.txt @@ -0,0 +1,6 @@ +cmake_minimum_required(VERSION 3.21) + +project(os3_host C) + +add_subdirectory(../libfat ${CMAKE_CURRENT_BINARY_DIR}/libfat) +add_subdirectory(mbrcopy) \ No newline at end of file diff --git a/host/mbrcopy/CMakeLists.txt b/host/mbrcopy/CMakeLists.txt new file mode 100644 index 0000000..b92409a --- /dev/null +++ b/host/mbrcopy/CMakeLists.txt @@ -0,0 +1,2 @@ +add_executable(mbrcopy mbrcopy.c) +target_link_libraries(mbrcopy libfat) \ No newline at end of file diff --git a/host/mbrcopy/mbrcopy.c b/host/mbrcopy/mbrcopy.c new file mode 100644 index 0000000..3a342c5 --- /dev/null +++ b/host/mbrcopy/mbrcopy.c @@ -0,0 +1,96 @@ +#include "libfat.h" +#include "stdio.h" +#include "stdlib.h" + +os_u32 readRoutine(os_u32 amount, void* buffer, void* user_data) { + if (user_data == 0) { + return 0; + } + FILE** f = (FILE**)user_data; + + os_u32 read_bytes = fread(buffer, 1, amount, *f); + return read_bytes; +} + +os_u32 writeRoutine(os_u32 amount, void* buffer, void* user_data) { + if (user_data == 0) { + return 0; + } + + FILE** f = (FILE**)user_data; + + os_u32 written_bytes = fwrite(buffer, 1, amount, *f); + return written_bytes; +} + +os_bool seekRoutine(os_u32 offset, os_u32 direction, void* user_data) { + if (user_data == 0) { + return OS_FALSE; + } + + FILE** f = (FILE**)user_data; + int seek_dir = SEEK_SET; + switch(direction) { + case LIBFAT_SEEK_ORIGIN: + seek_dir = SEEK_SET; + break; + case LIBFAT_SEEK_CURRENT: + seek_dir = SEEK_CUR; + break; + case LIBFAT_SEEK_END: + seek_dir = SEEK_END; + break; + } + + int result = fseek(*f, offset, seek_dir); + return result == 0 ? OS_TRUE : OS_FALSE; +} + +os_u32 tellRoutine(void* user_data) { + if (user_data == 0) { + return 0; + } + + FILE** f = (FILE**)user_data; + + os_u32 result = ftell(*f); + return result; +} + +void printRoutine(os_s8* data, os_u16 size) { + if (size == 0) { + printf("%s\n", data); + return; + } + + for(os_u16 s = 0; s < size; s++) { + printf("%c", *data); + data++; + } + printf("\n"); +} + +void printNumber(os_u32 number) { + printf("%#x\n", number); +} + +int main(int argc, char** argv) { + if (argc < 2) { + printf("No file provided\n"); + return 1; + } + + FILE* f = fopen(argv[1], "rb"); + + FileHandle h; + h.read = readRoutine; + h.write = writeRoutine; + h.seek = seekRoutine; + h.tell = tellRoutine; + h.user_data = (void*)&f; + + libfat_test(h, printRoutine, printNumber); + + fclose(f); + return 0; +} \ No newline at end of file diff --git a/libfat/CMakeLists.txt b/libfat/CMakeLists.txt new file mode 100644 index 0000000..7d6bde9 --- /dev/null +++ b/libfat/CMakeLists.txt @@ -0,0 +1,3 @@ +add_library(libfat libfat.c include/libfat.h) +target_include_directories(libfat PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include") +target_include_directories(libfat PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/../os3_common/") \ No newline at end of file diff --git a/libfat/include/libfat.h b/libfat/include/libfat.h new file mode 100644 index 0000000..79cba1c --- /dev/null +++ b/libfat/include/libfat.h @@ -0,0 +1,147 @@ +#ifndef __OS3_LIBFAT_H +#define __OS3_LIBFAT_H + +#include "datatypes.h" +#include "packing.h" + +#define LIBFAT_SEEK_ORIGIN 0 +#define LIBFAT_SEEK_CURRENT 1 +#define LIBFAT_SEEK_END 2 + +typedef os_u32 (*ReadRoutine)(os_u32 amount, void* buffer, void* user_data); +typedef os_u32 (*WriteRoutine)(os_u32 amount, void* buffer, void* user_data); +typedef os_bool (*SeekRoutine)(os_u32 offset, os_u32 direction, void* user_data); +typedef os_u32 (*TellRoutine)(void* user_data); + +typedef void (*PrintNumber)(os_u32 number); +typedef void (*PrintRoutine)(os_s8* data, os_u16 size); + +typedef struct _FileHandle { + ReadRoutine read; + WriteRoutine write; + SeekRoutine seek; + TellRoutine tell; + void* user_data; +} FileHandle; + +OS_PACK_START +struct _FatHeader_12 { + os_u8 jump[3]; + os_s8 oem[8]; + os_u16 bytes_per_sector; + os_u8 sectors_per_cluster; + os_u16 reserved_sectors; + os_u8 number_of_fats; + os_u16 root_dir_entries; + os_u16 logical_sectors; + os_u8 media_descriptor; + os_u16 sectors_per_fat; + os_u16 sectors_per_track; + os_u16 num_heads; + os_u16 hidden_sectors; +} OS_PACK_MID; +OS_PACK_END + +typedef struct _FatHeader_12 FatHeader_12; + +OS_PACK_START +struct _FatHeader_16 { + FatHeader_12 base; + os_u16 hidden_sectors_high; + os_u32 total_sectors; + os_u8 drive_number; + os_u8 reserved; + os_u8 extended_signature; //0x28 / 0x29 + os_u32 serial; + os_s8 volume_label[11]; + os_s8 fat_type[8]; +} OS_PACK_END; +OS_PACK_END + +typedef struct _FatHeader_16 FatHeader_16; + +OS_PACK_START +struct _FatHeader_32 { + FatHeader_12 base; + os_u16 hidden_sectors_high; + os_u32 total_sectors; + os_u32 sectors_per_fat_32; + os_u16 mirror_flags; + os_u16 fs_version; + os_u32 first_root_cluster; + os_u16 fsinfo_sector; + os_u16 backup_boot_location; + os_u8 reserved_fat32[12]; + os_u8 logical_drive_number; + os_u8 reserved_winnt; + os_u8 extended_sig_fat32; //0x29 + os_u32 serial_number; + os_s8 volume_label[11]; + os_s8 fat_type[8]; +} OS_PACK_MID; +OS_PACK_END; + +#define FAT_READONLY_BIT 1 +#define FAT_HIDDEN_BIT 2 +#define FAT_SYSTEM_BIT 4 +#define FAT_VOLUME_BIT 8 +#define FAT_SUBDIRECTORY_BIT 16 +#define FAT_ARCHIVE_BIT 32 + +#define FAT_LAST_CLUSTER_32 0xFFFFFFF8 + +OS_PACK_START +struct _FatDirectoryEntry { + os_s8 file_name[8]; + os_s8 extension[3]; + os_s8 attribute; + os_u8 reserved[8]; + os_u16 start_cluster_high; + os_u16 time; + os_u16 date; + os_u16 start_cluster; + os_u32 file_size; +} OS_PACK_MID; +OS_PACK_END + +typedef struct _FatDirectoryEntry FatDirectoryEntry; + +typedef struct _FatHeader_32 FatHeader_32; + +typedef struct _FatControlBlock { + FileHandle handle; + FatHeader_32 header; + os_u32 first_loaded_cluster; + os_u32* loaded_fat_segment; + os_u32 loaded_fat_cluster_amount; +} FatControlBlock; + +typedef struct _LibFatFile { + FatControlBlock* fat; + FatDirectoryEntry file_entry; + os_u32 current_cluster; + os_u32 position; + os_u32 in_cluster_position; + os_u32 fat_data_offset; + os_u32 fat_cluster_size; +} LibFatFile; + +typedef struct _LibFatDirectory { + FatControlBlock* fat; + os_u32 fat_cluster_size; + os_u32 base_cluster; + os_u32 current_cluster; + os_u32 position_in_cluster; + os_bool done; +} LibFatDirectory; + + +extern os_bool libfat_init(FileHandle handle, void* buffer, os_u32 buffer_size, FatControlBlock* result); +extern os_bool libfat_open_read(FatControlBlock* fat, FatDirectoryEntry* entry, LibFatFile* result); +extern os_u32 libfat_read(LibFatFile* file, void* buffer, os_u32 buffer_size); +extern os_u32 libfat_tell(LibFatFile* file); + +extern os_bool libfat_open_directory(FatControlBlock* fat, FatDirectoryEntry* entry, LibFatDirectory* result); +extern void libfat_test(FileHandle image_file, PrintRoutine print, PrintNumber rintNumber); + +#endif //!__OS3_LIBFAT_H \ No newline at end of file diff --git a/libfat/libfat.c b/libfat/libfat.c new file mode 100644 index 0000000..8951093 --- /dev/null +++ b/libfat/libfat.c @@ -0,0 +1,272 @@ +#include "libfat.h" + +os_u32 loaded_fat_segment[512]; + +#define DIRECTORY_BUFFER_SIZE 32 + +FatDirectoryEntry directory_buffer[DIRECTORY_BUFFER_SIZE]; + + +os_bool libfat_read_header_12(FileHandle handle, FatHeader_12* result) { + + handle.seek(0, LIBFAT_SEEK_END, handle.user_data); + os_u32 size = handle.tell(handle.user_data); + + if (size < sizeof(FatHeader_12)) { + return OS_FALSE; + } + + handle.seek(0, LIBFAT_SEEK_ORIGIN, handle.user_data); + handle.read(sizeof(FatHeader_12), (void*)result, handle.user_data); + + return OS_TRUE; +} + +os_bool libfat_read_header_32(FileHandle handle, FatHeader_32* result) { + handle.seek(0, LIBFAT_SEEK_END, handle.user_data); + os_u32 size = handle.tell(handle.user_data); + + if (size < sizeof(FatHeader_32)) { + return OS_FALSE; + } + + handle.seek(0, LIBFAT_SEEK_ORIGIN, handle.user_data); + handle.read(sizeof(FatHeader_32), (void*)result, handle.user_data); + + return OS_TRUE; +} + +os_bool libfat_img_write_mbr(FileHandle image_file, FileHandle mbr_file) { + return OS_TRUE; +} + +os_u32 libfat_img_copy_file(FileHandle image_file, FileHandle file, os_s8* name) { + return 0; +} + +os_bool libfat_load_fat_cluster(FatControlBlock* fat, os_u32 target_cluster, os_bool force) { + + if (fat->first_loaded_cluster > target_cluster || + fat->first_loaded_cluster + fat->loaded_fat_cluster_amount <= target_cluster || + force != OS_FALSE) { + os_u32 fat_size = fat->header.sectors_per_fat_32 * fat->header.base.bytes_per_sector; + os_u32 fat_offset = (fat->header.base.bytes_per_sector * fat->header.base.reserved_sectors) + fat_size; + fat->handle.seek(fat_offset, LIBFAT_SEEK_ORIGIN, fat->handle.user_data); + + os_u32 fat_clusters = fat_size / sizeof(os_u32); + + if (target_cluster >= fat_clusters) { + 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; + } + + return OS_TRUE; +} + +os_u32 libfat_read_cluster(FatControlBlock* fat, os_u32 cluster) { + if(libfat_load_fat_cluster(fat, cluster, OS_FALSE) == OS_FALSE) { + return 0; + } + + return fat->loaded_fat_segment[cluster - fat->first_loaded_cluster]; +} + +os_u32 libfat_load_cluster(FatControlBlock* fat, os_u32 cluster, void* buffer, os_u32 buffer_size, os_u32 offset_in_cluster) { + 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; + + if (offset_in_cluster >= cluster_size) { + return 0; + } + + os_u32 cluster_offset = data_offset + ((cluster - 2) * cluster_size) + offset_in_cluster; + + os_u32 amount_to_read = cluster_size - offset_in_cluster > buffer_size ? buffer_size : cluster_size - offset_in_cluster; + + if(!fat->handle.seek(cluster_offset, LIBFAT_SEEK_ORIGIN, fat->handle.user_data)) { + return 0; + } + os_u32 read = fat->handle.read(amount_to_read, buffer, fat->handle.user_data); + + return read; + +} + +os_bool libfat_open_read(FatControlBlock* fat, FatDirectoryEntry* entry, LibFatFile* result) { + if(result == 0 || fat == 0 || entry == 0) { + return OS_FALSE; + } + + if ((entry->attribute & FAT_SYSTEM_BIT) != 0 || + (entry->attribute & FAT_VOLUME_BIT) != 0) { + return OS_FALSE; + } + + result->fat = fat; + result->file_entry = *entry; + result->fat_cluster_size = fat->header.base.sectors_per_cluster * fat->header.base.bytes_per_sector; + result->fat_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; + result->position = 0; + result->current_cluster = (((os_u32)entry->start_cluster_high) << 16) + entry->start_cluster; + result->in_cluster_position = 0; + + return OS_TRUE; +} + +os_bool libfat_open_directory(FatControlBlock* fat, FatDirectoryEntry* entry, LibFatDirectory* result) { + if (fat == 0 || result == 0) { + return OS_FALSE; + } + + if (entry != 0 && (entry->attribute & FAT_SUBDIRECTORY_BIT) == 0) { + return OS_FALSE; + } + + result->fat = fat; + result->fat_cluster_size = fat->header.base.sectors_per_cluster * fat->header.base.bytes_per_sector; + result->current_cluster = entry == 0 ? fat->header.first_root_cluster : (((os_u32)entry->start_cluster_high) << 16) + entry->start_cluster; + result->base_cluster = result->current_cluster; + result->position_in_cluster = 0; + result->done = 0; + + return OS_TRUE; +} + +os_bool libfat_read_directory(LibFatDirectory* dir, FatDirectoryEntry* entry) { + if (dir == 0 || entry == 0) { + return OS_FALSE; + } + + if (dir->done == OS_TRUE) { + return OS_FALSE; + } + + FatDirectoryEntry my_entry; + os_u32 read = libfat_load_cluster(dir->fat, dir->current_cluster, &my_entry, sizeof(FatDirectoryEntry), dir->position_in_cluster); + dir->position_in_cluster += read; + if (dir->position_in_cluster == dir->fat_cluster_size) { + os_u32 next_cluster = libfat_read_cluster(dir->fat, dir->current_cluster); + if (next_cluster >= FAT_LAST_CLUSTER_32) { + dir->done = OS_TRUE; + } + } + + if (my_entry.file_name[0] == '\0') { + dir->done = OS_TRUE; + return OS_FALSE; + } + + *entry = my_entry; + return OS_TRUE; +} + +os_u32 libfat_read(LibFatFile* file, void* buffer, os_u32 buffer_size) { + os_u32 read = 0; + os_bool eof = file->position >= file->file_entry.file_size ? OS_TRUE : OS_FALSE; + while(read < buffer_size && eof != OS_TRUE) { + os_u32 amount_left = file->file_entry.file_size - file->position; + os_u32 amount_to_read = (buffer_size - read) > amount_left ? amount_left : buffer_size - read; + + os_u32 local_read; + if (file->in_cluster_position + amount_to_read >= file->fat_cluster_size) { + local_read = file->fat_cluster_size - file->in_cluster_position; + } else { + local_read = amount_to_read; + } + + os_u32 r = libfat_load_cluster(file->fat, file->current_cluster, buffer, local_read, file->in_cluster_position); + + read += r; + buffer += r; + file->position += r; + file->in_cluster_position += r; + if (file->in_cluster_position == file->fat_cluster_size) { + file->current_cluster = libfat_read_cluster(file->fat, file->current_cluster); + file->in_cluster_position = 0; + } + + if (file->position == file->file_entry.file_size) { + eof = OS_TRUE; + } + } + + return read; +} + +os_u32 libfat_tell(LibFatFile* file) { + if(file == 0) { + return 0; + } + + return file->position; +} + +os_bool libfat_init(FileHandle file, void* buffer, os_u32 buffer_size, FatControlBlock* result) { + if(libfat_read_header_32(file, &result->header) != OS_TRUE) { + return OS_FALSE; + } + + result->handle = file; + result->loaded_fat_segment = (os_u32*)buffer; + result->loaded_fat_cluster_amount = buffer_size / sizeof(os_u32); + result->first_loaded_cluster = 0; + + if(libfat_load_fat_cluster(result, 2, OS_TRUE) != OS_TRUE) { + return OS_FALSE; + } + + return OS_TRUE; +} + +void libfat_test(FileHandle handle, PrintRoutine print, PrintNumber printNumber) { + FatControlBlock cb; + if (libfat_init(handle, loaded_fat_segment, 512 * sizeof(os_u32), &cb) != OS_TRUE) { + print("Failed to init FAT.", 0); + return; + } + + LibFatDirectory dir; + if (libfat_open_directory(&cb, 0, &dir) != OS_TRUE) { + print("Failecd to open directory.", 0); + return; + } + + FatDirectoryEntry entry; + while(libfat_read_directory(&dir, &entry) == OS_TRUE) { + if ((entry.attribute & (os_s8)FAT_HIDDEN_BIT) != 0 || + (entry.attribute & (os_s8)FAT_VOLUME_BIT) != 0 || + (entry.attribute & (os_s8)FAT_SYSTEM_BIT) != 0) { + continue; + } + + print("Entry name: ", 0); + print(entry.file_name, 11); + + os_u32 cluster = (((os_u32)entry.start_cluster_high) << 16) + entry.start_cluster; + + print("Cluster: ", 0); + printNumber(cluster); + + print("Size: ", 0); + printNumber(entry.file_size); + + os_u32 effective_size = entry.file_size > 512 ? 512 : entry.file_size; + if(effective_size > 0) { + LibFatFile f; + if (libfat_open_read(&cb, &entry, &f) == OS_TRUE) { + char buffer[512]; + os_u32 amount = libfat_read(&f, buffer, 512); + print("Content: ", 0); + print(buffer, amount); + } + } + + print("--------", 0); + } +} \ No newline at end of file diff --git a/mbr/CMakeLists.txt b/mbr/CMakeLists.txt new file mode 100644 index 0000000..a302118 --- /dev/null +++ b/mbr/CMakeLists.txt @@ -0,0 +1,3 @@ +add_executable(mbr mbr.asm linker.ld) + +target_link_options(mbr PRIVATE -T${CMAKE_CURRENT_SOURCE_DIR}/linker.ld) \ No newline at end of file diff --git a/mbr/linker.ld b/mbr/linker.ld new file mode 100644 index 0000000..9c11568 --- /dev/null +++ b/mbr/linker.ld @@ -0,0 +1,16 @@ +ENTRY(_main) +SECTIONS +{ + . = 0x7C00; + .text : AT(0x7c00){ + *.o(.text); + *.o(.data); + } + .sig : AT(0x7DFE){ + SHORT(0xaa55); + } + . = 0x7E00; + .eh_frame : AT(0x7E00){ + *.o(.eh_frame); + } +} \ No newline at end of file diff --git a/mbr/mbr.asm b/mbr/mbr.asm new file mode 100644 index 0000000..052fc21 --- /dev/null +++ b/mbr/mbr.asm @@ -0,0 +1,125 @@ +USE16 + +NULL equ 0 + +section .text +global _main +_main: + JMP entry +; FAT32 Header. +global fat_header +fat_header: times 87 db 0 + +; function READ_SECTORS_EXTENDED: Read sectors from disk +; 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: RETURN ADDRESS +; Returns: +; AX: 0 = Ok, Other = Error +; +; +; SP + 0: Old BP +; 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 +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 + 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 + MOV AL, AH ; move error to Al + MOV AH, 0 ; zero-out AH +read_sectors_extended_exit: ; leave function + POP BP ; restore BP + POP SI ; restore SI + POP DX ; restore DX + + +; function PRINT: teletype to display +; uses INT 10h AH=0Eh from: http://www.ctyme.com/intr/rb-0106.htm +; parameters (in order of PUSH): +; - WORD: address of string +; - WORD: size of string +; returns: +; AX: 0 +print: + PUSH BX ; save BX + PUSH CX ; save CX + PUSH BP ; save BP (can change due to scrolling) + MOV BP, SP ; set up stack frame + + + MOV AH, 0Eh ; load INT 10h parameter + MOV BX, 0 ; zero-out BX (extra parameters) + + +entry: + ; Set up stack and segments + MOV AX, 0 ; set up stack segment + MOV SS, AX ; ^^^ + MOV SP, 0x7C00 ; set up stack pointer (0x6c00-x7BFF) + ; 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 + MOV DS, AX ; set up segment registers + MOV ES, AX ; ^^^ + MOV FS, AX ; ^^^ + MOV GS, AX ; ^^^ + + + PUSH DX ; save drive number (DL) + + ; 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 + + + + +section .data +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 + +read_sectors_packet: +packet_size db 10h +packet_reserved db 0h +packet_blocks dw 0h +packet_buffer dd 0h +packet_lba dq 0h + +build_settings: +build_settings_magic_0 dd 0x49494949 +build_settings_bytes dw 0x0 +build_settings_magic_1 dd 0x49494949 \ No newline at end of file diff --git a/os3_common/datatypes.h b/os3_common/datatypes.h new file mode 100644 index 0000000..1abbc88 --- /dev/null +++ b/os3_common/datatypes.h @@ -0,0 +1,17 @@ +#ifndef __OS3_DATATYPES_H +#define __OS3_DATATYPES_H + +typedef char os_s8; +typedef unsigned char os_u8; +typedef short os_s16; +typedef unsigned short os_u16; +typedef int os_s32; +typedef unsigned int os_u32; +typedef long long os_s64; +typedef unsigned long long os_u64; + +typedef int os_bool; +#define OS_FALSE 0 +#define OS_TRUE 1 + +#endif //!__OS3_DATAYPES_H \ No newline at end of file diff --git a/os3_common/packing.h b/os3_common/packing.h new file mode 100644 index 0000000..ab234ce --- /dev/null +++ b/os3_common/packing.h @@ -0,0 +1,13 @@ +#ifndef __OS3_PACKING_H +#define __OS3_PACKING_H + +#ifdef __MSC_VER +#define OS_PACK_START #pragma pack(push, 1) +#define OS_PACK_MID +#define OS_PACK_END #pragma pack(pop) +#else +#define OS_PACK_START +#define OS_PACK_MID __attribute__((packed)) +#define OS_PACK_END +#endif +#endif //!__OS3_PACKING_H \ No newline at end of file diff --git a/rawimg/CMakeLists.txt b/rawimg/CMakeLists.txt new file mode 100644 index 0000000..6584d46 --- /dev/null +++ b/rawimg/CMakeLists.txt @@ -0,0 +1,9 @@ +set(IMAGE_TARGET ${CMAKE_CURRENT_BINARY_DIR}/raw.img) + +if (CMAKE_HOST_APPLE) +set(IMAGE_GEN_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/mkimg_macos.sh) +elseif (CMAKE_HOST_UNIX) +set(IMAGE_GEN_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/mkimg_linux.sh) +endif (CMAKE_HOST_APPLE) + +add_custom_target(raw_img COMMAND sh ${IMAGE_GEN_SCRIPT} ${IMAGE_TARGET} BYPRODUCTS ${IMAGE_TARGET}) \ No newline at end of file diff --git a/rawimg/mkimg_macos.sh b/rawimg/mkimg_macos.sh new file mode 100644 index 0000000..3ea3e39 --- /dev/null +++ b/rawimg/mkimg_macos.sh @@ -0,0 +1,6 @@ +#!/bin/bash +echo "Generating image $1...." +qemu-img create $1 512M +disk_id=$(hdiutil attach -nomount $1) +newfs_msdos -F 32 -v OS3_BOOT $disk_id +hdiutil detach $disk_id