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