[Host/KernelCopy] First implementation of KernelCopy

[LibFat] Add libfat
[Stage1] Add stage1 project
This commit is contained in:
Johnh Stefanelli 2022-10-06 21:20:29 +02:00
parent 2329bce7d3
commit 642385797c
Signed by: jstefanelli
GPG key ID: 60EDE2437640D2AA
15 changed files with 352 additions and 90 deletions

View file

@ -5,4 +5,5 @@ set(CMAKE_C_STANDARD 17)
add_subdirectory(mbr)
add_subdirectory(libfat)
add_subdirectory(stage1)
add_subdirectory(rawimg)

View file

@ -11,7 +11,7 @@ set(CMAKE_CXX_LINK_EXECUTABLE "i686-elf-ld <CMAKE_CXX_LINK_FLAGS> <LINK_FLAGS> <
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_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 "")

View file

@ -3,4 +3,6 @@ cmake_minimum_required(VERSION 3.21)
project(os3_host C)
add_subdirectory(../libfat ${CMAKE_CURRENT_BINARY_DIR}/libfat)
add_subdirectory(mbrcopy)
add_subdirectory(libhost)
add_subdirectory(mbrcopy)
add_subdirectory(kernelcopy)

View file

@ -0,0 +1,2 @@
add_executable(kernelcopy kernelcopy.c)
target_link_libraries(kernelcopy host libfat)

View file

@ -0,0 +1,144 @@
#include "libfat.h"
#include "libhost.h"
#include "stdio.h"
#include "string.h"
#include "stdlib.h"
os_u32 fat_buffer[512];
#define STAGE1_NAME "OS3ST1 "
#define STAGE1_EXT "BIN"
#define STAGE1_FULL_NAME "OS3ST1 BIN"
OS_PACK_START
typedef struct _MBR_BuildSettings {
os_u16 sig_0;
os_u16 sector;
os_u16 size;
os_u16 sig_1;
} OS_PACK_MID MBR_BuildSettings;
OS_PACK_END
#define MBR_SETTINGS_SIG_0 ((os_u16)0x4952)
#define MBR_SETTINGS_SIG_1 ((os_u16)0x4953)
int main(int argc, char** argv) {
if (argc < 3) {
fprintf(stderr, "Not enough arguments.\n");
return 1;
}
FILE* image = fopen(argv[1], "rb+");
FILE* kernel = fopen(argv[2], "rb");
if (image == NULL) {
fprintf(stderr, "Failed to open image file\n");
return 1;
}
LFFileHandle image_handle = libhost_create_handle(image);
LFControlBlock fat;
if(libfat_init(image_handle, fat_buffer, sizeof(fat_buffer), &fat) != OS_TRUE) {
fprintf(stderr, "Failed to read FAT header\n");
return 1;
}
printf("FAT OK.\n");
LFDirectory root_dir;
if(libfat_open_directory(&fat, 0, &root_dir) != OS_TRUE) {
fprintf(stderr, "Failed to open root directory\n");
return 1;
}
LFFile handle;
os_bool handle_found = OS_FALSE;
LFDirectoryEntry entry;
while(libfat_read_directory(&root_dir, &entry) == OS_TRUE) {
if(strcmp(entry.entry.file_name, STAGE1_NAME) == 0 && strcmp(entry.entry.extension, STAGE1_EXT) == 0) {
printf("Found existing 'OS3ST1.BIN'.\n");
if(libfat_truncate(&fat, &entry) != OS_TRUE) {
fprintf(stderr, "Failed to truncate existing kernel.\n");
return 1;
}
handle_found = OS_TRUE;
break;
}
}
if(handle_found == OS_FALSE) {
if(libfat_create(&fat, 0, STAGE1_FULL_NAME, OS_FALSE, &entry) != OS_TRUE) {
fprintf(stderr, "Failed to create kernel file\n");
return 1;
}
printf("Created 'OS3ST1.BIN'.\n");
}
if(libfat_open(&fat, &entry, &handle) != OS_TRUE) {
fprintf(stderr, "Failed to open kernel.\n");
return 1;
}
char* buffer = malloc(8192);
os_u32 kernel_size = 0;
os_u32 read;
do {
read = fread(buffer, 1, 8192, kernel);
if(read > 0) {
if(libfat_write(&handle, buffer, read) != read) {
free(buffer);
fprintf(stderr, "Error during kernel copy\n");
return 1;
}
}
kernel_size += read;
} while(read > 0);
printf("Kernel copy OK.");
free(buffer);
fclose(kernel);
os_u32 kernel_offset = libfat_get_true_entry_offset(&fat, &handle.file_entry);
if (kernel_offset == 0) {
fprintf(stderr, "Failed to get true file sector.\n");
return 1;
}
if (kernel_offset % fat.header.base.bytes_per_sector != 0) {
fprintf(stderr, "Error: STAGE1 not aligned to sector\n");
return 1;
}
fseek(image, 0, SEEK_SET);
char mbr[512];
fread(mbr, 1, 512, image);
os_bool found = OS_FALSE;
os_s8* ptr = mbr;
for(int i = 0; i < 512 - sizeof(MBR_BuildSettings); i++) {
MBR_BuildSettings* settings = (MBR_BuildSettings*)ptr;
if (settings->sig_0 == MBR_SETTINGS_SIG_0 && settings->sig_1 == MBR_SETTINGS_SIG_1) {
settings->sector = kernel_offset / fat.header.base.bytes_per_sector;
settings->size = kernel_size;
found = OS_TRUE;
break;
}
ptr++;
}
if (found == OS_FALSE) {
fprintf(stderr, "Error: could not find BUILD_SETTINGS markers\n");
return 1;
}
fseek(image, 0, SEEK_SET);
fwrite(mbr, 1, 512, image);
fclose(image);
return 0;
}

