/bootloader/stage1.asm

http://github.com/Pokelover980/Poke-and-Necro-Hobby-OS · Assembly · 243 lines · 199 code · 28 blank · 16 comment · 0 complexity · 8932d093f4233a442b387fbc1a649b54 MD5 · raw file

  1. ; -------------------------------------------------------------
  2. ; Pokelover and Necro's Hobby OS Bootloader - Stage 1
  3. ;
  4. ; Based on the MikeOS bootloader, which is based on the free
  5. ; bootloader by E Dehling. It looks for the STAGE2.BIN file on
  6. ; a FAT12 filesystem (specifically a floppy). Takes up exactly
  7. ; one sector and MUST end in 0xAA55, which is the bootloader
  8. ; signature.
  9. ; -------------------------------------------------------------
  10. [BITS 16] ; Let NASM know we want 16 bit mode, even though
  11. ; it should be able to detect it on it's own
  12. jmp short BootStart ; Jump over disk info.
  13. nop
  14. OEMLabel db "PNOSBOOT" ; Disk label
  15. BytesPerSector dw 512 ; Bytes per sector
  16. SectorsPerCluster db 1 ; Sectors per cluster
  17. ReservedForBoot dw 1 ; Reserved sectors for boot record
  18. NumberOfFats db 2 ; Number of copies of the FAT
  19. RootDirEntries dw 224 ; Number of entries in root dir
  20. ; (224 * 32 = 7168 = 14 sectors to read)
  21. LogicalSectors dw 2880 ; Number of logical sectors
  22. MediumByte db 0F0h ; Medium descriptor byte
  23. SectorsPerFat dw 9 ; Sectors per FAT
  24. SectorsPerTrack dw 18 ; Sectors per track (36/cylinder)
  25. Sides dw 2 ; Number of sides/heads
  26. HiddenSectors dd 0 ; Number of hidden sectors
  27. LargeSectors dd 0 ; Number of LBA sectors
  28. DriveNo dw 0 ; Drive No: 0
  29. Signature db 41 ; Drive signature: 41 for floppy
  30. VolumeID dd 00000000h ; Volume ID: any number
  31. VolumeLabel db "PNOS "; Volume Label: any 11 chars
  32. FileSystem db "FAT12 " ; File system type: don't change!
  33. BootStart:
  34. mov ax, 0x07C0 ; This is our entry point, we're going to set up
  35. ; a 4K stack space above this
  36. add ax, 544 ; And first we need a 544 paragraph buffer so we don't
  37. ; interfere with this or the disk buffer!
  38. cli ; Disable interrupts while changing stack
  39. mov ss, ax
  40. mov sp, 4096
  41. sti ; Restore interrupts
  42. mov ax, 0x07C0 ; Set data segment to where we've loaded to make things easier
  43. mov ds, ax
  44. mov byte [BootDev], dl ; Save boot device number
  45. mov eax, 0 ; Older BIOSes may need this
  46. FloppyOk: ; Ready to read first block of data
  47. mov ax, 19 ; Root dir starts at logical sector 19
  48. call l2hts
  49. mov si, Buffer ; Set ES:BX to our buffer
  50. mov bx, ds
  51. mov es, bx
  52. mov bx, si
  53. mov ah, 2 ; int 0x13 params: Read floppy sectors
  54. mov al, 14 ; 14 floppy sectors to read
  55. pusha ; Push registers to stack to prepare for loop
  56. ReadRootDir:
  57. popa ; Just in case int 0x13 modified anything
  58. pusha
  59. stc ; Not all BIOSes set properly on error
  60. int 0x13 ; Read sectors
  61. jnc SearchDir ; If read was OK, skip ahead
  62. call ResetFloppy ; If not, reset floppy and try again
  63. jnc ReadRootDir ; Did the floppy reset fine?
  64. jmp Reboot ; If it didn't, double error, restart
  65. SearchDir:
  66. popa
  67. mov ax, ds ; Root dir is now in [Buffer]
  68. mov es, ax ; Give this info to DI
  69. mov di, Buffer
  70. mov cx, word [RootDirEntries] ; Search all entries
  71. mov ax, 0 ; Start at 0
  72. NextRootEntry:
  73. xchg cx, dx ; We use cx in the inner loop
  74. mov si, BootFileName ; Start searching for stage2 filename
  75. mov cx, 11
  76. rep cmpsb
  77. je FoundFileToLoad ; Pointer DI will be at offset 11
  78. add ax, 32 ; Bump by one entry (32 bytes per entry)
  79. mov di, Buffer ; Point to next entry
  80. add di, ax
  81. xchg dx, cx ; Get cx back
  82. loop NextRootEntry
  83. mov si, NoFile
  84. call PrintString
  85. jmp Reboot
  86. FoundFileToLoad: ; Let's load the FAT into RAM
  87. mov ax, word[es:di+0x0F] ; Offset 11+15=26 contains our first cluster
  88. mov word[Cluster], ax
  89. mov ax, 1 ; Sector 1 = first sector of FAT
  90. call l2hts
  91. mov di, Buffer
  92. mov bx, di ; ES:BX points to our buffer
  93. mov ah, 2 ; int 0x13 params: read FAT sectors
  94. mov al, 9 ; All 9 sectors of first FAT
  95. pusha ; Push registers to stack to prepare for loop
  96. ReadFat:
  97. popa ; In case int 0x13 modified anything
  98. pusha
  99. stc
  100. int 0x13 ; Read sectors using BIOS
  101. jnc ReadFatOkay ; If read was okay, skip ahead
  102. call ResetFloppy ; Otherwise, reset floppy and try again
  103. jnc ReadFat ; Floppy reset OK?
  104. mov si, DiskError
  105. call PrintString ; If not, print an error and reboot
  106. jmp Reboot
  107. ReadFatOkay:
  108. popa
  109. mov ax, 0x2000 ; Segment where we're loading kernel
  110. mov es, ax
  111. mov bx, 0
  112. mov ah, 2 ; int 0x13 read params
  113. mov al, 1
  114. push ax ; Save in case it gets lost
  115. ; We're gonna load the FAT from the disk now
  116. LoadFileSector:
  117. mov ax, word [Cluster] ; Convert sector to logical
  118. add ax, 31
  119. call l2hts
  120. mov ax, 0x2000 ; Set buffer past what we've read
  121. mov es, ax
  122. mov bx, word [Pointer]
  123. pop ax ; Save in case it gets lost
  124. push ax
  125. stc
  126. int 0x13
  127. jnc CalculateNextCluster ; If there's no error
  128. call ResetFloppy ; If there is, reset floppy
  129. jmp LoadFileSector
  130. CalculateNextCluster:
  131. mov ax, [Cluster]
  132. mov dx, 0
  133. mov bx, 3
  134. mul bx
  135. mov bx, 2
  136. div bx ; DX = [Cluster] mod 2
  137. mov si, Buffer
  138. add si, ax ; AX = word in FAT for 12 bit entry
  139. mov ax, word [ds:si]
  140. or dx, dx ; If DX = 0 [Cluster] is even; if 1, [Cluster] is odd
  141. jz even ; If [Cluster] is even, drop last 4 bits of word with
  142. ; next clusters; if odd, drop first 4 bits
  143. odd:
  144. shr ax, 4
  145. jmp short NextClusterCont
  146. even:
  147. and ax, 0x0FFF ; Mask out final four bits
  148. NextClusterCont:
  149. mov word [Cluster], ax ; Store cluster
  150. cmp ax, 0x0FF8 ; 0xFF8 = end of file in FAT12
  151. jae end
  152. add word [Pointer], 512 ; Increase buffer point 1 sector
  153. jmp LoadFileSector
  154. end: ; Hooray, we've reached the end and got the file to load!
  155. pop ax ; Clean up stack, as we pushed AX earlier
  156. mov dl, byte[BootDev] ; Provide Stage2/Kernel with boot device info
  157. mov si, NoFile
  158. call PrintString
  159. jmp 0x2000:0x0 ; Jump to entry point of stage2!
  160. ; Subroutines below
  161. Reboot:
  162. mov ax, 0
  163. int 0x16 ; Wait for keystroke
  164. mov ax, 0
  165. int 0x19 ; Reboot
  166. PrintString:
  167. pusha
  168. mov ax, 0x0E
  169. .repeat:
  170. lodsb
  171. cmp al, 0
  172. je .done ; If char is 0, we've reached the end of the string
  173. int 0x10 ; Otherwise, we print it
  174. jmp short .repeat
  175. .done:
  176. popa
  177. ret
  178. ResetFloppy: ; Carry set on error
  179. push ax
  180. push dx
  181. mov ax, 0
  182. mov dl, byte [BootDev]
  183. stc
  184. int 0x13
  185. pop dx
  186. pop ax
  187. ret
  188. l2hts: ; Calculate head, track and sector for int 0x13
  189. push bx
  190. push ax
  191. mov bx, ax
  192. mov dx, 0
  193. div word [SectorsPerTrack]
  194. add dl, 0x01
  195. mov cl, dl
  196. mov ax, bx
  197. mov dx, 0
  198. div word [SectorsPerTrack]
  199. mov dx, 0
  200. div word [Sides]
  201. mov dh, dl
  202. mov ch, al
  203. pop ax
  204. pop bx
  205. mov dl, byte [BootDev]
  206. ret
  207. BootFileName db "STAGE2 BIN" ; Stage2 filename
  208. DiskError db "Disk error! Press any key to reboot...", 0 ; Something went wrong!
  209. NoFile db "No STAGE2.BIN", 0 ; Someone forgot to add something...
  210. BootDev db 0
  211. Cluster dw 0
  212. Pointer dw 0
  213. times 510-($-$$) db 0
  214. dw 0AA55h
  215. Buffer: