1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273
|
use16
ORG $7C00
LOAD_SEGMENT = 0x1000
FAT_SEGMENT = 0x0ee0
;===========================================
start:
jmp main ;jump to beginning of code
nop
;----------------------------------------
OEM: db "DevOS " ;OEM String
SectSize: dw 0x200 ;Bytes per sector
ClustSize: db 1 ;Sectors per cluster
ResSect: dw 1 ;#of reserved sectors
FatCnt: db 2 ;#of fat copies
RootSize: dw 224 ;size of root directory
TotalSect: dw 2880 ;total ;of sectors if below 32 MB
Media: db 0xF0 ;Media Descriptor
FatSize: dw 9 ;Size of each FAT
TrackSect: dw 9 ;Sectors per track
HeadCnt: dw 2 ;number of read-write heads
HiddenSect: db 0 ;number of hidden sectors
Sect32: db 0 ;;sectors if over 32 MB
BootDrive: db 0 ;holds drive that the boot sector came from
Reserved: db 0 ;reserved, empty
BootSign: db 0x29 ;extended boot sector signature
VolID: db "seri" ;disk serial
acVolLabel: db "MYVOLUME " ;just placeholder. We don't yet use volume labels.
acFSType: db "FAT16 " ;file system type
;===============================
main:
cli
;mov dl, BootDrive ;save what drive we booted from (should be 0x0)
mov ax, cs ;CS is set to 0x0, because that is where boot sector is loaded (0:07c00)
mov ds, ax ;DS = CS = 0x0
mov es, ax ;ES = CS = 0x0
mov ss, ax ;SS = CS = 0x0
mov sp, 0x7C00 ;Stack grows down from offset 0x7C00 toward 0x0000.
;sti ; we don't need hardware interrupts
;-----------------------
mov dl, [BootDrive] ;drive to reset
xor ax, ax ;subfunction 0
int 0x13 ;call interrupt 13h
jc bootFailure ;display error message if carry set (error)
;-------------
; display loading message
mov si, loadmsg
call WriteString
;---------------------
mov ax, LOAD_SEGMENT
mov es, ax
mov ax, 32
xor dx, dx
mul word [RootSize]
div word [SectSize] ;Divide (dx:ax,sectsize) -> (ax,dx)
mov cx, ax
mov [root_scts], cx
xor ax, ax ;find the root directory
mov al, [FatCnt] ;ax = number of FAT tables
mov bx, word [FatSize] ;bx = sectors per FAT
mul bx ;ax = #FATS * sectors per FAT
add ax, word [HiddenSect] ;Add hidden sectors to ax
adc ax, word [HiddenSect+2]
add ax, word [ResSect] ;Add reserved sectors to ax
mov [root_strt], ax
read_next_sector:
push cx
push ax
xor bx, bx
call ReadSector
check_entry:
mov cx, 11 ;Directory entries filenames are 11 bytes.
mov di, bx ;es:di = Directory entry address
mov si, kernelname ;ds:si = Address of kernelname we are looking for.
repz cmpsb ;Compare kernelname to memory.
je found_file ;If found, jump away.
add bx, word 32 ;Move to next entry. Complete entries are 32 bytes.
cmp bx, word [SectSize] ;Have we moved out of the sector yet?
jne check_entry ;If not, try next directory entry.
pop ax
inc ax ;check next sector when we loop again
pop cx
loopnz read_next_sector ;loop until either found or not
jmp bootFailure ;could not find file: abort
found_file:
mov ax, [es:bx+0x1a]
mov [file_strt], ax
;------------------------------
mov ax, FAT_SEGMENT
mov es, ax
;Calculate offset of FAT:
mov ax, word [ResSect] ;Add reserved sectors to ax
add ax, word [HiddenSect] ;Add hidden sectors to ax
adc ax, word [HiddenSect+2]
;Read all FAT sectors into memory:
mov cx, word [FatSize] ;Number of sectors in FAT
xor bx, bx ;Memory offset to read into (es:bx)
read_next_fat_sector:
push cx
push ax
call ReadSector
pop ax
pop cx
inc ax
add bx, word [SectSize]
loopnz read_next_fat_sector ;continue with next sector
;----------------------------
;Set memory segment that will receive the file:
mov ax, LOAD_SEGMENT
mov es, ax
;Set memory offset for loading to 0.
xor bx, bx
;Set memory segment for FAT:
mov cx, [file_strt] ;CX now points to file's first FAT entry
read_file_next_sector:
;Locate sector:
mov ax, cx ;Sector to read is equal to current FAT entry
add ax, [root_strt] ;Plus the start of the root directory
add ax, [root_scts] ;Plus the size of the root directory
sub ax, 2 ;... but minus 2
;Read sector:
push cx ;Read a sector from disk, but save CX
call ReadSector ;as it contains our FAT entry
pop cx
add bx, [SectSize] ;Move memory pointer to next section
;Get next sector from FAT:
push ds ;Make DS:SI point to FAT table
mov dx, FAT_SEGMENT ;in memory.
mov ds, dx
mov si, cx ;Make SI point to the current FAT entry
mov dx, cx ;(offset is entry value * 1.5 bytes)
;shr dx
add si, dx
mov dx, [ds:si] ;Read the FAT entry from memory
test dx, 1 ;See which way to shift
jz read_next_file_even
and dx, 0x0fff
jmp read_next_file_cluster_done
read_next_file_even:
shr dx, 4
read_next_file_cluster_done:
pop ds ;Restore DS to the normal data segment
mov cx, dx ;Store the new FAT entry in CX
cmp cx, 0xff8 ;If the FAT entry is greater or equal
jl read_file_next_sector ;to 0xff8, then we've reached end-of-file
;--------------------------------
; Make es and ds point to segment where 2nd stage was loaded.
mov ax, word LOAD_SEGMENT
mov es, ax
mov ds, ax
; Jump to second stage start of code:
jmp LOAD_SEGMENT:0
;-------------------
;then reboot.
bootFailure:
mov si, diskerror
call WriteString
call Reboot
;=============================
; functions
;============================
WriteString:
lodsb ; load byte at ds:si into al (advancing si)
or al, al ; test if character is 0 (end)
jz WriteString_done ; jump to end if 0.
mov ah, 0xe ; Subfunction 0xe of int 10h (video teletype output).
mov bx, 7 ; Set bh (page number) to 0, and bl (attribute) to white (9).
int 0x10 ; call BIOS interrupt.
jmp WriteString ; Repeat for next character.
WriteString_done:
ret
;----------------------------------------
Reboot:
mov si, rebootmsg ; Load address of reboot message into si
call WriteString ; print the string
xor ax, ax ; subfuction 0
int 0x16 ; call bios to wait for key
db 0xEA ; machine language to jump to FFFF:0000 (reboot)
dw 0x0000
dw 0xFFFF
;---------------------------------------------
ReadSector:
xor cx, cx ; Set try count = 0
readsect:
push ax ; Store logical block
push cx ; Store try number
push bx ; Store data buffer offset
mov bx, [TrackSect] ; Get sectors per track
xor dx, dx
div bx ; Divide (dx:ax/bx to ax,dx)
; Quotient (ax) = LBA / SectorsPerTrack
; Remainder (dx) = LBA mod SectorsPerTrack
inc dx ; Add 1 to remainder, since sector
mov cl, dl ; Store result in cl for int 13h call.
mov bx, [HeadCnt] ; Get number of heads
xor dx, dx
div bx ; Divide (dx:ax/bx to ax,dx)
; Quotient (ax) = Cylinder
; Remainder (dx) = head
mov ch, al ; ch = cylinder
xchg dl, dh ; dh = head number
mov ax, 0x0201 ; Subfunction 2, read 1 sector
pop bx ; Restore data buffer offset.
int 0x13
jc readfail
; On success, return to caller.
pop cx ; Discard try number
pop ax ; Get logical block from stack
ret
readfail:
pop cx ; Get try number
inc cx ; Next try
cmp cx, word 4 ; Stop at 4 tries
je bootFailure
; Reset the disk system:
xor ax, ax
int 0x13
; Get logical block from stack and retry.
pop ax
jmp readsect
;=============================
;PROGRAM DATA
;======================
kernelname: db "KERNEL BIN"
rebootmsg: db "Press any key to reboot.",0
diskerror: db "Disk error. ",0
loadmsg: db "Loading KERNEL...",0
root_strt: db 0 ;hold offset of root directory on disk
root_scts: db 0 ;holds ;sectors in root directory
file_strt: db 0 ;holds offset of bootloader on disk
;====================================
DB 510 - ($ - $$) DUP(0) ; remplir à hauteur de 510 octets
DW $AA55 ; et placer le marqueur de disque bootable |