View file

@ -0,0 +1,3 @@
add_library(host libhost.c include/libhost.h)
target_link_libraries(host libfat)
target_include_directories(host PUBLIC ${CMAKE_CURRENT_LIST_DIR}/include)

View file

@ -0,0 +1,10 @@
#include "libfat.h"
#include "stdio.h"
extern os_u32 libhost_readRoutine(os_u32 amount, void* buffer, void* user_data);
extern os_u32 libhost_writeRoutine(os_u32 amount, void* buffer, void* user_data);
extern os_bool libhost_seekRoutine(os_u32 offset, os_u32 direction, void* user_data);
extern os_u32 libhost_tellRoutine(void* user_data);
extern void libhost_printRoutine(os_s8* data, os_u16 size);
extern void libhost_printNumber(os_u32 number);
extern LFFileHandle libhost_create_handle(FILE* f);

86
host/libhost/libhost.c Normal file
View file

@ -0,0 +1,86 @@
#include "libhost.h"
#include "stdio.h"
os_u32 libhost_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 libhost_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 libhost_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 libhost_tellRoutine(void* user_data) {
if (user_data == 0) {
return 0;
}
FILE* f = (FILE*)user_data;
os_u32 result = ftell(f);
return result;
}
void libhost_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 libhost_printNumber(os_u32 number) {
printf("%#x\n", number);
}
extern LFFileHandle libhost_create_handle(FILE* f) {
LFFileHandle h;
h.read = libhost_readRoutine;
h.write = libhost_writeRoutine;
h.seek = libhost_seekRoutine;
h.tell = libhost_tellRoutine;
h.user_data = (void*)f;
return h;
}

View file

@ -1,2 +1,2 @@
add_executable(mbrcopy mbrcopy.c)
target_link_libraries(mbrcopy libfat)
target_link_libraries(mbrcopy host libfat)

View file

