From a805431f7cb27d5f09c85eb7e03b1f1607c6a1f3 Mon Sep 17 00:00:00 2001 From: Adrien Bourmault Date: Sat, 22 Dec 2018 23:58:46 +0100 Subject: [PATCH] Clean-up and conveniance for mbr and loader --- bin/disk.img | Bin 18944000 -> 18944000 bytes bin/loader.bin | Bin 990 -> 1002 bytes bin/mbr.bin | Bin 512 -> 512 bytes obj/boot/loader.bin | Bin 990 -> 1002 bytes obj/boot/mbr.bin | Bin 512 -> 512 bytes src/Makefile | 2 +- src/boot/loader.s | 202 ++++++++------------------------------------ src/boot/mbr.s | 194 +++++------------------------------------- 8 files changed, 55 insertions(+), 343 deletions(-) diff --git a/bin/disk.img b/bin/disk.img index 3ab40ba2bea958c7cc8ee598d7185f4991adbc9b..beefdec936f8d328364a9e9bbb1f74bb163acbb4 100644 GIT binary patch delta 2626 zcmdUvd0bRg6vxjSV1{jA1R>PY(b7tVK%#}req%zo019YoWl~~VsU_HI;MUJlGjS4H zw9HD))HF=XY#^=FjM8l1L(K`w%xtrAI*->fF7;P`)SJ)u-Shd~bMBmb?zwN$!f6qc zlsUc5$jTl)zO>9;SXO*hi94&HAiuz!>CVe{_sjS6$|{hfXDdt6jPlCrE}0X>h?yw0 z;-0;^R>c39nldx5MOxkTS9}%nY?OSvxGZ66om*vN^Yk4JeqWaO-xB}F;*B*DlSi2T zW~ghh-zhT^%cW6VA_x5|WVk&wkoHFZseapxVa^|Rh1e&0^NryH%B40;o-u6o@ujh; zyX)igCmiryDgH!hat|4dkYQ1!j#(Qgz3iI3v0=5Nc+>Lmx-$Ekn0i;!cbn4c>J!(* zta8@7Rz+H<(yHdL5pItT1U)s8;rsIE9#>qNTp=B5t8%MyMUr%kmc|ef<Hv#!HI6 zV`UJ!{PES>QIGp1t$jBJ+J#e2I>sA~uarks^&RmQs!1JxY=#O;VeGx{$6^ zRNyJhNiI**C0re4#G>C9Fvl>{L-vf(m|Pho9$jGGMKaJkU}^Uje`acCY-U>1KD;4& zZIba(NLb_kfb6d^Y;8kBn!3;N8n*K?8ZVSON7MhM5eonHMi{tk(II;k4Ck50sc=e4 z^9h=|NTj7Mpe-s{oFaF9+SJy9?TGW&2Nf(alrRVz5kjaPM%W1l5l%!9kwg>`O*n}dB9?FwEr>WG zo@hxV5Q)SIL=w@8Xic;sP9#nu+7j&uH_@KxK%7jRLUbfL5vLNT5vLQKi7rG}BAG}b z&LC2WG@=`kPMk?(5N8o*6Xy`;5}Cw#M0etRq6cvS0m4J{BrYU+5m`hwaS@S2^d|Zc zeTjZVE|Ev%6a9$+L;+Dq6cGc7LBz$xU}6X{l(>Yrl(>u-MqEw|CyI$Hh%1Q^Lj3%xot|6`^#t>tPam01R^~89hlqe%65H}Dv5;qYy6Sokz5)+Brh;pKWm_$q_ zrVvw!X~gXWiRr{0#GS+pVkR+*xQm!g+)d0ODv7y-m$-+RM^q8j#J$9Q#Qnqr#C&1_ z@gVUKv5MXV;CB5H^=#M8uDVjb}e z@hq{Pc#haWJWu$DTB444f!IiFB3>k3B3>po6I+O_#4E%$;#H!ac#U|S*iP&q-XL}o zZxU}2Zxinj?-K73?-L&o9}*uC9}}MtpAw%D4a6>DH?fEKoY+hFi7$voqKWvD_=?y^ zd`;{pz99|}-x3Fj?}+b-ABZ1`pNK=m&%`gpuf$;@FaySH7>Z2^Q9_k4#jZG%a3w;C wRHBq<#i_(7v5HG+p~NZiN=qd{NmNcyl9X0TYo(2HqH>bbR%vIfgxlEu8)<3=RsaA1 delta 3422 zcmeHIYjjlA89jIMV3J8PH#0E=5C}@plwygNM{Nq5N+420C`bqu!lQC|DGeoB#L@(! z8%>l)rjWk0qJ;udiv)RC9Rg9(s4j7}KmZ#g<9F^PA^z}R*XmkbowfEo z`+nbd&Y8Qvv+pf??yWp`C) zZVOK?L{yPyQJ1IommM%y?mxM$%Z$3M?%I;r9Z3yl)1|tA;quqC8t&Kx)$t35Yx=lP zZI#ijjz=l=(SvG$8mjVCf%2-gcc^;R8@lObd|&cjiJMynSQ0x zRBnBAMqD6x{w5r}t1snMEd71demC;BZz!fls&%cyTU zV2!iZPxV`wI-YsNs+S2`ZmY2A#iq?QUMu*nPa3~gq!=kuTyhmy!QoP2mxrxjuS+_& zq(hOm)ZDNg6ShBY4K#%^l9wdAo%XGYS)8oYs+flZea=^Tp6w7V#}O?@i*|R87A?0t zIz#^lSJQjbit2JJqcbMTU9J(Gq0{Z7Q7?b~)p0tli*qw0>C7X#5mT#2R~WYh=C}9* zn=kAu)$>#5wYuwhiC7QSOZGq-( zeRFEs`c}{>J|4;y8Kkrwa z5WnhWWSB04V_SU!?$h1!MBKVab8oO&J8`z=@eyI18gI~%Ccjhsu1Nixx_(Hfcz?|k zgNtP!ySMN-=Lq!n+Y99cyb-n0HrzYQjCTyvs!YhZEVHfhGsd>Wi(7WRzszWi?K}7S zm!i&95IpMBUy7BV`%)aOZk%Hr?l(lXh^Tm6mQiIM`JBq7V3M`RtMrO>mDw4`s~eXY z-N)z(M_aw)b#2edoz_&R+s97Y>SC>}PDix8?5obLFs@C}6GhF_GDKd2^CA-DO2Br^ zP!= z*dAkJb?I`WZr6zU#@=YcAY4QgAv}hNCAtu9B94eBJVXMKNF)(n!X%OjAK@obh#QDh zqAQU`bR)VGJ%}5LoCA#NgWCi)T?L_gvd;#MM)_!7~d_%bnoxQ+M#9hQlB8M17j3#o4yNNNxw}^X) zJYp=7PmCkJO^hcd5cd)ji2`C0QAkWCzC+wcOd+NcMZ`2>Ix&NoNqm>MpO{5h#B5>? zF_)M}%qJco9wZhJ-y@2Ng~a!XMMMel5b-ea17b1p2(g5Cl=vaBl=u-*N|X`Hh~-2% z@fh(qL1G2*1o0$MK~xe?5l<5tS6o)ULbx&Y#=rgza};jn~5#Ni^NvqH^fWCZ;5Th%fxn~hS)*8LhK}V5xa>! z#H+;bh}VeMi6F6;s3rCh`-wW@4dPAW08vl;p7;at7V$Rm4$(loOZ<^INE{*#6MrK9 zO#FrTD{+K4N*p8pM!ZM7PyC%YPMjbr98QSqD&smEUHQ%#_QYhafdy+SyZKfJP$^oQY4!3 zIOFlxy8=McAjKY<5NXZpATyOFyD(`?E@1jq57OGtqACQW_Aq?lWO!ls@BjbJ-1{aA zF)+Lc1F`w{Ed#N=Kx{6cgMn@r1mg;;AD7V_3!`x z&D{H@3o$Uf2m-PB_pJi4-9T(EpsRswuo`}#+ktF7BylAOI{+ju24eH>(*vpJ02q3P54TF#rGn diff --git a/obj/boot/loader.bin b/obj/boot/loader.bin index c38ae047d158a0550601c66f28288a1c27b814fe..0887d7cb4875b2480b8e66286202d25974c9022c 100644 GIT binary patch delta 284 zcmcb|{)&CVUX@&-7w`VZy_ox-ze$)mY#)p8i~Ilg?Gk!%^MBlvNjyx?CIQ7JKD@-8 zEX=?l!QgS6MU`vvK1L-*uE`G>r98QSqD&smEUHQ%#_QYhafdy+SyZKfJP$^oQY4!3 zIOFlxy8=McAjKY<5NXZpATyOFyD(`?E@1jq57OGtqACQW_Aq?lWO!ls@BjbJ-1{aA zF)+Lc1F`w{Ed#N=Kx{6cgMn@r1mg;;AD7V_3!`x z&D{H@3o$Uf2m-PB_pJi4-9T(EpsRswuo`}#+ktF7BylAOI{+ju24eH>(*vpJ02q3P54TF#rGn diff --git a/src/Makefile b/src/Makefile index 8caea17..6d51fb0 100644 --- a/src/Makefile +++ b/src/Makefile @@ -29,7 +29,7 @@ SYSTDIR=kaleid/system 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 boot.loader.s: $(BOOTDIR)/loader.s diff --git a/src/boot/loader.s b/src/boot/loader.s index c5afb8a..8c46cd4 100644 --- a/src/boot/loader.s +++ b/src/boot/loader.s @@ -7,8 +7,12 @@ ; Desc: Kernel (second stage) Loader for OS/K ; ; (x86_64 architecture only) ; ;=----------------------------------------------------------------------------=; + +;;VIDEO %define TRAM 0x0B8000 ; [T]ext[RAM] %define VRAM 0x0A0000 ; [V]ideo[RAM] + +;; BPB %define OEMName bp+0x03 ; Disk label %define bytesPerSector bp+0x0b ; Bytes per sector %define sectorsPerCluster bp+0x0d ; Sectors per cluster @@ -32,9 +36,9 @@ [BITS 16] [ORG 0x1000] -mov ax, cs -mov ds, ax -mov es, ax +mov ax, cs ; correcting cs after the horrible far jump +mov ds, ax ; hm... And ds too +mov es, ax ; And es because it is jealous mov [Bootdrv], dl jmp 0x0000:main @@ -48,13 +52,13 @@ VIDEO_MODE dw 0 ;; GDT WITH DOC GDT64: NULL_SELECTOR: ;; null selector within 64 bits - dw GDT_LENGTH ; limit of GDT - dw GDT64 ; linear address of GDT + dw GDT_LENGTH ; limit of GDT + dw GDT64 ; linear address of GDT dd 0x0 CODE_SELECTOR: ;; 32-bit code selector (ring 0) - dw 0x0FFFF ; Segment Limit 15:00 - db 0x0, 0x0, 0x0 ; Base Address 23:00 - db 10011010b ; |7|6|5|4|3|2|1|0| + dw 0x0FFFF ; Segment Limit + db 0x0, 0x0, 0x0 ; Base Address + db 10011010b ; |7|6|5|4|3|2|1|0| ; | | | | | | | `----- 1 when segment used. ; | | | | | | `------ 1 when writable. ; | | | | | `------- 1 if "conformant". Don't know what is it... spectral ? xD @@ -63,7 +67,7 @@ GDT64: ; | | `---------- DPL !!! 0 for ring 0 ; | `----------- DPL (2/2) ; `------------ 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 17 ; | | | | | `------- Limit 18 @@ -72,12 +76,12 @@ GDT64: ; | | `---------- 0 always ; | `----------- size of data. 1 for 32bits ; `------------ 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) - dw 0x0FFFF ; Segment Limit 15:00 - db 0x0, 0x0, 0x0 ; Base Address 23:00 - db 10010010b ; |7|6|5|4|3|2|1|0| + DATA_SELECTOR: ;; flat data selector (ring 0) + dw 0x0FFFF ; Segment Limit + db 0x0, 0x0, 0x0 ; Base Address + db 10010010b ; |7|6|5|4|3|2|1|0| ; | | | | | | | `----- 1 when segment used. ; | | | | | | `------ 1 when writable. ; | | | | | `------- expansion direction. 1 for a LIFO @@ -86,7 +90,7 @@ GDT64: ; | | `---------- DPL !!! 0 for ring 0 ; | `----------- DPL (2/2) ; `------------ 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 17 ; | | | | | `------- Limit 18 @@ -95,12 +99,12 @@ GDT64: ; | | `---------- 0 always ; | `----------- size of data. 1 for 32bits ; `------------ 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) - dw 0x0FFFF ; Segment Limit 15:00 - db 0x0, 0x0, 0x0 ; Base Address 23:00 - db 10011010b ; |7|6|5|4|3|2|1|0| + dw 0x0FFFF ; Segment Limit + db 0x0, 0x0, 0x0 ; Base Address + db 10011010b ; |7|6|5|4|3|2|1|0| ; | | | | | | | `----- 1 when segment used. ; | | | | | | `------ 1 when writable. ; | | | | | `------- 1 if "conformant". Don't know what is it... spectral ? xD @@ -118,89 +122,10 @@ GDT64: ; | | `---------- 0 always ; | `----------- size of data. 1 for 32bits ; `------------ 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: -disable_cursor: - 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 +%include "boot/loader16.inc" main: ;; compatibility check @@ -308,74 +233,12 @@ main32: push dword [VGA_HEIGHT] jmp (LONG_SELECTOR-GDT64):main64 -[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 +[BITS 64] -write: -;-----------------------------------------------------------------------; -; 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 +%include "boot/loader64.inc" ;; 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 Reinit db "Booting OS/K !", 0x0D, 0x0A, 0x0D, 0x0A, 0 CPUIDD db 0x09, " Checking CPUID...", 0 @@ -417,10 +280,14 @@ main64: mov esi, Pass call write - mov bl, 0x0A + mov bl, 0x0F mov esi, txt call write + mov bl, 0x0A + mov esi, Pass + call write + mov bl, 0x0D mov esi, msg call write @@ -434,5 +301,4 @@ ErrorNo64: Die: cli hlt ; die nooooow - retf -KERNEL: + jmp 0xF000:0xFFF0 diff --git a/src/boot/mbr.s b/src/boot/mbr.s index 8d65ca7..3387242 100644 --- a/src/boot/mbr.s +++ b/src/boot/mbr.s @@ -24,16 +24,16 @@ %define LOAD_SEG 0x0000 ; (LOAD_SEG << 4) + LOAD_OFF = 0x001000 %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: 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: + ;---------------------------------------------------; + ; Disk description table ; + ;---------------------------------------------------; %define OEMName bp+0x03 ; Disk label %define bytesPerSector bp+0x0b ; Bytes per sector %define sectorsPerCluster bp+0x0d ; Sectors per cluster @@ -53,7 +53,8 @@ BPB: %define volumeId bp+0x27 ; Volume ID %define volumeLabel bp+0x2b ; Volume Label %define fatTypeLabel bp+0x36 ; File system type - times 0x3b db 0x00 + + times 0x3b db 0x00 ; ALLOCATE THE SECTORS FOR THE BPB ;; ENTRY POINT _start: @@ -63,11 +64,11 @@ bootstrap: jmp go ;; LOVELY DATA -FileNotFound db "FStage ERR : NO LOADER", 0 ; File was not found -DiskError db "FStage ERR : DISK", 0 ; Error while reading from the disk -UserData dw 0 ; Start of the data sectors -Bootdrv db 0 ; Boot Bootdrv number -filename db "LOADER BIN" ; Filename +FileNotFound db "First Stage ERROR : NO LOADER", 0 +DiskError db "First Stage ERROR : DISK", 0 +UserData dw 0 +Bootdrv db 0 +filename db "LOADER BIN" ;; GO ! @@ -82,7 +83,7 @@ go: mov ss, ax ; Continue init the staaaaaaaack mov sp, STACK_OFF ; Ok man, the stack is in 4K :O 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 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 es, di 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 mov di, BUFFER_OFF ; Set es:di to the disk buffer @@ -127,30 +128,17 @@ search_root: mov si, filename ; Load the filename mov cx, 11 ; Compare first 11 bytes 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 mov di, BUFFER_OFF ; Point back to the start of the entry add di, ax ; Add the offset to point to the next entry xchg dx, cx - loop search_root ; Continue to search for the file + loop search_root ; Continue to search for the file ;; ERROR... mov si, FileNotFound ; Could not find the file call print - - ;; 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 + call reboot ;; LOAD THE FAT FROM THE FILE load_fat: @@ -162,7 +150,7 @@ load_fat: mov cx, ax ; Store in cx 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 - call read_sectors ; Read the sectooooooooooors !!! + call read_sectors ; Read the sectooooooooooors !!! ;; LOAD THE CLUSTERS OF THE LOADER AND JUMP mov di, LOAD_SEG @@ -178,152 +166,10 @@ load_fat: ; ... ; I hope.... ; ... + call reboot - - -;---------------------------------------------------; -; 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 +%include "boot/mbr.inc" ;; END times 510 - ($ - $$) db 0 ; Pad remainder of boot sector with zeros dw 0xaa55 ; Boot signature -