commit 70a0e7557c5fdcda0d9047a42a7a034b95d77cf1
parent 4e464a4dab52b685b9b90bd12507eb85209e00bc
Author: Stefan <misc@stefan-koch.name>
Date: Sun, 18 Oct 2015 18:45:46 +0200
switch to GRUB and start C kernel with multiboot
Diffstat:
M | Makefile | | | 39 | +++++++++++++++++++++++++++++++-------- |
D | a20.asm | | | 132 | ------------------------------------------------------------------------------- |
M | bochsrc | | | 4 | ++-- |
M | boot.asm | | | 50 | ++++++++++++++++++++++---------------------------- |
A | grub/grub.cfg | | | 7 | +++++++ |
D | kernel.asm | | | 58 | ---------------------------------------------------------- |
A | kernel.c | | | 18 | ++++++++++++++++++ |
A | kernel.ld | | | 38 | ++++++++++++++++++++++++++++++++++++++ |
A | sos.img.layout | | | 6 | ++++++ |
9 files changed, 124 insertions(+), 228 deletions(-)
diff --git a/Makefile b/Makefile
@@ -1,15 +1,38 @@
ASM = nasm
ASMFLAGS =
+GCC = $(HOME)/opt/cross/bin/i586-elf-gcc
+GCCFLAGS = -std=gnu99 -ffreestanding -O2 -Wall -Wextra
-all: $(ASM_FILES)
- $(ASM) $(ASMFLAGS) boot.asm -o boot.bin
- $(ASM) $(ASMFLAGS) kernel.asm -o kernel.bin
+all: image kernel kernel-install
+
+kernel:
+ $(ASM) boot.asm -o boot.o -f elf
+ $(GCC) -c kernel.c -o kernel.o $(GCCFLAGS)
+ $(GCC) -T kernel.ld -o sos-kernel.img -ffreestanding -O2 -nostdlib boot.o kernel.o -lgcc
+
+kernel-install:
+ sudo losetup /dev/loop1 sos.img -o 1048576
+ sudo mount /dev/loop1 /mnt
+ sudo cp sos-kernel.img /mnt/boot/
+ sudo umount /mnt
+ sudo losetup -d /dev/loop1
+
+image:
+ dd if=/dev/zero of=sos.img bs=512 count=131072
+ sfdisk sos.img < sos.img.layout
- dd if=/dev/zero of=sos.img bs=1k count=1440
- cat boot.bin kernel.bin > /tmp/sos.bin
- dd status=noxfer conv=notrunc if=/tmp/sos.bin of=sos.img
+ sudo losetup /dev/loop0 sos.img
+ sudo losetup /dev/loop1 sos.img -o 1048576
+ sudo mke2fs /dev/loop1
+ sudo mount /dev/loop1 /mnt
+ sudo grub-install --root-directory=/mnt --no-floppy --modules="normal ext2 part_msdos multiboot" /dev/loop0
+ sudo cp sos-kernel.img /mnt/boot/
+ sudo cp grub/* /mnt/boot/grub/
+ sudo losetup -d /dev/loop0
+ sudo umount /mnt
+ sudo losetup -d /dev/loop1
clean:
- rm boot.bin
- rm kernel.bin
+ rm *.o
+ rm sos-kernel.img
rm sos.img
diff --git a/a20.asm b/a20.asm
@@ -1,132 +0,0 @@
-a20_enable:
- call a20_stop_if_active
-
-a20_bios:
- mov ax, 2401h
- int 15h
-
- call a20_stop_if_active
-
-a20_keyboard:
- call a20_wait_inbuf ; disable the keyboard
- mov al, 0adh
- out 64h, al
-
- call a20_wait_inbuf ; tell the controller we want to read data
- mov al, 0d0h
- out 64h, al
-
- call a20_wait_outbuf ; read the P2 port provided by the controller
- in al, 60h
- push ax
-
- call a20_wait_inbuf ; tell the controller we want to write data
- mov al, 0d1h
- out 64h, al
-
- call a20_wait_inbuf ; write the new P2 port with A20 line active
- pop ax
- or al, 2
- out 60h, al
-
- call a20_wait_inbuf ; re-enable the keyboard
- mov al, 0aeh
- out 64h, al
-
- call a20_wait_inbuf
-
- call a20_stop_if_active_loop
-
-a20_fast:
- in al, 92h
- test al, 2
- jnz a20_done ; A20 Fast Gate is already activated
- or al, 2
- and al, 0feh
- out 92h, al
-
- call a20_stop_if_active_loop
-
- jmp a20_done ; give up, no other methods there
- ; could jump to another location and display an error
-
-a20_wait_inbuf:
- in al, 64h
- test al, 2
- jnz a20_wait_inbuf
- ret
-
-a20_wait_outbuf:
- in al, 64h,
- test al, 1
- jz a20_wait_outbuf
- ret
-
-a20_active:
- pushf
- push ds
- push es
- push di
- push si
-
- xor ax, ax ; ax = 0
- mov es, ax
-
- not ax; ax = 0xffff
- mov ds, ax
-
- mov di, 0500h
- mov si, 0510h
-
- mov al, byte [es:di] ; save the old values from memory
- push ax
-
- mov al, byte [ds:si]
- push ax
-
- mov byte [es:di], 00h ; write 0x00 to one and 0xff to the other location
- mov byte [ds:si], 0ffh
-
- cmp byte [es:di], 0ffh ; check if the address we set to 0x00 was
- ; set to 0xff later, then we have only 20 bit
- ; addresses
-
- pop ax ; restore the bytes we set before
- mov byte [ds:si], al
-
- pop ax
- mov byte [es:di], al
-
- mov ax, 0
- je a20_active_end
- mov ax, 1
-
-a20_active_end:
- pop si
- pop di
- pop es
- pop ds
- popf
- ret
-
-a20_stop_if_active:
- call a20_active
- test ax, ax ; check if all bits are 0, then ZF = 1
- jnz a20_done
- ret
-
-a20_stop_if_active_loop: ; try in a loop if a20 is active for k times
- mov bx, 0ffh
-a20_stop_if_active_loop_iterator:
- dec bx
- call a20_stop_if_active
- test ax, ax
- jnz a20_done
-
- test bx, bx ; check if bx 0
- jnz a20_stop_if_active_loop_iterator
-
- ret
-
-
-a20_done:
diff --git a/bochsrc b/bochsrc
@@ -1,6 +1,6 @@
romimage: file="$HOME/opt/bochs/share/bochs/BIOS-bochs-latest"
vgaromimage: file="$HOME/opt/bochs/share/bochs/VGABIOS-elpin-2.40"
-boot: floppy
-floppya: 1_44="sos.img", status=inserted
+boot: disk
+ata0-master: type=disk, path="sos.img", mode=flat
cpu: count=1, ips=4000000, reset_on_triple_fault=0
magic_break: enabled=1
diff --git a/boot.asm b/boot.asm
@@ -1,28 +1,22 @@
-[BITS 16]
-[ORG 0x7C00]
-
-xor ax, ax ; set ax to 0 = first segment
-mov ss, ax
-mov ds, ax
-mov es, ax
-
-disk_reset:
- xor ah, ah ; ah=0, reset drive head
- int 13h
- jc disk_reset
-
-disk_read:
- mov ah, 0x02 ; with interrupt 3h: reading!
- mov al, 10 ; read 10 sectors
- mov cl, 2 ; from sector 2
- mov bx, 0x8000 ; save data to location 0x8000
-
- mov ch, 0
- mov dh, 0
- int 13h
- jc disk_read
-
- jmp 0x0000:0x8000 ; jump to the new program, hooray
-
-times 510-($-$$) db 0
-dw 0xaa55
+section .multiboot
+align 4
+ dd 1BADB002h
+ dd 0003h ; set align boot modules to page boundaries, supply memory map
+ dd -(1BADB002h + 0003h)
+
+section .bootstrap_stack
+stack_bottom:
+ resb 16384 ; 16 KiB
+stack_top:
+
+section .text
+extern kernel_main
+global _start
+_start:
+ mov esp, stack_top
+ call kernel_main
+
+ cli
+ hlt
+.lhang:
+ jmp .lhang
diff --git a/grub/grub.cfg b/grub/grub.cfg
@@ -0,0 +1,7 @@
+set timeout=15
+set default=0
+
+menuentry "SOS" {
+ multiboot /boot/sos-kernel.img
+ boot
+}
diff --git a/kernel.asm b/kernel.asm
@@ -1,58 +0,0 @@
-[BITS 16]
-[ORG 0x8000]
-
-xor ax, ax ; set ax to 0 = first segment
-mov ss, ax
-mov ds, ax
-mov es, ax
-
-cli
-
-%include "a20.asm"
-
-enter_pmode:
- lgdt [gdtr]
- mov eax, cr0
- or eax, 1
- mov cr0, eax
-
- jmp 08h:far_jump
-
-[BITS 32]
-far_jump:
- mov ax, 10h
- mov ds, ax
- mov ss, ax
- mov esp, 090000h
- mov byte [ds:0B8000h], 'P'
- mov byte [ds:0B8001h], 1Bh
-
-hang:
- jmp hang
-
-gdt_null: ; the first element is the so called null descriptor
- dd 0 ; it is not referenced by the processor
- dd 0
-
-gdt_code: ; usually we want at least one segment descriptor for code
- dw 0ffffh ; segment length bits 0-15
- dw 0 ; segment base byte 0,1
- db 0 ; segment base byte 2
- db 10011010b ; access rights
- db 11001111b ; bit 7-4: 4 flag bits: granularity, default operation
- ; size bit, 2 bits available for OS
- ; bit 3-0: segment length bits 16-19
- db 0 ; segment base byte 3
-
-gdt_data: ; usually we want at least one segment descriptor for data
- dw 0ffffh
- dw 0
- db 0
- db 10010010b
- db 11001111b
- db 0
-gdt_end:
-
-gdtr:
- dw gdt_end - gdt_null - 1 ; 2 bytes are the size of the GDT in bytes - 1
- dd gdt_null ; 4 bytes are the address of the GDT start
diff --git a/kernel.c b/kernel.c
@@ -0,0 +1,18 @@
+void kernel_main()
+{
+ char *vidmem = (char*) 0xb8000;
+ vidmem[0] = 'H';
+ vidmem[2] = 'e';
+ vidmem[4] = 'l';
+ vidmem[6] = 'l';
+ vidmem[8] = 'o';
+ vidmem[10] = ' ';
+ vidmem[12] = 'W';
+ vidmem[14] = 'o';
+ vidmem[16] = 'r';
+ vidmem[18] = 'l';
+ vidmem[20] = 'd';
+
+ while (1) {
+ }
+}
diff --git a/kernel.ld b/kernel.ld
@@ -0,0 +1,38 @@
+ENTRY(_start)
+OUTPUT_FORMAT(elf32-i386)
+
+SECTIONS
+{
+ /* Begin putting sections at 1 MiB, a conventional place for kernels to be
+ loaded at by the bootloader. */
+ . = 1M;
+
+ /* First put the multiboot header, as it is required to be put very early
+ early in the image or the bootloader won't recognize the file format.
+ Next we'll put the .text section. */
+ .text BLOCK(4K) : ALIGN(4K)
+ {
+ *(.multiboot)
+ *(.text)
+ }
+
+ .rodata BLOCK(4K) : ALIGN(4K)
+ {
+ *(.rodata)
+ }
+
+ .data BLOCK(4K) : ALIGN(4K)
+ {
+ *(.data)
+ }
+
+ .bss BLOCK(4K) : ALIGN(4K)
+ {
+ *(COMMON)
+ *(.bss)
+ *(.bootstrap_stack)
+ }
+
+ /* The compiler may produce other sections, by default it will put them in
+ a segment with the same name. Simply add stuff here as needed. */
+}
diff --git a/sos.img.layout b/sos.img.layout
@@ -0,0 +1,6 @@
+label: dos
+label-id: 0x8e648a50
+device: sos.img
+unit: sectors
+
+sos.img1 : start= 2048, size= 129024, type=83, bootable