feat(bootload): load next stage and preload kernel from FAT
This commit is contained in:
		
							parent
							
								
									d94d9fb5bb
								
							
						
					
					
						commit
						7f88017ed7
					
				
					 10 changed files with 590 additions and 363 deletions
				
			
		
							
								
								
									
										6
									
								
								Makefile
									
										
									
									
									
								
							
							
						
						
									
										6
									
								
								Makefile
									
										
									
									
									
								
							|  | @ -32,7 +32,11 @@ stupid.tar.gz: $(SUBDIRS) | |||
| 
 | ||||
| .PHONY: floppy_boot.img | ||||
| floppy_boot.img: | ||||
| 	@ echo | ||||
| 	dd if=/dev/zero of=$@ bs=512 count=1440 | ||||
| 	mformat -C -f 1440 -i $@ | ||||
| 	dd if=boot/bootsector.bin of=$@ conv=notrunc | ||||
| 	mcopy -i $@ boot/stpdboot.sys ::/STPDBOOT.SYS | ||||
| 	mcopy -i $@ kernel/vmstupid ::/VMSTUPID.SYS | ||||
| 
 | ||||
| .PHONY: clean | ||||
| clean: $(SUBDIRS) | ||||
|  |  | |||
|  | @ -1,17 +1,24 @@ | |||
| AS = fasm | ||||
| RM = rm | ||||
| 
 | ||||
| TARGET = bootcode.bin | ||||
| TARGET = bootsector.bin stpdboot.sys | ||||
| 
 | ||||
| SRCS	= boot.asm \
 | ||||
| STAGE0_SRCS	= boot0.asm \
 | ||||
| 			const.inc \
 | ||||
| 			fat12.inc | ||||
| 
 | ||||
| STAGE1_SRCS	= boot1.asm \
 | ||||
| 			const.inc \
 | ||||
| 			a20.inc | ||||
| 
 | ||||
| .PHONY: all | ||||
| all: $(TARGET) | ||||
| 
 | ||||
| $(TARGET): $(SRCS) | ||||
| 	$(AS) boot.asm $@ | ||||
| bootsector.bin: $(STAGE0_SRCS) | ||||
| 	$(AS) boot0.asm $@ | ||||
| 
 | ||||
| stpdboot.sys: $(STAGE1_SRCS) | ||||
| 	$(AS) boot1.asm $@ | ||||
| 
 | ||||
| .PHONY: clean | ||||
| clean: | ||||
|  |  | |||
							
								
								
									
										2
									
								
								boot/README.org
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								boot/README.org
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,2 @@ | |||
| #+TITLE: StupidOS Bootloader | ||||
| 
 | ||||
							
								
								
									
										125
									
								
								boot/boot.asm
									
										
									
									
									
								
							
							
						
						
									
										125
									
								
								boot/boot.asm
									
										
									
									
									
								
							|  | @ -1,125 +0,0 @@ | |||
|         ORG 0x7C00 | ||||
|         USE16 | ||||
| 
 | ||||
|         jmp short _start | ||||
|         nop | ||||
| 
 | ||||
|         ; Boot Record | ||||
| OEM_identifier      db 'STUPID  ' | ||||
| bytes_per_sector    dw 512 | ||||
| sectors_per_cluster db 1 | ||||
| reserved_sectors    dw 1 | ||||
| FAT_count           db 2 | ||||
| root_dir_entries    dw 224 | ||||
| total_sectors       dw 2880 | ||||
| media_desc_type     db 0xF0 | ||||
| sectors_per_FAT     dw 9 | ||||
| sectors_per_track   dw 18 | ||||
| heads_per_cylinder  dw 2 | ||||
| hidden_sectors      dd 0 | ||||
| large_sector_count  dd 0 | ||||
| 
 | ||||
|         ; Extended Boot Record | ||||
| drive_number db 0x0 | ||||
| reserved     db 0x0 | ||||
| signature    db 0x29   ; 0x28 or 0x29 | ||||
| volume_id    dd 0xB00B135 ; hope mine will grow :'( | ||||
| volume_label db 'Stupid Boot' | ||||
| system_id    db 'FAT12  ' | ||||
| 
 | ||||
| 
 | ||||
| _start: | ||||
|         cli | ||||
|         cld | ||||
|         jmp 0x0:.canonicalize_cs | ||||
| 
 | ||||
