Skip to content

Commit

Permalink
Added MBR support to stage2
Browse files Browse the repository at this point in the history
  • Loading branch information
chibicitiberiu committed Aug 9, 2022
1 parent b8688b1 commit ab1eaa6
Show file tree
Hide file tree
Showing 10 changed files with 130 additions and 24 deletions.
1 change: 1 addition & 0 deletions scripts/debug.sh
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ esac

cat > .gdb_script.gdb << EOF
b *0x7c00
set disassembly-flavor intel
layout asm
target remote | qemu-system-i386 $QEMU_ARGS
EOF
Expand Down
16 changes: 15 additions & 1 deletion src/bootloader/stage1/boot.asm
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,14 @@ section .entry
global start

start:
; move partition entry from MBR to a different location so we
; don't overwrite it (which is passed through DS:SI)
mov ax, PARTITION_ENTRY_SEGMENT
mov es, ax
mov di, PARTITION_ENTRY_OFFSET
mov cx, 16
rep movsb
; setup data segments
mov ax, 0 ; can't set ds/es directly
mov ds, ax
Expand Down Expand Up @@ -118,7 +126,9 @@ section .entry
; jump to our kernel
mov dl, [ebr_drive_number] ; boot device in dl

mov si, PARTITION_ENTRY_OFFSET
mov di, PARTITION_ENTRY_SEGMENT
mov ax, STAGE2_LOAD_SEGMENT ; set segment registers
mov ds, ax
mov es, ax
Expand Down Expand Up @@ -329,6 +339,10 @@ section .data
STAGE2_LOAD_SEGMENT equ 0x0
STAGE2_LOAD_OFFSET equ 0x500

PARTITION_ENTRY_SEGMENT equ 0x2000
PARTITION_ENTRY_OFFSET equ 0x0


section .data
global stage2_location
stage2_location: times 30 db 0
Expand Down
9 changes: 9 additions & 0 deletions src/bootloader/stage2/entry.asm
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ entry:

; save boot drive
mov [g_BootDrive], dl
mov [g_BootPartitionOff], si
mov [g_BootPartitionSeg], di

; setup stack
mov ax, ds
Expand Down Expand Up @@ -54,6 +56,11 @@ entry:
call _init

; expect boot drive in dl, send it as argument to cstart function
mov dx, [g_BootPartitionSeg]
shl edx, 16
mov dx, [g_BootPartitionOff]
push edx

xor edx, edx
mov dl, [g_BootDrive]
push edx
Expand Down Expand Up @@ -171,3 +178,5 @@ g_GDTDesc: dw g_GDTDesc - g_GDT - 1 ; limit = size of GDT
dd g_GDT ; address of GDT

g_BootDrive: db 0
g_BootPartitionSeg: dw 0
g_BootPartitionOff: dw 0
36 changes: 22 additions & 14 deletions src/bootloader/stage2/fat.c
Original file line number Diff line number Diff line change
Expand Up @@ -70,19 +70,25 @@ typedef struct
static FAT_Data* g_Data;
static uint8_t* g_Fat = NULL;
static uint32_t g_DataSectionLba;
static uint8_t g_FatType;


bool FAT_ReadBootSector(DISK* disk)
bool FAT_ReadBootSector(Partition* disk)
{
return DISK_ReadSectors(disk, 0, 1, g_Data->BS.BootSectorBytes);
return Partition_ReadSectors(disk, 0, 1, g_Data->BS.BootSectorBytes);
}

bool FAT_ReadFat(DISK* disk)
bool FAT_ReadFat(Partition* disk)
{
return DISK_ReadSectors(disk, g_Data->BS.BootSector.ReservedSectors, g_Data->BS.BootSector.SectorsPerFat, g_Fat);
return Partition_ReadSectors(disk, g_Data->BS.BootSector.ReservedSectors, g_Data->BS.BootSector.SectorsPerFat, g_Fat);
}

bool FAT_Initialize(DISK* disk)
void FAT_Detect()
{

}

bool FAT_Initialize(Partition* disk)
{
g_Data = (FAT_Data*)MEMORY_FAT_ADDR;

Expand All @@ -95,6 +101,8 @@ bool FAT_Initialize(DISK* disk)

// read FAT
g_Fat = (uint8_t*)g_Data + sizeof(FAT_Data);
printf("BS.BytesPerSector = %x\n", g_Data->BS.BootSector.BytesPerSector);
printf("BS.SectorsPerFat = %x\n", g_Data->BS.BootSector.SectorsPerFat);
uint32_t fatSize = g_Data->BS.BootSector.BytesPerSector * g_Data->BS.BootSector.SectorsPerFat;
if (sizeof(FAT_Data) + fatSize >= MEMORY_FAT_SIZE)
{
Expand All @@ -121,7 +129,7 @@ bool FAT_Initialize(DISK* disk)
g_Data->RootDirectory.CurrentCluster = rootDirLba;
g_Data->RootDirectory.CurrentSectorInCluster = 0;

if (!DISK_ReadSectors(disk, rootDirLba, 1, g_Data->RootDirectory.Buffer))
if (!Partition_ReadSectors(disk, rootDirLba, 1, g_Data->RootDirectory.Buffer))
{
printf("FAT: read root directory failed\r\n");
return false;
Expand All @@ -143,7 +151,7 @@ uint32_t FAT_ClusterToLba(uint32_t cluster)
return g_DataSectionLba + (cluster - 2) * g_Data->BS.BootSector.SectorsPerCluster;
}

FAT_File* FAT_OpenEntry(DISK* disk, FAT_DirectoryEntry* entry)
FAT_File* FAT_OpenEntry(Partition* disk, FAT_DirectoryEntry* entry)
{
// find empty handle
int handle = -1;
Expand All @@ -170,7 +178,7 @@ FAT_File* FAT_OpenEntry(DISK* disk, FAT_DirectoryEntry* entry)
fd->CurrentCluster = fd->FirstCluster;
fd->CurrentSectorInCluster = 0;

if (!DISK_ReadSectors(disk, FAT_ClusterToLba(fd->CurrentCluster), 1, fd->Buffer))
if (!Partition_ReadSectors(disk, FAT_ClusterToLba(fd->CurrentCluster), 1, fd->Buffer))
{
printf("FAT: open entry failed - read error cluster=%u lba=%u\n", fd->CurrentCluster, FAT_ClusterToLba(fd->CurrentCluster));
for (int i = 0; i < 11; i++)
Expand All @@ -193,7 +201,7 @@ uint32_t FAT_NextCluster(uint32_t currentCluster)
return (*(uint16_t*)(g_Fat + fatIndex)) >> 4;
}

uint32_t FAT_Read(DISK* disk, FAT_File* file, uint32_t byteCount, void* dataOut)
uint32_t FAT_Read(Partition* disk, FAT_File* file, uint32_t byteCount, void* dataOut)
{
// get file data
FAT_FileData* fd = (file->Handle == ROOT_DIRECTORY_HANDLE)
Expand Down Expand Up @@ -226,7 +234,7 @@ uint32_t FAT_Read(DISK* disk, FAT_File* file, uint32_t byteCount, void* dataOut)
++fd->CurrentCluster;

// read next sector
if (!DISK_ReadSectors(disk, fd->CurrentCluster, 1, fd->Buffer))
if (!Partition_ReadSectors(disk, fd->CurrentCluster, 1, fd->Buffer))
{
printf("FAT: read error!\r\n");
break;
Expand All @@ -249,7 +257,7 @@ uint32_t FAT_Read(DISK* disk, FAT_File* file, uint32_t byteCount, void* dataOut)
}

// read next sector
if (!DISK_ReadSectors(disk, FAT_ClusterToLba(fd->CurrentCluster) + fd->CurrentSectorInCluster, 1, fd->Buffer))
if (!Partition_ReadSectors(disk, FAT_ClusterToLba(fd->CurrentCluster) + fd->CurrentSectorInCluster, 1, fd->Buffer))
{
printf("FAT: read error!\r\n");
break;
Expand All @@ -261,7 +269,7 @@ uint32_t FAT_Read(DISK* disk, FAT_File* file, uint32_t byteCount, void* dataOut)
return u8DataOut - (uint8_t*)dataOut;
}

bool FAT_ReadEntry(DISK* disk, FAT_File* file, FAT_DirectoryEntry* dirEntry)
bool FAT_ReadEntry(Partition* disk, FAT_File* file, FAT_DirectoryEntry* dirEntry)
{
return FAT_Read(disk, file, sizeof(FAT_DirectoryEntry), dirEntry) == sizeof(FAT_DirectoryEntry);
}
Expand All @@ -279,7 +287,7 @@ void FAT_Close(FAT_File* file)
}
}

bool FAT_FindFile(DISK* disk, FAT_File* file, const char* name, FAT_DirectoryEntry* entryOut)
bool FAT_FindFile(Partition* disk, FAT_File* file, const char* name, FAT_DirectoryEntry* entryOut)
{
char fatName[12];
FAT_DirectoryEntry entry;
Expand Down Expand Up @@ -313,7 +321,7 @@ bool FAT_FindFile(DISK* disk, FAT_File* file, const char* name, FAT_DirectoryEnt
return false;
}

FAT_File* FAT_Open(DISK* disk, const char* path)
FAT_File* FAT_Open(Partition* disk, const char* path)
{
char name[MAX_PATH_SIZE];

Expand Down
10 changes: 5 additions & 5 deletions src/bootloader/stage2/fat.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#pragma once
#include "stdint.h"
#include "disk.h"
#include "mbr.h"

typedef struct
{
Expand Down Expand Up @@ -37,8 +37,8 @@ enum FAT_Attributes
FAT_ATTRIBUTE_LFN = FAT_ATTRIBUTE_READ_ONLY | FAT_ATTRIBUTE_HIDDEN | FAT_ATTRIBUTE_SYSTEM | FAT_ATTRIBUTE_VOLUME_ID
};

bool FAT_Initialize(DISK* disk);
FAT_File * FAT_Open(DISK* disk, const char* path);
uint32_t FAT_Read(DISK* disk, FAT_File* file, uint32_t byteCount, void* dataOut);
bool FAT_ReadEntry(DISK* disk, FAT_File* file, FAT_DirectoryEntry* dirEntry);
bool FAT_Initialize(Partition* disk);
FAT_File * FAT_Open(Partition* disk, const char* path);
uint32_t FAT_Read(Partition* disk, FAT_File* file, uint32_t byteCount, void* dataOut);
bool FAT_ReadEntry(Partition* disk, FAT_File* file, FAT_DirectoryEntry* dirEntry);
void FAT_Close(FAT_File* file);
14 changes: 10 additions & 4 deletions src/bootloader/stage2/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,34 +5,40 @@
#include "fat.h"
#include "memdefs.h"
#include "memory.h"
#include "mbr.h"

uint8_t* KernelLoadBuffer = (uint8_t*)MEMORY_LOAD_KERNEL;
uint8_t* Kernel = (uint8_t*)MEMORY_KERNEL_ADDR;

typedef void (*KernelStart)();

void __attribute__((cdecl)) start(uint16_t bootDrive)
void __attribute__((cdecl)) start(uint16_t bootDrive, void* partition)
{
clrscr();

printf("partition=%x\r\n", partition);

DISK disk;
if (!DISK_Initialize(&disk, bootDrive))
{
printf("Disk init error\r\n");
goto end;
}

if (!FAT_Initialize(&disk))
Partition part;
MBR_DetectPartition(&part, &disk, partition);

if (!FAT_Initialize(&part))
{
printf("FAT init error\r\n");
goto end;
}

// load kernel
FAT_File* fd = FAT_Open(&disk, "/kernel.bin");
FAT_File* fd = FAT_Open(&part, "/kernel.bin");
uint32_t read;
uint8_t* kernelBuffer = Kernel;
while ((read = FAT_Read(&disk, fd, MEMORY_LOAD_SIZE, KernelLoadBuffer)))
while ((read = FAT_Read(&part, fd, MEMORY_LOAD_SIZE, KernelLoadBuffer)))
{
memcpy(kernelBuffer, KernelLoadBuffer, read);
kernelBuffer += read;
Expand Down
46 changes: 46 additions & 0 deletions src/bootloader/stage2/mbr.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#include "mbr.h"
#include "memory.h"
#include "stdio.h"

typedef struct {
// 0x00 1 Drive attributes (bit 7 set = active or bootable)
uint8_t attributes;

// 0x01 3 CHS Address of partition start
uint8_t chsStart[3];

// 0x04 1 Partition type
uint8_t partitionType;

// 0x05 3 CHS address of last partition sector
uint8_t chsEnd[3];

// 0x08 4 LBA of partition start
uint32_t lbaStart;

// 0x0C 4 Number of sectors in partition
uint32_t size;

} __attribute__((packed)) MBR_Entry;


void MBR_DetectPartition(Partition* part, DISK* disk, void* partition)
{
if (disk->id < 0x80) {
part->partitionOffset = 0;
part->partitionSize = (uint32_t)(disk->cylinders)
* (uint32_t)(disk->heads)
* (uint32_t)(disk->sectors);
}

else {
MBR_Entry* entry = (MBR_Entry*)segoffset_to_linear(partition);
part->partitionOffset = entry->lbaStart;
part->partitionSize = entry->size;
}
}

bool Partition_ReadSectors(Partition* part, uint32_t lba, uint8_t sectors, void* lowerDataOut)
{
return DISK_ReadSectors(part->disk, lba + part->partitionOffset, sectors, lowerDataOut);
}
14 changes: 14 additions & 0 deletions src/bootloader/stage2/mbr.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#pragma once
#include "disk.h"
#include <stdbool.h>
#include <stdint.h>

typedef struct {
DISK* disk;
uint32_t partitionOffset;
uint32_t partitionSize;
} Partition;

void MBR_DetectPartition(Partition* part, DISK* disk, void* partitionEntry);

bool Partition_ReadSectors(Partition* disk, uint32_t lba, uint8_t sectors, void* lowerDataOut);
7 changes: 7 additions & 0 deletions src/bootloader/stage2/memory.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,10 @@ int memcmp(const void* ptr1, const void* ptr2, uint16_t num)

return 0;
}

void* segoffset_to_linear(void* addr)
{
uint32_t offset = (uint32_t)(addr) & 0xFFFF;
uint32_t segment = (uint32_t)(addr) >> 16;
return (void*)(segment * 16 + offset);
}
1 change: 1 addition & 0 deletions src/bootloader/stage2/memory.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ void* memcpy(void* dst, const void* src, uint16_t num);
void* memset(void* ptr, int value, uint16_t num);
int memcmp(const void* ptr1, const void* ptr2, uint16_t num);

void* segoffset_to_linear(void* addr);

0 comments on commit ab1eaa6

Please sign in to comment.