From 3acb3975496cda317cb001523bb8434cb8160515 Mon Sep 17 00:00:00 2001 From: Alexander Myltsev Date: Thu, 17 Nov 2022 23:16:57 +0300 Subject: [PATCH] Use ELF kernel image. --- Makefile | 8 ++++---- drivers/ata.c | 2 +- elf.h | 38 ++++++++++++++++++++++++++++++++++++++ kernel.c | 5 +---- mbr.S | 40 +++++++++++++++++++++++++++++++++++++--- port.h | 10 ++++++++++ 6 files changed, 91 insertions(+), 12 deletions(-) create mode 100644 elf.h diff --git a/Makefile b/Makefile index 36e2470..2aa02de 100644 --- a/Makefile +++ b/Makefile @@ -7,17 +7,17 @@ run: image.bin debug: image.bin qemu-system-i386 -drive format=raw,file=$< -s -S & - i386-elf-gdb \ + x86_64-elf-gdb \ -ex "target remote localhost:1234" \ -ex "set architecture i8086" \ - -ex "break *0x7c00" \ + -ex "break *0x7c5d" \ -ex "continue" image.bin: mbr.bin kernel.bin cat $^ >$@ -kernel.bin: kernel.o vga.o string.o - $(LD) -m elf_i386 -o $@ -Ttext 0x1000 $^ --oformat binary +kernel.bin: kernel.o vga.o string.o drivers/ata.o + $(LD) -m elf_i386 -o $@ -Ttext 0x1000 $^ %.o: %.c $(CC) -m32 -ffreestanding -c $< -o $@ diff --git a/drivers/ata.c b/drivers/ata.c index 2fe161c..8574c79 100644 --- a/drivers/ata.c +++ b/drivers/ata.c @@ -3,7 +3,7 @@ #include #include "ata.h" -#include "../ports.h" +#include "../port.h" /* BSY: a 1 means that the controller is busy executing a command. No register should be accessed (except the digital output register) while this bit is set. diff --git a/elf.h b/elf.h new file mode 100644 index 0000000..3f46100 --- /dev/null +++ b/elf.h @@ -0,0 +1,38 @@ +#pragma once + +#include + +enum { + EI_NIDENT = 16, +}; + +typedef uint32_t Elf32_Addr; +typedef uint32_t Elf32_Off; + +typedef struct { + unsigned char e_ident[EI_NIDENT]; + uint16_t e_type; + uint16_t e_machine; + uint32_t e_version; + Elf32_Addr e_entry; + Elf32_Off e_phoff; + Elf32_Off e_shoff; + uint32_t e_flags; + uint16_t e_ehsize; + uint16_t e_phentsize; + uint16_t e_phnum; + uint16_t e_shentsize; + uint16_t e_shnum; + uint16_t e_shstrndx; +} Elf32_Ehdr; + +typedef struct { + uint32_t p_type; + Elf32_Off p_offset; + Elf32_Addr p_vaddr; + Elf32_Addr p_paddr; + uint32_t p_filesz; + uint32_t p_memsz; + uint32_t p_flags; + uint32_t p_align; +} Elf32_Phdr; diff --git a/kernel.c b/kernel.c index 181cc7f..e9959e9 100644 --- a/kernel.c +++ b/kernel.c @@ -1,11 +1,8 @@ -asm("jmp main"); - #include "vga.h" -int main() { +void _start() { vga_clear_screen(); for (int i = 0; i < 24; i++) { vga_print_string("hello world\n"); } - return 0; } diff --git a/mbr.S b/mbr.S index 1b51de8..b4104a8 100644 --- a/mbr.S +++ b/mbr.S @@ -11,11 +11,39 @@ _start: jmp . // loop forever +.equ ELF32_ENTRY_OFFSET, 0x18 +.equ ELF32_PHDR_OFFSET, 0x1c +.equ ELF32_PHDR_FILESZ_OFFSET, 4*4 .equ KERNEL_OFFSET, 0x1000 + +.equ MBR_SECTORS, 1 +.equ SECTOR_BASE, 1 +.equ ELFHDR_SECTORS, 8 + +.equ SECTOR_SIZE, 512 +.equ SECTOR_SHIFT, 9 + load_kernel: + mov $1, %al // sectors to read + mov $SECTOR_BASE + MBR_SECTORS, %cl // start after MBR + call bios_disk_read + + mov KERNEL_OFFSET + ELF32_ENTRY_OFFSET, %si + mov %si, entry // store entry point + + mov KERNEL_OFFSET + ELF32_PHDR_OFFSET, %di + mov KERNEL_OFFSET + ELF32_PHDR_FILESZ_OFFSET(%di), %ax + sub $0x1000, %ax // we won't load the header + add $SECTOR_SIZE - 1, %ax + shr $SECTOR_SHIFT, %ax // round up to sector count + + mov $SECTOR_BASE + MBR_SECTORS + ELFHDR_SECTORS, %cl //start after ELF header + call bios_disk_read + ret + +bios_disk_read: + // expects %al to specify number of sectors, %cl the initial sector 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 @@ -46,7 +74,8 @@ init_32bit: mov $0x90000, %ebp // 6. setup stack mov %ebp, %esp - call KERNEL_OFFSET // 7. jump to the kernel + movzwl entry, %esi + call *%esi // 7. jump to the kernel jmp . // 8. loop forever @@ -70,6 +99,11 @@ boot_drive: banner: .asciz "YABLOKO bootloader started\r\n" + .balign 2 +entry: + .word 0 + + .balign 4 gdt_start: .quad 0x0 // null descriptor diff --git a/port.h b/port.h index edfdf90..2cbb9d0 100644 --- a/port.h +++ b/port.h @@ -6,6 +6,16 @@ static unsigned char port_byte_in(unsigned short port) { return result; } +static unsigned short port_word_in(unsigned short port) { + unsigned short result; + __asm__("in %%dx, %%ax" : "=a" (result) : "d" (port)); + return result; +} + static void port_byte_out(unsigned short port, unsigned char data) { __asm__("out %%al, %%dx" : : "a" (data), "d" (port)); } + +static void port_long_out(unsigned short port, unsigned int data) { + __asm__("out %%eax, %%dx" : : "a" (data), "d" (port)); +}