stage2.asm 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  1. [BITS 16]
  2. [ORG 0x7E00]
  3. ; Set VESA Video Mode (1024x768x32 - Bochs VBE mode)
  4. mov ax, 0x4F02
  5. mov bx, 0x4144 ; mode 0x144 + LFB bit = 32bpp guaranteed
  6. int 0x10
  7. ; Get VBE Mode Info to find the LFB address and pitch
  8. mov ax, 0x4F01
  9. mov cx, 0x0144
  10. mov di, 0x3000
  11. int 0x10
  12. movzx eax, word [0x3010] ; BytesPerScanLine (actual pitch)
  13. mov [screen_pitch], eax
  14. mov edi, [0x3028] ; LFB Physical Address
  15. mov [lfb_addr], edi
  16. ; Enter Unreal Mode
  17. cli
  18. push ds
  19. push es
  20. in al, 0x92
  21. or al, 2
  22. out 0x92, al
  23. lgdt [gdt_desc]
  24. mov eax, cr0
  25. or al, 1
  26. mov cr0, eax
  27. jmp $+2
  28. mov bx, 0x08
  29. mov ds, bx
  30. mov es, bx
  31. mov fs, bx
  32. mov gs, bx
  33. mov ss, bx
  34. and al, 0xFE
  35. mov cr0, eax
  36. jmp $+2
  37. xor ax, ax
  38. mov ds, ax
  39. mov es, ax
  40. mov fs, ax
  41. mov gs, ax
  42. mov ss, ax
  43. sti
  44. mov [boot_drive], byte 0x80
  45. ; Load animation.bin to 0x2000000 (32MB)
  46. mov eax, [animation_lba]
  47. mov ecx, [animation_size_sectors]
  48. mov edi, 0x2000000
  49. call read_sectors_high
  50. ; Play Animation (nucleus expansion only — electrons done by Swift later)
  51. mov ecx, 60
  52. mov esi, 0x2000000 ; Source of animation frames
  53. .play_anim:
  54. push ecx
  55. mov edi, [lfb_addr]
  56. ; Center X = (1024-200)/2 = 412
  57. ; Center Y = (768-200)/2 = 284
  58. ; Dest offset = 284 * pitch + 412 * 4
  59. mov eax, 284
  60. imul eax, dword [screen_pitch]
  61. add eax, 412 * 4
  62. add edi, eax
  63. mov cx, 200 ; 200 lines
  64. .draw_line:
  65. push ecx
  66. push edi
  67. mov ecx, 200 ; 200 pixels * 4 bytes (32bpp) = 800 bytes = 200 dwords
  68. a32 rep movsd
  69. pop edi
  70. add edi, [screen_pitch] ; Advance by actual pitch
  71. pop ecx
  72. dec cx
  73. jnz .draw_line
  74. ; Wait ~16ms (16666 microseconds)
  75. mov ah, 0x86
  76. mov cx, 0 ; High word of microseconds
  77. mov dx, 16666 ; Low word of microseconds
  78. int 0x15
  79. pop ecx
  80. dec ecx
  81. jnz .play_anim
  82. ; 1. Read first sector of bzImage to get setup_sects
  83. mov eax, [bzimage_lba]
  84. mov ebx, 0x9000
  85. mov es, bx
  86. xor bx, bx
  87. mov cx, 1
  88. call read_sectors
  89. jc .err_read1
  90. mov al, [es:0x01F1]
  91. cmp al, 0
  92. jne .has_setup
  93. mov al, 4
  94. .has_setup:
  95. inc al
  96. movzx cx, al
  97. ; 2. Read setup sectors to 0x90000
  98. mov eax, [bzimage_lba]
  99. mov bx, 0x9000
  100. mov es, bx
  101. xor bx, bx
  102. call read_sectors
  103. jc .err_read2
  104. ; 3. Read protected mode kernel to 0x100000
  105. mov eax, [bzimage_lba]
  106. add eax, ecx
  107. mov edx, [bzimage_size_sectors]
  108. sub edx, ecx
  109. mov ecx, edx
  110. mov edi, 0x100000
  111. call read_sectors_high
  112. jc .err_read3
  113. ; 4. Read initramfs to 0x8000000
  114. mov eax, [initramfs_lba]
  115. mov ecx, [initramfs_size_sectors]
  116. mov edi, 0x8000000
  117. call read_sectors_high
  118. jc .err_read4
  119. ; Setup Boot Params at 0x90000
  120. mov bx, 0x9000
  121. mov ds, bx
  122. mov byte [0x210], 0xFF
  123. mov al, [0x211]
  124. or al, 0x80
  125. mov [0x211], al
  126. mov word [0x224], 0xFE00
  127. mov dword [0x218], 0x8000000
  128. mov eax, [cs:initramfs_size_bytes]
  129. mov dword [0x21C], eax
  130. mov dword [0x228], 0x99000
  131. push ds
  132. xor ax, ax
  133. mov ds, ax
  134. mov si, cmd_line
  135. pop es
  136. mov di, 0x9000
  137. .copy_cmd:
  138. lodsb
  139. stosb
  140. test al, al
  141. jnz .copy_cmd
  142. mov ax, 0x9000
  143. mov ds, ax
  144. mov es, ax
  145. mov fs, ax
  146. mov gs, ax
  147. mov ss, ax
  148. cli
  149. jmp 0x9000:0x0200
  150. .err_read1:
  151. mov si, msg_err1
  152. call print_string
  153. jmp halt
  154. .err_read2:
  155. mov si, msg_err2
  156. call print_string
  157. jmp halt
  158. .err_read3:
  159. mov si, msg_err3
  160. call print_string
  161. jmp halt
  162. .err_read4:
  163. mov si, msg_err4
  164. call print_string
  165. halt:
  166. hlt
  167. jmp halt
  168. ; --- Functions ---
  169. print_string:
  170. push ds
  171. push ax
  172. xor ax, ax
  173. mov ds, ax
  174. .loop:
  175. lodsb
  176. or al, al
  177. jz .done
  178. mov ah, 0x0E
  179. int 0x10
  180. jmp .loop
  181. .done:
  182. pop ax
  183. pop ds
  184. ret
  185. ; read_sectors: LBA in EAX, Count in CX, Buffer in ES:BX. Returns CF=1 on error.
  186. read_sectors:
  187. pusha
  188. .loop:
  189. push eax
  190. push cx
  191. mov [dap_lba], eax
  192. mov [dap_buf_offset], bx
  193. mov ax, es
  194. mov [dap_buf_segment], ax
  195. mov word [dap_count], 1
  196. mov ah, 0x42
  197. mov dl, [boot_drive]
  198. mov si, dap
  199. int 0x13
  200. jc .disk_error
  201. pop cx
  202. pop eax
  203. inc eax
  204. add bx, 512
  205. dec cx
  206. jnz .loop
  207. popa
  208. clc
  209. ret
  210. .disk_error:
  211. pop cx
  212. pop eax
  213. popa
  214. stc
  215. ret
  216. ; read_sectors_high: LBA in EAX, Count in ECX, Dest Physical in EDI. Returns CF=1 on error.
  217. read_sectors_high:
  218. pusha
  219. .loop_high:
  220. push eax
  221. push ecx
  222. ; Use temporary buffer at 0x0000:0x2000
  223. mov word [dap_lba], ax
  224. shr eax, 16
  225. mov word [dap_lba+2], ax
  226. mov word [dap_buf_offset], 0x2000
  227. mov word [dap_buf_segment], 0x0000
  228. mov word [dap_count], 1
  229. mov ah, 0x42
  230. mov dl, [boot_drive]
  231. mov si, dap
  232. push edi ; Preserve EDI against BIOS corruption
  233. int 0x13
  234. pop edi
  235. jc .disk_error_high
  236. push ds
  237. push es
  238. xor ax, ax
  239. mov ds, ax
  240. mov es, ax
  241. mov esi, 0x2000
  242. mov ecx, 128
  243. a32 rep movsd
  244. pop es
  245. pop ds
  246. pop ecx
  247. pop eax
  248. inc eax
  249. dec ecx
  250. jnz .loop_high
  251. popa
  252. clc
  253. ret
  254. .disk_error_high:
  255. pop ecx
  256. pop eax
  257. popa
  258. stc
  259. ret
  260. ; --- Data ---
  261. msg_stage2: db "Stage 2 Bootloader...", 13, 10, 0
  262. msg_unreal: db "Unreal Mode Activated...", 13, 10, 0
  263. msg_setup_ok: db "Setup loaded.", 13, 10, 0
  264. msg_kernel_ok: db "Kernel loaded.", 13, 10, 0
  265. msg_initrd_ok: db "Initrd loaded.", 13, 10, 0
  266. msg_err1: db "Error: Failed to read first kernel sector", 13, 10, 0
  267. msg_err2: db "Error: Failed to read kernel setup sectors", 13, 10, 0
  268. msg_err3: db "Error: Failed to read protected kernel", 13, 10, 0
  269. msg_err4: db "Error: Failed to read initramfs", 13, 10, 0
  270. boot_drive: db 0x80
  271. align 16
  272. global_vars:
  273. bzimage_lba: dd 8
  274. bzimage_size_sectors: dd 0
  275. initramfs_lba: dd 0
  276. initramfs_size_sectors: dd 0
  277. initramfs_size_bytes: dd 0
  278. animation_lba: dd 0
  279. animation_size_sectors: dd 0
  280. lfb_addr: dd 0
  281. screen_pitch: dd 0
  282. cmd_line: db "console=tty0 loglevel=0 logo.nologo init=/init root=/dev/sdb rw quiet vt.global_cursor_default=0", 0
  283. align 4
  284. dap:
  285. dap_size: db 0x10
  286. dap_zero: db 0
  287. dap_count: dw 1
  288. dap_buf_offset: dw 0
  289. dap_buf_segment: dw 0
  290. dap_lba: dq 0
  291. gdt_start:
  292. dq 0
  293. gdt_data:
  294. dw 0xFFFF
  295. dw 0x0000
  296. db 0x00
  297. db 0x92
  298. db 0xCF
  299. db 0x00
  300. gdt_desc:
  301. dw gdt_desc - gdt_start - 1
  302. dd gdt_start