Clean-up and conveniance for mbr and loader
This commit is contained in:
parent
bcff95e6d0
commit
a805431f7c
BIN
bin/disk.img
BIN
bin/disk.img
Binary file not shown.
BIN
bin/loader.bin
BIN
bin/loader.bin
Binary file not shown.
BIN
bin/mbr.bin
BIN
bin/mbr.bin
Binary file not shown.
Binary file not shown.
BIN
obj/boot/mbr.bin
BIN
obj/boot/mbr.bin
Binary file not shown.
|
@ -29,7 +29,7 @@ SYSTDIR=kaleid/system
|
||||||
|
|
||||||
all: bootloader
|
all: bootloader
|
||||||
|
|
||||||
boot.mbr.s: $(BOOTDIR)/mbr.s
|
boot.mbr.s: $(BOOTDIR)/mbr.s $(BOOTDIR)/mbr.inc
|
||||||
$(ASM) $(BOOTFLAGS) $(BOOTDIR)/mbr.s -o $(OBJDIR)/boot/mbr.bin
|
$(ASM) $(BOOTFLAGS) $(BOOTDIR)/mbr.s -o $(OBJDIR)/boot/mbr.bin
|
||||||
|
|
||||||
boot.loader.s: $(BOOTDIR)/loader.s
|
boot.loader.s: $(BOOTDIR)/loader.s
|
||||||
|
|
|
@ -7,8 +7,12 @@
|
||||||
; Desc: Kernel (second stage) Loader for OS/K ;
|
; Desc: Kernel (second stage) Loader for OS/K ;
|
||||||
; (x86_64 architecture only) ;
|
; (x86_64 architecture only) ;
|
||||||
;=----------------------------------------------------------------------------=;
|
;=----------------------------------------------------------------------------=;
|
||||||
|
|
||||||
|
;;VIDEO
|
||||||
%define TRAM 0x0B8000 ; [T]ext[RAM]
|
%define TRAM 0x0B8000 ; [T]ext[RAM]
|
||||||
%define VRAM 0x0A0000 ; [V]ideo[RAM]
|
%define VRAM 0x0A0000 ; [V]ideo[RAM]
|
||||||
|
|
||||||
|
;; BPB
|
||||||
%define OEMName bp+0x03 ; Disk label
|
%define OEMName bp+0x03 ; Disk label
|
||||||
%define bytesPerSector bp+0x0b ; Bytes per sector
|
%define bytesPerSector bp+0x0b ; Bytes per sector
|
||||||
%define sectorsPerCluster bp+0x0d ; Sectors per cluster
|
%define sectorsPerCluster bp+0x0d ; Sectors per cluster
|
||||||
|
@ -32,9 +36,9 @@
|
||||||
[BITS 16]
|
[BITS 16]
|
||||||
[ORG 0x1000]
|
[ORG 0x1000]
|
||||||
|
|
||||||
mov ax, cs
|
mov ax, cs ; correcting cs after the horrible far jump
|
||||||
mov ds, ax
|
mov ds, ax ; hm... And ds too
|
||||||
mov es, ax
|
mov es, ax ; And es because it is jealous
|
||||||
|
|
||||||
mov [Bootdrv], dl
|
mov [Bootdrv], dl
|
||||||
jmp 0x0000:main
|
jmp 0x0000:main
|
||||||
|
@ -48,13 +52,13 @@ VIDEO_MODE dw 0
|
||||||
;; GDT WITH DOC
|
;; GDT WITH DOC
|
||||||
GDT64:
|
GDT64:
|
||||||
NULL_SELECTOR: ;; null selector within 64 bits
|
NULL_SELECTOR: ;; null selector within 64 bits
|
||||||
dw GDT_LENGTH ; limit of GDT
|
dw GDT_LENGTH ; limit of GDT
|
||||||
dw GDT64 ; linear address of GDT
|
dw GDT64 ; linear address of GDT
|
||||||
dd 0x0
|
dd 0x0
|
||||||
CODE_SELECTOR: ;; 32-bit code selector (ring 0)
|
CODE_SELECTOR: ;; 32-bit code selector (ring 0)
|
||||||
dw 0x0FFFF ; Segment Limit 15:00
|
dw 0x0FFFF ; Segment Limit
|
||||||
db 0x0, 0x0, 0x0 ; Base Address 23:00
|
db 0x0, 0x0, 0x0 ; Base Address
|
||||||
db 10011010b ; |7|6|5|4|3|2|1|0|
|
db 10011010b ; |7|6|5|4|3|2|1|0|
|
||||||
; | | | | | | | `----- 1 when segment used.
|
; | | | | | | | `----- 1 when segment used.
|
||||||
; | | | | | | `------ 1 when writable.
|
; | | | | | | `------ 1 when writable.
|
||||||
; | | | | | `------- 1 if "conformant". Don't know what is it... spectral ? xD
|
; | | | | | `------- 1 if "conformant". Don't know what is it... spectral ? xD
|
||||||
|
@ -63,7 +67,7 @@ GDT64:
|
||||||
; | | `---------- DPL !!! 0 for ring 0
|
; | | `---------- DPL !!! 0 for ring 0
|
||||||
; | `----------- DPL (2/2)
|
; | `----------- DPL (2/2)
|
||||||
; `------------ 1 if in physical memory, 0 if page fault
|
; `------------ 1 if in physical memory, 0 if page fault
|
||||||
db 11001111b ; |7|6|5|4|3|2|1|0|
|
db 11001111b ; |7|6|5|4|3|2|1|0|
|
||||||
; | | | | | | | `----- Limit 16
|
; | | | | | | | `----- Limit 16
|
||||||
; | | | | | | `------ Limit 17
|
; | | | | | | `------ Limit 17
|
||||||
; | | | | | `------- Limit 18
|
; | | | | | `------- Limit 18
|
||||||
|
@ -72,12 +76,12 @@ GDT64:
|
||||||
; | | `---------- 0 always
|
; | | `---------- 0 always
|
||||||
; | `----------- size of data. 1 for 32bits
|
; | `----------- size of data. 1 for 32bits
|
||||||
; `------------ 0 if limit is in Bytes, 1 if it's in pages (4ko)
|
; `------------ 0 if limit is in Bytes, 1 if it's in pages (4ko)
|
||||||
db 0x0 ; Base Address 31:24
|
db 0x0 ; Base Address
|
||||||
|
|
||||||
DATA_SELECTOR: ;; flat data selector (ring 0)
|
DATA_SELECTOR: ;; flat data selector (ring 0)
|
||||||
dw 0x0FFFF ; Segment Limit 15:00
|
dw 0x0FFFF ; Segment Limit
|
||||||
db 0x0, 0x0, 0x0 ; Base Address 23:00
|
db 0x0, 0x0, 0x0 ; Base Address
|
||||||
db 10010010b ; |7|6|5|4|3|2|1|0|
|
db 10010010b ; |7|6|5|4|3|2|1|0|
|
||||||
; | | | | | | | `----- 1 when segment used.
|
; | | | | | | | `----- 1 when segment used.
|
||||||
; | | | | | | `------ 1 when writable.
|
; | | | | | | `------ 1 when writable.
|
||||||
; | | | | | `------- expansion direction. 1 for a LIFO
|
; | | | | | `------- expansion direction. 1 for a LIFO
|
||||||
|
@ -86,7 +90,7 @@ GDT64:
|
||||||
; | | `---------- DPL !!! 0 for ring 0
|
; | | `---------- DPL !!! 0 for ring 0
|
||||||
; | `----------- DPL (2/2)
|
; | `----------- DPL (2/2)
|
||||||
; `------------ 1 if in physical memory, 0 if page fault
|
; `------------ 1 if in physical memory, 0 if page fault
|
||||||
db 10001111b ; |7|6|5|4|3|2|1|0|
|
db 10001111b ; |7|6|5|4|3|2|1|0|
|
||||||
; | | | | | | | `----- Limit 16
|
; | | | | | | | `----- Limit 16
|
||||||
; | | | | | | `------ Limit 17
|
; | | | | | | `------ Limit 17
|
||||||
; | | | | | `------- Limit 18
|
; | | | | | `------- Limit 18
|
||||||
|
@ -95,12 +99,12 @@ GDT64:
|
||||||
; | | `---------- 0 always
|
; | | `---------- 0 always
|
||||||
; | `----------- size of data. 1 for 32bits
|
; | `----------- size of data. 1 for 32bits
|
||||||
; `------------ 0 if limit is in Bytes, 1 if it's in pages (4ko)
|
; `------------ 0 if limit is in Bytes, 1 if it's in pages (4ko)
|
||||||
db 0x0 ; Base Address 31:24
|
db 0x0 ; Base Address
|
||||||
|
|
||||||
LONG_SELECTOR: ;; 64-bit code selector (ring 0)
|
LONG_SELECTOR: ;; 64-bit code selector (ring 0)
|
||||||
dw 0x0FFFF ; Segment Limit 15:00
|
dw 0x0FFFF ; Segment Limit
|
||||||
db 0x0, 0x0, 0x0 ; Base Address 23:00
|
db 0x0, 0x0, 0x0 ; Base Address
|
||||||
db 10011010b ; |7|6|5|4|3|2|1|0|
|
db 10011010b ; |7|6|5|4|3|2|1|0|
|
||||||
; | | | | | | | `----- 1 when segment used.
|
; | | | | | | | `----- 1 when segment used.
|
||||||
; | | | | | | `------ 1 when writable.
|
; | | | | | | `------ 1 when writable.
|
||||||
; | | | | | `------- 1 if "conformant". Don't know what is it... spectral ? xD
|
; | | | | | `------- 1 if "conformant". Don't know what is it... spectral ? xD
|
||||||
|
@ -118,89 +122,10 @@ GDT64:
|
||||||
; | | `---------- 0 always
|
; | | `---------- 0 always
|
||||||
; | `----------- size of data. 1 for 32bits
|
; | `----------- size of data. 1 for 32bits
|
||||||
; `------------ 0 if limit is in Bytes, 1 if it's in pages (4ko)
|
; `------------ 0 if limit is in Bytes, 1 if it's in pages (4ko)
|
||||||
db 0x0 ; Base Address 31:24
|
db 0x0 ; Base Address
|
||||||
GDT_LENGTH:
|
GDT_LENGTH:
|
||||||
|
|
||||||
disable_cursor:
|
%include "boot/loader16.inc"
|
||||||
pushf
|
|
||||||
push eax
|
|
||||||
push edx
|
|
||||||
|
|
||||||
mov dx, 0x3D4
|
|
||||||
mov al, 0xA ; low cursor shape register
|
|
||||||
out dx, al
|
|
||||||
|
|
||||||
inc dx
|
|
||||||
mov al, 0x20 ; bits 6-7 unused, bit 5 disables the cursor, bits 0-4 control the cursor shape
|
|
||||||
out dx, al
|
|
||||||
|
|
||||||
pop edx
|
|
||||||
pop eax
|
|
||||||
popf
|
|
||||||
ret
|
|
||||||
|
|
||||||
get_dimensions:
|
|
||||||
push eax
|
|
||||||
push ebx
|
|
||||||
mov ah, 0x0F
|
|
||||||
int 0x10
|
|
||||||
mov [VGA_HEIGHT], ah
|
|
||||||
mov [VIDEO_MODE], al
|
|
||||||
pop ebx
|
|
||||||
pop eax
|
|
||||||
ret
|
|
||||||
|
|
||||||
;-----------------------------------------------------------------------;
|
|
||||||
; Checks if the CPU is compatible with 64-bits operating systems ;
|
|
||||||
; If the 21th bit of the eax register is set, then CPUID is supported ;
|
|
||||||
; We then test CPUID's result to see if long mode is supported ;
|
|
||||||
;-----------------------------------------------------------------------;
|
|
||||||
Is64bits:
|
|
||||||
pushfd ; recovering the flags in eax
|
|
||||||
pop eax
|
|
||||||
mov ecx, eax
|
|
||||||
xor eax, 0x200000
|
|
||||||
push eax
|
|
||||||
popfd
|
|
||||||
pushfd
|
|
||||||
pop eax
|
|
||||||
xor eax, ecx
|
|
||||||
shr eax, 21
|
|
||||||
and eax, 1 ; magical spell of murta
|
|
||||||
push ecx
|
|
||||||
popfd
|
|
||||||
test eax, eax
|
|
||||||
jz .NonCompat ; if (CPUID non supporté) goto NonCompat
|
|
||||||
mov eax, 0x80000000
|
|
||||||
cpuid
|
|
||||||
cmp eax, 0x80000001
|
|
||||||
jb .NonCompat ; if (eax <= 0x80000001) goto NonCompat
|
|
||||||
mov eax, 0x80000001
|
|
||||||
cpuid
|
|
||||||
test edx, 1 << 29
|
|
||||||
jz .NonCompat ; if (edx != 1 << 29) goto NonCompat
|
|
||||||
ret ; back to mbr.s
|
|
||||||
.NonCompat:
|
|
||||||
stc
|
|
||||||
ret
|
|
||||||
|
|
||||||
PrintB:
|
|
||||||
;---------------------------------------------------;
|
|
||||||
; Print out a simple string. ;
|
|
||||||
; ;
|
|
||||||
; Expects: DS:SI = String to print ;
|
|
||||||
; ;
|
|
||||||
; Returns: None ;
|
|
||||||
; ;
|
|
||||||
;---------------------------------------------------;
|
|
||||||
lodsb ; Load byte from ds:si to al
|
|
||||||
or al, al ; If al is empty stop looping
|
|
||||||
jz .done ; Done looping and return
|
|
||||||
mov ah, 0x0e ; Teletype output
|
|
||||||
int 0x10 ; Video interupt
|
|
||||||
jmp PrintB ; Loop untill string is null
|
|
||||||
.done:
|
|
||||||
ret
|
|
||||||
|
|
||||||
main:
|
main:
|
||||||
;; compatibility check
|
;; compatibility check
|
||||||
|
@ -308,74 +233,12 @@ main32:
|
||||||
push dword [VGA_HEIGHT]
|
push dword [VGA_HEIGHT]
|
||||||
jmp (LONG_SELECTOR-GDT64):main64
|
jmp (LONG_SELECTOR-GDT64):main64
|
||||||
|
|
||||||
[BITS 64]
|
[BITS 64]
|
||||||
;; FUNCTIONS
|
|
||||||
clear:
|
|
||||||
;-----------------------------------------------------------------------;
|
|
||||||
; x64/LM Clear Text Screen Function ;
|
|
||||||
;-----------------------------------------------------------------------;
|
|
||||||
mov qword [NextTRAM], TRAM
|
|
||||||
mov edi, TRAM
|
|
||||||
push rsi
|
|
||||||
push rdi
|
|
||||||
push rcx
|
|
||||||
mov ah, 0
|
|
||||||
mov al, 0
|
|
||||||
mov rcx, 0x4000 ; traditionnal value
|
|
||||||
rep stosw ; fill screen with al while cx > 0
|
|
||||||
pop rcx
|
|
||||||
pop rsi
|
|
||||||
pop rdi
|
|
||||||
ret
|
|
||||||
|
|
||||||
write:
|
%include "boot/loader64.inc"
|
||||||
;-----------------------------------------------------------------------;
|
|
||||||
; x64/LM Text Printing Functions ;
|
|
||||||
; bl : color code ;
|
|
||||||
; esi : string address ;
|
|
||||||
;-----------------------------------------------------------------------;
|
|
||||||
mov edi, [NextTRAM] ;TRAM ADDRESS
|
|
||||||
push rsi
|
|
||||||
push rdi
|
|
||||||
.pLoop:
|
|
||||||
lodsb
|
|
||||||
cmp al, 0 ; while @al, i.e. while we're not hitting '\0'
|
|
||||||
je .pEnd
|
|
||||||
cmp al, 0x0A ; LF
|
|
||||||
je .lf
|
|
||||||
cmp al, 0x0D ; CR
|
|
||||||
je .cr
|
|
||||||
stosb ; text subpixel
|
|
||||||
mov al, bl
|
|
||||||
stosb ; color subpixel
|
|
||||||
add qword [NextTRAM], 0x2 ; Cursor moving
|
|
||||||
add qword [VGA_X], 0x2 ; coord + 2 because 2 subpixels
|
|
||||||
jmp .pLoop
|
|
||||||
.pEnd:
|
|
||||||
pop rdi
|
|
||||||
pop rsi
|
|
||||||
ret
|
|
||||||
.lf:
|
|
||||||
mov rax, [VGA_HEIGHT64]
|
|
||||||
add [NextTRAM], rax ; Cursor moving
|
|
||||||
add [NextTRAM], rax
|
|
||||||
add edi, eax ; Address moving
|
|
||||||
add edi, eax
|
|
||||||
jmp .pLoop
|
|
||||||
.cr:
|
|
||||||
push rax
|
|
||||||
mov rax, qword [VGA_X]
|
|
||||||
sub qword [NextTRAM], rax ; pos = X + Y * VGA_HEIGHT64. Donc pos - X = début de ligne
|
|
||||||
sub edi, edx
|
|
||||||
mov qword [VGA_X], 0
|
|
||||||
pop rax
|
|
||||||
jmp .pLoop
|
|
||||||
.scroll:
|
|
||||||
|
|
||||||
jmp .pLoop
|
|
||||||
|
|
||||||
;; DATA
|
;; DATA
|
||||||
txt db 0x09, " Switching to Long Mode... OK", 0x0A, 0x0D, 0
|
txt db 0x09, " Switching to Long Mode... ", 0
|
||||||
Init db "Booting OS/K !", 0x0D, 0x0A, 0x0D, 0x0A, 0x09, " Checking CPUID...",0
|
Init db "Booting OS/K !", 0x0D, 0x0A, 0x0D, 0x0A, 0x09, " Checking CPUID...",0
|
||||||
Reinit db "Booting OS/K !", 0x0D, 0x0A, 0x0D, 0x0A, 0
|
Reinit db "Booting OS/K !", 0x0D, 0x0A, 0x0D, 0x0A, 0
|
||||||
CPUIDD db 0x09, " Checking CPUID...", 0
|
CPUIDD db 0x09, " Checking CPUID...", 0
|
||||||
|
@ -417,10 +280,14 @@ main64:
|
||||||
mov esi, Pass
|
mov esi, Pass
|
||||||
call write
|
call write
|
||||||
|
|
||||||
mov bl, 0x0A
|
mov bl, 0x0F
|
||||||
mov esi, txt
|
mov esi, txt
|
||||||
call write
|
call write
|
||||||
|
|
||||||
|
mov bl, 0x0A
|
||||||
|
mov esi, Pass
|
||||||
|
call write
|
||||||
|
|
||||||
mov bl, 0x0D
|
mov bl, 0x0D
|
||||||
mov esi, msg
|
mov esi, msg
|
||||||
call write
|
call write
|
||||||
|
@ -434,5 +301,4 @@ ErrorNo64:
|
||||||
Die:
|
Die:
|
||||||
cli
|
cli
|
||||||
hlt ; die nooooow
|
hlt ; die nooooow
|
||||||
retf
|
jmp 0xF000:0xFFF0
|
||||||
KERNEL:
|
|
||||||
|
|
194
src/boot/mbr.s
194
src/boot/mbr.s
|
@ -24,16 +24,16 @@
|
||||||
%define LOAD_SEG 0x0000 ; (LOAD_SEG << 4) + LOAD_OFF = 0x001000
|
%define LOAD_SEG 0x0000 ; (LOAD_SEG << 4) + LOAD_OFF = 0x001000
|
||||||
%define LOAD_OFF 0x1000
|
%define LOAD_OFF 0x1000
|
||||||
|
|
||||||
[BITS 16] ; Ensure 16-bit code (because fuck UEFI)
|
[BITS 16] ; Ensure 16-bit code (because fuck UEFI)
|
||||||
|
|
||||||
;---------------------------------------------------;
|
|
||||||
; Disk description table ;
|
|
||||||
;---------------------------------------------------;
|
|
||||||
Intro:
|
Intro:
|
||||||
|
|
||||||
jmp short _start ; Jump over the BIOS PARAMETER BLOCK
|
jmp short _start ; Jump over the BIOS PARAMETER BLOCK
|
||||||
nop ; Required by BIOS to recognize the Disk
|
nop ; Required by BIOS to recognize the Disk loul
|
||||||
BPB:
|
BPB:
|
||||||
|
;---------------------------------------------------;
|
||||||
|
; Disk description table ;
|
||||||
|
;---------------------------------------------------;
|
||||||
%define OEMName bp+0x03 ; Disk label
|
%define OEMName bp+0x03 ; Disk label
|
||||||
%define bytesPerSector bp+0x0b ; Bytes per sector
|
%define bytesPerSector bp+0x0b ; Bytes per sector
|
||||||
%define sectorsPerCluster bp+0x0d ; Sectors per cluster
|
%define sectorsPerCluster bp+0x0d ; Sectors per cluster
|
||||||
|
@ -53,7 +53,8 @@ BPB:
|
||||||
%define volumeId bp+0x27 ; Volume ID
|
%define volumeId bp+0x27 ; Volume ID
|
||||||
%define volumeLabel bp+0x2b ; Volume Label
|
%define volumeLabel bp+0x2b ; Volume Label
|
||||||
%define fatTypeLabel bp+0x36 ; File system type
|
%define fatTypeLabel bp+0x36 ; File system type
|
||||||
times 0x3b db 0x00
|
|
||||||
|
times 0x3b db 0x00 ; ALLOCATE THE SECTORS FOR THE BPB
|
||||||
|
|
||||||
;; ENTRY POINT
|
;; ENTRY POINT
|
||||||
_start:
|
_start:
|
||||||
|
@ -63,11 +64,11 @@ bootstrap:
|
||||||
jmp go
|
jmp go
|
||||||
|
|
||||||
;; LOVELY DATA
|
;; LOVELY DATA
|
||||||
FileNotFound db "FStage ERR : NO LOADER", 0 ; File was not found
|
FileNotFound db "First Stage ERROR : NO LOADER", 0
|
||||||
DiskError db "FStage ERR : DISK", 0 ; Error while reading from the disk
|
DiskError db "First Stage ERROR : DISK", 0
|
||||||
UserData dw 0 ; Start of the data sectors
|
UserData dw 0
|
||||||
Bootdrv db 0 ; Boot Bootdrv number
|
Bootdrv db 0
|
||||||
filename db "LOADER BIN" ; Filename
|
filename db "LOADER BIN"
|
||||||
|
|
||||||
|
|
||||||
;; GO !
|
;; GO !
|
||||||
|
@ -82,7 +83,7 @@ go:
|
||||||
mov ss, ax ; Continue init the staaaaaaaack
|
mov ss, ax ; Continue init the staaaaaaaack
|
||||||
mov sp, STACK_OFF ; Ok man, the stack is in 4K :O
|
mov sp, STACK_OFF ; Ok man, the stack is in 4K :O
|
||||||
sti
|
sti
|
||||||
mov bp, (0x7c0-STACK_SEG) << 4 ; Correct bp for the disk description table !
|
mov bp, (0x7c0-STACK_SEG) << 4 ; Correct bp (the disk description table)
|
||||||
|
|
||||||
;; INITIALIZE BOOT DISK
|
;; INITIALIZE BOOT DISK
|
||||||
or dl, dl ; Verifying dl points actually to the boot drive
|
or dl, dl ; Verifying dl points actually to the boot drive
|
||||||
|
@ -116,7 +117,7 @@ load_root:
|
||||||
mov di, BUFFER_SEG ; Set the extra segment to the disk buffer
|
mov di, BUFFER_SEG ; Set the extra segment to the disk buffer
|
||||||
mov es, di
|
mov es, di
|
||||||
mov di, BUFFER_OFF ; Set es:di and load the root directory into the disk buffer
|
mov di, BUFFER_OFF ; Set es:di and load the root directory into the disk buffer
|
||||||
call read_sectors ; Read the sectoooooooors !
|
call read_sectors ; Read the sectoooooooors !
|
||||||
|
|
||||||
;; FIND THE SECOND STAGE LOADER
|
;; FIND THE SECOND STAGE LOADER
|
||||||
mov di, BUFFER_OFF ; Set es:di to the disk buffer
|
mov di, BUFFER_OFF ; Set es:di to the disk buffer
|
||||||
|
@ -127,30 +128,17 @@ search_root:
|
||||||
mov si, filename ; Load the filename
|
mov si, filename ; Load the filename
|
||||||
mov cx, 11 ; Compare first 11 bytes
|
mov cx, 11 ; Compare first 11 bytes
|
||||||
rep cmpsb ; Compare si and di cx times
|
rep cmpsb ; Compare si and di cx times
|
||||||
je load_fat ; We found the LOADEEEEEEEER!!!
|
je load_fat ; We found the LOADEEEEEEEER!!!
|
||||||
add ax, 32 ; File entry offset
|
add ax, 32 ; File entry offset
|
||||||
mov di, BUFFER_OFF ; Point back to the start of the entry
|
mov di, BUFFER_OFF ; Point back to the start of the entry
|
||||||
add di, ax ; Add the offset to point to the next entry
|
add di, ax ; Add the offset to point to the next entry
|
||||||
xchg dx, cx
|
xchg dx, cx
|
||||||
loop search_root ; Continue to search for the file
|
loop search_root ; Continue to search for the file
|
||||||
|
|
||||||
;; ERROR...
|
;; ERROR...
|
||||||
mov si, FileNotFound ; Could not find the file
|
mov si, FileNotFound ; Could not find the file
|
||||||
call print
|
call print
|
||||||
|
call reboot
|
||||||
;; REBOOT
|
|
||||||
reboot:
|
|
||||||
xor ax, ax
|
|
||||||
int 0x16 ; Get a single keypress
|
|
||||||
mov ah, 0x0e ; Teletype output
|
|
||||||
mov al, 0x0d ; Carriage return
|
|
||||||
int 0x10 ; Video interupt
|
|
||||||
mov al, 0x0a ; Line feed
|
|
||||||
int 0x10 ; Video interupt
|
|
||||||
mov al, 0x0a ; Line feed
|
|
||||||
int 0x10 ; Video interupt
|
|
||||||
xor ax, ax
|
|
||||||
int 0x19 ; Reboot the system
|
|
||||||
|
|
||||||
;; LOAD THE FAT FROM THE FILE
|
;; LOAD THE FAT FROM THE FILE
|
||||||
load_fat:
|
load_fat:
|
||||||
|
@ -162,7 +150,7 @@ load_fat:
|
||||||
mov cx, ax ; Store in cx
|
mov cx, ax ; Store in cx
|
||||||
mov ax, word [reservedSectors] ; Convert the first fat on the disk
|
mov ax, word [reservedSectors] ; Convert the first fat on the disk
|
||||||
mov di, BUFFER_OFF ; Set es:di and load the fat sectors into the disk buffer
|
mov di, BUFFER_OFF ; Set es:di and load the fat sectors into the disk buffer
|
||||||
call read_sectors ; Read the sectooooooooooors !!!
|
call read_sectors ; Read the sectooooooooooors !!!
|
||||||
|
|
||||||
;; LOAD THE CLUSTERS OF THE LOADER AND JUMP
|
;; LOAD THE CLUSTERS OF THE LOADER AND JUMP
|
||||||
mov di, LOAD_SEG
|
mov di, LOAD_SEG
|
||||||
|
@ -178,152 +166,10 @@ load_fat:
|
||||||
; ...
|
; ...
|
||||||
; I hope....
|
; I hope....
|
||||||
; ...
|
; ...
|
||||||
|
call reboot
|
||||||
|
|
||||||
|
%include "boot/mbr.inc"
|
||||||
|
|
||||||
;---------------------------------------------------;
|
|
||||||
; FUNCTIONS ;
|
|
||||||
;---------------------------------------------------;
|
|
||||||
|
|
||||||
read_clusters:
|
|
||||||
;---------------------------------------------------;
|
|
||||||
; Read file clusters, starting at the given cluster,;
|
|
||||||
; expects FAT to be loaded into the disk buffer. ;
|
|
||||||
; Please note that this may allocate up to 128KB ;
|
|
||||||
; of ram. ;
|
|
||||||
; ;
|
|
||||||
; Expects: AX = Starting cluster ;
|
|
||||||
; ES:DI = Location to load clusters ;
|
|
||||||
; ;
|
|
||||||
; Returns: None ;
|
|
||||||
; ;
|
|
||||||
;---------------------------------------------------;
|
|
||||||
pusha
|
|
||||||
push es
|
|
||||||
.cluster_loop:
|
|
||||||
xor bh, bh
|
|
||||||
xor dx, dx
|
|
||||||
push ax ; Get the cluster start = (cluster - 2) * sectorsPerCluster + UserData
|
|
||||||
sub ax, 2 ; Subtract 2
|
|
||||||
mov bl, byte [sectorsPerCluster] ; Sectors per cluster is a byte value
|
|
||||||
mul bx ; multiply (cluster - 2) * sectorsPerCluster
|
|
||||||
add ax, word [UserData] ; add the UserData
|
|
||||||
xor ch, ch
|
|
||||||
mov cl, byte [sectorsPerCluster] ; Sectors to read
|
|
||||||
call read_sectors ; Read the sectors
|
|
||||||
pop ax ; Current cluster number
|
|
||||||
xor dx, dx
|
|
||||||
;; Calculate next sector for FAT16 (cluster * 2)
|
|
||||||
mov bx, 2 ; Multiply the cluster by two (cluster is in ax)
|
|
||||||
mul bx
|
|
||||||
;; Load sector in RAM
|
|
||||||
push ds
|
|
||||||
push si
|
|
||||||
mov si, BUFFER_SEG
|
|
||||||
mov ds, si ; Temporarly set ds:si to the FAT buffer
|
|
||||||
mov si, BUFFER_OFF
|
|
||||||
add si, ax ; Point to the next cluster in the FAT entry
|
|
||||||
mov ax, word [ds:si] ; Load ax to the next cluster in FAT
|
|
||||||
pop si
|
|
||||||
pop ds
|
|
||||||
;; Next
|
|
||||||
cmp ax, 0xfff8 ; Check if we are at the end of the file?
|
|
||||||
jae .done
|
|
||||||
add di, 512 ; Add to the pointer offset
|
|
||||||
jnc .cluster_loop
|
|
||||||
;; Correct the buffer because an error will occur if the buffer in memory
|
|
||||||
mov dx, es ; overlaps a 64k page boundry, when di overflows
|
|
||||||
add dh, 0x10 ; it will trigger the carry flag, so correct
|
|
||||||
mov es, dx ; extra segment by 0x1000
|
|
||||||
jmp .cluster_loop ; Load the next file cluster
|
|
||||||
.done:
|
|
||||||
pop es
|
|
||||||
popa
|
|
||||||
ret
|
|
||||||
|
|
||||||
|
|
||||||
read_sectors:
|
|
||||||
;---------------------------------------------------;
|
|
||||||
; Read sectors starting at a given sector by ;
|
|
||||||
; the given times and load into a buffer. Please ;
|
|
||||||
; note that this may allocate up to 128KB of ram. ;
|
|
||||||
; ;
|
|
||||||
; Expects: AX = Starting sector ;
|
|
||||||
; CX = Number of sectors to read ;
|
|
||||||
; ES:DI = Location to load sectors ;
|
|
||||||
; ;
|
|
||||||
; Returns: None ;
|
|
||||||
; ;
|
|
||||||
;---------------------------------------------------;
|
|
||||||
pusha
|
|
||||||
push es
|
|
||||||
mov bx, di ; Convert es:di to es:bx for int 13h
|
|
||||||
.sector_loop:
|
|
||||||
push ax
|
|
||||||
push cx
|
|
||||||
xor dx, dx
|
|
||||||
div word [sectorsPerTrack] ; Divide the lba (value in ax) by sectorsPerTrack
|
|
||||||
mov cx, dx ; Save the absolute sector value
|
|
||||||
inc cx
|
|
||||||
xor dx, dx ; Divide by the number of heads
|
|
||||||
div word [heads] ; to get absolute head and track values
|
|
||||||
mov dh, dl ; Move the absolute head into dh
|
|
||||||
mov ch, al ; Low 8 bits of absolute track
|
|
||||||
shl ah, 1 ; High 2 bits of absolute track
|
|
||||||
shl ah, 1
|
|
||||||
shl ah, 1
|
|
||||||
shl ah, 1
|
|
||||||
shl ah, 1
|
|
||||||
shl ah, 1
|
|
||||||
or cl, ah ; Now cx is set with respective track and sector numbers
|
|
||||||
mov dl, byte [Bootdrv] ; Set correct Bootdrv for int 13h
|
|
||||||
mov di, 5 ; Try five times to read the sector because i love 5
|
|
||||||
.attempt_read:
|
|
||||||
mov ax, 0x0201 ; Read Sectors func of int 13h, read one sector
|
|
||||||
int 0x13 ; Call int 13h (BIOS disk I/O)
|
|
||||||
jnc .read_ok ; If no carry set, the sector has been read
|
|
||||||
xor ah, ah ; Reset Bootdrv func of int 13h
|
|
||||||
int 0x13 ; Call int 13h (BIOS disk I/O)
|
|
||||||
dec di ; Decrease read attempt counter
|
|
||||||
jnz .attempt_read ; Try to read the sector again
|
|
||||||
mov si, DiskError ; Error reading the disk :/
|
|
||||||
call print
|
|
||||||
jmp reboot
|
|
||||||
.read_ok:
|
|
||||||
pop cx
|
|
||||||
pop ax
|
|
||||||
inc ax ; Increase the next sector to read
|
|
||||||
add bx, word [bytesPerSector] ; Add to the buffer address for the next sector
|
|
||||||
jnc .next_sector
|
|
||||||
;; Fixing buffer because an error will occur if the buffer in memory
|
|
||||||
mov dx, es ; overlaps a 64k page boundry, when bx overflows
|
|
||||||
add dh, 0x10 ; it will trigger the carry flag, so correct
|
|
||||||
mov es, dx ; es segment by 0x1000
|
|
||||||
.next_sector:
|
|
||||||
loop .sector_loop
|
|
||||||
pop es
|
|
||||||
popa
|
|
||||||
ret
|
|
||||||
|
|
||||||
print:
|
|
||||||
;---------------------------------------------------;
|
|
||||||
; Print out a simple string. ;
|
|
||||||
; ;
|
|
||||||
; Expects: DS:SI = String to print ;
|
|
||||||
; ;
|
|
||||||
; Returns: None ;
|
|
||||||
; ;
|
|
||||||
;---------------------------------------------------;
|
|
||||||
lodsb ; Load byte from ds:si to al
|
|
||||||
or al, al ; If al is empty stop looping
|
|
||||||
jz .done ; Done looping and return
|
|
||||||
mov ah, 0x0e ; Teletype output
|
|
||||||
int 0x10 ; Video interupt
|
|
||||||
jmp print ; Loop untill string is null
|
|
||||||
.done:
|
|
||||||
ret
|
|
||||||
|
|
||||||
;; END
|
;; END
|
||||||
times 510 - ($ - $$) db 0 ; Pad remainder of boot sector with zeros
|
times 510 - ($ - $$) db 0 ; Pad remainder of boot sector with zeros
|
||||||
dw 0xaa55 ; Boot signature
|
dw 0xaa55 ; Boot signature
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue