Initial commit
This commit is contained in:
commit
58de4d6c32
18 changed files with 760 additions and 0 deletions
BIN
.DS_Store
vendored
Normal file
BIN
.DS_Store
vendored
Normal file
Binary file not shown.
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
build/
|
||||||
|
.idea/
|
||||||
5
.vscode/settings.json
vendored
Normal file
5
.vscode/settings.json
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"cmake.configureArgs": [
|
||||||
|
"-DCMAKE_TOOLCHAIN_FILE=CMakeToolchain.txt"
|
||||||
|
]
|
||||||
|
}
|
||||||
8
CMakeLists.txt
Normal file
8
CMakeLists.txt
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
cmake_minimum_required(VERSION 3.21)
|
||||||
|
project(os3 C ASM_NASM)
|
||||||
|
|
||||||
|
set(CMAKE_C_STANDARD 17)
|
||||||
|
|
||||||
|
add_subdirectory(mbr)
|
||||||
|
add_subdirectory(libfat)
|
||||||
|
add_subdirectory(rawimg)
|
||||||
30
CMakeToolchain.txt
Normal file
30
CMakeToolchain.txt
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
# Tag as cross-compiler for no specific system
|
||||||
|
set(CMAKE_SYSTEM_NAME Generic)
|
||||||
|
set(CMAKE_SYSTEM_PROCESSOR i686)
|
||||||
|
|
||||||
|
# Find compilers
|
||||||
|
set(CMAKE_C_COMPILER i686-elf-gcc)
|
||||||
|
set(CMAKE_CXX_COMPILER i686-elf-g++)
|
||||||
|
set(CMAKE_ASM_COMPILER nasm)
|
||||||
|
set(CMAKE_C_LINK_EXECUTABLE "i686-elf-ld <CMAKE_C_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>")
|
||||||
|
set(CMAKE_CXX_LINK_EXECUTABLE "i686-elf-ld <CMAKE_CXX_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>")
|
||||||
|
set(CMAKE_ASM_NASM_LINK_EXECUTABLE "i686-elf-ld <CMAKE_ASM_NASM_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>")
|
||||||
|
|
||||||
|
# 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)
|
||||||
|
|
||||||
6
host/CMakeLists.txt
Normal file
6
host/CMakeLists.txt
Normal file
|
|
@ -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)
|
||||||
2
host/mbrcopy/CMakeLists.txt
Normal file
2
host/mbrcopy/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
add_executable(mbrcopy mbrcopy.c)
|
||||||
|
target_link_libraries(mbrcopy libfat)
|
||||||
96
host/mbrcopy/mbrcopy.c
Normal file
96
host/mbrcopy/mbrcopy.c
Normal file
|
|
@ -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;
|
||||||
|
}
|
||||||
3
libfat/CMakeLists.txt
Normal file
3
libfat/CMakeLists.txt
Normal file
|
|
@ -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/")
|
||||||
147
libfat/include/libfat.h
Normal file
147
libfat/include/libfat.h
Normal file
|
|
@ -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
|
||||||
272
libfat/libfat.c
Normal file
272
libfat/libfat.c
Normal file
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
3
mbr/CMakeLists.txt
Normal file
3
mbr/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
add_executable(mbr mbr.asm linker.ld)
|
||||||
|
|
||||||
|
target_link_options(mbr PRIVATE -T${CMAKE_CURRENT_SOURCE_DIR}/linker.ld)
|
||||||
16
mbr/linker.ld
Normal file
16
mbr/linker.ld
Normal file
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
125
mbr/mbr.asm
Normal file
125
mbr/mbr.asm
Normal file
|
|
@ -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
|
||||||
17
os3_common/datatypes.h
Normal file
17
os3_common/datatypes.h
Normal file
|
|
@ -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
|
||||||
13
os3_common/packing.h
Normal file
13
os3_common/packing.h
Normal file
|
|
@ -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
|
||||||
9
rawimg/CMakeLists.txt
Normal file
9
rawimg/CMakeLists.txt
Normal file
|
|
@ -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})
|
||||||
6
rawimg/mkimg_macos.sh
Normal file
6
rawimg/mkimg_macos.sh
Normal file
|
|
@ -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
|
||||||
Loading…
Add table
Reference in a new issue