Completely changed how XnoeOS boots, organised the code somewhat, renamed kernel32 to kernel, now uses the 9 sectors after the boot sector to store a 32 bit stage2 loader. No longer spends unnecessary time in real mode. Updated atapio to properly account for the reserved sector count.
This commit is contained in:
parent
d617de6a0c
commit
c235befa43
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,5 +1,6 @@
|
|||||||
*.bin
|
*.bin
|
||||||
*.img
|
*.img
|
||||||
|
*.stage2
|
||||||
*.sector
|
*.sector
|
||||||
*.o
|
*.o
|
||||||
img.d/
|
img.d/
|
18
Makefile
18
Makefile
@ -1,15 +1,16 @@
|
|||||||
CFLAGS = -m32 -mgeneral-regs-only -nostdlib -fno-builtin -fno-exceptions -fno-leading-underscore -fno-pie -fno-stack-protector -Wno-pointer-to-int-cast
|
CFLAGS = -m32 -mgeneral-regs-only -nostdlib -fno-builtin -fno-exceptions -fno-leading-underscore -fno-pie -fno-stack-protector -Wno-pointer-to-int-cast
|
||||||
LDFLAGS =
|
LDFLAGS =
|
||||||
|
|
||||||
DISK_IMG_FILES = kernel.bin boot32.bin kernel32.bin
|
DISK_IMG_FILES = kernel.bin
|
||||||
KERNEL32_OBJS = screenstuff.o io.o idt.o keyboard.o strings.o atapio.o kernel32_strap.o kernel32.o
|
KERNEL32_OBJS = screenstuff.o io.o idt.o keyboard.o strings.o atapio.o c_code_entry.o kernel.o
|
||||||
|
|
||||||
run: disk.img
|
run: disk.img
|
||||||
qemu-system-x86_64 disk.img
|
qemu-system-x86_64 disk.img
|
||||||
|
|
||||||
disk.img: clean boot.sector $(DISK_IMG_FILES)
|
disk.img: clean boot.sector boot.stage2 $(DISK_IMG_FILES)
|
||||||
dd if=/dev/zero of=disk.img count=43 bs=100k
|
dd if=/dev/zero of=disk.img count=43 bs=100k
|
||||||
dd if=boot.sector of=disk.img conv=notrunc
|
dd if=boot.sector of=disk.img conv=notrunc
|
||||||
|
dd obs=512 seek=1 if=boot.stage2 of=disk.img conv=notrunc
|
||||||
mount disk.img img.d
|
mount disk.img img.d
|
||||||
cp *.bin img.d/
|
cp *.bin img.d/
|
||||||
cp hello.txt img.d/
|
cp hello.txt img.d/
|
||||||
@ -22,14 +23,23 @@ clean:
|
|||||||
boot.sector: boot.asm
|
boot.sector: boot.asm
|
||||||
nasm $< -o $@
|
nasm $< -o $@
|
||||||
|
|
||||||
|
boot.stage2: boot_stage2.ld boot.stage2.o
|
||||||
|
ld $(LDFLAGS) -T $< boot.stage2.o
|
||||||
|
|
||||||
|
boot.stage2.o: src/boot_stage2/main.c io.o atapio.o strings.o c_code_entry.o screenstuff.o
|
||||||
|
gcc $(CFLAGS) -o $@ -c $<
|
||||||
|
|
||||||
%.bin: %.asm
|
%.bin: %.asm
|
||||||
nasm $< -o $@
|
nasm $< -o $@
|
||||||
|
|
||||||
kernel32.bin: kernel32.ld $(KERNEL32_OBJS)
|
kernel.bin: kernel.ld $(KERNEL32_OBJS)
|
||||||
ld $(LDFLAGS) -T $< $(KERNEL32_OBJS)
|
ld $(LDFLAGS) -T $< $(KERNEL32_OBJS)
|
||||||
|
|
||||||
%.o: src/kernel/%.asm
|
%.o: src/kernel/%.asm
|
||||||
nasm -felf32 $< -o $@
|
nasm -felf32 $< -o $@
|
||||||
|
|
||||||
|
%.o: src/%.asm
|
||||||
|
nasm -felf32 $< -o $@
|
||||||
|
|
||||||
%.o: src/kernel/%.c
|
%.o: src/kernel/%.c
|
||||||
gcc $(CFLAGS) -o $@ -c $<
|
gcc $(CFLAGS) -o $@ -c $<
|
172
boot.asm
172
boot.asm
@ -1,3 +1,4 @@
|
|||||||
|
[ORG 0x7C00]
|
||||||
[BITS 16]
|
[BITS 16]
|
||||||
|
|
||||||
jmp short bootcode
|
jmp short bootcode
|
||||||
@ -7,7 +8,7 @@ bpOEMid db "XNOE "
|
|||||||
|
|
||||||
bpBytesPerSector dw 512
|
bpBytesPerSector dw 512
|
||||||
bpSectorsPerCluster db 1
|
bpSectorsPerCluster db 1
|
||||||
bpReservedSectors dw 1
|
bpReservedSectors dw 10 ; We should reserve 10 sectors. Boot sector + stage2
|
||||||
bpNoFATs db 2
|
bpNoFATs db 2
|
||||||
bpRootDirEntries dw 256
|
bpRootDirEntries dw 256
|
||||||
bpLVSectors dw 8586
|
bpLVSectors dw 8586
|
||||||
@ -27,8 +28,6 @@ bpVolumeLabel db "XNOE OS "
|
|||||||
bpFileSystem db "FAT16 "
|
bpFileSystem db "FAT16 "
|
||||||
|
|
||||||
bootcode:
|
bootcode:
|
||||||
mov ax, 7c0h
|
|
||||||
mov ds, ax
|
|
||||||
|
|
||||||
mov byte [bpDriveNo], dl
|
mov byte [bpDriveNo], dl
|
||||||
|
|
||||||
@ -43,137 +42,34 @@ bootcode:
|
|||||||
movzx cx, cl
|
movzx cx, cl
|
||||||
mov word [bpSectorsPerTrack], cx
|
mov word [bpSectorsPerTrack], cx
|
||||||
|
|
||||||
mov si, boot_msg
|
; Load the stage2 (32-bit) from the next sectors
|
||||||
call _boot_print
|
; Load it at 0x10000
|
||||||
|
mov ax, 7e0h
|
||||||
mov ax, ds
|
|
||||||
mov es, ax
|
mov es, ax
|
||||||
mov bx, buffer
|
xor bx, bx
|
||||||
|
|
||||||
; Calculate position of rootdirentries
|
mov ax, 2 ; Begin with the 2nd sector
|
||||||
mov ax, word [bpSectorsPerFat]
|
|
||||||
movzx cx, byte [bpNoFATs]
|
|
||||||
mul cx
|
|
||||||
|
|
||||||
add ax, 2
|
|
||||||
call prep_i13
|
call prep_i13
|
||||||
|
mov al, 9 ; Load the next 9 sectors (4.5k)
|
||||||
int 13h
|
int 13h
|
||||||
|
|
||||||
mov cx, [bpRootDirEntries]
|
; Now we should prepare to enter in to protected mode for the sole purpose of running the stage2 bootloader
|
||||||
mov di, buffer
|
|
||||||
|
|
||||||
mov ax, 0
|
; Enable the A20 line
|
||||||
|
in al, 0x92
|
||||||
|
or al, 2
|
||||||
|
out 0x92, al
|
||||||
|
|
||||||
; jmp $
|
; Load the temporary GDT
|
||||||
|
cli
|
||||||
|
lgdt [gdt_desc]
|
||||||
|
mov eax, cr0
|
||||||
|
or eax, 1
|
||||||
|
mov cr0, eax
|
||||||
|
|
||||||
kernel_finder:
|
jmp 08h:7e00h ; Far jump to where we loaded the stage 2
|
||||||
xchg cx, dx
|
|
||||||
|
|
||||||
mov di, buffer
|
; In ax with sector addr, out correct values for int 13h
|
||||||
add di, ax
|
|
||||||
|
|
||||||
mov si, kernel_file
|
|
||||||
mov cx, 11
|
|
||||||
rep cmpsb
|
|
||||||
je kernel_found
|
|
||||||
|
|
||||||
add ax, 20h
|
|
||||||
|
|
||||||
xchg cx, dx
|
|
||||||
loop kernel_finder
|
|
||||||
|
|
||||||
mov si, kernel_nf
|
|
||||||
call _boot_print
|
|
||||||
|
|
||||||
jmp $
|
|
||||||
|
|
||||||
kernel_found:
|
|
||||||
; jmp $
|
|
||||||
mov ax, [es:di+0fh]
|
|
||||||
mov word [cluster], ax
|
|
||||||
|
|
||||||
fat_loader:
|
|
||||||
mov ax, ds
|
|
||||||
mov es, ax
|
|
||||||
mov bx, buffer
|
|
||||||
|
|
||||||
mov ax, word [bpSectorsPerFat]
|
|
||||||
mov ah, 2
|
|
||||||
mov cl, 2
|
|
||||||
mov ch, 0
|
|
||||||
mov dh, 0
|
|
||||||
mov dl, byte [bpDriveNo]
|
|
||||||
|
|
||||||
int 13h
|
|
||||||
|
|
||||||
kernel_loader:
|
|
||||||
|
|
||||||
; Calculate file offset
|
|
||||||
mov ax, word [bpSectorsPerFat]
|
|
||||||
movzx cx, byte [bpNoFATs]
|
|
||||||
mul cx
|
|
||||||
|
|
||||||
push ax
|
|
||||||
mov ax, word [bpRootDirEntries]
|
|
||||||
mov cx, 16
|
|
||||||
div cx
|
|
||||||
|
|
||||||
mov bx, ax
|
|
||||||
pop ax
|
|
||||||
add ax, bx
|
|
||||||
|
|
||||||
mov word [fileoffset], ax
|
|
||||||
|
|
||||||
mov ax, 2000h
|
|
||||||
mov es, ax
|
|
||||||
mov bx, word [pointer]
|
|
||||||
|
|
||||||
movzx ax, byte [cluster]
|
|
||||||
add ax, word [fileoffset]
|
|
||||||
|
|
||||||
call prep_i13
|
|
||||||
|
|
||||||
int 13h
|
|
||||||
|
|
||||||
add word [pointer], 512
|
|
||||||
|
|
||||||
mov si, word [cluster]
|
|
||||||
shl si, 1
|
|
||||||
add si, buffer
|
|
||||||
cmp word [si], 0ffffh
|
|
||||||
je kernel_loaded
|
|
||||||
|
|
||||||
add word [cluster], 1
|
|
||||||
jmp kernel_loader
|
|
||||||
|
|
||||||
kernel_loaded:
|
|
||||||
jmp 2000h:0h
|
|
||||||
|
|
||||||
_boot_print:
|
|
||||||
mov ah, 0eh
|
|
||||||
mov cx, 1
|
|
||||||
mov bh, 0
|
|
||||||
_boot_print_loop:
|
|
||||||
lodsb
|
|
||||||
cmp al, 0
|
|
||||||
je _boot_print_exit
|
|
||||||
int 10h
|
|
||||||
jmp _boot_print_loop
|
|
||||||
_boot_print_exit:
|
|
||||||
ret
|
|
||||||
|
|
||||||
boot_msg db "Boot Sector OK!", 13, 10, 0
|
|
||||||
kernel_nf db "KERNEL.BIN Missing!", 13, 10, 0
|
|
||||||
new_line db " ", 0
|
|
||||||
kernel_file db "KERNEL BIN"
|
|
||||||
|
|
||||||
fileoffset dw 0
|
|
||||||
|
|
||||||
cluster dw 0
|
|
||||||
pointer dw 0
|
|
||||||
|
|
||||||
; AX set to the logical sector number.
|
|
||||||
prep_i13:
|
prep_i13:
|
||||||
xor dx, dx
|
xor dx, dx
|
||||||
div word [bpSectorsPerTrack]
|
div word [bpSectorsPerTrack]
|
||||||
@ -195,7 +91,27 @@ prep_i13:
|
|||||||
|
|
||||||
ret
|
ret
|
||||||
|
|
||||||
TIMES 510 - ($ - $$) db 0
|
gdt:
|
||||||
DW 0xAA55
|
null:
|
||||||
|
dq 0
|
||||||
|
code:
|
||||||
|
dw 0xffff
|
||||||
|
dw 0
|
||||||
|
db 0
|
||||||
|
db 10011010b
|
||||||
|
db 11001111b
|
||||||
|
db 0
|
||||||
|
data:
|
||||||
|
dw 0xffff
|
||||||
|
dw 0
|
||||||
|
db 0
|
||||||
|
db 10010010b
|
||||||
|
db 11001111b
|
||||||
|
db 0
|
||||||
|
gdt_end:
|
||||||
|
gdt_desc:
|
||||||
|
dw gdt_desc - gdt_end - 1
|
||||||
|
dd gdt
|
||||||
|
|
||||||
buffer:
|
TIMES 510 - ($ - $$) db 0
|
||||||
|
DW 0xAA55
|
91
boot32.asm
91
boot32.asm
@ -1,91 +0,0 @@
|
|||||||
[ORG 0x40000]
|
|
||||||
|
|
||||||
push bp
|
|
||||||
mov bp, sp
|
|
||||||
mov ax, [bp + 6]
|
|
||||||
; xor ax, ax
|
|
||||||
mov ds, ax
|
|
||||||
mov word [program_segment], ax
|
|
||||||
|
|
||||||
mov si, kernel32_name
|
|
||||||
mov ah, 4
|
|
||||||
int 22h
|
|
||||||
|
|
||||||
cmp ax, 0
|
|
||||||
je load_err
|
|
||||||
|
|
||||||
push ax
|
|
||||||
|
|
||||||
mov si, kernel32_found_success_msg
|
|
||||||
mov ah, 1
|
|
||||||
int 22h
|
|
||||||
|
|
||||||
; Enable the A20 line
|
|
||||||
; We don't really care about supporting super old machines
|
|
||||||
in al, 0x92
|
|
||||||
or al, 2
|
|
||||||
out 0x92, al
|
|
||||||
|
|
||||||
pop si
|
|
||||||
mov di, 0 ; Load kernel32.bin at 0x40200
|
|
||||||
mov bx, 8000h
|
|
||||||
mov ah, 3
|
|
||||||
int 22h
|
|
||||||
|
|
||||||
mov si, kernel32_exec_msg
|
|
||||||
mov ah, 1
|
|
||||||
int 22h
|
|
||||||
|
|
||||||
; Prepare for for kernel32.bin execution
|
|
||||||
|
|
||||||
cli
|
|
||||||
lgdt [gdt_desc]
|
|
||||||
mov eax, cr0
|
|
||||||
or eax, 1
|
|
||||||
mov cr0, eax
|
|
||||||
|
|
||||||
; Execute kernel32.bin
|
|
||||||
|
|
||||||
jmp 08h:0
|
|
||||||
|
|
||||||
jmp exit
|
|
||||||
|
|
||||||
|
|
||||||
load_err:
|
|
||||||
mov si, kernel32_load_err_msg
|
|
||||||
mov ah, 1
|
|
||||||
int 22h
|
|
||||||
|
|
||||||
exit:
|
|
||||||
pop bp
|
|
||||||
retf
|
|
||||||
|
|
||||||
kernel32_name db "KERNEL32BIN"
|
|
||||||
kernel32_load_err_msg db "FAILED TO LOAD KERNEL32.BIN", 10, 0
|
|
||||||
kernel32_found_success_msg db "FOUND KERNEL32.BIN", 10, 0
|
|
||||||
kernel32_exec_msg db "EXECUTING KERNEL32.BIN...", 10, 0
|
|
||||||
|
|
||||||
program_segment dw 0
|
|
||||||
|
|
||||||
gdt:
|
|
||||||
gdt_null:
|
|
||||||
dq 0
|
|
||||||
gdt_code:
|
|
||||||
dw 0xffff
|
|
||||||
dw 0x0
|
|
||||||
db 0x8
|
|
||||||
db 10011010b
|
|
||||||
db 01001111b
|
|
||||||
db 0
|
|
||||||
gdt_data:
|
|
||||||
dw 0xffff
|
|
||||||
dw 0x0
|
|
||||||
db 0x0
|
|
||||||
db 10010010b
|
|
||||||
db 01001111b
|
|
||||||
db 0
|
|
||||||
gdt_end:
|
|
||||||
|
|
||||||
gdt_desc:
|
|
||||||
dw gdt_end - gdt - 1
|
|
||||||
dd gdt
|
|
15
boot_stage2.ld
Normal file
15
boot_stage2.ld
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
OUTPUT_FORMAT(binary)
|
||||||
|
OUTPUT_ARCH(i386:i386)
|
||||||
|
|
||||||
|
INPUT(io.o atapio.o strings.o c_code_entry.o screenstuff.o)
|
||||||
|
OUTPUT(boot.stage2)
|
||||||
|
|
||||||
|
SECTIONS {
|
||||||
|
. = 0x7E00;
|
||||||
|
|
||||||
|
.text : {
|
||||||
|
c_code_entry.o(.text)
|
||||||
|
boot.stage2.o(.text)
|
||||||
|
*(.text)
|
||||||
|
}
|
||||||
|
}
|
471
kernel.asm
471
kernel.asm
@ -1,471 +0,0 @@
|
|||||||
bpBytesPerSector equ 0x0b
|
|
||||||
bpSectorsPerCluster equ 0x0d
|
|
||||||
bpReservedSectors equ 0x0e
|
|
||||||
bpNoFATs equ 0x10
|
|
||||||
bpRootDirEntries equ 0x11
|
|
||||||
bpLVSectors equ 0x13
|
|
||||||
bpMediumID equ 0x15
|
|
||||||
bpSectorsPerFat equ 0x16
|
|
||||||
bpSectorsPerTrack equ 0x18
|
|
||||||
bpHeads equ 0x1a
|
|
||||||
bpHiddenSectors equ 0x1c
|
|
||||||
bpDriveNo equ 0x24
|
|
||||||
bpSignature equ 0x26
|
|
||||||
|
|
||||||
[BITS 16]
|
|
||||||
; Update the IVT with our interrupt handler
|
|
||||||
mov bx, 0
|
|
||||||
mov ds, bx
|
|
||||||
mov word [ds:136], ihdlr
|
|
||||||
mov word [ds:138], cs
|
|
||||||
|
|
||||||
mov ax, 2000h
|
|
||||||
mov ds, ax
|
|
||||||
|
|
||||||
mov ax, 7c0h
|
|
||||||
mov fs, ax
|
|
||||||
|
|
||||||
; Set up kernel specifics
|
|
||||||
|
|
||||||
; Root Directory Entries will be at 2000h:2000h
|
|
||||||
; FAT1 will be at 2000h:4000h
|
|
||||||
|
|
||||||
; Load sectors RDE to 2000h:2000h
|
|
||||||
mov ax, 2000h
|
|
||||||
mov es, ax
|
|
||||||
mov bx, 2000h
|
|
||||||
|
|
||||||
; Calculate position of RDE
|
|
||||||
mov ax, word [fs:bpSectorsPerFat]
|
|
||||||
movzx cx, byte [fs:bpNoFATs]
|
|
||||||
mul cx
|
|
||||||
|
|
||||||
add ax, 2
|
|
||||||
|
|
||||||
call prep_i13
|
|
||||||
mov al, 16
|
|
||||||
|
|
||||||
int 13h
|
|
||||||
|
|
||||||
; Load sectors 2 through 36 to 2000h:4000h
|
|
||||||
mov ax, 2000h
|
|
||||||
mov es, ax
|
|
||||||
mov bx, 4000h
|
|
||||||
mov ax, 2
|
|
||||||
call prep_i13
|
|
||||||
mov ax, word [fs:bpSectorsPerFat]
|
|
||||||
mov ah, 2
|
|
||||||
|
|
||||||
|
|
||||||
int 13h
|
|
||||||
|
|
||||||
; Calculate file offset
|
|
||||||
mov ax, word [fs:bpSectorsPerFat]
|
|
||||||
movzx cx, byte [fs:bpNoFATs]
|
|
||||||
mul cx
|
|
||||||
|
|
||||||
push ax
|
|
||||||
mov ax, word [fs:bpRootDirEntries]
|
|
||||||
mov cx, 16
|
|
||||||
div cx
|
|
||||||
|
|
||||||
mov bx, ax
|
|
||||||
pop ax
|
|
||||||
add ax, bx
|
|
||||||
|
|
||||||
mov word [fileoffset], ax
|
|
||||||
|
|
||||||
push msg
|
|
||||||
call print
|
|
||||||
|
|
||||||
cmd_loop:
|
|
||||||
push cmd_prompt
|
|
||||||
call print
|
|
||||||
|
|
||||||
; Clear command buffer
|
|
||||||
mov al, 0
|
|
||||||
mov di, user_cmd
|
|
||||||
mov cx, 64
|
|
||||||
|
|
||||||
clear_loop:
|
|
||||||
stosb
|
|
||||||
loop clear_loop
|
|
||||||
|
|
||||||
push user_cmd
|
|
||||||
push 64
|
|
||||||
call readline
|
|
||||||
|
|
||||||
push newline
|
|
||||||
call print
|
|
||||||
|
|
||||||
mov si, user_cmd
|
|
||||||
mov di, cmd_help_text
|
|
||||||
mov cx, 4
|
|
||||||
rep cmpsb
|
|
||||||
je cmd_help
|
|
||||||
|
|
||||||
mov si, user_cmd
|
|
||||||
mov di, cmd_clear_text
|
|
||||||
mov cx, 5
|
|
||||||
rep cmpsb
|
|
||||||
je cmd_clear
|
|
||||||
|
|
||||||
; If the user hasn't run a command we should determine if they're trying to run a program.
|
|
||||||
|
|
||||||
; Decode input to filename
|
|
||||||
push user_cmd
|
|
||||||
call decode_filename
|
|
||||||
|
|
||||||
; Search for file
|
|
||||||
|
|
||||||
|
|
||||||
mov si, ax
|
|
||||||
call file_exists
|
|
||||||
; If it doesn't exist jump to error
|
|
||||||
cmp ax, 0
|
|
||||||
je handle_error
|
|
||||||
|
|
||||||
; Define the segment where we will load our programs
|
|
||||||
program_segment equ 4000h
|
|
||||||
|
|
||||||
; If the file exists load it at program_segment:0
|
|
||||||
push ax
|
|
||||||
push 0
|
|
||||||
push program_segment
|
|
||||||
call load_file
|
|
||||||
|
|
||||||
; Let programs know what segment they're loaded at
|
|
||||||
push program_segment
|
|
||||||
; Make a call to program_segment:0
|
|
||||||
call program_segment:0
|
|
||||||
; We've now returned.
|
|
||||||
; Clean up pushed segment
|
|
||||||
pop ax
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
; Recover ds
|
|
||||||
mov ax, 2000h
|
|
||||||
mov ds, ax
|
|
||||||
mov es, ax
|
|
||||||
|
|
||||||
; jmp $
|
|
||||||
|
|
||||||
; Loop
|
|
||||||
jmp cmd_loop
|
|
||||||
|
|
||||||
handle_error:
|
|
||||||
push cmd_err
|
|
||||||
call print
|
|
||||||
|
|
||||||
jmp cmd_loop
|
|
||||||
|
|
||||||
cmd_help:
|
|
||||||
push cmd_help_msg
|
|
||||||
call print
|
|
||||||
jmp cmd_loop
|
|
||||||
|
|
||||||
cmd_help_msg:
|
|
||||||
db "XnoeOS Help Dialogue", 13, 10
|
|
||||||
db "--------------------", 13, 10
|
|
||||||
db "Commands: ", 13, 10
|
|
||||||
db " - help", 13, 10
|
|
||||||
db " : Displays this message", 13, 10
|
|
||||||
db " - clear", 13, 10
|
|
||||||
db " : Clears the screen", 13, 10
|
|
||||||
db 0
|
|
||||||
|
|
||||||
cmd_clear:
|
|
||||||
mov ah, 02h
|
|
||||||
mov dh, 0
|
|
||||||
mov dl, 0
|
|
||||||
int 10h
|
|
||||||
|
|
||||||
mov ah, 0ah
|
|
||||||
mov cx, 2000
|
|
||||||
mov al, 20h
|
|
||||||
int 10h
|
|
||||||
|
|
||||||
jmp cmd_loop
|
|
||||||
|
|
||||||
data:
|
|
||||||
msg db "Kernel OK!", 13, 10, 0
|
|
||||||
cmd_prompt db ">>> ", 0
|
|
||||||
cmd_err db "Bad Command or filename!", 13, 10, 13, 10, 0
|
|
||||||
|
|
||||||
cmd_help_text db "HELP"
|
|
||||||
cmd_clear_text db "CLEAR"
|
|
||||||
|
|
||||||
newline db 13, 10, 0
|
|
||||||
|
|
||||||
program_two db "HELLO BIN"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
user_cmd:
|
|
||||||
times 64 db 0
|
|
||||||
|
|
||||||
; print(str)
|
|
||||||
print:
|
|
||||||
push bp
|
|
||||||
mov bp, sp
|
|
||||||
mov si, [bp + 4]
|
|
||||||
mov ah, 0eh
|
|
||||||
mov cx, 1
|
|
||||||
mov bh, 0
|
|
||||||
print_loop:
|
|
||||||
lodsb
|
|
||||||
cmp al, 0
|
|
||||||
je print_exit
|
|
||||||
; Use Unix Line endings (\n)
|
|
||||||
cmp al, 10
|
|
||||||
jne _print_skip
|
|
||||||
int 10h
|
|
||||||
mov al, 13
|
|
||||||
int 10h
|
|
||||||
_print_skip:
|
|
||||||
int 10h
|
|
||||||
jmp print_loop
|
|
||||||
print_exit:
|
|
||||||
pop bp
|
|
||||||
ret 2
|
|
||||||
|
|
||||||
; readline(max length, buffer)
|
|
||||||
readline:
|
|
||||||
push bp
|
|
||||||
mov bp, sp
|
|
||||||
mov di, [bp + 6]
|
|
||||||
mov bx, 0
|
|
||||||
readline_loop:
|
|
||||||
mov ah, 0h
|
|
||||||
int 16h
|
|
||||||
|
|
||||||
cmp ah, 01ch
|
|
||||||
je readline_exit
|
|
||||||
|
|
||||||
cmp ah, 0eh
|
|
||||||
je readline_backspace
|
|
||||||
|
|
||||||
; Process all user input as upper case
|
|
||||||
cmp al, 0x61
|
|
||||||
jl not_lower
|
|
||||||
cmp al, 0x79
|
|
||||||
jg not_lower
|
|
||||||
and al, 223
|
|
||||||
not_lower:
|
|
||||||
mov byte [di], al
|
|
||||||
inc di
|
|
||||||
inc bx
|
|
||||||
|
|
||||||
mov ah, 0eh
|
|
||||||
mov cx, 1
|
|
||||||
int 10h
|
|
||||||
|
|
||||||
mov ax, [bp + 4]
|
|
||||||
cmp bx, ax
|
|
||||||
je readline_exit
|
|
||||||
|
|
||||||
jmp readline_loop
|
|
||||||
|
|
||||||
readline_backspace:
|
|
||||||
|
|
||||||
cmp bx, 0
|
|
||||||
je readline_loop
|
|
||||||
|
|
||||||
dec di
|
|
||||||
dec bx
|
|
||||||
|
|
||||||
mov ah, 0eh
|
|
||||||
mov cx, 1
|
|
||||||
int 10h
|
|
||||||
|
|
||||||
mov ah, 0ah
|
|
||||||
mov cx, 1
|
|
||||||
mov al, 20h
|
|
||||||
int 10h
|
|
||||||
|
|
||||||
jmp readline_loop
|
|
||||||
|
|
||||||
readline_exit:
|
|
||||||
pop bp
|
|
||||||
ret 4
|
|
||||||
|
|
||||||
file_exists:
|
|
||||||
push si
|
|
||||||
|
|
||||||
mov bp, sp
|
|
||||||
mov cx, 256 ; Hardcode the amount of entries for now
|
|
||||||
|
|
||||||
mov ax, 2000h
|
|
||||||
mov es, ax
|
|
||||||
|
|
||||||
xor ax, ax
|
|
||||||
file_exists_loop:
|
|
||||||
pop si ; Get value in to si
|
|
||||||
push si ; Keep track of original value
|
|
||||||
|
|
||||||
xchg cx, dx
|
|
||||||
|
|
||||||
mov di, 2000h ; Root Entries is at 2000h:2000h
|
|
||||||
add di, ax
|
|
||||||
mov cx, 11
|
|
||||||
rep cmpsb
|
|
||||||
je file_exists_found
|
|
||||||
|
|
||||||
add ax, 32
|
|
||||||
|
|
||||||
xchg cx, dx
|
|
||||||
loop file_exists_loop
|
|
||||||
file_exists_not_found:
|
|
||||||
mov ax, 0
|
|
||||||
pop si
|
|
||||||
ret
|
|
||||||
file_exists_found:
|
|
||||||
mov ax, [es:di+0fh]
|
|
||||||
pop si
|
|
||||||
ret
|
|
||||||
|
|
||||||
; loadfile(segment, offset, initsector)
|
|
||||||
load_file:
|
|
||||||
push bp
|
|
||||||
mov bp, sp
|
|
||||||
|
|
||||||
push ds
|
|
||||||
push fs
|
|
||||||
mov ax, 7c0h
|
|
||||||
mov fs, ax
|
|
||||||
mov ax, 2000h
|
|
||||||
mov ds, ax
|
|
||||||
|
|
||||||
mov ax, word [bp + 4]
|
|
||||||
mov es, ax
|
|
||||||
|
|
||||||
load_file_loop:
|
|
||||||
mov bx, word [bp + 6]
|
|
||||||
movzx ax, byte [bp + 8]
|
|
||||||
add ax, word [fileoffset]
|
|
||||||
call prep_i13
|
|
||||||
|
|
||||||
int 13h
|
|
||||||
|
|
||||||
add word [bp + 6], 512
|
|
||||||
|
|
||||||
mov si, word [bp + 8]
|
|
||||||
shl si, 1
|
|
||||||
add si, 4000h
|
|
||||||
; add si, 1
|
|
||||||
cmp word [ds:si], 0ffffh
|
|
||||||
je load_file_loaded
|
|
||||||
|
|
||||||
add word [bp + 8], 1
|
|
||||||
jmp load_file_loop
|
|
||||||
|
|
||||||
load_file_loaded:
|
|
||||||
pop fs
|
|
||||||
pop ds
|
|
||||||
pop bp
|
|
||||||
ret 6
|
|
||||||
|
|
||||||
decode_filename:
|
|
||||||
push bp
|
|
||||||
mov bp, sp
|
|
||||||
push word [bp + 4]
|
|
||||||
; First we want to clear the buffer with 0x20s
|
|
||||||
mov al, 20h
|
|
||||||
mov cx, 11
|
|
||||||
mov di, _decode_buffer
|
|
||||||
decode_clear_loop:
|
|
||||||
stosb
|
|
||||||
loop decode_clear_loop
|
|
||||||
|
|
||||||
pop si
|
|
||||||
|
|
||||||
|
|
||||||
mov cx, 8
|
|
||||||
mov bx, 0
|
|
||||||
decode_filename_loop:
|
|
||||||
|
|
||||||
lodsb
|
|
||||||
cmp al, "."
|
|
||||||
je decode_filename_stage2
|
|
||||||
mov byte [_decode_buffer+bx], al
|
|
||||||
|
|
||||||
inc bx
|
|
||||||
|
|
||||||
loop decode_filename_loop
|
|
||||||
|
|
||||||
decode_filename_stage2:
|
|
||||||
mov bx, 8
|
|
||||||
mov cx, 3
|
|
||||||
|
|
||||||
decode_filename_stage2_loop:
|
|
||||||
|
|
||||||
lodsb
|
|
||||||
cmp al, 0
|
|
||||||
je decode_filename_final
|
|
||||||
mov byte [_decode_buffer+bx], al
|
|
||||||
|
|
||||||
inc bx
|
|
||||||
|
|
||||||
loop decode_filename_stage2_loop
|
|
||||||
|
|
||||||
decode_filename_final:
|
|
||||||
pop bp
|
|
||||||
mov ax, _decode_buffer
|
|
||||||
ret 2
|
|
||||||
|
|
||||||
_decode_buffer:
|
|
||||||
times 11 db 0
|
|
||||||
|
|
||||||
ihdlr:
|
|
||||||
cmp ah, 01h
|
|
||||||
jne _ihdlr_2
|
|
||||||
push si
|
|
||||||
call print
|
|
||||||
jmp _ihdlr_fin
|
|
||||||
_ihdlr_2:
|
|
||||||
cmp ah, 02h
|
|
||||||
jne _ihdlr_3
|
|
||||||
push si
|
|
||||||
push di
|
|
||||||
call readline
|
|
||||||
jmp _ihdlr_fin
|
|
||||||
_ihdlr_3:
|
|
||||||
cmp ah, 03h
|
|
||||||
jne _ihdlr_4
|
|
||||||
push si
|
|
||||||
push di
|
|
||||||
push bx
|
|
||||||
call load_file
|
|
||||||
jmp _ihdlr_fin
|
|
||||||
_ihdlr_4:
|
|
||||||
cmp ah, 04h
|
|
||||||
jne _ihdlr_5
|
|
||||||
call file_exists
|
|
||||||
jmp _ihdlr_fin
|
|
||||||
_ihdlr_5:
|
|
||||||
_ihdlr_fin:
|
|
||||||
iret
|
|
||||||
|
|
||||||
prep_i13:
|
|
||||||
xor dx, dx
|
|
||||||
div word [fs:bpSectorsPerTrack]
|
|
||||||
|
|
||||||
push dx
|
|
||||||
|
|
||||||
xor dx, dx
|
|
||||||
div word [fs:bpHeads]
|
|
||||||
|
|
||||||
mov ch, al
|
|
||||||
mov dh, dl
|
|
||||||
mov dl, byte [fs:bpDriveNo]
|
|
||||||
|
|
||||||
pop ax
|
|
||||||
mov cl, al
|
|
||||||
|
|
||||||
mov al, 1
|
|
||||||
mov ah, 2
|
|
||||||
|
|
||||||
ret
|
|
||||||
|
|
||||||
fileoffset dw 0
|
|
@ -1,14 +1,14 @@
|
|||||||
OUTPUT_FORMAT(binary)
|
OUTPUT_FORMAT(binary)
|
||||||
OUTPUT_ARCH(i386:i386)
|
OUTPUT_ARCH(i386:i386)
|
||||||
|
|
||||||
OUTPUT(kernel32.bin)
|
OUTPUT(kernel.bin)
|
||||||
|
|
||||||
SECTIONS {
|
SECTIONS {
|
||||||
. = 0x80000;
|
. = 0x80000;
|
||||||
|
|
||||||
.text : {
|
.text : {
|
||||||
kernel32_strap.o(.text)
|
c_code_entry.o(.text)
|
||||||
kernel32.o(.text)
|
kernel.o(.text)
|
||||||
*(.text)
|
*(.text)
|
||||||
heap_section = .;
|
heap_section = .;
|
||||||
}
|
}
|
17
src/boot_stage2/main.c
Normal file
17
src/boot_stage2/main.c
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#include "../kernel/atapio.h"
|
||||||
|
#include "../kernel/screenstuff.h"
|
||||||
|
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
init_term();
|
||||||
|
init_atapio();
|
||||||
|
|
||||||
|
uint8_t* kernel_location = 0x80000;
|
||||||
|
load_file("KERNEL BIN", kernel_location);
|
||||||
|
|
||||||
|
printf("Stage2 success!");
|
||||||
|
|
||||||
|
//while (1);
|
||||||
|
|
||||||
|
((void(*)(void))kernel_location)();
|
||||||
|
}
|
@ -59,8 +59,8 @@ void init_atapio() {
|
|||||||
total_28_lbas = *(uint32_t*)(identify_result+60);
|
total_28_lbas = *(uint32_t*)(identify_result+60);
|
||||||
|
|
||||||
// We've initialised now, let's load the FAT and RootDirEntries.
|
// We've initialised now, let's load the FAT and RootDirEntries.
|
||||||
read_sectors(sectorsPerFAT * countFATs + 1, countRDEs / 16, rootDirEntries);
|
read_sectors(sectorsPerFAT * countFATs + countReserved, countRDEs / 16, rootDirEntries);
|
||||||
read_sectors(1, sectorsPerFAT, FAT1);
|
read_sectors(countReserved, sectorsPerFAT, FAT1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void read_sector(uint32_t address, uint8_t* buffer) {
|
void read_sector(uint32_t address, uint8_t* buffer) {
|
||||||
@ -111,7 +111,7 @@ void load_file(char* filename, uint8_t* destination) {
|
|||||||
|
|
||||||
bool loaded = false;
|
bool loaded = false;
|
||||||
while (!loaded) {
|
while (!loaded) {
|
||||||
uint16_t fromSector = location + (sectorsPerFAT * countFATs) + (countRDEs / 16) - 1;
|
uint16_t fromSector = location + (sectorsPerFAT * countFATs) + (countRDEs / 16) + (countReserved - 1) - 1;
|
||||||
read_sector(fromSector, destination+offset);
|
read_sector(fromSector, destination+offset);
|
||||||
offset += 512;
|
offset += 512;
|
||||||
|
|
||||||
|
@ -6,7 +6,6 @@
|
|||||||
#include "io.h"
|
#include "io.h"
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include "strings.h"
|
#include "strings.h"
|
||||||
#include "screenstuff.h"
|
|
||||||
|
|
||||||
void init_atapio();
|
void init_atapio();
|
||||||
void read_sector(uint32_t address, uint8_t* buffer);
|
void read_sector(uint32_t address, uint8_t* buffer);
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
GateEntry idt[256];
|
GateEntry idt[256];
|
||||||
|
|
||||||
void set_entry(uint8_t interrupt_number, uint16_t code_segment, void* handler, uint8_t type) {
|
void set_entry(uint8_t interrupt_number, uint16_t code_segment, void* handler, uint8_t type) {
|
||||||
uint32_t handler_addr = (uint16_t)handler;
|
uint32_t handler_addr = (uint32_t)handler;
|
||||||
uint16_t* handler_halves = (uint16_t*)&handler_addr;
|
uint16_t* handler_halves = (uint16_t*)&handler_addr;
|
||||||
idt[interrupt_number] = (GateEntry){
|
idt[interrupt_number] = (GateEntry){
|
||||||
.offset_low = handler_halves[0],
|
.offset_low = handler_halves[0],
|
||||||
|
@ -13,9 +13,11 @@ int main() {
|
|||||||
printf("KERNEL32 OK!\n");
|
printf("KERNEL32 OK!\n");
|
||||||
|
|
||||||
printf("Hello, World!\n\nWe are running XnoeOS Code in C now, Protected Mode has been achieved and everything is working super nicely!\n\nHow wonderful!\n\nNow I just need to hope my print function works properly too~~\n");
|
printf("Hello, World!\n\nWe are running XnoeOS Code in C now, Protected Mode has been achieved and everything is working super nicely!\n\nHow wonderful!\n\nNow I just need to hope my print function works properly too~~\n");
|
||||||
|
|
||||||
init_keyboard();
|
init_keyboard();
|
||||||
|
|
||||||
enable_idt();
|
enable_idt();
|
||||||
|
printf("A\n");
|
||||||
init_atapio();
|
init_atapio();
|
||||||
|
|
||||||
uint8_t sector[512];
|
uint8_t sector[512];
|
Loading…
x
Reference in New Issue
Block a user