From dbaad4cf880f7c919994836cc4815078c7ec5d18 Mon Sep 17 00:00:00 2001 From: Alexander Myltsev Date: Wed, 21 Sep 2022 18:25:06 +0300 Subject: [PATCH] Add dummy kernel. --- Makefile | 14 +++++++++-- kernel.c | 7 ++++++ mbr.S | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 96 insertions(+), 2 deletions(-) create mode 100644 kernel.c diff --git a/Makefile b/Makefile index 3be925f..e5bb583 100644 --- a/Makefile +++ b/Makefile @@ -1,10 +1,11 @@ AS=x86_64-elf-as LD=x86_64-elf-ld +CC=x86_64-elf-gcc -run: mbr.bin +run: image.bin qemu-system-i386 -drive format=raw,file=$< -debug: mbr.bin +debug: image.bin qemu-system-i386 -drive format=raw,file=$< -s -S & i386-elf-gdb \ -ex "target remote localhost:1234" \ @@ -12,6 +13,15 @@ debug: mbr.bin -ex "break *0x7c00" \ -ex "continue" +image.bin: mbr.bin kernel.bin + cat $^ >$@ + +kernel.bin: kernel.o + $(LD) -m elf_i386 -o $@ -Ttext 0x1000 $^ --oformat binary + +%.o: %.c + $(CC) -m32 -ffreestanding -c $< -o $@ + %.o: %.S $(AS) $^ -o $@ diff --git a/kernel.c b/kernel.c new file mode 100644 index 0000000..a1e5157 --- /dev/null +++ b/kernel.c @@ -0,0 +1,7 @@ +asm("jmp main"); + +int main() { + char* video_memory = (char*) 0xb8000; + *video_memory = 'X'; + return 0; +} diff --git a/mbr.S b/mbr.S index 419ec05..1b51de8 100644 --- a/mbr.S +++ b/mbr.S @@ -1,12 +1,56 @@ .code16 .global _start _start: + mov %dl, boot_drive mov $banner, %si call print_string + call load_kernel + call switch_to_32bit + jmp . // loop forever +.equ KERNEL_OFFSET, 0x1000 +load_kernel: + mov $2, %ah // read mode + mov $2, %al // sectors to read + mov $2, %cl // start from sector 2 + mov $0, %ch // cylinder 0 + mov $0, %dh // head 0 + mov $KERNEL_OFFSET, %bx // bx -> destination + mov boot_drive, %dl // dl -> disk + int $0x13 + // no error checking, let's hope it works + ret + + +switch_to_32bit: + cli // 1. disable interrupts + lgdt gdt_descriptor // 2. load GDT descriptor + mov %cr0, %eax + or $1, %eax // 3. enable protected mode + mov %eax, %cr0 + ljmp $CODE_SEG, $init_32bit // 4. far jump + + +.code32 +init_32bit: + mov $DATA_SEG, %ax // 5. update segment registers + mov %ax, %ds + mov %ax, %ss + mov %ax, %es + mov %ax, %fs + mov %ax, %gs + + mov $0x90000, %ebp // 6. setup stack + mov %ebp, %esp + + call KERNEL_OFFSET // 7. jump to the kernel + jmp . // 8. loop forever + + +.code16 print_string: mov $0x0e, %ah // "teletype output" repeat: @@ -21,8 +65,41 @@ done: ret . = _start + 256 # pad to 256 bytes +boot_drive: + .byte 0 banner: .asciz "YABLOKO bootloader started\r\n" +gdt_start: + .quad 0x0 // null descriptor + +// code segment descriptor +gdt_code: + .word 0xffff // segment length, bits 0-15 + .word 0x0 // segment base, bits 0-15 + .byte 0x0 // segment base, bits 16-23 + .byte 0b10011010 // flags (8 bits) + .byte 0b11001111 // flags (4 bits) + segment length, bits 16-19 + .byte 0x0 // segment base, bits 24-31 + +// data segment descriptor +gdt_data: + .word 0xffff // segment length, bits 0-15 + .word 0x0 // segment base, bits 0-15 + .byte 0x0 // segment base, bits 16-23 + .byte 0b10010010 // flags (8 bits) + .byte 0b11001111 // flags (4 bits) + segment length, bits 16-19 + .byte 0x0 // segment base, bits 24-31 + +gdt_end: + +// GDT descriptor +gdt_descriptor: + .word gdt_end - gdt_start - 1 // size (16 bit) + .int gdt_start // address (32 bit) + +.equ CODE_SEG, gdt_code - gdt_start +.equ DATA_SEG, gdt_data - gdt_start + . = _start + 510 # pad to 510 bytes .byte 0x55, 0xaa # boot sector magic value