| .canonicalize_cs: | ||||
|         xor ax, ax | ||||
|         mov ds, ax | ||||
|         mov ss, ax | ||||
|         mov es, ax | ||||
|         mov sp, 0x7c00 | ||||
| 
 | ||||
|         ; clear screen | ||||
|         mov al, 0x03 | ||||
|         mov ah, 0 | ||||
|         int 0x10 | ||||
| 
 | ||||
|         mov si, msg_hello | ||||
|         call bios_print | ||||
| 
 | ||||
|         ; reset floppy disk | ||||
| @@: | ||||
|         xor ah, ah | ||||
|         int 0x13 | ||||
|         jc @b | ||||
| 
 | ||||
|         mov si, msg_load_stage | ||||
|         call bios_print | ||||
| 
 | ||||
|         ; read sector into ES:BX (0100:0000) | ||||
|         mov ax, 0x100 ; 100 segment | ||||
|         mov es, ax    ; 0100:0000 (0000:1000) | ||||
|         xor bx, bx | ||||
| 
 | ||||
|         mov ah, 0x2 ; read | ||||
|         mov al, 0x1 ; one sector | ||||
|         mov ch, 0x0 ; cylinder 0 | ||||
|         mov cl, 0x2 ; second sector | ||||
|         mov dh, 0x0 ; head 0 | ||||
|         int 0x13 | ||||
|         jc .error | ||||
| 
 | ||||
|         jmp 0x0:0x1000 | ||||
| 
 | ||||
| .error: | ||||
|         mov si, msg_error_sector | ||||
|         call bios_print | ||||
| 
 | ||||
|         hlt | ||||
|         jmp $ | ||||
| 
 | ||||
| bios_print: | ||||
|         lodsb | ||||
|         or al, al | ||||
|         jz @f | ||||
|         mov ah, 0x0E | ||||
|         int 0x10 | ||||
|         jmp bios_print | ||||
| @@: | ||||
|         ret | ||||
| 
 | ||||
| msg_hello        db "StupidOS Bootloader", 0x0D, 0x0A, 0 | ||||
| msg_load_stage   db "Loading next stage", 0x0D, 0x0A, 0 | ||||
| msg_error_sector db "ERROR: Can't read sector", 0x0D, 0x0A, 0 | ||||
| 
 | ||||
|         rb 0x7C00+512-2-$ | ||||
|         db 0x55, 0xAA | ||||
| 
 | ||||
| ; ---------- stage 1 -------------- | ||||
| 
 | ||||
|         ORG 0x1000 | ||||
| stage2: | ||||
|         push cs | ||||
|         pop ds | ||||
| 
 | ||||
|         mov si, msg_stage2 | ||||
|         call bios_print | ||||
| 
 | ||||
|         call a20_enable | ||||
|         jc .error_a20 | ||||
| 
 | ||||
|         xchg bx, bx | ||||
| 
 | ||||
|         jmp .hang | ||||
| .error_a20: | ||||
|         mov si, msg_error_a20 | ||||
|         call bios_print | ||||
| .hang: | ||||
|         hlt | ||||
|         jmp $ | ||||
| 
 | ||||
|         INCLUDE 'a20.inc' | ||||
| 
 | ||||
| msg_stage2    db "StupidOS Bootloader (Stage 2)", 0x0D, 0x0A, 0 | ||||
| msg_error_a20 db "ERROR: can't enable a20 line", 0x0D, 0x0A, 0 | ||||
							
								
								
									
										120
									
								
								boot/boot0.asm
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										120
									
								
								boot/boot0.asm
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,120 @@ | |||
|         INCLUDE 'const.inc' | ||||
| 
 | ||||
|         ORG STAGE0_BASE | ||||
|         USE16 | ||||
| 
 | ||||
|         jmp short _start | ||||
|         nop | ||||
| 
 | ||||
|         ; Boot Record | ||||
| OEM_identifier      db 'STUPID  ' | ||||
| bytes_per_sector    dw 512 | ||||
| sectors_per_cluster db 1 | ||||
| reserved_sectors    dw 1 | ||||
| FAT_count           db 2 | ||||
| root_dir_entries    dw 224 | ||||
| total_sectors       dw 2880 | ||||
| media_desc_type     db 0xF0 | ||||
| sectors_per_FAT     dw 9 | ||||
| sectors_per_track   dw 18 | ||||
| heads_per_cylinder  dw 2 | ||||
| hidden_sectors      dd 0 | ||||
| large_sector_count  dd 0 | ||||
| 
 | ||||
|         ; Extended Boot Record | ||||
| drive_number db 0x0 | ||||
| reserved     db 0x0 | ||||
| signature    db 0x29   ; 0x28 or 0x29 | ||||
| volume_id    dd 0xB00B135 ; hope mine will grow :'( | ||||
| volume_label db 'Stupid Boot' | ||||
| system_id    db 'FAT12  ' | ||||
| 
 | ||||
| 
 | ||||
| _start: | ||||
|         cli | ||||
|         cld | ||||
|         jmp 0x0:.canonicalize_cs | ||||
| 
 | ||||
| .canonicalize_cs: | ||||
|         xor ax, ax | ||||
|         mov ds, ax | ||||
|         mov ss, ax | ||||
|         mov es, ax | ||||
|         mov sp, 0x7c00 | ||||
| 
 | ||||
|         mov [drive_number], dl | ||||
| 
 | ||||
|         ; reset floppy disk | ||||
| @@: | ||||
|         mov dl, [drive_number] | ||||
|         xor ah, ah | ||||
|         int 0x13 | ||||
|         jc @b | ||||
| 
 | ||||
|         call fat_load_root | ||||
| 
 | ||||
|         ; search in root directory | ||||
| 
 | ||||
|         mov si, kernel_file | ||||
|         call fat_search_root | ||||
|         jc .error_not_found | ||||
|         mov [kernel_start], ax | ||||
| 
 | ||||
|         mov si, stage1_file | ||||
|         call fat_search_root | ||||
|         jc .error_not_found | ||||
|         mov [stage1_start], ax | ||||
| 
 | ||||
|         ; load fat | ||||
|         xor ax, ax | ||||
|         mov al, [FAT_count] | ||||
|         mul word [sectors_per_FAT] | ||||
|         mov cx, ax | ||||
|         mov ax, [reserved_sectors] | ||||
| 
 | ||||
|         xor bx, bx | ||||
| 
 | ||||
|         call disk_read_sectors | ||||
| 
 | ||||
|         ; preload kernel | ||||
|         mov ax, KERNEL_PRELOAD/0x10 | ||||
|         mov es, ax | ||||
|         mov ax, [kernel_start] | ||||
|         xor bx, bx | ||||
|         call fat_load_binary | ||||
| 
 | ||||
|         ; load stage 2 | ||||
|         mov ax, STAGE1_BASE/0x10 | ||||
|         mov es, ax | ||||
|         mov ax, [stage1_start] | ||||
|         xor bx, bx | ||||
|         call fat_load_binary | ||||
| 
 | ||||
|         jmp 0x0:STAGE1_BASE | ||||
| 
 | ||||
| .error_not_found: | ||||
|         push si | ||||
|         mov si, msg_error | ||||
|         call bios_print | ||||
|         pop si | ||||
|         call bios_print | ||||
|         mov si, msg_not_found | ||||
|         call bios_print | ||||
|         hlt | ||||
|         jmp $ | ||||
| 
 | ||||
|         INCLUDE "utils.inc" | ||||
|         INCLUDE "fat12.inc" | ||||
| 
 | ||||
| msg_error                  db "ERROR: ", 0 | ||||
| msg_not_found              db " not found", CR, LF, 0 | ||||
| 
 | ||||
| kernel_file db "VMSTUPIDSYS", 0 | ||||
| stage1_file db "STPDBOOTSYS", 0 | ||||
| 
 | ||||
| kernel_start dw 0x0 | ||||
| stage1_start dw 0x0 | ||||
| 
 | ||||
| 
 | ||||
|         rb 0x7C00+512-2-$ | ||||
|         db 0x55, 0xAA | ||||
							
								
								
									
										28
									
								
								boot/boot1.asm
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								boot/boot1.asm
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,28 @@ | |||
|         INCLUDE 'const.inc' | ||||
| 
 | ||||
|         ORG STAGE1_BASE | ||||
|         USE16 | ||||
| 
 | ||||
