[Host/KernelCopy] First implementation of KernelCopy
[LibFat] Add libfat [Stage1] Add stage1 project
This commit is contained in:
parent
2329bce7d3
commit
642385797c
15 changed files with 352 additions and 90 deletions
|
|
@ -5,4 +5,5 @@ set(CMAKE_C_STANDARD 17)
|
|||
|
||||
add_subdirectory(mbr)
|
||||
add_subdirectory(libfat)
|
||||
add_subdirectory(stage1)
|
||||
add_subdirectory(rawimg)
|
||||
|
|
|
|||
|
|
@ -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 "")
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
2
host/kernelcopy/CMakeLists.txt
Normal file
2
host/kernelcopy/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
add_executable(kernelcopy kernelcopy.c)
|
||||
target_link_libraries(kernelcopy host libfat)
|
||||
144
host/kernelcopy/kernelcopy.c
Normal file
144
host/kernelcopy/kernelcopy.c
Normal 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;
|
||||
}
|
||||
3
host/libhost/CMakeLists.txt
Normal file
3
host/libhost/CMakeLists.txt
Normal 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)
|
||||
10
host/libhost/include/libhost.h
Normal file
10
host/libhost/include/libhost.h
Normal 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
86
host/libhost/libhost.c
Normal 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;
|
||||
}
|
||||
|
|
@ -1,2 +1,2 @@
|
|||
add_executable(mbrcopy mbrcopy.c)
|
||||
target_link_libraries(mbrcopy libfat)
|
||||
target_link_libraries(mbrcopy host libfat)
|
||||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
10
mbr/mbr.asm
10
mbr/mbr.asm
|
|
@ -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
2
stage1/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
add_executable(stage1 stage1.c)
|
||||
target_link_libraries(stage1 libfat)
|
||||
8
stage1/stage1.c
Normal file
8
stage1/stage1.c
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
//
|
||||
// Created by barba on 06/10/2022.
|
||||
//
|
||||
|
||||
|
||||
int main() {
|
||||
return 0;
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue