-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Boot loader code, kernel boot and startup routine
- Loading branch information
0 parents
commit c67a052
Showing
5 changed files
with
356 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
/*****************************************************************************/ | ||
/* File: boot32.S */ | ||
/* */ | ||
/* Description: This is the boot code for kernel. */ | ||
/* It should be written at sector 1 (second sector). Uses boot32.ld. */ | ||
/* It turns on paging and maps the first 4MB of kernel at 0x800000000 */ | ||
/* virtual memory location. It then calls start_kernel routine from start.c */ | ||
/* */ | ||
/* Author: Shoily O Rahman */ | ||
/* */ | ||
/* Date: Feb 11, 2020 */ | ||
/* */ | ||
/*****************************************************************************/ | ||
|
||
.code32 | ||
.text | ||
|
||
.equ KERNEL_VIRT_ADDR, 0x80000000 | ||
.equ KERNEL_PGDIR_ENTRY, (KERNEL_VIRT_ADDR >> 20) | ||
.equ STACK_SIZE, 0x1000 | ||
|
||
.globl boot_pg_table | ||
.globl _start | ||
_start: | ||
|
||
// populating page directory entries for identity mapping and at 0x80000000 | ||
movl $boot_pg_table-KERNEL_VIRT_ADDR, %edx | ||
movl $boot_page_directory-KERNEL_VIRT_ADDR, %edi | ||
leal 0x1(%edx), %eax | ||
leal KERNEL_PGDIR_ENTRY(%edi), %ecx | ||
movl %eax, (%edi) | ||
movl %eax, (%ecx) | ||
|
||
// populating page table entries that maps 4MB spaces starting from 0x100000 (1MB) | ||
cld | ||
movl $0x3, %eax | ||
movl $1024, %ecx | ||
movl $boot_pg_table-KERNEL_VIRT_ADDR, %edi | ||
|
||
1: | ||
stosl | ||
addl $0x1000, %eax | ||
loop 1b | ||
|
||
// turning on paging | ||
movl $boot_page_directory-KERNEL_VIRT_ADDR, %eax | ||
movl %eax, %cr3 | ||
movl %cr0, %eax | ||
orl $0x80000000, %eax | ||
movl %eax, %cr0 | ||
|
||
// jump to kernel address 0x80000000 | ||
ljmpl $0x8, $highaddress | ||
|
||
highaddress: | ||
|
||
// invalidate identity mapping | ||
movl $0, (boot_page_directory) | ||
invlpg (0) | ||
|
||
// setting up kernel mode stack in high address | ||
movl $(stack+STACK_SIZE), %esp | ||
movl %esp, %ebp | ||
|
||
// call start_kernel routine | ||
pushl %ebp | ||
call start_kernel | ||
|
||
loop: | ||
jmp loop | ||
|
||
.data | ||
.p2align 12 | ||
|
||
// page table for kernel | ||
boot_pg_table: | ||
.fill 1024, 4, 0 | ||
|
||
// page directory | ||
boot_page_directory: | ||
.fill 1024, 4, 0 | ||
|
||
.bss | ||
.p2align 5 | ||
|
||
// stack in high address | ||
.lcomm stack, STACK_SIZE |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
OUTPUT_FORMAT(elf32-i386) | ||
OUTPUT_ARCH(i386) | ||
|
||
ENTRY(_start) | ||
|
||
SECTIONS | ||
{ | ||
. = 0X80100000; | ||
.text : AT(ADDR(.text) - 0x80000000) {*(.text); } | ||
.data : AT(ADDR(.data) - 0x80000000) {*(.data); } | ||
.bss : AT(ADDR(.bss) - 0x80000000) {*(.bss); } | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,183 @@ | ||
/*****************************************************************************/ | ||
/* File: bootldr.S */ | ||
/* */ | ||
/* Description: This is the boot loader. It should be written at sector 0. */ | ||
/* It loads the kernel boot code from sector 1 at addres 0x7000, */ | ||
/* copies to 0x100000 (1MB) address, turns on protected mode and jumps */ | ||
/* to that address. It uses bootlds.ld to map itself at address 0x7C00 */ | ||
/* */ | ||
/* Author: Shoily O Rahman */ | ||
/* */ | ||
/* Date: Feb 11, 2020 */ | ||
/* */ | ||
/*****************************************************************************/ | ||
|
||
// machine boots in 16bit real mode | ||
.code16 | ||
|
||
.text | ||
.globl _start | ||
_start: | ||
|
||
// enable A20 line | ||
cli | ||
push %ax | ||
movb $0xdd, %al | ||
outb %al, $0x64 | ||
pop %ax | ||
sti | ||
|
||
// read kernel from second sector | ||
xorw %ax, %ax | ||
movw %ax, %ds | ||
movw %ax, %es | ||
movw %ax, %ss | ||
|
||
// memory buffer location of disk address packet | ||
movw dap, %si | ||
xorw %ax, %ax | ||
movw %ax, 4(%si) | ||
|
||
// read only one sector to load kernel | ||
movw $1, %ax | ||
movw %ax, 2(%si) | ||
|
||
// size of the disk packet | ||
movw $0x0010, (%si) | ||
|
||
// kernel is located in sector number 1. Read it. | ||
movl $1, %ebx | ||
movl %ebx, 8(%si) | ||
movl $0, %ebx | ||
movl %ebx, 12(%si) | ||
|
||
// segment of buffer address | ||
movw $0x7000, 6(%si) | ||
|
||
// set stack location at 4K offset | ||
movl $0x1000, %ebp | ||
movl %ebp, %esp | ||
|
||
// issue int 13h function 42h to read sector | ||
movb $0x42, %ah | ||
int $0x13 | ||
|
||
jc lba_read_error | ||
|
||
// initialize protected mode | ||
cli | ||
xor %ax, %ax | ||
movw %ax, %ds | ||
movw %ax, %es | ||
movw %ax, %ss | ||
sti | ||
|
||
// resets disk system | ||
movb %dl, boot_drive | ||
int $0x13 | ||
|
||
// loads gdt | ||
xorw %ax, %ax | ||
movw %ax, %ds | ||
lgdt gdtdescriptor | ||
|
||
// turn on protected mode | ||
movl %cr0, %eax | ||
orl $1, %eax | ||
movl %eax, %cr0 | ||
|
||
// jump to protected mode | ||
ljmpl $0x8,$protectedmodeaddress | ||
|
||
lba_read_error: | ||
|
||
// write 'X' in the screen to indicate read error | ||
movb $'X', %al | ||
movb $0x0e, %ah | ||
int $0x10 | ||
jmp loop | ||
|
||
// protected mode code | ||
.code32 | ||
|
||
protectedmodeaddress: | ||
|
||
cli | ||
|
||
// data descriptor is located in 0x10 location of GDT | ||
movl $0x10, %eax | ||
movl %eax, %ds | ||
movl %eax, %es | ||
movl %eax, %ss | ||
movl %eax, %fs | ||
movl %eax, %gs | ||
|
||
// initialize protected mode stack | ||
movl protectedmodestack, %eax | ||
movl %eax, %esp | ||
movl %eax, %ebp | ||
|
||
// copy kernel to 1 MB offset | ||
cld | ||
movl $0x100, %ecx | ||
movl $0x70000, %esi | ||
movl $0x100000, %edi | ||
rep movsw | ||
|
||
// call kernel at 1 MB | ||
movl $0x100000, %eax | ||
call *%eax | ||
|
||
loop: | ||
jmp loop | ||
|
||
protectedmodestack: | ||
.long 0xf000 | ||
|
||
boot_drive: | ||
.byte 0 | ||
mode: | ||
.byte 0 | ||
dap: /* disk address packet */ | ||
.long 0 | ||
.long 0 | ||
.long 0 | ||
.long 0 | ||
|
||
// global descriptor table (GDT) | ||
.p2align 5 | ||
gdt: | ||
// offset 0x0 - NULL descriptor | ||
.quad 0 | ||
|
||
code_seg_addr: | ||
// offset 0x8 - cs should point to this descriptor | ||
.word 0xFFFF | ||
.word 0 | ||
.byte 0 | ||
.byte 0x9A | ||
.byte 0xCF | ||
.byte 0 | ||
|
||
data_seg_addr: | ||
// offset 0x10 - ds, ss, es, fs, and gs should point to this descriptor | ||
.word 0xFFFF | ||
.word 0 | ||
.byte 0 | ||
.byte 0x92 | ||
.byte 0xCF | ||
.byte 0 | ||
|
||
end_of_gdt: | ||
|
||
gdtdescriptor: | ||
.word end_of_gdt-gdt-1 | ||
.long gdt | ||
|
||
.equ code_seg, code_seg_addr-gdt | ||
.equ data_seg, data_seg_addr-gdt | ||
|
||
// boot loader signature | ||
.section ".bootsig","a" | ||
.byte 0x55 | ||
.byte 0xaa |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
OUTPUT_FORMAT(elf32-i386) | ||
OUTPUT_ARCH(i386) | ||
|
||
ENTRY(_start) | ||
|
||
PHDRS { | ||
text PT_LOAD FILEHDR PHDRS; | ||
data PT_LOAD; | ||
bss PT_LOAD; | ||
bootsig PT_LOAD; | ||
} | ||
|
||
SECTIONS | ||
{ | ||
. = 0X7C00; | ||
.text : | ||
{*(.text); } : text | ||
.data : | ||
{*(.data); } : data | ||
.bss : | ||
{*(.bss); } : bss | ||
. = 0x7DFE; | ||
.bootsig : | ||
{*(.bootsig); } : bootsig | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
/*****************************************************************************/ | ||
/* File: start.c */ | ||
/* */ | ||
/* Description: Kernel initialization code. */ | ||
/* start_kernel routine is called from boot32.S. */ | ||
/* */ | ||
/* Author: Shoily O Rahman */ | ||
/* */ | ||
/* Date: Feb 11, 2020 */ | ||
/* */ | ||
/*****************************************************************************/ | ||
|
||
typedef int bool; | ||
#define true 1 | ||
#define false 0 | ||
|
||
#define VIDEO_BUFFER (0x800b8000) | ||
int vga_buffer_index = 0; | ||
|
||
// | ||
// Outputs a NULL terminated string in VGA buffer | ||
// | ||
void print_vga(char *c, bool newline) { | ||
|
||
unsigned short *p = (unsigned short *)(VIDEO_BUFFER+vga_buffer_index); | ||
|
||
while(*c) { | ||
|
||
*p = (4 << 8 | *c); | ||
c++; | ||
vga_buffer_index += 2; | ||
p++; | ||
} | ||
|
||
if (newline) { | ||
vga_buffer_index += (160 - vga_buffer_index); | ||
} | ||
} | ||
|
||
// | ||
// Start kernel routine | ||
// | ||
|
||
int start_kernel(void) { | ||
|
||
print_vga("Kernel started", true); | ||
|
||
return 0; | ||
} |