os3/host/kernelcopy/kernelcopy.c
John Stefanelli dad4ff6a34
[Stage1] Complete IDT implementation
[Stage1] Add IRQ remapping
[Stage1] Handle IRQ0 gracefully
[Stage1] Add error output functions
2023-01-18 17:11:28 +01:00

173 lines
No EOL
4.6 KiB
C

#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
OS_PACK_START
typedef struct _MBR_ReadPacket {
os_u16 sig_0;
os_u8 packet_size; //Fixed 10h
os_u8 reserved;
os_u16 blocks;
os_u16 buffer_offset;
os_u16 buffer_segment;
//os_u32 buffer;
os_u64 lba;
os_u16 sig_1;
} OS_PACK_MID MBR_ReadPacket;
OS_PACK_END
#define MBR_SETTINGS_SIG_0 ((os_u16)0x4952)
#define MBR_SETTINGS_SIG_1 ((os_u16)0x4953)
#define MBR_PACKET_SIG_0 ((os_u16) 0x4954)
#define MBR_PACKET_SIG_1 ((os_u16) 0x4955)
int main(int argc, char** argv) {
if (argc < 3) {
fprintf(stderr, "Not enough arguments. Usage: kernelcopy <image file> <kernel file>\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;
}
if (kernel == NULL) {
fprintf(stderr, "Failed to open kernel 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.\n");
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;
}
printf("Bytes per sector: %d\n", fat.header.base.bytes_per_sector);
printf("Kernel offset: %d, difference from bytes per sector: %d\n", kernel_offset, kernel_offset % fat.header.base.bytes_per_sector);
fflush(stdout);
if (kernel_offset % fat.header.base.bytes_per_sector != 0) {
fprintf(stderr, "Error: STAGE1 not aligned to sector\n");
return 1;
}
fseek(image, 0, SEEK_SET);
char mbr[512];
fread(mbr, 1, 512, image);
printf("Kernel size: %d", kernel_size);
os_bool found = OS_FALSE;
os_u8* ptr = mbr;
for (int i = 0; i < 512 - sizeof(MBR_ReadPacket); i++) {
MBR_ReadPacket * packet = (MBR_ReadPacket*)ptr;
if(packet->sig_0 == MBR_PACKET_SIG_0 && packet->sig_1 == MBR_PACKET_SIG_1) {
packet->lba = kernel_offset / fat.header.base.bytes_per_sector;
packet->blocks = (kernel_size / fat.header.base.bytes_per_sector) + ((kernel_size % fat.header.base.bytes_per_sector) == 0 ? 0 : 1);
packet->buffer_offset = 0x0000;
packet->buffer_segment = 0x1000;
//packet->buffer = 0x10000;
found = OS_TRUE;
break;
}
ptr++;
}
if (found == OS_FALSE) {
fprintf(stderr, "Error: could not find READ_PACKET markers\n");
return 1;
}
fseek(image, 0, SEEK_SET);
fwrite(mbr, 1, 512, image);
fclose(image);
return 0;
}