Adding code so far.
This commit is contained in:
commit
4700f983f8
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
bin/*
|
||||||
|
*.bin
|
||||||
|
*.o
|
24
LICENSE
Normal file
24
LICENSE
Normal 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
20
Makefile
Normal 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
55
boot_sect.asm
Normal 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
43
disk.asm
Normal 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
37
gdt.asm
Normal 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
10
kernel.c
Normal 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
27
print.asm
Normal 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
30
print32.asm
Normal 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
29
switch_prot.asm
Normal 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
|
Loading…
Reference in New Issue
Block a user