| stage2: | ||||
|         push cs | ||||
|         pop ds | ||||
| 
 | ||||
|         mov si, msg_stage2 | ||||
|         call bios_print | ||||
| 
 | ||||
|         call a20_enable | ||||
|         jc .error_a20 | ||||
| 
 | ||||
|         jmp .hang | ||||
| .error_a20: | ||||
|         mov si, msg_error_a20 | ||||
|         call bios_print | ||||
| .hang: | ||||
|         hlt | ||||
|         jmp $ | ||||
| 
 | ||||
|         INCLUDE 'a20.inc' | ||||
|         INCLUDE 'utils.inc' | ||||
| 
 | ||||
| msg_stage2    db "StupidOS Bootloader (Stage 1)", 0x0D, 0x0A, 0 | ||||
| msg_error_a20 db "ERROR: can't enable a20 line", 0x0D, 0x0A, 0 | ||||
|  | @ -1,4 +1,5 @@ | |||
| 
 | ||||
| CR   = 0x0D | ||||
| LF   = 0x0A | ||||
| ; -------- Address ---------- | ||||
| STAGE0_BASE    = 0x7C00 | ||||
| STAGE1_BASE    = 0x1000 | ||||
|  |  | |||
							
								
								
									
										181
									
								
								boot/fat12.inc
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										181
									
								
								boot/fat12.inc
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,181 @@ | |||
|         ATTR_READ_ONLY = 0x01 | ||||
|         ATTR_HIDDEN    = 0x02 | ||||
|         ATTR_SYSTEM    = 0x04 | ||||
|         ATTR_VOLUME_ID = 0x08 | ||||
|         ATTR_DIRECTORY = 0x10 | ||||
|         ATTR_ARCHIVE   = 0x20 | ||||
| 
 | ||||
|         struc fat_entry | ||||
|         { | ||||
|                 .name          db 8 dup ? | ||||
|                 .ext           db 3 dup ? | ||||
|                 .attrs         db ? | ||||
|                 .reserved      dw ? | ||||
|                 .creation_time dw ? | ||||
|                 .creation_date dw ? | ||||
|                 .access_date   dw ? | ||||
|                 .reserved2     dw ? | ||||
|                 .mod_time      dw ? | ||||
|                 .mod_date      dw ? | ||||
|                 .start         dw ? | ||||
|                 .size          dd ? | ||||
|         } | ||||
| 
 | ||||
|         virtual at di | ||||
| 
 | ||||
|                 fat_entry fat_entry | ||||
|         end virtual | ||||
| 
 | ||||
| 
 | ||||
|         ; CHS to LBA | ||||
|         ; LBA = (C * HPC + H) * SPT + (S - 1) | ||||
| 
 | ||||
|         ;;; Read sectors from disk to buffer | ||||
|         ;;; | ||||
|         ;;; @param AX LBA starting sector | ||||
|         ;;; @param CX sector count | ||||
|         ;;; @param ES:BX buffer | ||||
|         ;;; | ||||
| disk_read_sectors: | ||||
|         ; https://en.wikipedia.org/wiki/Logical_block_addressing | ||||
|         ; convert LBA to CHS | ||||
|         ; HPC = Head per Cluster | ||||
|         ; SPT = Sector per Track | ||||
| 
 | ||||
|         ; S = (LBA % SPT) + 1 | ||||
|         push ax | ||||
|         push bx | ||||
|         push cx | ||||
|         xor dx, dx | ||||
|         div word [sectors_per_track] | ||||
|         inc dx | ||||
|         mov [S], dx | ||||
| 
 | ||||
|         ; H = (LBA / SPT) % HPC | ||||
|         ; C =  LBA  / (HPC * SPT) | ||||
|         xor dx, dx | ||||
|         div word [heads_per_cylinder] | ||||
|         mov [C], ax | ||||
|         mov [H], dx | ||||
| 
 | ||||
|         ; read sectors | ||||
|         mov ah, 0x2 | ||||
|         mov al, 0x1 | ||||
|         mov ch, byte [C] | ||||
|         mov cl, byte [S] | ||||
|         mov dh, byte [H] | ||||
|         mov dl, [drive_number] | ||||
| 
 | ||||