@ -2,82 +2,11 @@
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "libhost.h"
os_u32 loaded_fat_segment[512];
os_u8 mbr_buffer[512];
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 < 3) {
printf("No files provided\n");
@ -86,12 +15,7 @@ int main(int argc, char** argv) {
FILE* f = fopen(argv[1], "rb+");
LFFileHandle h;
h.read = readRoutine;
h.write = writeRoutine;
h.seek = seekRoutine;
h.tell = tellRoutine;
h.user_data = (void*)&f;
LFFileHandle h = libhost_create_handle(f);
LFControlBlock fat;
if(libfat_init(h, loaded_fat_segment, 512 * sizeof(os_u32), &fat) != OS_TRUE) {
@ -101,12 +25,7 @@ int main(int argc, char** argv) {
FILE* f2 = fopen(argv[2], "rb");
LFFileHandle mbrHandle;
mbrHandle.read = readRoutine;
mbrHandle.write = writeRoutine;
mbrHandle.seek = seekRoutine;
mbrHandle.tell = tellRoutine;
mbrHandle.user_data = (void*)&f2;
LFFileHandle mbrHandle = libhost_create_handle(f2);
if(libfat_test_mbr(&mbrHandle) != OS_TRUE) {
printf("Failed to test MBR...\n");

View file

@ -146,6 +146,7 @@ typedef struct _LFDirectory {
extern os_bool libfat_init(LFFileHandle handle, void* buffer, os_u32 buffer_size, LFControlBlock* result);
extern os_bool libfat_truncate(LFControlBlock* fat, LFDirectoryEntry* entry);
extern os_bool libfat_open(LFControlBlock* fat, LFDirectoryEntry* entry, LFFile* result);
extern os_u32 libfat_read(LFFile* file, void* buffer, os_u32 buffer_size);
extern os_u32 libfat_write(LFFile* file, void* biffer, os_u32 buffer_size);

View file

@ -377,6 +377,86 @@ os_bool libfat_fsinfo_update(LFControlBlock* fat) {
return OS_TRUE;
}
os_bool libfat_fsinfo_free(LFControlBlock* fat, os_u32 freed_cluster) {
os_u32 fsinfo_offset = fat->header.fsinfo_sector * fat->header.base.bytes_per_sector;
if(fat->handle.seek(fsinfo_offset, LIBFAT_SEEK_ORIGIN, fat->handle.user_data) != OS_TRUE) {
return OS_FALSE;
}
os_u32 sig = 0;
os_u32 read = fat->handle.read(sizeof(os_u32), (void*)&sig, fat->handle.user_data);
if (read != sizeof(os_u32) || sig != FAT_FSINFO_SIG_0) {
return OS_FALSE;
}
if(fat->handle.seek(fsinfo_offset + 484, LIBFAT_SEEK_ORIGIN, fat->handle.user_data) != OS_TRUE) {
return OS_FALSE;
}
read = fat->handle.read(sizeof(os_u32), (void*)&sig, fat->handle.user_data);
if (read != sizeof(os_u32) || sig != FAT_FSINFO_SIG_1) {
return OS_FALSE;
}
os_u32 free_clusters = 0;
read = fat->handle.read(sizeof(os_u32), (void*)&free_clusters, fat->handle.user_data);
if (read != sizeof(os_u32)) {
return OS_FALSE;
}
os_u32 next_free_cluster = 0;
read = fat->handle.read(sizeof(os_u32), (void*)&next_free_cluster, fat->handle.user_data);
if (read != sizeof(os_u32)) {
return OS_FALSE;
}
if (free_clusters != 0xffffffff) {
free_clusters++;
if(fat->handle.seek(fsinfo_offset + 488, LIBFAT_SEEK_ORIGIN, fat->handle.user_data) == OS_TRUE) {
fat->handle.write(sizeof(os_u32), (void*)&free_clusters, fat->handle.user_data);
}
}
if (next_free_cluster != 0xffffffff && freed_cluster < next_free_cluster) {
next_free_cluster = libfat_find_free_cluster(fat);
if (next_free_cluster < 2) {
next_free_cluster = 0xffffffff;
}
if (fat->handle.seek(fsinfo_offset + 492, LIBFAT_SEEK_ORIGIN, fat->handle.user_data) == OS_TRUE) {
fat->handle.write(sizeof(os_u32), (void*)&next_free_cluster, fat->handle.user_data);
}
}
return OS_TRUE;
}
os_bool libfat_truncate(LFControlBlock* fat, LFDirectoryEntry* entry) {
if (fat == 0 || entry == 0) {
return OS_FALSE;
}
if ((entry->entry.attribute & FAT_SUBDIRECTORY_BIT) != 0) {
return OS_FALSE; //Disable truncating subdirectories
}
entry->entry.file_size = 0;
os_u32 written = libfat_write_cluster(fat, entry->entry_cluster, &entry->entry, sizeof(FatDirectoryEntry), entry->entry_offset);
if (written != sizeof(FatDirectoryEntry)) {
return OS_FALSE;
}
os_u32 cluster = libfat_read_cluster(fat, FAT_ENTRY_CLUSTER(entry->entry));
libfat_write_fat_cluster(fat, FAT_ENTRY_CLUSTER(entry->entry), FAT_LAST_CLUSTER_32_2);
while(cluster < FAT_LAST_CLUSTER_32) {
os_u32 next_cluster = libfat_read_cluster(fat, cluster);
libfat_write_fat_cluster(fat, cluster, 0);
libfat_fsinfo_free(fat, cluster);
cluster = next_cluster;
}
return OS_TRUE;
}
os_u32 libfat_add_cluster_to_chain(LFControlBlock* fat, os_u32 last_cluster_id) {
os_u32 cluster_value;
do {

View file

@ -218,6 +218,7 @@ entry:
SUB SP, 4 ; clear previous call parameters
; Enable A20
CALL check_a20 ; call check_a20. Result in Ax
CMP AX, 0 ; compare AX to 0 (0 = A20 disabled)
JNE after_a20 ; if AX != 0, a20 is enabled, skip enabling it
@ -243,6 +244,7 @@ endless_loop:
JMP endless_loop ; loop endlessly
section .data
info_marker dw 0x4950
disk_info_packet:
info_size dw 0x1A
info_flags dw 0x0
@ -251,6 +253,7 @@ info_heads dd 0x0
info_sectors dd 0x0
info_total_sec dq 0x0
info_bps dw 0x0
info_end dw 0x4951
read_sectors_packet:
packet_size db 10h
@ -260,9 +263,10 @@ 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
build_settings_magic_0 dw 0x4952
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"

2
stage1/CMakeLists.txt Normal file
View file

@ -0,0 +1,2 @@
add_executable(stage1 stage1.c)
target_link_libraries(stage1 libfat)

8
stage1/stage1.c Normal file
View file

@ -0,0 +1,8 @@
//
// Created by barba on 06/10/2022.
//
int main() {
return 0;
}