Adding code so far.

This commit is contained in:
Nicolás Ortega Froysa 2018-02-23 17:20:31 +01:00
commit 4700f983f8
No known key found for this signature in database
GPG Key ID: FEC70E3BAE2E69BF
10 changed files with 278 additions and 0 deletions

3
.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
bin/*
*.bin
*.o

24
LICENSE Normal file
View File

@ -0,0 +1,24 @@
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
means.
In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this
software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
For more information, please refer to <http://unlicense.org/>

20
Makefile Normal file
View File

@ -0,0 +1,20 @@
ASM=nasm
AFLAGS=-f bin
BIN=bin
CFLAGS=-ffreestanding -fno-pie -m32
CC=gcc
LD=ld
LDFLAGS=-melf_i386 -Ttext 0x1000 --oformat binary
basicos:
mkdir -p $(BIN)
$(ASM) boot_sect.asm $(AFLAGS) -o boot_sect.bin
$(CC) $(CFLAGS) -c kernel.c -o kernel.o
$(LD) $(LDFLAGS) -o kernel.bin kernel.o
cat boot_sect.bin kernel.bin > $(BIN)/os-image
.PHONY: clean
clean:
rm *.bin *.o

55
boot_sect.asm Normal file
View File

@ -0,0 +1,55 @@
[org 0x7c00]
KERNEL_OFFSET: equ 0x1000 ; kernel memory offset
mov [BOOT_DRIVE], dl ; store boot drive for later.
mov bp, 0x9000 ; setup the stack
mov sp, bp
mov bx, MSG_REAL_MODE
call print_string
call load_kernel ; load our kernel from memory
call switch_to_pm ; switch to 32-bit protected mode
jmp $
%include "print.asm"
%include "print32.asm"
%include "disk.asm"
%include "gdt.asm"
%include "switch_prot.asm"
[bits 16]
load_kernel:
mov bx, MSG_LOAD_KERNEL
call print_string
mov bx, KERNEL_OFFSET ; address to load the kernel to
mov dh, 15 ; number of sectors to load
mov dl, [BOOT_DRIVE] ; drive to load from
call disk_load
mov bx, MSG_KERNEL_LOADED
call print_string
ret
[bits 32]
BEGIN_PM:
mov ebx, MSG_PROT_MODE
call print_string_pm
call KERNEL_OFFSET
jmp $
;;;
; Data
BOOT_DRIVE: db 0
MSG_REAL_MODE: db "Started in 16-bit Real Mode",0
MSG_PROT_MODE: db "Successfully landed in 32-bit Protected Mode",0
MSG_LOAD_KERNEL: db "Loading kernel into memory...",0
MSG_KERNEL_LOADED: db "Successfully loaded kernel into memory",0
times 510-($-$$) db 0
dw 0xaa55

43
disk.asm Normal file
View File

@ -0,0 +1,43 @@
;;;
; disk_load
; ---------
; Load disk sectors into memory.
;
; Parameters:
; - dh: number of sectors to read
disk_load:
pusha
push dx ; store `dx' to check if the appropriate number of
; sectors were read later on.
mov ah, 0x02 ; BIOS read routine
mov al, dh ; read `dh' sectors
mov ch, 0x00 ; select cylinder 0
mov dh, 0x00 ; select head 0
mov cl, 0x02 ; start reading from second sector (after the boot
; sector)
int 0x13 ; BIOS interrupt
jc disk_load_error ; if `cf' flag has gone off then a read error has
; occurred
pop dx ; restore `dx'
cmp dh, al ; were the appropriate amount of sectors read?
jne disk_load_unexp ; if not then there was an error
popa
ret
disk_load_error:
mov bx, DISK_READ_ERROR ; print the error
jmp disk_load_print_exit
disk_load_unexp:
mov bx, DISK_READ_UNEXP
disk_load_print_exit:
call print_string
jmp $ ; lock due to failure
DISK_READ_UNEXP:
db "Unexpected amount of sectors read!",0
DISK_READ_ERROR:
db "Disk read error!",0

37
gdt.asm Normal file
View File

@ -0,0 +1,37 @@
; GDT
gdt_start:
gdt_null:
dd 0x0 ; the mandatory null-descriptor
dd 0x0
gdt_code: ; code segment of descriptor
dw 0xFFFF ; Limit (bits 0-15)
dw 0x0 ; Base (bits 0-15)
db 0x0 ; Base (bits 16-23
; 1st flags: (present)1, (privilege)00, (descriptor type)1 -> 1001b
; type flags: (code)1, (conforming)0, (readable)1, (accessed)0 -> 1010b
; 2nd flags: (granularity)1, (32-bit default)1, (64-bit seg)0, (AVL)0 -> 1100b
db 10011010b ; 1st flags and type flags
db 11001111b ; 2nd flags and Limit (bits 16-19)
db 0x0 ; Base (bits 24-31)
gdt_data:
; type flags: (code)0, (expand down)0, (writable)1, (accessed)0 -> 0010b
dw 0xFFFF ; Limit (bits 0-15)
dw 0x0 ; Base (bits 0-15)
db 0x0 ; Base (bits 16-23)
db 10010010b ; 1st flags and type flags
db 11001111b ; 2nd flags and Limit (bits 16-19)
db 0x0 ; Base (bits 24-31)
gdt_end: ; for calculating size of the gdt
gdt_descriptor:
dw gdt_end - gdt_start - 1 ; size of our GDT, always decrement true size by one
dd gdt_start ; start address of our GDT
;;;
; Constants used for GDT segment offsets
GDT_CODE_SEG: equ gdt_code - gdt_start
GDT_DATA_SEG: equ gdt_data - gdt_start

10
kernel.c Normal file
View File

@ -0,0 +1,10 @@
void main() {
/*
* point to first text cell of the video memory
*/
char *video_memory = (char*) 0xb8000;
/*
* store the character 'X' there
*/
*video_memory = 'X';
}