|         int 0x13 | ||||
|         jc @f | ||||
|         pop cx | ||||
|         pop bx | ||||
|         pop ax | ||||
|         add bx, word [bytes_per_sector] | ||||
|         inc ax | ||||
|         loop disk_read_sectors | ||||
|         ret | ||||
| @@: | ||||
|         mov si, msg_error_sector | ||||
|         call bios_print | ||||
|         ret | ||||
| 
 | ||||
| C dw 0x00 | ||||
| H dw 0x00 | ||||
| S dw 0x00 | ||||
| 
 | ||||
| fat_load_root: | ||||
|         mov ax, DISK_BUFFER/0x10 | ||||
|         mov es, ax | ||||
| 
 | ||||
|         ; load root directory | ||||
|         mov ax, [sectors_per_FAT] | ||||
|         xor cx, cx | ||||
|         mov cl, [FAT_count] | ||||
|         mul cx | ||||
|         add ax, [reserved_sectors] | ||||
|         push ax | ||||
| 
 | ||||
|         mov bx, [bytes_per_sector] | ||||
|         mov cl, 0x5 | ||||
|         shr bx, cl | ||||
|         mov ax, [root_dir_entries] | ||||
|         xor dx, dx | ||||
|         div bx | ||||
|         mov cx, ax | ||||
|         pop ax | ||||
| 
 | ||||
|         mov [data_start], ax | ||||
|         add [data_start], cx | ||||
| 
 | ||||
|         xor bx, bx | ||||
| 
 | ||||
|         call disk_read_sectors | ||||
| 
 | ||||
|         ret | ||||
| 
 | ||||
|         ;; @param SI filename to search | ||||
| fat_search_root: | ||||
|         mov cx, [root_dir_entries] | ||||
|         mov di, 0x0 | ||||
| @@: | ||||
|         push si | ||||
|         push cx | ||||
|         mov cx, 0xB ; name(8) + ext(3) | ||||
|         push di | ||||
|         rep cmpsb | ||||
|         pop di | ||||
|         pop cx | ||||
|         pop si | ||||
|         je .file_found | ||||
|         add di, 0x20 | ||||
|         loop @b | ||||
|         ; set carry if not found | ||||
|         stc | ||||
|         ret | ||||
| .file_found: | ||||
|         mov ax, [es:fat_entry.start] | ||||
|         clc | ||||
|         ret | ||||
| 
 | ||||
|         ;;; @param AX cluster | ||||
|         ;;; @param ES:BX buffer | ||||
| fat_load_binary: | ||||
|         push ax | ||||
|         sub ax, 0x2 | ||||
|         xor cx, cx | ||||
|         mov cl, [sectors_per_cluster] | ||||
|         mul cx | ||||
| 
 | ||||
|         add ax, [data_start] | ||||
|         xor cx, cx | ||||
|         mov cl, [sectors_per_cluster] | ||||
|         call disk_read_sectors | ||||
| 
 | ||||
|         pop ax | ||||
|         mov cx, ax | ||||
|         mov dx, ax | ||||
|         shr dx, 0x1 | ||||
|         add cx, dx | ||||
|         push bx | ||||
|         mov bx, DISK_BUFFER | ||||
|         add bx, cx | ||||
|         mov dx, [bx] | ||||
|         pop bx | ||||
| 
 | ||||
|         test ax, 0x1 | ||||
|         jnz .odd_cluster | ||||
| .even_cluster: | ||||
|         and dx, 0xFFF | ||||
|         jmp .end | ||||
| .odd_cluster: | ||||
|         shr dx, 0x4 | ||||
| .end: | ||||
|         mov ax, dx | ||||
|         cmp dx, 0xFF0 | ||||
|         jb fat_load_binary | ||||
|         ret | ||||
| 
 | ||||
| 
 | ||||
| msg_error_sector           db "ERROR: reading sector", CR, LF, 0 | ||||
| data_start dw 0x0 | ||||
							
								
								
									
										9
									
								
								boot/utils.inc
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								boot/utils.inc
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,9 @@ | |||
| bios_print: | ||||
|         lodsb | ||||
|         or al, al | ||||
|         jz @f | ||||
|         mov ah, 0x0E | ||||
|         int 0x10 | ||||
|         jmp bios_print | ||||
| @@: | ||||
|         ret | ||||
		Loading…
	
	Add table
		
		Reference in a new issue