Skip to content

Commit

Permalink
Boot loader code, kernel boot and startup routine
Browse files Browse the repository at this point in the history
  • Loading branch information
shoily committed Feb 12, 2020
0 parents commit c67a052
Show file tree
Hide file tree
Showing 5 changed files with 356 additions and 0 deletions.
87 changes: 87 additions & 0 deletions boot32.S
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
12 changes: 12 additions & 0 deletions boot32.ld
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); }
}
183 changes: 183 additions & 0 deletions bootldr.S
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
25 changes: 25 additions & 0 deletions bootldr.ld
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
}
49 changes: 49 additions & 0 deletions start.c
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;
}

0 comments on commit c67a052

Please sign in to comment.