Bootable kernel skeleton
This commit is contained in:
parent
8f4aff05d5
commit
d5902c5a20
|
@ -1,3 +1,12 @@
|
||||||
[package]
|
[package]
|
||||||
name = "kernel"
|
name = "kernel"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
crate-type = ["staticlib"]
|
||||||
|
|
||||||
|
[profile.dev]
|
||||||
|
panic = "abort"
|
||||||
|
|
||||||
|
[profile.release]
|
||||||
|
panic = "abort"
|
||||||
|
|
24
Makefile
Normal file
24
Makefile
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
ARCH?=x86_64
|
||||||
|
|
||||||
|
run: qemu
|
||||||
|
|
||||||
|
bochs: build/harddrive.bin
|
||||||
|
bochs -f bochs.$(ARCH)
|
||||||
|
|
||||||
|
qemu: build/harddrive.bin
|
||||||
|
qemu-system-$(ARCH) -drive file=$<,format=raw,index=0,media=disk
|
||||||
|
|
||||||
|
FORCE:
|
||||||
|
|
||||||
|
build/libkernel.a: FORCE
|
||||||
|
rustc --crate-type staticlib src/lib.rs -o $@
|
||||||
|
#--target $(ARCH)-unknown-none.json
|
||||||
|
|
||||||
|
build/kernel.bin: build/libkernel.a
|
||||||
|
ld -m elf_$(ARCH) -o $@ -T bootloader/x86/kernel.ld -z max-page-size=0x1000 $<
|
||||||
|
|
||||||
|
build/harddrive.bin: build/kernel.bin
|
||||||
|
nasm -f bin -o $@ -D ARCH_$(ARCH) -ibootloader/x86/ -ibuild/ bootloader/x86/harddrive.asm
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf build/*
|
14
bochs.x86_64
Normal file
14
bochs.x86_64
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
ata0-master: type=disk, path="build/harddrive.bin", mode=flat
|
||||||
|
boot: disk
|
||||||
|
com1: enabled=1, mode=file, dev=build/serial.log
|
||||||
|
megs: 1024
|
||||||
|
|
||||||
|
magic_break: enabled=1
|
||||||
|
display_library: x, options="gui_debug"
|
||||||
|
|
||||||
|
log: -
|
||||||
|
debug: action=ignore
|
||||||
|
info: action=report
|
||||||
|
error: action=report
|
||||||
|
panic: action=ask
|
||||||
|
debugger_log: -
|
131
bootloader/x86/bootsector.asm
Normal file
131
bootloader/x86/bootsector.asm
Normal file
|
@ -0,0 +1,131 @@
|
||||||
|
ORG 0x7C00
|
||||||
|
SECTION .text
|
||||||
|
USE16
|
||||||
|
|
||||||
|
boot: ; dl comes with disk
|
||||||
|
; initialize segment registers
|
||||||
|
xor ax, ax
|
||||||
|
mov ds, ax
|
||||||
|
mov es, ax
|
||||||
|
mov ss, ax
|
||||||
|
|
||||||
|
; initialize stack
|
||||||
|
mov sp, 0x7C00
|
||||||
|
|
||||||
|
mov [disk], dl
|
||||||
|
|
||||||
|
mov si, name
|
||||||
|
call print
|
||||||
|
call print_line
|
||||||
|
|
||||||
|
mov bh, 0
|
||||||
|
mov bl, [disk]
|
||||||
|
call print_num
|
||||||
|
call print_line
|
||||||
|
|
||||||
|
mov ax, (startup_start - boot) / 512
|
||||||
|
mov bx, startup_start
|
||||||
|
mov cx, (startup_end - startup_start) / 512
|
||||||
|
xor dx, dx
|
||||||
|
call load
|
||||||
|
|
||||||
|
mov si, finished
|
||||||
|
call print
|
||||||
|
call print_line
|
||||||
|
|
||||||
|
jmp startup
|
||||||
|
|
||||||
|
; load some sectors from disk to a buffer in memory
|
||||||
|
; buffer has to be below 1MiB
|
||||||
|
; IN
|
||||||
|
; ax: start sector
|
||||||
|
; bx: offset of buffer
|
||||||
|
; cx: number of sectors (512 Bytes each)
|
||||||
|
; dx: segment of buffer
|
||||||
|
; CLOBBER
|
||||||
|
; ax, bx, cx, dx, si
|
||||||
|
; TODO rewrite to (eventually) move larger parts at once
|
||||||
|
; if that is done increase buffer_size_sectors in startup-common to that (max 0x80000 - startup_end)
|
||||||
|
load:
|
||||||
|
cmp cx, 64
|
||||||
|
jbe .good_size
|
||||||
|
|
||||||
|
pusha
|
||||||
|
mov cx, 64
|
||||||
|
call load
|
||||||
|
popa
|
||||||
|
add ax, 64
|
||||||
|
add dx, 64 * 512 / 16
|
||||||
|
sub cx, 64
|
||||||
|
|
||||||
|
jmp load
|
||||||
|
.good_size:
|
||||||
|
mov [DAPACK.addr], ax
|
||||||
|
mov [DAPACK.buf], bx
|
||||||
|
mov [DAPACK.count], cx
|
||||||
|
mov [DAPACK.seg], dx
|
||||||
|
|
||||||
|
mov si, loading
|
||||||
|
call print
|
||||||
|
|
||||||
|
mov bx, [DAPACK.addr]
|
||||||
|
call print_num
|
||||||
|
|
||||||
|
mov al, '#'
|
||||||
|
call print_char
|
||||||
|
|
||||||
|
mov bx, [DAPACK.count]
|
||||||
|
call print_num
|
||||||
|
|
||||||
|
mov al, ' '
|
||||||
|
call print_char
|
||||||
|
|
||||||
|
mov bx, [DAPACK.seg]
|
||||||
|
call print_num
|
||||||
|
|
||||||
|
mov al, ':'
|
||||||
|
call print_char
|
||||||
|
|
||||||
|
mov bx, [DAPACK.buf]
|
||||||
|
call print_num
|
||||||
|
|
||||||
|
call print_line
|
||||||
|
|
||||||
|
mov dl, [disk]
|
||||||
|
mov si, DAPACK
|
||||||
|
mov ah, 0x42
|
||||||
|
int 0x13
|
||||||
|
jc error
|
||||||
|
ret
|
||||||
|
|
||||||
|
error:
|
||||||
|
mov si, errored
|
||||||
|
call print
|
||||||
|
call print_line
|
||||||
|
.halt:
|
||||||
|
cli
|
||||||
|
hlt
|
||||||
|
jmp .halt
|
||||||
|
|
||||||
|
%include "print16.asm"
|
||||||
|
|
||||||
|
name: db "Redox Loader",0
|
||||||
|
loading: db "Load ",0
|
||||||
|
errored: db "Could not read disk",0
|
||||||
|
finished: db "Finished Loading",0
|
||||||
|
line: db 13,10,0
|
||||||
|
|
||||||
|
disk: db 0
|
||||||
|
|
||||||
|
DAPACK:
|
||||||
|
db 0x10
|
||||||
|
db 0
|
||||||
|
.count: dw 0 ; int 13 resets this to # of blocks actually read/written
|
||||||
|
.buf: dw 0 ; memory buffer destination address (0:7c00)
|
||||||
|
.seg: dw 0 ; in memory page zero
|
||||||
|
.addr: dd 0 ; put the lba to read in this spot
|
||||||
|
dd 0 ; more storage bytes only for big lba's ( > 4 bytes )
|
||||||
|
|
||||||
|
times 510-($-$$) db 0
|
||||||
|
db 0x55
|
||||||
|
db 0xaa
|
46
bootloader/x86/descriptor_flags.inc
Normal file
46
bootloader/x86/descriptor_flags.inc
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
attrib:
|
||||||
|
.present equ 1 << 7
|
||||||
|
.ring1 equ 1 << 5
|
||||||
|
.ring2 equ 1 << 6
|
||||||
|
.ring3 equ 1 << 5 | 1 << 6
|
||||||
|
.user equ 1 << 4
|
||||||
|
;user
|
||||||
|
.code equ 1 << 3
|
||||||
|
; code
|
||||||
|
.conforming equ 1 << 2
|
||||||
|
.readable equ 1 << 1
|
||||||
|
; data
|
||||||
|
.expand_down equ 1 << 2
|
||||||
|
.writable equ 1 << 1
|
||||||
|
.accessed equ 1 << 0
|
||||||
|
;system
|
||||||
|
; legacy
|
||||||
|
.tssAvailabe16 equ 0x1
|
||||||
|
.ldt equ 0x2
|
||||||
|
.tssBusy16 equ 0x3
|
||||||
|
.call16 equ 0x4
|
||||||
|
.task equ 0x5
|
||||||
|
.interrupt16 equ 0x6
|
||||||
|
.trap16 equ 0x7
|
||||||
|
.tssAvailabe32 equ 0x9
|
||||||
|
.tssBusy32 equ 0xB
|
||||||
|
.call32 equ 0xC
|
||||||
|
.interrupt32 equ 0xE
|
||||||
|
.trap32 equ 0xF
|
||||||
|
; long mode
|
||||||
|
.ldt32 equ 0x2
|
||||||
|
.tssAvailabe64 equ 0x9
|
||||||
|
.tssBusy64 equ 0xB
|
||||||
|
.call64 equ 0xC
|
||||||
|
.interrupt64 equ 0xE
|
||||||
|
.trap64 equ 0xF
|
||||||
|
|
||||||
|
flags:
|
||||||
|
.granularity equ 1 << 7
|
||||||
|
.available equ 1 << 4
|
||||||
|
;user
|
||||||
|
.default_operand_size equ 1 << 6
|
||||||
|
; code
|
||||||
|
.long_mode equ 1 << 5
|
||||||
|
; data
|
||||||
|
.reserved equ 1 << 5
|
8
bootloader/x86/gdt_entry.inc
Normal file
8
bootloader/x86/gdt_entry.inc
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
struc GDTEntry
|
||||||
|
.limitl resw 1
|
||||||
|
.basel resw 1
|
||||||
|
.basem resb 1
|
||||||
|
.attribute resb 1
|
||||||
|
.flags__limith resb 1
|
||||||
|
.baseh resb 1
|
||||||
|
endstruc
|
21
bootloader/x86/harddrive.asm
Normal file
21
bootloader/x86/harddrive.asm
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
%include "bootsector.asm"
|
||||||
|
|
||||||
|
startup_start:
|
||||||
|
%ifdef ARCH_i386
|
||||||
|
%include "startup-i386.asm"
|
||||||
|
%endif
|
||||||
|
|
||||||
|
%ifdef ARCH_x86_64
|
||||||
|
%include "startup-x86_64.asm"
|
||||||
|
%endif
|
||||||
|
align 512, db 0
|
||||||
|
startup_end:
|
||||||
|
|
||||||
|
kernel_file:
|
||||||
|
incbin "kernel.bin"
|
||||||
|
align 512, db 0
|
||||||
|
.end:
|
||||||
|
.length equ kernel_file.end - kernel_file
|
||||||
|
.length_sectors equ .length / 512
|
||||||
|
|
||||||
|
times 1024*1024-($-$$) db 0
|
78
bootloader/x86/initialize.asm
Normal file
78
bootloader/x86/initialize.asm
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
SECTION .text
|
||||||
|
USE16
|
||||||
|
|
||||||
|
initialize:
|
||||||
|
.fpu: ;enable fpu
|
||||||
|
mov eax, cr0
|
||||||
|
and al, 11110011b
|
||||||
|
or al, 00100010b
|
||||||
|
mov cr0, eax
|
||||||
|
mov eax, cr4
|
||||||
|
or eax, 0x200
|
||||||
|
mov cr4, eax
|
||||||
|
fninit
|
||||||
|
ret
|
||||||
|
|
||||||
|
.sse: ;enable sse
|
||||||
|
mov eax, cr4
|
||||||
|
or ax, 0000011000000000b
|
||||||
|
mov cr4, eax
|
||||||
|
ret
|
||||||
|
|
||||||
|
;PIT Frequency
|
||||||
|
;If using nanoseconds, to minimize drift, one should find a frequency as close to an integer nanosecond value in wavelength
|
||||||
|
;Divider Hz Nanoseconds Properties
|
||||||
|
;2685 444.38795779019242706393 2250286.00003631746492922946 Best For Context Switching
|
||||||
|
;5370 222.19397889509621353196 4500572.00007263492985856020
|
||||||
|
;21029 56.73981961418358774390 17624306.99991199998882825455
|
||||||
|
;23714 50.31549576902532962244 19874592.99994831745375667118
|
||||||
|
;26399 45.19798729749864262535 22124878.99998463491868476373
|
||||||
|
;29084 41.02536331545408701233 24375165.00002095238361424615
|
||||||
|
;31769 37.55804925136663623868 26625451.00005726984854313455
|
||||||
|
;34454 34.63115071302799868423 28875737.00009358731347639618
|
||||||
|
;50113 23.80982313305263437963 41999471.99993295237244784676
|
||||||
|
;52798 22.59899364874932131267 44249757.99996926983737931766
|
||||||
|
;55483 21.50535599492937776736 46500044.00000558730230583335 Lowest Drift
|
||||||
|
;58168 20.51268165772704350616 48750330.00004190476724037528
|
||||||
|
;60853 19.60760630809765610021 51000616.00007822223218031738
|
||||||
|
|
||||||
|
.pit:
|
||||||
|
;initialize the PIT
|
||||||
|
mov ax, 5370 ;this is the divider for the PIT
|
||||||
|
out 0x40, al
|
||||||
|
rol ax, 8
|
||||||
|
out 0x40, al
|
||||||
|
;DISABLED ;enable rtc interrupt
|
||||||
|
;mov al, 0xB
|
||||||
|
;out 0x70, al
|
||||||
|
;rol ax, 8
|
||||||
|
;in al, 0x71
|
||||||
|
;rol ax, 8
|
||||||
|
;out 0x70, al
|
||||||
|
;rol ax, 8
|
||||||
|
;or al, 0x40
|
||||||
|
;out 0x71, al
|
||||||
|
ret
|
||||||
|
|
||||||
|
.pic: ;sets up IRQs at int 20-2F
|
||||||
|
mov al, 0x11
|
||||||
|
out 0x20, al
|
||||||
|
out 0xA0, al
|
||||||
|
mov al, 0x20 ;IRQ0 vector
|
||||||
|
out 0x21, al
|
||||||
|
mov al, 0x28 ;IRQ8 vector
|
||||||
|
out 0xA1, al
|
||||||
|
mov al, 4
|
||||||
|
out 0x21, al
|
||||||
|
mov al, 2
|
||||||
|
out 0xA1, al
|
||||||
|
mov al, 1
|
||||||
|
out 0x21, al
|
||||||
|
out 0xA1, al
|
||||||
|
xor al, al ;no IRQ masks
|
||||||
|
out 0x21, al
|
||||||
|
out 0xA1, al
|
||||||
|
mov al, 0x20 ;reset PIC's
|
||||||
|
out 0xA0, al
|
||||||
|
out 0x20, al
|
||||||
|
ret
|
105
bootloader/x86/interrupts-i386.asm
Normal file
105
bootloader/x86/interrupts-i386.asm
Normal file
|
@ -0,0 +1,105 @@
|
||||||
|
struc IDTEntry
|
||||||
|
.offsetl resw 1
|
||||||
|
.selector resw 1
|
||||||
|
.zero resb 1
|
||||||
|
.attribute resb 1
|
||||||
|
.offseth resw 1
|
||||||
|
endstruc
|
||||||
|
|
||||||
|
SECTION .text
|
||||||
|
USE32
|
||||||
|
|
||||||
|
interrupts:
|
||||||
|
.first:
|
||||||
|
mov [.entry], byte 0
|
||||||
|
jmp dword .handle
|
||||||
|
.second:
|
||||||
|
%assign i 1
|
||||||
|
%rep 255
|
||||||
|
mov [.entry], byte i
|
||||||
|
jmp dword .handle
|
||||||
|
%assign i i+1
|
||||||
|
%endrep
|
||||||
|
.handle:
|
||||||
|
push ebp
|
||||||
|
push esi
|
||||||
|
push edi
|
||||||
|
push edx
|
||||||
|
push ecx
|
||||||
|
push ebx
|
||||||
|
push eax
|
||||||
|
|
||||||
|
push esp
|
||||||
|
push dword [.entry]
|
||||||
|
|
||||||
|
mov eax, gdt.kernel_data
|
||||||
|
mov ds, eax
|
||||||
|
mov es, eax
|
||||||
|
mov fs, eax
|
||||||
|
mov gs, eax
|
||||||
|
|
||||||
|
call dword [.handler]
|
||||||
|
|
||||||
|
mov eax, gdt.user_data | 3
|
||||||
|
mov ds, eax
|
||||||
|
mov es, eax
|
||||||
|
mov fs, eax
|
||||||
|
mov eax, gdt.user_tls | 3
|
||||||
|
mov gs, eax
|
||||||
|
|
||||||
|
add esp, 8 ; Skip interrupt code and reg pointer
|
||||||
|
|
||||||
|
pop eax
|
||||||
|
pop ebx
|
||||||
|
pop ecx
|
||||||
|
pop edx
|
||||||
|
pop edi
|
||||||
|
pop esi
|
||||||
|
pop ebp
|
||||||
|
|
||||||
|
iretd
|
||||||
|
|
||||||
|
.handler: dd 0
|
||||||
|
.entry: dd 0
|
||||||
|
|
||||||
|
idtr:
|
||||||
|
dw (idt.end - idt) + 1
|
||||||
|
dd idt
|
||||||
|
|
||||||
|
idt:
|
||||||
|
%assign i 0
|
||||||
|
|
||||||
|
;Below system call
|
||||||
|
%rep 128
|
||||||
|
istruc IDTEntry
|
||||||
|
at IDTEntry.offsetl, dw interrupts+(interrupts.second-interrupts.first)*i
|
||||||
|
at IDTEntry.selector, dw gdt.kernel_code
|
||||||
|
at IDTEntry.zero, db 0
|
||||||
|
at IDTEntry.attribute, db attrib.present | attrib.interrupt32
|
||||||
|
at IDTEntry.offseth, dw 0
|
||||||
|
iend
|
||||||
|
%assign i i+1
|
||||||
|
%endrep
|
||||||
|
|
||||||
|
;System call
|
||||||
|
istruc IDTEntry
|
||||||
|
at IDTEntry.offsetl, dw interrupts+(interrupts.second-interrupts.first)*i
|
||||||
|
at IDTEntry.selector, dw gdt.kernel_code
|
||||||
|
at IDTEntry.zero, db 0
|
||||||
|
at IDTEntry.attribute, db attrib.present | attrib.ring3 | attrib.interrupt32
|
||||||
|
at IDTEntry.offseth, dw 0
|
||||||
|
iend
|
||||||
|
%assign i i+1
|
||||||
|
|
||||||
|
;Above system call
|
||||||
|
%rep 127
|
||||||
|
istruc IDTEntry
|
||||||
|
at IDTEntry.offsetl, dw interrupts+(interrupts.second-interrupts.first)*i
|
||||||
|
at IDTEntry.selector, dw gdt.kernel_code
|
||||||
|
at IDTEntry.zero, db 0
|
||||||
|
at IDTEntry.attribute, db attrib.present | attrib.interrupt32
|
||||||
|
at IDTEntry.offseth, dw 0
|
||||||
|
iend
|
||||||
|
%assign i i+1
|
||||||
|
%endrep
|
||||||
|
.end:
|
130
bootloader/x86/interrupts-x86_64.asm
Normal file
130
bootloader/x86/interrupts-x86_64.asm
Normal file
|
@ -0,0 +1,130 @@
|
||||||
|
struc IDTEntry
|
||||||
|
.offsetl resw 1
|
||||||
|
.selector resw 1
|
||||||
|
.ist resb 1
|
||||||
|
.attribute resb 1
|
||||||
|
.offsetm resw 1
|
||||||
|
.offseth resd 1
|
||||||
|
.reserved resd 1
|
||||||
|
endstruc
|
||||||
|
|
||||||
|
SECTION .text
|
||||||
|
USE64
|
||||||
|
interrupts:
|
||||||
|
.first:
|
||||||
|
mov [.entry], byte 0
|
||||||
|
jmp qword .handle
|
||||||
|
.second:
|
||||||
|
%assign i 1
|
||||||
|
%rep 255
|
||||||
|
mov [.entry], byte i
|
||||||
|
jmp qword .handle
|
||||||
|
%assign i i+1
|
||||||
|
%endrep
|
||||||
|
.handle:
|
||||||
|
push rbp
|
||||||
|
push r15
|
||||||
|
push r14
|
||||||
|
push r13
|
||||||
|
push r12
|
||||||
|
push r11
|
||||||
|
push r10
|
||||||
|
push r9
|
||||||
|
push r8
|
||||||
|
push rsi
|
||||||
|
push rdi
|
||||||
|
push rdx
|
||||||
|
push rcx
|
||||||
|
push rbx
|
||||||
|
push rax
|
||||||
|
|
||||||
|
mov rsi, rsp
|
||||||
|
push rsi
|
||||||
|
mov rdi, qword [.entry]
|
||||||
|
push rdi
|
||||||
|
|
||||||
|
mov rax, gdt.kernel_data
|
||||||
|
mov ds, rax
|
||||||
|
mov es, rax
|
||||||
|
mov fs, rax
|
||||||
|
mov gs, rax
|
||||||
|
|
||||||
|
call qword [.handler]
|
||||||
|
|
||||||
|
mov rax, gdt.user_data | 3
|
||||||
|
mov ds, rax
|
||||||
|
mov es, rax
|
||||||
|
mov gs, rax
|
||||||
|
mov rax, gdt.user_tls | 3
|
||||||
|
mov fs, rax
|
||||||
|
|
||||||
|
add rsp, 16 ; Skip interrupt code and reg pointer
|
||||||
|
|
||||||
|
pop rax
|
||||||
|
pop rbx
|
||||||
|
pop rcx
|
||||||
|
pop rdx
|
||||||
|
pop rdi
|
||||||
|
pop rsi
|
||||||
|
pop r8
|
||||||
|
pop r9
|
||||||
|
pop r10
|
||||||
|
pop r11
|
||||||
|
pop r12
|
||||||
|
pop r13
|
||||||
|
pop r14
|
||||||
|
pop r15
|
||||||
|
pop rbp
|
||||||
|
|
||||||
|
iretq
|
||||||
|
|
||||||
|
.handler: dq 0
|
||||||
|
.entry: dq 0
|
||||||
|
|
||||||
|
idtr:
|
||||||
|
dw (idt.end - idt) + 1
|
||||||
|
dq idt
|
||||||
|
|
||||||
|
idt:
|
||||||
|
%assign i 0
|
||||||
|
|
||||||
|
;Below syscall
|
||||||
|
%rep 128
|
||||||
|
istruc IDTEntry
|
||||||
|
at IDTEntry.offsetl, dw interrupts+(interrupts.second-interrupts.first)*i
|
||||||
|
at IDTEntry.selector, dw gdt.kernel_code
|
||||||
|
at IDTEntry.ist, db 0
|
||||||
|
at IDTEntry.attribute, db attrib.present | attrib.interrupt64
|
||||||
|
at IDTEntry.offsetm, dw 0
|
||||||
|
at IDTEntry.offseth, dd 0
|
||||||
|
at IDTEntry.reserved, dd 0
|
||||||
|
iend
|
||||||
|
%assign i i+1
|
||||||
|
%endrep
|
||||||
|
|
||||||
|
;Syscall
|
||||||
|
istruc IDTEntry
|
||||||
|
at IDTEntry.offsetl, dw interrupts+(interrupts.second-interrupts.first)*i
|
||||||
|
at IDTEntry.selector, dw gdt.kernel_code
|
||||||
|
at IDTEntry.ist, db 0
|
||||||
|
at IDTEntry.attribute, db attrib.present | attrib.ring3 | attrib.interrupt64
|
||||||
|
at IDTEntry.offsetm, dw 0
|
||||||
|
at IDTEntry.offseth, dd 0
|
||||||
|
at IDTEntry.reserved, dd 0
|
||||||
|
iend
|
||||||
|
%assign i i+1
|
||||||
|
|
||||||
|
;Above syscall
|
||||||
|
%rep 127
|
||||||
|
istruc IDTEntry
|
||||||
|
at IDTEntry.offsetl, dw interrupts+(interrupts.second-interrupts.first)*i
|
||||||
|
at IDTEntry.selector, dw gdt.kernel_code
|
||||||
|
at IDTEntry.ist, db 0
|
||||||
|
at IDTEntry.attribute, db attrib.present | attrib.interrupt64
|
||||||
|
at IDTEntry.offsetm, dw 0
|
||||||
|
at IDTEntry.offseth, dd 0
|
||||||
|
at IDTEntry.reserved, dd 0
|
||||||
|
iend
|
||||||
|
%assign i i+1
|
||||||
|
%endrep
|
||||||
|
.end:
|
40
bootloader/x86/kernel.ld
Normal file
40
bootloader/x86/kernel.ld
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
ENTRY(kmain)
|
||||||
|
|
||||||
|
SECTIONS {
|
||||||
|
kernel_base = 0x101000;
|
||||||
|
. = kernel_base;
|
||||||
|
|
||||||
|
.text : AT(ADDR(.text) - kernel_base) {
|
||||||
|
__text_start = .;
|
||||||
|
*(.text*)
|
||||||
|
. = ALIGN(4096);
|
||||||
|
__text_end = .;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rodata : AT(ADDR(.rodata) - kernel_base) {
|
||||||
|
__rodata_start = .;
|
||||||
|
*(.rodata*)
|
||||||
|
. = ALIGN(4096);
|
||||||
|
__rodata_end = .;
|
||||||
|
}
|
||||||
|
|
||||||
|
.data : AT(ADDR(.data) - kernel_base) {
|
||||||
|
__data_start = .;
|
||||||
|
*(.data*)
|
||||||
|
. = ALIGN(4096);
|
||||||
|
__data_end = .;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bss : AT(ADDR(.bss) - kernel_base) {
|
||||||
|
__bss_start = .;
|
||||||
|
*(.bss*)
|
||||||
|
. = ALIGN(4096);
|
||||||
|
__bss_end = .;
|
||||||
|
}
|
||||||
|
|
||||||
|
/DISCARD/ : {
|
||||||
|
*(.comment)
|
||||||
|
*(.eh_frame)
|
||||||
|
*(.rel.eh_frame)
|
||||||
|
}
|
||||||
|
}
|
32
bootloader/x86/memory_map.asm
Normal file
32
bootloader/x86/memory_map.asm
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
SECTION .text
|
||||||
|
USE16
|
||||||
|
;Generate a memory map at 0x500 to 0x5000 (available memory not used for kernel or bootloader)
|
||||||
|
memory_map:
|
||||||
|
.start equ 0x0500
|
||||||
|
.end equ 0x5000
|
||||||
|
.length equ .end - .start
|
||||||
|
|
||||||
|
xor eax, eax
|
||||||
|
mov di, .start
|
||||||
|
mov ecx, .length / 4 ; moving 4 Bytes at once
|
||||||
|
cld
|
||||||
|
rep stosd
|
||||||
|
|
||||||
|
mov di, .start
|
||||||
|
mov edx, 0x534D4150
|
||||||
|
xor ebx, ebx
|
||||||
|
.lp:
|
||||||
|
mov eax, 0xE820
|
||||||
|
mov ecx, 24
|
||||||
|
|
||||||
|
int 0x15
|
||||||
|
jc .done ; Error or finished
|
||||||
|
|
||||||
|
cmp ebx, 0
|
||||||
|
je .done ; Finished
|
||||||
|
|
||||||
|
add di, 24
|
||||||
|
cmp di, .end
|
||||||
|
jb .lp ; Still have buffer space
|
||||||
|
.done:
|
||||||
|
ret
|
66
bootloader/x86/print16.asm
Normal file
66
bootloader/x86/print16.asm
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
SECTION .text
|
||||||
|
USE16
|
||||||
|
; provide function for printing in x86 real mode
|
||||||
|
|
||||||
|
|
||||||
|
; a newline
|
||||||
|
newline: db 0xD, 0xA, 0
|
||||||
|
|
||||||
|
; print a string and a newline
|
||||||
|
; IN
|
||||||
|
; si: points at zero-terminated String
|
||||||
|
; CLOBBER
|
||||||
|
; ax
|
||||||
|
print_line:
|
||||||
|
mov si, newline
|
||||||
|
call print
|
||||||
|
ret
|
||||||
|
|
||||||
|
; print a string
|
||||||
|
; IN
|
||||||
|
; si: points at zero-terminated String
|
||||||
|
; CLOBBER
|
||||||
|
; ax
|
||||||
|
print:
|
||||||
|
lodsb
|
||||||
|
test al, al
|
||||||
|
jz .done
|
||||||
|
call print_char
|
||||||
|
jmp print
|
||||||
|
.done:
|
||||||
|
ret
|
||||||
|
|
||||||
|
; print a character
|
||||||
|
; IN
|
||||||
|
; al: character to print
|
||||||
|
; CLOBBER
|
||||||
|
; ah
|
||||||
|
print_char:
|
||||||
|
mov ah, 0x0e
|
||||||
|
int 0x10
|
||||||
|
ret
|
||||||
|
|
||||||
|
; print a number in hex
|
||||||
|
; IN
|
||||||
|
; bx: the number
|
||||||
|
; CLOBBER
|
||||||
|
; cx, ax
|
||||||
|
print_num:
|
||||||
|
mov cx, 4
|
||||||
|
.lp:
|
||||||
|
mov al, bh
|
||||||
|
shr al, 4
|
||||||
|
|
||||||
|
cmp al, 0xA
|
||||||
|
jb .below_0xA
|
||||||
|
|
||||||
|
add al, 'A' - 0xA - '0'
|
||||||
|
.below_0xA:
|
||||||
|
add al, '0'
|
||||||
|
|
||||||
|
call print_char
|
||||||
|
|
||||||
|
shl bx, 4
|
||||||
|
loop .lp
|
||||||
|
|
||||||
|
ret
|
89
bootloader/x86/startup-common.asm
Normal file
89
bootloader/x86/startup-common.asm
Normal file
|
@ -0,0 +1,89 @@
|
||||||
|
SECTION .text
|
||||||
|
USE16
|
||||||
|
|
||||||
|
startup:
|
||||||
|
; enable A20-Line via IO-Port 92, might not work on all motherboards
|
||||||
|
in al, 0x92
|
||||||
|
or al, 2
|
||||||
|
out 0x92, al
|
||||||
|
|
||||||
|
; loading kernel to 1MiB
|
||||||
|
; move part of kernel to startup_end via bootsector#load and then copy it up
|
||||||
|
; repeat until all of the kernel is loaded
|
||||||
|
|
||||||
|
; buffersize in multiple of sectors (512 Bytes)
|
||||||
|
; min 1
|
||||||
|
; max (0x70000 - startup_end) / 512
|
||||||
|
buffer_size_sectors equ 1
|
||||||
|
; buffer size in Bytes
|
||||||
|
buffer_size_bytes equ buffer_size_sectors * 512
|
||||||
|
|
||||||
|
kernel_base equ 0x100000
|
||||||
|
|
||||||
|
; how often do we need to call load and move memory
|
||||||
|
mov ecx, kernel_file.length_sectors / buffer_size_sectors
|
||||||
|
|
||||||
|
mov ax, (kernel_file - boot) / 512
|
||||||
|
mov edi, kernel_base
|
||||||
|
cld
|
||||||
|
.lp:
|
||||||
|
; saving counter
|
||||||
|
push cx
|
||||||
|
|
||||||
|
; populating buffer
|
||||||
|
mov cx, buffer_size_sectors
|
||||||
|
mov bx, startup_end
|
||||||
|
mov dx, 0x0
|
||||||
|
|
||||||
|
push ax
|
||||||
|
call load
|
||||||
|
|
||||||
|
; moving buffer
|
||||||
|
call unreal
|
||||||
|
pop ax
|
||||||
|
|
||||||
|
mov esi, startup_end
|
||||||
|
mov ecx, buffer_size_bytes / 4
|
||||||
|
a32 rep movsd
|
||||||
|
|
||||||
|
; preparing next iteration
|
||||||
|
add ax, buffer_size_sectors
|
||||||
|
|
||||||
|
pop cx
|
||||||
|
loop .lp
|
||||||
|
|
||||||
|
; load the part of the kernel that does not fill the buffer completely
|
||||||
|
mov cx, kernel_file.length_sectors % buffer_size_sectors
|
||||||
|
test cx, cx
|
||||||
|
jz finished_loading ; if cx = 0 => skip
|
||||||
|
|
||||||
|
mov bx, startup_end
|
||||||
|
mov dx, 0x0
|
||||||
|
call load
|
||||||
|
|
||||||
|
; moving remnants of kernel
|
||||||
|
call unreal
|
||||||
|
|
||||||
|
mov esi, startup_end
|
||||||
|
mov ecx, (kernel_file.length_sectors % buffer_size_bytes) / 4
|
||||||
|
a32 rep movsd
|
||||||
|
finished_loading:
|
||||||
|
|
||||||
|
|
||||||
|
call memory_map
|
||||||
|
|
||||||
|
call vesa
|
||||||
|
|
||||||
|
call initialize.fpu
|
||||||
|
call initialize.sse
|
||||||
|
call initialize.pit
|
||||||
|
call initialize.pic
|
||||||
|
|
||||||
|
jmp startup_arch
|
||||||
|
|
||||||
|
%include "descriptor_flags.inc"
|
||||||
|
%include "gdt_entry.inc"
|
||||||
|
%include "unreal.asm"
|
||||||
|
%include "memory_map.asm"
|
||||||
|
%include "vesa.asm"
|
||||||
|
%include "initialize.asm"
|
150
bootloader/x86/startup-i386.asm
Normal file
150
bootloader/x86/startup-i386.asm
Normal file
|
@ -0,0 +1,150 @@
|
||||||
|
%include "startup-common.asm"
|
||||||
|
|
||||||
|
startup_arch:
|
||||||
|
; load protected mode GDT and IDT
|
||||||
|
cli
|
||||||
|
lgdt [gdtr]
|
||||||
|
lidt [idtr]
|
||||||
|
; set protected mode bit of cr0
|
||||||
|
mov eax, cr0
|
||||||
|
or eax, 1
|
||||||
|
mov cr0, eax
|
||||||
|
|
||||||
|
; far jump to load CS with 32 bit segment
|
||||||
|
jmp gdt.kernel_code:protected_mode
|
||||||
|
|
||||||
|
USE32
|
||||||
|
protected_mode:
|
||||||
|
; load all the other segments with 32 bit data segments
|
||||||
|
mov eax, gdt.kernel_data
|
||||||
|
mov ds, eax
|
||||||
|
mov es, eax
|
||||||
|
mov fs, eax
|
||||||
|
mov gs, eax
|
||||||
|
mov ss, eax
|
||||||
|
|
||||||
|
mov esp, 0x800000 - 128
|
||||||
|
|
||||||
|
mov eax, gdt.tss
|
||||||
|
ltr ax
|
||||||
|
|
||||||
|
;rust init
|
||||||
|
mov eax, [kernel_base + 0x18]
|
||||||
|
mov [interrupts.handler], eax
|
||||||
|
mov eax, gdtr
|
||||||
|
mov ebx, idtr
|
||||||
|
mov ecx, tss
|
||||||
|
int 255
|
||||||
|
.lp:
|
||||||
|
sti
|
||||||
|
hlt
|
||||||
|
jmp .lp
|
||||||
|
|
||||||
|
gdtr:
|
||||||
|
dw gdt.end + 1 ; size
|
||||||
|
dd gdt ; offset
|
||||||
|
|
||||||
|
gdt:
|
||||||
|
.null equ $ - gdt
|
||||||
|
dq 0
|
||||||
|
|
||||||
|
.kernel_code equ $ - gdt
|
||||||
|
istruc GDTEntry
|
||||||
|
at GDTEntry.limitl, dw 0xFFFF
|
||||||
|
at GDTEntry.basel, dw 0
|
||||||
|
at GDTEntry.basem, db 0
|
||||||
|
at GDTEntry.attribute, db attrib.present | attrib.user | attrib.code | attrib.readable
|
||||||
|
at GDTEntry.flags__limith, db 0xFF | flags.granularity | flags.default_operand_size
|
||||||
|
at GDTEntry.baseh, db 0
|
||||||
|
iend
|
||||||
|
|
||||||
|
.kernel_data equ $ - gdt
|
||||||
|
istruc GDTEntry
|
||||||
|
at GDTEntry.limitl, dw 0xFFFF
|
||||||
|
at GDTEntry.basel, dw 0
|
||||||
|
at GDTEntry.basem, db 0
|
||||||
|
at GDTEntry.attribute, db attrib.present | attrib.user | attrib.writable
|
||||||
|
at GDTEntry.flags__limith, db 0xFF | flags.granularity | flags.default_operand_size
|
||||||
|
at GDTEntry.baseh, db 0
|
||||||
|
iend
|
||||||
|
|
||||||
|
.user_code equ $ - gdt
|
||||||
|
istruc GDTEntry
|
||||||
|
at GDTEntry.limitl, dw 0xFFFF
|
||||||
|
at GDTEntry.basel, dw 0
|
||||||
|
at GDTEntry.basem, db 0
|
||||||
|
at GDTEntry.attribute, db attrib.present | attrib.ring3 | attrib.user | attrib.code | attrib.readable
|
||||||
|
at GDTEntry.flags__limith, db 0xFF | flags.granularity | flags.default_operand_size
|
||||||
|
at GDTEntry.baseh, db 0
|
||||||
|
iend
|
||||||
|
|
||||||
|
.user_data equ $ - gdt
|
||||||
|
istruc GDTEntry
|
||||||
|
at GDTEntry.limitl, dw 0xFFFF
|
||||||
|
at GDTEntry.basel, dw 0
|
||||||
|
at GDTEntry.basem, db 0
|
||||||
|
at GDTEntry.attribute, db attrib.present | attrib.ring3 | attrib.user | attrib.writable
|
||||||
|
at GDTEntry.flags__limith, db 0xFF | flags.granularity | flags.default_operand_size
|
||||||
|
at GDTEntry.baseh, db 0
|
||||||
|
iend
|
||||||
|
|
||||||
|
.user_tls equ $ - gdt
|
||||||
|
istruc GDTEntry
|
||||||
|
at GDTEntry.limitl, dw 0xFFFF
|
||||||
|
at GDTEntry.basel, dw 0
|
||||||
|
at GDTEntry.basem, db 0
|
||||||
|
at GDTEntry.attribute, db attrib.present | attrib.ring3 | attrib.user | attrib.writable
|
||||||
|
at GDTEntry.flags__limith, db 0xFF | flags.granularity | flags.default_operand_size
|
||||||
|
at GDTEntry.baseh, db 0
|
||||||
|
iend
|
||||||
|
|
||||||
|
.tss equ $ - gdt
|
||||||
|
istruc GDTEntry
|
||||||
|
at GDTEntry.limitl, dw (tss.end - tss) & 0xFFFF
|
||||||
|
at GDTEntry.basel, dw (tss-$$+0x7C00) & 0xFFFF
|
||||||
|
at GDTEntry.basem, db ((tss-$$+0x7C00) >> 16) & 0xFF
|
||||||
|
at GDTEntry.attribute, db attrib.present | attrib.ring3 | attrib.tssAvailabe32
|
||||||
|
at GDTEntry.flags__limith, db ((tss.end - tss) >> 16) & 0xF
|
||||||
|
at GDTEntry.baseh, db ((tss-$$+0x7C00) >> 24) & 0xFF
|
||||||
|
iend
|
||||||
|
.end equ $ - gdt
|
||||||
|
|
||||||
|
struc TSS
|
||||||
|
.prev_tss resd 1 ;The previous TSS - if we used hardware task switching this would form a linked list.
|
||||||
|
.esp0 resd 1 ;The stack pointer to load when we change to kernel mode.
|
||||||
|
.ss0 resd 1 ;The stack segment to load when we change to kernel mode.
|
||||||
|
.esp1 resd 1 ;everything below here is unused now..
|
||||||
|
.ss1 resd 1
|
||||||
|
.esp2 resd 1
|
||||||
|
.ss2 resd 1
|
||||||
|
.cr3 resd 1
|
||||||
|
.eip resd 1
|
||||||
|
.eflags resd 1
|
||||||
|
.eax resd 1
|
||||||
|
.ecx resd 1
|
||||||
|
.edx resd 1
|
||||||
|
.ebx resd 1
|
||||||
|
.esp resd 1
|
||||||
|
.ebp resd 1
|
||||||
|
.esi resd 1
|
||||||
|
.edi resd 1
|
||||||
|
.es resd 1
|
||||||
|
.cs resd 1
|
||||||
|
.ss resd 1
|
||||||
|
.ds resd 1
|
||||||
|
.fs resd 1
|
||||||
|
.gs resd 1
|
||||||
|
.ldt resd 1
|
||||||
|
.trap resw 1
|
||||||
|
.iomap_base resw 1
|
||||||
|
endstruc
|
||||||
|
|
||||||
|
tss:
|
||||||
|
istruc TSS
|
||||||
|
at TSS.esp0, dd 0x800000 - 128
|
||||||
|
at TSS.ss0, dd gdt.kernel_data
|
||||||
|
at TSS.iomap_base, dw 0xFFFF
|
||||||
|
iend
|
||||||
|
.end:
|
||||||
|
|
||||||
|
%include "interrupts-i386.asm"
|
191
bootloader/x86/startup-x86_64.asm
Normal file
191
bootloader/x86/startup-x86_64.asm
Normal file
|
@ -0,0 +1,191 @@
|
||||||
|
%include "startup-common.asm"
|
||||||
|
|
||||||
|
startup_arch:
|
||||||
|
cli
|
||||||
|
; setting up Page Tables
|
||||||
|
; Identity Mapping first GB
|
||||||
|
mov ax, 0x7000
|
||||||
|
mov es, ax
|
||||||
|
|
||||||
|
xor edi, edi
|
||||||
|
xor eax, eax
|
||||||
|
mov ecx, 3 * 4096 / 4 ;PML4, PDP, PD / moves 4 Bytes at once
|
||||||
|
cld
|
||||||
|
rep stosd
|
||||||
|
|
||||||
|
xor edi, edi
|
||||||
|
;Link first PML4 to PDP
|
||||||
|
mov DWORD [es:edi], 0x71000 | 1 << 1 | 1
|
||||||
|
add edi, 0x1000
|
||||||
|
;Link first PDP to PD
|
||||||
|
mov DWORD [es:edi], 0x72000 | 1 << 1 | 1
|
||||||
|
add edi, 0x1000
|
||||||
|
;Link all PD's (512 per PDP, 2MB each)y
|
||||||
|
mov ebx, 1 << 7 | 1 << 1 | 1
|
||||||
|
mov ecx, 512
|
||||||
|
.setpd:
|
||||||
|
mov [es:edi], ebx
|
||||||
|
add ebx, 0x200000
|
||||||
|
add edi, 8
|
||||||
|
loop .setpd
|
||||||
|
|
||||||
|
xor ax, ax
|
||||||
|
mov es, ax
|
||||||
|
|
||||||
|
;cr3 holds pointer to PML4
|
||||||
|
mov edi, 0x70000
|
||||||
|
mov cr3, edi
|
||||||
|
|
||||||
|
;enable Page Address Extension and Page Size Extension
|
||||||
|
mov eax, cr4
|
||||||
|
or eax, 1 << 5 | 1 << 4
|
||||||
|
mov cr4, eax
|
||||||
|
|
||||||
|
; load protected mode GDT
|
||||||
|
lgdt [gdtr]
|
||||||
|
|
||||||
|
mov ecx, 0xC0000080 ; Read from the EFER MSR.
|
||||||
|
rdmsr
|
||||||
|
or eax, 0x00000100 ; Set the Long-Mode-Enable bit.
|
||||||
|
wrmsr
|
||||||
|
|
||||||
|
;enabling paging and protection simultaneously
|
||||||
|
mov ebx, cr0
|
||||||
|
or ebx, 0x80000001 ;Bit 31: Paging, Bit 0: Protected Mode
|
||||||
|
mov cr0, ebx
|
||||||
|
|
||||||
|
; far jump to enable Long Mode and load CS with 64 bit segment
|
||||||
|
jmp gdt.kernel_code:long_mode
|
||||||
|
|
||||||
|
USE64
|
||||||
|
long_mode:
|
||||||
|
; load all the other segments with 64 bit data segments
|
||||||
|
mov rax, gdt.kernel_data
|
||||||
|
mov ds, rax
|
||||||
|
mov es, rax
|
||||||
|
mov fs, rax
|
||||||
|
mov gs, rax
|
||||||
|
mov ss, rax
|
||||||
|
|
||||||
|
; load long mode IDT
|
||||||
|
lidt [idtr]
|
||||||
|
|
||||||
|
mov rsp, 0x800000 - 128
|
||||||
|
|
||||||
|
mov rax, gdt.tss
|
||||||
|
ltr ax
|
||||||
|
|
||||||
|
;rust init
|
||||||
|
mov eax, [kernel_base + 0x18]
|
||||||
|
mov [interrupts.handler], rax
|
||||||
|
mov rax, gdtr
|
||||||
|
mov rbx, idtr
|
||||||
|
mov rcx, tss
|
||||||
|
int 0xFF
|
||||||
|
.lp:
|
||||||
|
sti
|
||||||
|
hlt
|
||||||
|
jmp .lp
|
||||||
|
|
||||||
|
gdtr:
|
||||||
|
dw gdt.end + 1 ; size
|
||||||
|
dq gdt ; offset
|
||||||
|
|
||||||
|
gdt:
|
||||||
|
.null equ $ - gdt
|
||||||
|
dq 0
|
||||||
|
|
||||||
|
.kernel_code equ $ - gdt
|
||||||
|
istruc GDTEntry
|
||||||
|
at GDTEntry.limitl, dw 0
|
||||||
|
at GDTEntry.basel, dw 0
|
||||||
|
at GDTEntry.basem, db 0
|
||||||
|
at GDTEntry.attribute, db attrib.present | attrib.user | attrib.code
|
||||||
|
at GDTEntry.flags__limith, db flags.long_mode
|
||||||
|
at GDTEntry.baseh, db 0
|
||||||
|
iend
|
||||||
|
|
||||||
|
.kernel_data equ $ - gdt
|
||||||
|
istruc GDTEntry
|
||||||
|
at GDTEntry.limitl, dw 0
|
||||||
|
at GDTEntry.basel, dw 0
|
||||||
|
at GDTEntry.basem, db 0
|
||||||
|
; AMD System Programming Manual states that the writeable bit is ignored in long mode, but ss can not be set to this descriptor without it
|
||||||
|
at GDTEntry.attribute, db attrib.present | attrib.user | attrib.writable
|
||||||
|
at GDTEntry.flags__limith, db 0
|
||||||
|
at GDTEntry.baseh, db 0
|
||||||
|
iend
|
||||||
|
|
||||||
|
.user_code equ $ - gdt
|
||||||
|
istruc GDTEntry
|
||||||
|
at GDTEntry.limitl, dw 0
|
||||||
|
at GDTEntry.basel, dw 0
|
||||||
|
at GDTEntry.basem, db 0
|
||||||
|
at GDTEntry.attribute, db attrib.present | attrib.ring3 | attrib.user | attrib.code
|
||||||
|
at GDTEntry.flags__limith, db flags.long_mode
|
||||||
|
at GDTEntry.baseh, db 0
|
||||||
|
iend
|
||||||
|
|
||||||
|
.user_data equ $ - gdt
|
||||||
|
istruc GDTEntry
|
||||||
|
at GDTEntry.limitl, dw 0
|
||||||
|
at GDTEntry.basel, dw 0
|
||||||
|
at GDTEntry.basem, db 0
|
||||||
|
; AMD System Programming Manual states that the writeable bit is ignored in long mode, but ss can not be set to this descriptor without it
|
||||||
|
at GDTEntry.attribute, db attrib.present | attrib.ring3 | attrib.user | attrib.writable
|
||||||
|
at GDTEntry.flags__limith, db 0
|
||||||
|
at GDTEntry.baseh, db 0
|
||||||
|
iend
|
||||||
|
|
||||||
|
.user_tls equ $ - gdt
|
||||||
|
istruc GDTEntry
|
||||||
|
at GDTEntry.limitl, dw 0
|
||||||
|
at GDTEntry.basel, dw 0
|
||||||
|
at GDTEntry.basem, db 0
|
||||||
|
; AMD System Programming Manual states that the writeable bit is ignored in long mode, but ss can not be set to this descriptor without it
|
||||||
|
at GDTEntry.attribute, db attrib.present | attrib.ring3 | attrib.user | attrib.writable
|
||||||
|
at GDTEntry.flags__limith, db 0
|
||||||
|
at GDTEntry.baseh, db 0
|
||||||
|
iend
|
||||||
|
|
||||||
|
.tss equ $ - gdt
|
||||||
|
istruc GDTEntry
|
||||||
|
at GDTEntry.limitl, dw (tss.end - tss) & 0xFFFF
|
||||||
|
at GDTEntry.basel, dw (tss-$$+0x7C00) & 0xFFFF
|
||||||
|
at GDTEntry.basem, db ((tss-$$+0x7C00) >> 16) & 0xFF
|
||||||
|
at GDTEntry.attribute, db attrib.present | attrib.ring3 | attrib.tssAvailabe64
|
||||||
|
at GDTEntry.flags__limith, db ((tss.end - tss) >> 16) & 0xF
|
||||||
|
at GDTEntry.baseh, db ((tss-$$+0x7C00) >> 24) & 0xFF
|
||||||
|
iend
|
||||||
|
dq 0 ;tss descriptors are extended to 16 Bytes
|
||||||
|
|
||||||
|
.end equ $ - gdt
|
||||||
|
|
||||||
|
struc TSS
|
||||||
|
.reserved1 resd 1 ;The previous TSS - if we used hardware task switching this would form a linked list.
|
||||||
|
.rsp0 resq 1 ;The stack pointer to load when we change to kernel mode.
|
||||||
|
.rsp1 resq 1 ;everything below here is unused now..
|
||||||
|
.rsp2 resq 1
|
||||||
|
.reserved2 resd 1
|
||||||
|
.reserved3 resd 1
|
||||||
|
.ist1 resq 1
|
||||||
|
.ist2 resq 1
|
||||||
|
.ist3 resq 1
|
||||||
|
.ist4 resq 1
|
||||||
|
.ist5 resq 1
|
||||||
|
.ist6 resq 1
|
||||||
|
.ist7 resq 1
|
||||||
|
.reserved4 resd 1
|
||||||
|
.reserved5 resd 1
|
||||||
|
.reserved6 resw 1
|
||||||
|
.iomap_base resw 1
|
||||||
|
endstruc
|
||||||
|
|
||||||
|
tss:
|
||||||
|
istruc TSS
|
||||||
|
at TSS.rsp0, dd 0x800000 - 128
|
||||||
|
at TSS.iomap_base, dw 0xFFFF
|
||||||
|
iend
|
||||||
|
.end:
|
||||||
|
|
||||||
|
%include "interrupts-x86_64.asm"
|
54
bootloader/x86/unreal.asm
Normal file
54
bootloader/x86/unreal.asm
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
SECTION .text
|
||||||
|
USE16
|
||||||
|
|
||||||
|
; switch to unreal mode; ds and es can address up to 4GiB
|
||||||
|
unreal:
|
||||||
|
cli
|
||||||
|
|
||||||
|
lgdt [unreal_gdtr]
|
||||||
|
|
||||||
|
push es
|
||||||
|
push ds
|
||||||
|
|
||||||
|
mov eax, cr0 ; switch to pmode by
|
||||||
|
or al,1 ; set pmode bit
|
||||||
|
mov cr0, eax
|
||||||
|
|
||||||
|
jmp $+2
|
||||||
|
|
||||||
|
; http://wiki.osdev.org/Babystep7
|
||||||
|
; When this register given a "selector", a "segment descriptor cache register"
|
||||||
|
; is filled with the descriptor values, including the size (or limit). After
|
||||||
|
; the switch back to real mode, these values are not modified, regardless of
|
||||||
|
; what value is in the 16-bit segment register. So the 64k limit is no longer
|
||||||
|
; valid and 32-bit offsets can be used with the real-mode addressing rules
|
||||||
|
mov bx, unreal_gdt.data
|
||||||
|
mov es, bx
|
||||||
|
mov ds, bx
|
||||||
|
|
||||||
|
and al,0xFE ; back to realmode
|
||||||
|
mov cr0, eax ; by toggling bit again
|
||||||
|
|
||||||
|
pop ds
|
||||||
|
pop es
|
||||||
|
sti
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
unreal_gdtr:
|
||||||
|
dw unreal_gdt.end + 1 ; size
|
||||||
|
dd unreal_gdt ; offset
|
||||||
|
|
||||||
|
unreal_gdt:
|
||||||
|
.null equ $ - unreal_gdt
|
||||||
|
dq 0
|
||||||
|
.data equ $ - unreal_gdt
|
||||||
|
istruc GDTEntry
|
||||||
|
at GDTEntry.limitl, dw 0xFFFF
|
||||||
|
at GDTEntry.basel, dw 0x0
|
||||||
|
at GDTEntry.basem, db 0x0
|
||||||
|
at GDTEntry.attribute, db attrib.present | attrib.user | attrib.writable
|
||||||
|
at GDTEntry.flags__limith, db 0xFF | flags.granularity | flags.default_operand_size
|
||||||
|
at GDTEntry.baseh, db 0x0
|
||||||
|
iend
|
||||||
|
.end equ $ - unreal_gdt
|
304
bootloader/x86/vesa.asm
Normal file
304
bootloader/x86/vesa.asm
Normal file
|
@ -0,0 +1,304 @@
|
||||||
|
%include "vesa.inc"
|
||||||
|
SECTION .text
|
||||||
|
USE16
|
||||||
|
vesa:
|
||||||
|
.getcardinfo:
|
||||||
|
mov ax, 0x4F00
|
||||||
|
mov di, VBECardInfo
|
||||||
|
int 0x10
|
||||||
|
cmp ax, 0x4F
|
||||||
|
je .edid
|
||||||
|
mov eax, 1
|
||||||
|
ret
|
||||||
|
.edid:
|
||||||
|
cmp dword [.required], 0 ;if both required x and required y are set, forget this
|
||||||
|
jne near .findmode
|
||||||
|
mov ax, 0x4F15
|
||||||
|
mov bx, 1
|
||||||
|
xor cx, cx
|
||||||
|
xor dx, dx
|
||||||
|
mov di, VBEEDID
|
||||||
|
int 0x10
|
||||||
|
cmp ax, 0x4F
|
||||||
|
jne near .noedid
|
||||||
|
xor di, di
|
||||||
|
.lp:
|
||||||
|
xor cx, cx
|
||||||
|
mov cl, [di+VBEEDID.standardtiming]
|
||||||
|
shl cx, 3
|
||||||
|
add cx, 248
|
||||||
|
push ecx
|
||||||
|
call decshowrm
|
||||||
|
mov al, 'x'
|
||||||
|
call charrm
|
||||||
|
pop ecx
|
||||||
|
mov bx, cx
|
||||||
|
inc di
|
||||||
|
mov al, [di+VBEEDID.standardtiming]
|
||||||
|
and al, 11000000b
|
||||||
|
cmp al, VBEEDID.aspect.4.3
|
||||||
|
jne .not43
|
||||||
|
mov ax, 3
|
||||||
|
mul cx
|
||||||
|
mov cx, ax
|
||||||
|
shr cx, 2
|
||||||
|
jmp .gotres
|
||||||
|
.not43:
|
||||||
|
cmp al, VBEEDID.aspect.5.4
|
||||||
|
jne .not54
|
||||||
|
shl cx, 2
|
||||||
|
mov ax, cx
|
||||||
|
mov cx, 5
|
||||||
|
xor dx, dx
|
||||||
|
div cx
|
||||||
|
mov cx, ax
|
||||||
|
jmp .gotres
|
||||||
|
.not54:
|
||||||
|
cmp al, VBEEDID.aspect.16.10
|
||||||
|
jne .not1610
|
||||||
|
mov ax, 10
|
||||||
|
mul cx
|
||||||
|
mov cx, ax
|
||||||
|
shr cx, 4
|
||||||
|
jmp .gotres
|
||||||
|
.not1610:
|
||||||
|
mov ax, 9
|
||||||
|
mul cx
|
||||||
|
mov cx, ax
|
||||||
|
shr cx, 4
|
||||||
|
.gotres:
|
||||||
|
call decshowrm
|
||||||
|
mov si, .edidmsg
|
||||||
|
call printrm
|
||||||
|
inc di
|
||||||
|
cmp di, 8
|
||||||
|
jb .lp
|
||||||
|
jmp .findmode
|
||||||
|
.noedid:
|
||||||
|
mov si, .noedidmsg
|
||||||
|
call printrm
|
||||||
|
jmp .findmode
|
||||||
|
.resetlist:
|
||||||
|
;if needed, reset mins/maxes/stuff
|
||||||
|
xor cx, cx
|
||||||
|
mov [.minx], cx
|
||||||
|
mov [.miny], cx
|
||||||
|
mov [.requiredx], cx
|
||||||
|
mov [.requiredy], cx
|
||||||
|
mov [.requiredmode], cx
|
||||||
|
.findmode:
|
||||||
|
mov si, [VBECardInfo.videomodeptr]
|
||||||
|
mov ax, [VBECardInfo.videomodeptr+2]
|
||||||
|
mov fs, ax
|
||||||
|
sub si, 2
|
||||||
|
mov cx, [.requiredmode]
|
||||||
|
test cx, cx
|
||||||
|
jnz .getmodeinfo
|
||||||
|
.searchmodes:
|
||||||
|
add si, 2
|
||||||
|
mov cx, [fs:si]
|
||||||
|
cmp cx, 0xFFFF
|
||||||
|
jne .getmodeinfo
|
||||||
|
cmp word [.goodmode], 0
|
||||||
|
je .resetlist
|
||||||
|
jmp .findmode
|
||||||
|
.getmodeinfo:
|
||||||
|
push esi
|
||||||
|
mov [.currentmode], cx
|
||||||
|
mov ax, 0x4F01
|
||||||
|
mov di, VBEModeInfo
|
||||||
|
int 0x10
|
||||||
|
pop esi
|
||||||
|
cmp ax, 0x4F
|
||||||
|
je .foundmode
|
||||||
|
mov eax, 1
|
||||||
|
ret
|
||||||
|
.foundmode:
|
||||||
|
;check minimum values, really not minimums from an OS perspective but ugly for users
|
||||||
|
cmp byte [VBEModeInfo.bitsperpixel], 32
|
||||||
|
jb .searchmodes
|
||||||
|
.testx:
|
||||||
|
mov cx, [VBEModeInfo.xresolution]
|
||||||
|
cmp word [.requiredx], 0
|
||||||
|
je .notrequiredx
|
||||||
|
cmp cx, [.requiredx]
|
||||||
|
je .testy
|
||||||
|
jmp .searchmodes
|
||||||
|
.notrequiredx:
|
||||||
|
cmp cx, [.minx]
|
||||||
|
jb .searchmodes
|
||||||
|
.testy:
|
||||||
|
mov cx, [VBEModeInfo.yresolution]
|
||||||
|
cmp word [.requiredy], 0
|
||||||
|
je .notrequiredy
|
||||||
|
cmp cx, [.requiredy]
|
||||||
|
jne .searchmodes ;as if there weren't enough warnings, USE WITH CAUTION
|
||||||
|
cmp word [.requiredx], 0
|
||||||
|
jnz .setmode
|
||||||
|
jmp .testgood
|
||||||
|
.notrequiredy:
|
||||||
|
cmp cx, [.miny]
|
||||||
|
jb .searchmodes
|
||||||
|
.testgood:
|
||||||
|
mov cx, [.currentmode]
|
||||||
|
mov [.goodmode], cx
|
||||||
|
push esi
|
||||||
|
call decshowrm
|
||||||
|
mov al, ':'
|
||||||
|
call charrm
|
||||||
|
mov cx, [VBEModeInfo.xresolution]
|
||||||
|
call decshowrm
|
||||||
|
mov al, 'x'
|
||||||
|
call charrm
|
||||||
|
mov cx, [VBEModeInfo.yresolution]
|
||||||
|
call decshowrm
|
||||||
|
mov al, '@'
|
||||||
|
call charrm
|
||||||
|
xor ch, ch
|
||||||
|
mov cl, [VBEModeInfo.bitsperpixel]
|
||||||
|
call decshowrm
|
||||||
|
mov si, .modeok
|
||||||
|
call printrm
|
||||||
|
xor ax, ax
|
||||||
|
int 0x16
|
||||||
|
pop esi
|
||||||
|
cmp al, 'y'
|
||||||
|
jne .searchmodes
|
||||||
|
.setmode:
|
||||||
|
mov bx, [.currentmode]
|
||||||
|
cmp bx, 0
|
||||||
|
je .nomode
|
||||||
|
or bx, 0x4000
|
||||||
|
mov ax, 0x4F02
|
||||||
|
int 0x10
|
||||||
|
.nomode:
|
||||||
|
cmp ax, 0x4F
|
||||||
|
je .returngood
|
||||||
|
mov eax, 1
|
||||||
|
ret
|
||||||
|
.returngood:
|
||||||
|
xor eax, eax
|
||||||
|
ret
|
||||||
|
|
||||||
|
.minx dw 640
|
||||||
|
.miny dw 480
|
||||||
|
.required:
|
||||||
|
.requiredx dw 0 ;1024 ;USE THESE WITH CAUTION
|
||||||
|
.requiredy dw 0 ;768
|
||||||
|
.requiredmode dw 0
|
||||||
|
|
||||||
|
.noedidmsg db "EDID not supported.",10,13,0
|
||||||
|
.edidmsg db " is supported.",10,13,0
|
||||||
|
.modeok db ": Is this OK?(y/n)",10,13,0
|
||||||
|
|
||||||
|
.goodmode dw 0
|
||||||
|
.currentmode dw 0
|
||||||
|
;useful functions
|
||||||
|
|
||||||
|
decshowrm:
|
||||||
|
mov si, .number
|
||||||
|
.clear:
|
||||||
|
mov al, "0"
|
||||||
|
mov [si], al
|
||||||
|
inc si
|
||||||
|
cmp si, .numberend
|
||||||
|
jb .clear
|
||||||
|
dec si
|
||||||
|
call convertrm
|
||||||
|
mov si, .number
|
||||||
|
.lp:
|
||||||
|
lodsb
|
||||||
|
cmp si, .numberend
|
||||||
|
jae .end
|
||||||
|
cmp al, "0"
|
||||||
|
jbe .lp
|
||||||
|
.end:
|
||||||
|
dec si
|
||||||
|
call printrm
|
||||||
|
ret
|
||||||
|
|
||||||
|
.number times 7 db 0
|
||||||
|
.numberend db 0
|
||||||
|
|
||||||
|
convertrm:
|
||||||
|
dec si
|
||||||
|
mov bx, si ;place to convert into must be in si, number to convert must be in cx
|
||||||
|
.cnvrt:
|
||||||
|
mov si, bx
|
||||||
|
sub si, 4
|
||||||
|
.ten4: inc si
|
||||||
|
cmp cx, 10000
|
||||||
|
jb .ten3
|
||||||
|
sub cx, 10000
|
||||||
|
inc byte [si]
|
||||||
|
jmp .cnvrt
|
||||||
|
.ten3: inc si
|
||||||
|
cmp cx, 1000
|
||||||
|
jb .ten2
|
||||||
|
sub cx, 1000
|
||||||
|
inc byte [si]
|
||||||
|
jmp .cnvrt
|
||||||
|
.ten2: inc si
|
||||||
|
cmp cx, 100
|
||||||
|
jb .ten1
|
||||||
|
sub cx, 100
|
||||||
|
inc byte [si]
|
||||||
|
jmp .cnvrt
|
||||||
|
.ten1: inc si
|
||||||
|
cmp cx, 10
|
||||||
|
jb .ten0
|
||||||
|
sub cx, 10
|
||||||
|
inc byte [si]
|
||||||
|
jmp .cnvrt
|
||||||
|
.ten0: inc si
|
||||||
|
cmp cx, 1
|
||||||
|
jb .return
|
||||||
|
sub cx, 1
|
||||||
|
inc byte [si]
|
||||||
|
jmp .cnvrt
|
||||||
|
.return:
|
||||||
|
ret
|
||||||
|
|
||||||
|
printrm:
|
||||||
|
mov al, [si]
|
||||||
|
test al, al
|
||||||
|
jz .return
|
||||||
|
call charrm
|
||||||
|
inc si
|
||||||
|
jmp printrm
|
||||||
|
.return:
|
||||||
|
ret
|
||||||
|
|
||||||
|
charrm: ;char must be in al
|
||||||
|
mov bx, 7
|
||||||
|
mov ah, 0xE
|
||||||
|
int 10h
|
||||||
|
ret
|
||||||
|
|
||||||
|
; .bestmode: ;preference is width > height > color
|
||||||
|
; mov bx, [VBEModeInfo.xresolution]
|
||||||
|
; cmp bx, [.width]
|
||||||
|
; ja .switchmode
|
||||||
|
; jb .searchmodes
|
||||||
|
; mov bx, [VBEModeInfo.yresolution]
|
||||||
|
; cmp bx, [.height]
|
||||||
|
; ja .switchmode
|
||||||
|
; jb .searchmodes
|
||||||
|
; mov bl, [VBEModeInfo.bitsperpixel]
|
||||||
|
; cmp bl, [.color]
|
||||||
|
; jb .searchmodes
|
||||||
|
; .switchmode:
|
||||||
|
; mov cx, [.currentmode]
|
||||||
|
; mov [.mode], cx
|
||||||
|
; mov bx, [VBEModeInfo.xresolution]
|
||||||
|
; mov [.width], bx
|
||||||
|
; mov bx, [VBEModeInfo.yresolution]
|
||||||
|
; mov [.height], bx
|
||||||
|
; mov bl, [VBEModeInfo.bitsperpixel]
|
||||||
|
; mov [.color], bl
|
||||||
|
; jmp .searchmodes
|
||||||
|
|
||||||
|
; .mode dw 0
|
||||||
|
; .color db 0
|
||||||
|
; .height dw 0
|
||||||
|
; .width dw 0
|
90
bootloader/x86/vesa.inc
Normal file
90
bootloader/x86/vesa.inc
Normal file
|
@ -0,0 +1,90 @@
|
||||||
|
ABSOLUTE 0x5000
|
||||||
|
VBECardInfo:
|
||||||
|
.signature resb 4
|
||||||
|
.version resw 1
|
||||||
|
.oemstring resd 1
|
||||||
|
.capabilities resd 1
|
||||||
|
.videomodeptr resd 1
|
||||||
|
.totalmemory resw 1
|
||||||
|
.oemsoftwarerev resw 1
|
||||||
|
.oemvendornameptr resd 1
|
||||||
|
.oemproductnameptr resd 1
|
||||||
|
.oemproductrevptr resd 1
|
||||||
|
.reserved resb 222
|
||||||
|
.oemdata resb 256
|
||||||
|
|
||||||
|
ABSOLUTE 0x5200
|
||||||
|
VBEModeInfo:
|
||||||
|
.attributes resw 1
|
||||||
|
.winA resb 1
|
||||||
|
.winB resb 1
|
||||||
|
.granularity resw 1
|
||||||
|
.winsize resw 1
|
||||||
|
.segmentA resw 1
|
||||||
|
.segmentB resw 1
|
||||||
|
.winfuncptr resd 1
|
||||||
|
.bytesperscanline resw 1
|
||||||
|
.xresolution resw 1
|
||||||
|
.yresolution resw 1
|
||||||
|
.xcharsize resb 1
|
||||||
|
.ycharsize resb 1
|
||||||
|
.numberofplanes resb 1
|
||||||
|
.bitsperpixel resb 1
|
||||||
|
.numberofbanks resb 1
|
||||||
|
.memorymodel resb 1
|
||||||
|
.banksize resb 1
|
||||||
|
.numberofimagepages resb 1
|
||||||
|
.unused resb 1
|
||||||
|
.redmasksize resb 1
|
||||||
|
.redfieldposition resb 1
|
||||||
|
.greenmasksize resb 1
|
||||||
|
.greenfieldposition resb 1
|
||||||
|
.bluemasksize resb 1
|
||||||
|
.bluefieldposition resb 1
|
||||||
|
.rsvdmasksize resb 1
|
||||||
|
.rsvdfieldposition resb 1
|
||||||
|
.directcolormodeinfo resb 1
|
||||||
|
.physbaseptr resd 1
|
||||||
|
.offscreenmemoryoffset resd 1
|
||||||
|
.offscreenmemsize resw 1
|
||||||
|
.reserved resb 206
|
||||||
|
|
||||||
|
VBE.ModeAttributes:
|
||||||
|
.available equ 1 << 0
|
||||||
|
.bios equ 1 << 2
|
||||||
|
.color equ 1 << 3
|
||||||
|
.graphics equ 1 << 4
|
||||||
|
.vgacompatible equ 1 << 5
|
||||||
|
.notbankable equ 1 << 6
|
||||||
|
.linearframebuffer equ 1 << 7
|
||||||
|
|
||||||
|
ABSOLUTE 0x5400
|
||||||
|
VBEEDID:
|
||||||
|
.header resb 8
|
||||||
|
.manufacturer resw 1
|
||||||
|
.productid resw 1
|
||||||
|
.serial resd 1
|
||||||
|
.manufactureweek resb 1
|
||||||
|
.manufactureyear resb 1
|
||||||
|
.version resb 1
|
||||||
|
.revision resb 1
|
||||||
|
.input resb 1
|
||||||
|
.horizontalsize resb 1
|
||||||
|
.verticalsize resb 1
|
||||||
|
.gamma resb 1
|
||||||
|
.displaytype resb 1
|
||||||
|
.chromaticity resb 10
|
||||||
|
.timingI resb 1
|
||||||
|
.timingII resb 1
|
||||||
|
.timingreserved resb 1
|
||||||
|
.standardtiming: resw 8 ;format: db (horizontal-248)/8, aspectratio | verticalfrequency - 60
|
||||||
|
.aspect.16.10 equ 0 ;mul horizontal by 10, shr 4 to get vertical resolution
|
||||||
|
.aspect.4.3 equ 1 << 6 ;mul horizontal by 3, shr 2 to get vertical resolution
|
||||||
|
.aspect.5.4 equ 2 << 6 ;shl horizontal by 2, div by 5 to get vertical resolution
|
||||||
|
.aspect.16.9 equ 3 << 6 ;mul horizontal by 9, shr by 4 to get vertical resolution
|
||||||
|
.descriptorblock1 resb 18
|
||||||
|
.descriptorblock2 resb 18
|
||||||
|
.descriptorblock3 resb 18
|
||||||
|
.descriptorblock4 resb 18
|
||||||
|
.extensionflag resb 1
|
||||||
|
.checksum resb 1
|
4
src/arch/mod.rs
Normal file
4
src/arch/mod.rs
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
//! Architecture specific items
|
||||||
|
|
||||||
|
#[cfg(target_arch = "x86_64")]
|
||||||
|
pub mod x86_64;
|
8
src/arch/x86_64/irq.rs
Normal file
8
src/arch/x86_64/irq.rs
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
//! # IRQ handling
|
||||||
|
//! This module defines IRQ handling functions. These functions should all be #[naked],
|
||||||
|
//! unsafe, extern, and end in `iretq`
|
||||||
|
|
||||||
|
#[naked]
|
||||||
|
pub unsafe extern fn irq() {
|
||||||
|
|
||||||
|
}
|
11
src/arch/x86_64/main.rs
Normal file
11
src/arch/x86_64/main.rs
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
/// This function is where the kernel sets up IRQ handlers
|
||||||
|
/// It is increcibly unsafe, and should be minimal in nature
|
||||||
|
/// It must create the IDT with the correct entries, those entries are
|
||||||
|
/// defined in other files inside of the `arch` module
|
||||||
|
#[naked]
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern fn kmain() {
|
||||||
|
asm!("xchg bx, bx" : : : : "intel", "volatile");
|
||||||
|
|
||||||
|
loop{}
|
||||||
|
}
|
5
src/arch/x86_64/mod.rs
Normal file
5
src/arch/x86_64/mod.rs
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
/// IRQ Handling
|
||||||
|
pub mod irq;
|
||||||
|
|
||||||
|
/// Initialization and main function
|
||||||
|
pub mod main;
|
34
src/lib.rs
34
src/lib.rs
|
@ -11,31 +11,37 @@
|
||||||
//! `open(path: &str, flags: usize) -> Result<file_descriptor: usize>`
|
//! `open(path: &str, flags: usize) -> Result<file_descriptor: usize>`
|
||||||
//!
|
//!
|
||||||
//! Open a file, providing a path as a `&str` and flags, defined elsewhere.
|
//! Open a file, providing a path as a `&str` and flags, defined elsewhere.
|
||||||
|
//!
|
||||||
//! Returns a number, known as a file descriptor, that is passed to other syscalls
|
//! Returns a number, known as a file descriptor, that is passed to other syscalls
|
||||||
//!
|
//!
|
||||||
//! ### Close
|
//! ### Close
|
||||||
//! `close(file_descriptor: usize) -> Result<()>`
|
//! `close(file_descriptor: usize) -> Result<()>`
|
||||||
//!
|
//!
|
||||||
//! Close a file descriptor, providing the file descriptor from `open`
|
//! Close a file descriptor, providing the file descriptor from `open`
|
||||||
|
//!
|
||||||
//! Returns an error, `EBADF`, if the file descriptor was not found.
|
//! Returns an error, `EBADF`, if the file descriptor was not found.
|
||||||
|
//!
|
||||||
//! This potential error is often ignored by userspace
|
//! This potential error is often ignored by userspace
|
||||||
//!
|
//!
|
||||||
//! ### Duplicate
|
//! ### Duplicate
|
||||||
//! `dup(file_descriptor: usize) -> Result<file_descriptor: usize>`
|
//! `dup(file_descriptor: usize) -> Result<file_descriptor: usize>`
|
||||||
//!
|
//!
|
||||||
//! Duplicate a file descriptor, providing the file descriptor from `open`
|
//! Duplicate a file descriptor, providing the file descriptor from `open`
|
||||||
|
//!
|
||||||
//! Returns a new file descriptor, or an error
|
//! Returns a new file descriptor, or an error
|
||||||
//!
|
//!
|
||||||
//! ### Read
|
//! ### Read
|
||||||
//! `read(file_descriptor: usize, buffer: &mut [u8]) -> Result<count: usize>`
|
//! `read(file_descriptor: usize, buffer: &mut [u8]) -> Result<count: usize>`
|
||||||
//!
|
//!
|
||||||
//! Read from a file descriptor, providing the file descriptor from `open` and a mutable buffer
|
//! Read from a file descriptor, providing the file descriptor from `open` and a mutable buffer
|
||||||
|
//!
|
||||||
//! Returns the number of bytes actually read, or an error
|
//! Returns the number of bytes actually read, or an error
|
||||||
//!
|
//!
|
||||||
//! ### Write
|
//! ### Write
|
||||||
//! `write(file_descriptor: usize, buffer: &[u8]) -> Result<count: usize>`
|
//! `write(file_descriptor: usize, buffer: &[u8]) -> Result<count: usize>`
|
||||||
//!
|
//!
|
||||||
//! Write to a file descriptor, providing the file descriptor from `open` and a const buffer
|
//! Write to a file descriptor, providing the file descriptor from `open` and a const buffer
|
||||||
|
//!
|
||||||
//! Returns the number of bytes actually written, or an error
|
//! Returns the number of bytes actually written, or an error
|
||||||
//!
|
//!
|
||||||
//! ### Stat
|
//! ### Stat
|
||||||
|
@ -43,12 +49,34 @@
|
||||||
//!
|
//!
|
||||||
//! Get information from a file descriptor, providing the file descriptor from `open`
|
//! Get information from a file descriptor, providing the file descriptor from `open`
|
||||||
//! and a mutable Stat struct, defined elsewhere.
|
//! and a mutable Stat struct, defined elsewhere.
|
||||||
|
//!
|
||||||
//! Returns an error if the operation failed
|
//! Returns an error if the operation failed
|
||||||
//!
|
//!
|
||||||
//! ### Path
|
//! ### Path
|
||||||
//! `fpath(file_descriptor: usize, buffer: &mut [u8]) -> Result<count: usize>`
|
//! `fpath(file_descriptor: usize, buffer: &mut [u8]) -> Result<count: usize>`
|
||||||
//!
|
//!
|
||||||
//! Read the path of a file descriptor, providing the file descriptor from `open`
|
//! Read the path of a file descriptor, providing the file descriptor from `open` and
|
||||||
//! and a mutable buffer. The buffer should be 4096 bytes, to ensure that the
|
//! a mutable buffer.
|
||||||
//! entire path will fit.
|
//!
|
||||||
//! Returns the number of bytes actually read, or an error
|
//! Returns the number of bytes actually read, or an error
|
||||||
|
//!
|
||||||
|
//! The buffer should be 4096 bytes, to ensure that the entire path will fit.
|
||||||
|
//! An error will be returned, `ENOBUFS`, if the buffer is not long enough for the name.
|
||||||
|
//! In this case, it is recommended to add one page, 4096 bytes, to the buffer and retry.
|
||||||
|
|
||||||
|
#![feature(asm)]
|
||||||
|
#![feature(lang_items)]
|
||||||
|
#![feature(naked_functions)]
|
||||||
|
#![no_std]
|
||||||
|
|
||||||
|
/// Architecture specific items
|
||||||
|
pub mod arch;
|
||||||
|
|
||||||
|
#[cfg(not(test))]
|
||||||
|
#[lang = "eh_personality"]
|
||||||
|
extern "C" fn eh_personality() {}
|
||||||
|
|
||||||
|
#[cfg(not(test))]
|
||||||
|
/// Required to handle panics
|
||||||
|
#[lang = "panic_fmt"]
|
||||||
|
extern "C" fn panic_fmt() -> ! {loop{}}
|
||||||
|
|
11
src/scheme/mod.rs
Normal file
11
src/scheme/mod.rs
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
/// A scheme is a primitive for handling filesystem syscalls in Redox.
|
||||||
|
/// Schemes accept paths from the kernel for `open`, and file descriptors that they generate
|
||||||
|
/// are then passed for operations like `close`, `read`, `write`, etc.
|
||||||
|
///
|
||||||
|
/// The kernel validates paths and file descriptors before they are passed to schemes,
|
||||||
|
/// also stripping the scheme identifier of paths if necessary.
|
||||||
|
pub trait Scheme {
|
||||||
|
/// Open the file at `path` with `flags`.
|
||||||
|
/// Returns a file descriptor or an error
|
||||||
|
fn open(path: &str, flags: usize) -> Result<usize>;
|
||||||
|
}
|
25
x86_64-unknown-none.json
Normal file
25
x86_64-unknown-none.json
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
{
|
||||||
|
"llvm-target": "x86_64-unknown-none",
|
||||||
|
"target-endian": "little",
|
||||||
|
"target-pointer-width": "64",
|
||||||
|
"data-layout": "e-m:e-i64:64-f80:128-n8:16:32:64-S128",
|
||||||
|
"arch": "x86_64",
|
||||||
|
"os": "none",
|
||||||
|
"env": "",
|
||||||
|
"vendor": "unknown",
|
||||||
|
"target-family": "redox",
|
||||||
|
"pre-link-args": ["-m64", "-nostdlib", "-static"],
|
||||||
|
"features": "-sse3,-ssse3,-sse4.1,-sse4.2,-3dnow,-3dnowa,-avx,-avx2",
|
||||||
|
"dynamic-linking": false,
|
||||||
|
"executables": false,
|
||||||
|
"relocation-model": "static",
|
||||||
|
"code-model": "kernel",
|
||||||
|
"disable-redzone": true,
|
||||||
|
"eliminate-frame-pointer": true,
|
||||||
|
"exe-suffix": "",
|
||||||
|
"has-rpath": false,
|
||||||
|
"no-compiler-rt": true,
|
||||||
|
"no-default-libraries": true,
|
||||||
|
"position-independent-executables": false,
|
||||||
|
"has-elf-tls": false
|
||||||
|
}
|
25
x86_64-unknown-redox.json
Normal file
25
x86_64-unknown-redox.json
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
{
|
||||||
|
"llvm-target": "x86_64-unknown-redox",
|
||||||
|
"target-endian": "little",
|
||||||
|
"target-pointer-width": "64",
|
||||||
|
"data-layout": "e-m:e-i64:64-f80:128-n8:16:32:64-S128",
|
||||||
|
"arch": "x86_64",
|
||||||
|
"os": "redox",
|
||||||
|
"env": "",
|
||||||
|
"vendor": "unknown",
|
||||||
|
"target-family": "redox",
|
||||||
|
"pre-link-args": ["-m64", "-nostdlib", "-static"],
|
||||||
|
"features": "-sse3,-ssse3,-sse4.1,-sse4.2,-3dnow,-3dnowa,-avx,-avx2",
|
||||||
|
"dynamic-linking": false,
|
||||||
|
"executables": true,
|
||||||
|
"relocation-model": "static",
|
||||||
|
"code-model": "kernel",
|
||||||
|
"disable-redzone": true,
|
||||||
|
"eliminate-frame-pointer": true,
|
||||||
|
"exe-suffix": ".bin",
|
||||||
|
"has-rpath": false,
|
||||||
|
"no-compiler-rt": true,
|
||||||
|
"no-default-libraries": true,
|
||||||
|
"position-independent-executables": false,
|
||||||
|
"has-elf-tls": false
|
||||||
|
}
|
Loading…
Reference in a new issue