27
print.asm Normal file
View File

@ -0,0 +1,27 @@
;;;
; print_string
; ------------
; Print a string from memory.
;
; Parameters:
; - bx: pointer to string
;
; Internal Variables:
; - ah: scrolling teletype BIOS routine code
; - al: Byte containing character to print
; - bx: shifting pointer to string
print_string:
pusha ; save the state of all registers to the stack
mov ah, 0x0e ; scrolling teletype BIOS routine code
print_string_start:
mov al, [bx] ; load first letter into `al'
cmp al, 0
je print_string_end ; if null-termination then return
int 0x10 ; print the letter
add bx, 0x1 ; offset to next character
jmp print_string_start ; go back to beginning
print_string_end:
popa ; return the state of all the registers
ret

30
print32.asm Normal file
View File

@ -0,0 +1,30 @@
[bits 32]
VIDEO_MEMORY: equ 0xB8000
WHITE_ON_BLACK: equ 0x0F
;;;
; print_string_pm
; ------------
; Print a string stored in memory.
;
; Parameters:
; - ebx: pointer to string in memory
print_string_pm:
pusha
mov edx, VIDEO_MEMORY ; set `edx' to the start of the video memory
print_string_pm_loop:
mov al, [ebx] ; store the char at `ebx' in `al'
mov ah, WHITE_ON_BLACK ; store the attributes in `ah'
cmp al, 0 ; if null-termination then done
je print_string_pm_done
mov [edx], ax ; store char and attributes
add ebx, 1 ; increment ebx to next char
add edx, 2 ; increment to next char cell in vidmem
jmp print_string_pm_loop
print_string_pm_done:
popa
ret

29
switch_prot.asm Normal file
View File

@ -0,0 +1,29 @@
[bits 16]
switch_to_pm:
cli ; turn off all interrupts until we have properly
; properly set them up
lgdt [gdt_descriptor] ; load the global descriptor table defining
; protected mode segments
mov eax, cr0 ; set flag in register to switch to protected mode
or eax, 0x1
mov cr0, eax
jmp GDT_CODE_SEG:init_pm ; make a far jump to the 32-bit code forcing a flush
; of the pipelining
[bits 32]
; initialize registers and the stack once in protected mode
init_pm:
mov ax, GDT_DATA_SEG ; point our new segment registers to the data
mov ds, ax ; selector defined in the GDT, since we cannot
mov ss, ax ; use the old 16-bit code
mov es, ax
mov fs, ax
mov gs, ax
mov ebp, 0x90000 ; Update the stack position so it's at the top
mov esp, ebp ; of the free space
call BEGIN_PM