[MBR] Add GDT setup
[Host/Kernelcopy] Add support for direct writing into MBR's DAP [Rawimg] Add kernelcopy support
This commit is contained in:
parent
f7d06b8ff3
commit
d57078cc2d
12 changed files with 205 additions and 64 deletions
|
|
@ -1,8 +1,9 @@
|
|||
cmake_minimum_required(VERSION 3.21)
|
||||
|
||||
project(os3_host C)
|
||||
project(os3_host C CXX)
|
||||
|
||||
add_subdirectory(../libfat ${CMAKE_CURRENT_BINARY_DIR}/libfat)
|
||||
add_subdirectory(libhost)
|
||||
add_subdirectory(mbrcopy)
|
||||
add_subdirectory(kernelcopy)
|
||||
add_subdirectory(kernelcopy)
|
||||
add_subdirectory(gdtCreator)
|
||||
1
host/gdtCreator/CMakeLists.txt
Normal file
1
host/gdtCreator/CMakeLists.txt
Normal file
|
|
@ -0,0 +1 @@
|
|||
add_executable(gdtCreator gdtCreator.cpp)
|
||||
51
host/gdtCreator/gdtCreator.cpp
Normal file
51
host/gdtCreator/gdtCreator.cpp
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
//
|
||||
// Created by John Stefanelli on 13/01/23.
|
||||
//
|
||||
|
||||
#include <iostream>
|
||||
|
||||
uint64_t makeEntry(uint32_t base, uint16_t limit, bool present, unsigned char dpl, bool executable, bool exec_write) {
|
||||
uint64_t value = 0x0;
|
||||
//auto* target = (uint8_t*) &value;
|
||||
|
||||
uint8_t access_byte = (present ? 0x80 : 0x00) + ((dpl & 0x3) << 5) + 16 + (executable ? 8 : 0) + (exec_write ? 2 : 0);
|
||||
uint8_t flags = 0xC;
|
||||
|
||||
value |= limit & 0xFFFF; //Low 16 bits of limit
|
||||
value |= (base & 0xFFFFFF) << 16; //Low 24 bits of base
|
||||
|
||||
value |= ((uint64_t) access_byte) << 40;
|
||||
value |= ((uint64_t) limit & 0xF0000) << 32;
|
||||
value |= ((uint64_t) flags) << 52;
|
||||
value |= ((uint64_t) base & 0xFF000000) << 32;
|
||||
|
||||
|
||||
/*
|
||||
// Encode the limit
|
||||
target[0] = limit & 0xFF;
|
||||
target[1] = (limit >> 8) & 0xFF;
|
||||
target[6] = (limit >> 16) & 0x0F;
|
||||
|
||||
// Encode the base
|
||||
target[2] = base & 0xFF;
|
||||
target[3] = (base >> 8) & 0xFF;
|
||||
target[4] = (base >> 16) & 0xFF;
|
||||
target[7] = (base >> 24) & 0xFF;
|
||||
|
||||
// Encode the access byte
|
||||
target[5] = access_byte;
|
||||
|
||||
// Encode the flags
|
||||
target[6] |= (flags << 4);
|
||||
*/
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
std::cout << std::hex << "Code: " << makeEntry(0, 0xFFFF, true, 0x0, true, true) << std::endl;
|
||||
std::cout << std::hex << "Data: " << makeEntry(0, 0xFFFF, true, 0x0, false, true) << std::endl;
|
||||
std::cout << std::hex << "User Code: " << makeEntry(0, 0xFFFF, true, 0x3, true, true) << std::endl;
|
||||
std::cout << std::hex << "User Data: " << makeEntry(0, 0xFFFF, true, 0x3, false, true) << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -19,12 +19,27 @@ typedef struct _MBR_BuildSettings {
|
|||
} 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_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.\n");
|
||||
fprintf(stderr, "Not enough arguments. Usage: kernelcopy <image file> <kernel file>\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
@ -97,7 +112,7 @@ int main(int argc, char** argv) {
|
|||
}
|
||||
kernel_size += read;
|
||||
} while(read > 0);
|
||||
printf("Kernel copy OK.");
|
||||
printf("Kernel copy OK.\n");
|
||||
|
||||
free(buffer);
|
||||
fclose(kernel);
|
||||
|
|
@ -109,6 +124,9 @@ int main(int argc, char** argv) {
|
|||
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;
|
||||
|
|
@ -131,10 +149,32 @@ int main(int argc, char** argv) {
|
|||
ptr++;
|
||||
}
|
||||
|
||||
if (found == OS_FALSE) {
|
||||
fprintf(stderr, "Error: could not find BUILD_SETTINGS markers\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (found == OS_FALSE) {
|
||||
fprintf(stderr, "Error: could not find BUILD_SETTINGS markers\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
found = OS_FALSE;
|
||||
|
||||
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 = 0x0100;
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
add_library(host libhost.c include/libhost.h)
|
||||
add_library(host libhost.c include/libhost.h ../gdtCreator/gdtCreator.cpp)
|
||||
target_link_libraries(host libfat)
|
||||
target_include_directories(host PUBLIC ${CMAKE_CURRENT_LIST_DIR}/include)
|
||||
|
|
@ -51,9 +51,6 @@ os_bool libfat_load_fat_cluster(LFControlBlock* fat, os_u32 target_cluster, os_b
|
|||
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;
|
||||
}
|
||||
|
|
@ -581,7 +578,6 @@ os_u32 libfat_write(LFFile* f, void* buffer, os_u32 buffer_size) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
os_u32 start_position = f->position;
|
||||
os_u32 written = 0;
|
||||
|
||||
while (buffer_size > 0) {
|
||||
|
|
@ -622,7 +618,7 @@ os_u32 libfat_get_true_entry_offset(LFControlBlock* fat, LFDirectoryEntry* entry
|
|||
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;
|
||||
|
||||
return data_offset + (cluster_size * FAT_ENTRY_CLUSTER(entry->entry) - 2);
|
||||
return data_offset + (cluster_size * (FAT_ENTRY_CLUSTER(entry->entry) - 2));
|
||||
}
|
||||
|
||||
os_bool libfat_test_mbr(LFFileHandle* mbr) {
|
||||
|
|
|
|||
112
mbr/mbr.asm
112
mbr/mbr.asm
|
|
@ -16,9 +16,7 @@ fat_header:
|
|||
; 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: Address of packet
|
||||
; - WORD: RETURN ADDRESS
|
||||
; Returns:
|
||||
; AX: 0 = Ok, Other = Error
|
||||
|
|
@ -28,29 +26,18 @@ fat_header:
|
|||
; 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
|
||||
; SP + 8: Address of packet
|
||||
; SP + 10: 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
|
||||
MOV DL, [BP + 10] ; load drive number
|
||||
MOV SI, [BP + 8] ; load address of packet
|
||||
MOV AH, 42h ; set AH to 42h
|
||||
MOV AL, 0h ; set 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
|
||||
|
|
@ -60,6 +47,7 @@ read_sectors_extended_exit: ; leave function
|
|||
POP BP ; restore BP
|
||||
POP SI ; restore SI
|
||||
POP DX ; restore DX
|
||||
RET ; return
|
||||
|
||||
|
||||
; function PRINT: teletype to display
|
||||
|
|
@ -192,7 +180,7 @@ entry:
|
|||
; Set up stack and segments
|
||||
MOV AX, 0 ; set up stack segment
|
||||
MOV SS, AX ; ^^^
|
||||
MOV SP, 0x7C00 ; set up stack pointer (0x6c00-0x7BFF)
|
||||
MOV SP, 0x7bFF ; set up stack pointer (0x6c00-0x7BFE)
|
||||
; 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
|
||||
|
|
@ -201,22 +189,31 @@ entry:
|
|||
MOV FS, AX ; ^^^
|
||||
MOV GS, AX ; ^^^
|
||||
|
||||
PUSH DX ; save drive number (DL)
|
||||
PUSH DX ; save drive number (DL)
|
||||
|
||||
; Load kernel image
|
||||
MOV BX, packet_blocks ; Load address of packet_blocks
|
||||
MOV AX, [BX] ; Load value of packet_blocks
|
||||
CMP AX, 0 ; See if amount of packets to read is 0
|
||||
JE endless_loop ; if no packets are to be loaded, the kernel is not present. Loop endlessly
|
||||
POP AX ; load 'drive number'
|
||||
PUSH AX ; pushing it twice to keep it saved, CBA to mess with SP, BP and stuff right now
|
||||
PUSH AX ; push parameter 'drive number'
|
||||
MOV AX, read_sectors_packet ; load 'packet address'
|
||||
PUSH AX ; push parameter 'packet address'
|
||||
CALL read_sectors_extended ; try to read these damned sectors
|
||||
ADD SP, 4 ; clear previous call parameters
|
||||
|
||||
; 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
|
||||
|
||||
|
||||
; Print message
|
||||
MOV AX, msg ; load address of msg
|
||||
PUSH AX ; push parameter 'address of string'
|
||||
MOV AX, 12 ; load size of msg
|
||||
MOV AX, 14 ; load size of msg
|
||||
PUSH AX ; push parameter 'size of string'
|
||||
CALL print ; call function 'print'
|
||||
|
||||
SUB SP, 4 ; clear previous call parameters
|
||||
ADD SP, 4 ; clear previous call parameters
|
||||
|
||||
; Enable A20
|
||||
CALL check_a20 ; call check_a20. Result in Ax
|
||||
|
|
@ -231,36 +228,45 @@ entry:
|
|||
|
||||
MOV AX, a20_msg ; load address of 'a20_msg'
|
||||
PUSH AX ; push parameter 'address of string'
|
||||
MOV AX, 6 ; load size of 'a20_msg'
|
||||
MOV AX, 8 ; load size of 'a20_msg'
|
||||
PUSH AX ; push parameter 'size of string'
|
||||
CALL print ; print 'a20_msg'
|
||||
JMP endless_loop ; loop endlessly
|
||||
|
||||
|
||||
|
||||
after_a20:
|
||||
|
||||
; load GDT
|
||||
CLI ; disable interrupts
|
||||
MOV AX, gdt ; load address of GDT
|
||||
MOV [gdt_ptr_base], AX ; save address of GDT to gdt_ptr_base
|
||||
LGDT [gdt_ptr_base] ; load GDT
|
||||
|
||||
|
||||
; print message
|
||||
MOV AX, gdt_msg ; load address of 'gdt_ms'
|
||||
PUSH AX ; push parameter 'address of string'
|
||||
MOV AX, 8 ; load size of 'gdt_msg'
|
||||
PUSH AX ; push parameter 'size of string'
|
||||
CALL print ; print 'gdt_msg'
|
||||
|
||||
JMP endless_loop ; loop endlessly
|
||||
|
||||
|
||||
endless_loop:
|
||||
JMP endless_loop ; loop endlessly
|
||||
|
||||
section .data
|
||||
info_marker dw 0x4950
|
||||
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
|
||||
info_end dw 0x4951
|
||||
|
||||
packet_sig_0 dw 0x4954
|
||||
read_sectors_packet:
|
||||
packet_size db 10h
|
||||
packet_reserved db 0h
|
||||
packet_blocks dw 0h
|
||||
packet_buffer dd 0h
|
||||
packet_lba dq 0h
|
||||
packet_size db 10h
|
||||
packet_reserved db 0h
|
||||
packet_blocks dw 0h
|
||||
packet_buffer_off dw 0h
|
||||
packet_buffer_seg dw 0h
|
||||
packet_lba dq 0h
|
||||
packet_sig_1 dw 0x4955
|
||||
|
||||
build_settings:
|
||||
build_settings_magic_0 dw 0x4952
|
||||
|
|
@ -268,5 +274,17 @@ 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"
|
||||
msg db "OS3_KRNL_OK!", 10, 13
|
||||
a20_msg db "NO_A20", 10, 13
|
||||
gdt_msg db "GDT_OK", 10, 13
|
||||
|
||||
gdt:
|
||||
null_sec dq 0x0
|
||||
kernel_code dq 0xc09a000000ffff
|
||||
kernel_data dq 0xc092000000ffff
|
||||
user_code dq 0xc0fa000000ffff
|
||||
user_data dq 0xc0f2000000ffff
|
||||
|
||||
gdt_ptr:
|
||||
gdt_ptr_limit dw 40
|
||||
gdt_ptr_base dd 0
|
||||
|
|
@ -7,10 +7,16 @@ set(IMAGE_GEN_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/mkimg_linux.sh)
|
|||
endif (CMAKE_HOST_APPLE)
|
||||
|
||||
cmake_path(SET MBR_BIN_PATH NORMALIZE "${CMAKE_CURRENT_BINARY_DIR}/../mbr/mbr.bin")
|
||||
add_custom_command(OUTPUT ${MBR_BIN_PATH} COMMAND ${OS3_OBJCOPY_EXE} -O binary -g -S -R .eh_frame $<TARGET_FILE:mbr> ${MBR_BIN_PATH} COMMAND ${OS3_OBJCOPY_EXE} --only-keep-debug $<TARGET_FILE:mbr> ${MBR_BIN_PATH}.sym COMMAND echo "Building .bin file" DEPENDS mbr BYPRODUCTS ${MBR_BIN_PATH}.sym)
|
||||
cmake_path(SET ST1_BIN_PATH NORMALIZE "${CMAKE_CURRENT_BINARY_DIR}/../stage1/stage1.bin")
|
||||
|
||||
add_custom_command(OUTPUT ${MBR_BIN_PATH} COMMAND ${OS3_OBJCOPY_EXE} -O binary -g -S -R .eh_frame $<TARGET_FILE:mbr> ${MBR_BIN_PATH} COMMAND ${OS3_OBJCOPY_EXE} --only-keep-debug $<TARGET_FILE:mbr> ${MBR_BIN_PATH}.sym DEPENDS mbr BYPRODUCTS ${MBR_BIN_PATH}.sym)
|
||||
|
||||
cmake_path(SET MBR_IMAGE_TARGET "${CMAKE_CURRENT_BINARY_DIR}/mbr.img")
|
||||
cmake_path(SET KERNEL_IMAGE_TARGET "${CMAKE_CURRENT_BINARY_DIR}/kernel.img")
|
||||
|
||||
add_custom_command(OUTPUT ${IMAGE_TARGET} COMMAND sh ${IMAGE_GEN_SCRIPT} ${IMAGE_TARGET})
|
||||
add_custom_command(OUTPUT ${MBR_IMAGE_TARGET} COMMAND sh ${CMAKE_CURRENT_SOURCE_DIR}/mkmbrimg.sh ${IMAGE_TARGET} ${MBR_BIN_PATH} ${MBR_IMAGE_TARGET} DEPENDS ${IMAGE_TARGET} ${MBR_BIN_PATH})
|
||||
add_custom_target(image DEPENDS ${MBR_IMAGE_TARGET})
|
||||
|
||||
add_custom_command(OUTPUT ${ST1_BIN_PATH} COMMAND ${OS3_OBJCOPY_EXE} -O binary -g -S -R .eh_frame $<TARGET_FILE:stage1> ${ST1_BIN_PATH} COMMAND ${OS3_OBJCOPY_EXE} --only-keep-debug $<TARGET_FILE:stage1> ${ST1_BIN_PATH}.sym DEPENDS stage1 BYPRODUCTS ${ST1_BIN_PATH}.sym)
|
||||
add_custom_command(OUTPUT ${KERNEL_IMAGE_TARGET} COMMAND sh ${CMAKE_CURRENT_SOURCE_DIR}/mkkernelimg.sh ${MBR_IMAGE_TARGET} ${ST1_BIN_PATH} ${KERNEL_IMAGE_TARGET} DEPENDS ${MBR_IMAGE_TARGET} ${ST1_BIN_PATH})
|
||||
add_custom_target(image DEPENDS ${KERNEL_IMAGE_TARGET})
|
||||
5
rawimg/mkkernelimg.sh
Normal file
5
rawimg/mkkernelimg.sh
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
#!/bin/sh
|
||||
|
||||
BASEDIR=$(dirname "$0")
|
||||
cp "$1" "$3"
|
||||
"${BASEDIR}/../build/host/kernelcopy/kernelcopy" "$3" "$2"
|
||||
|
|
@ -1,2 +1,5 @@
|
|||
add_executable(stage1 stage1.c)
|
||||
target_compile_options(stage1 PUBLIC -ffreestanding)
|
||||
set_target_properties(stage1 PROPERTIES LINK_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/linker.ld)
|
||||
target_link_options(stage1 PRIVATE -T${CMAKE_CURRENT_SOURCE_DIR}/linker.ld)
|
||||
target_link_libraries(stage1 libfat)
|
||||
17
stage1/linker.ld
Normal file
17
stage1/linker.ld
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
ENTRY(main)
|
||||
SECTIONS
|
||||
{
|
||||
. = 0x10000;
|
||||
.text : AT(0x10000){
|
||||
*.o(.text);
|
||||
}
|
||||
.data : {
|
||||
*.o(.data);
|
||||
}
|
||||
.rodata : {
|
||||
*.o(.rodata);
|
||||
}
|
||||
.bss : {
|
||||
*.o(.bss);
|
||||
}
|
||||
}
|
||||
|
|
@ -2,7 +2,10 @@
|
|||
// Created by barba on 06/10/2022.
|
||||
//
|
||||
|
||||
|
||||
int main() {
|
||||
while(1) {
|
||||
|
||||
};
|
||||
|
||||
return 0;
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue