ORG 0x7C00 BITS 16 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; SLRboot ; Bootloader for SingOS ; version 0.2.1.0-exp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; cli jmp long 0x0000:start start: mov ax, 0x1000 mov ss, ax mov sp, 0xb000 mov ax, 0 mov ds, ax mov es, ax mov [disk_identifier], dl sti mov si, 0x7c00 mov di, 0x600 mov cx, 0x100 rep movsw mov bx, relocated sub bx, 0x7600 ; Calculate the offset. push bx ret ; Return far ;jmp long 0:bx relocated: mov si, message ; Put address of the null-terminated string to output into 'si' call print ; Call our string-printing routine ; Check for more than one active partition that we can start from. xor bx, bx xor cx, cx mov ax, [partition_1.active_partition] cmp al, 0x80 jne check_p_2 mov bx, 0x01 ; Partion 1 active inc cx check_p_2: mov ax, [partition_2.active_partition] cmp al, 0x80 jne check_p_3 inc cx mov bx, 0x02 ; Partion 2 active check_p_3: mov ax, [partition_3.active_partition] cmp al, 0x80 jne check_p_4 inc cx mov bx, 0x03 ; Partion 3 active check_p_4: mov al, [partition_4.active_partition] cmp ax, 0x80 jne eval_active_partion_number inc cx mov bx, 0x04 ; Partion 4 active cli hlt eval_active_partion_number: cmp cx, 1 je boot_partition ; here goes wait call, for the user to enter debug mode. ; Wating for 2 seconds: mov ah, 0x86 ; code for waiting interupt call mov cx, 0x001e ; high count of microseconds mov dx, 0x8480 ; low count int 0x15 .busy_wait_for_key: xor ax, ax mov ah, 0x01 ; BIOS call to wait for key int 0x16 boot_partition: ; IMPORTANT bx, has to hold the value 1-4 for the partiotion that wanted to be booted. mov ax, partition_1 .loop: cmp bx, 1 je break add ax, 0x10 dec bx jmp .loop break: add ax, 8 ; This is the offset to fetch the LBA start adress of the partition record mov bx, ax xor ax, ax mov ax, [bx] ; first part of LBA mov WORD [DAPACK.lba_addr_dw_low], ax call dumpax add bx, 2 ; next part mov ax, [bx] mov WORD [DAPACK.lba_addr_dw_low + 1], ax call dumpax mov WORD [DAPACK.blkcnt], 0x01 mov WORD [DAPACK.db_addr_segment], 0x0000 mov WORD [DAPACK.db_addr_offset], 0x7c00 mov si, DAPACK ; address of "disk address packet" xor ax, ax mov ah, 0x42 ; READ mov dl, [disk_identifier] int 0x13 jc endcarrycheck ; An error ocurred when reading from disk. ; If no error then jump to volume boot record notcarry: jmp long 0x0:0x7c00 cli hlt ; If we did not suceed to read from disk endcarrycheck: mov si, error_str call print cli ; Clear the Interrupt Flag (disable external interrupts) hlt ; Halt the CPU (until the next external interrupt) debug_mode: mov si, welcome_debug call print cli ; Clear the Interrupt Flag (disable external interrupts) hlt ;Routine for printing a 'ax' as hex dumpax: pusha ; save registers mov bx, ax mov ah, 0xE ; Teletype output mov cx, 4 ; 4 nipples in a 16 bit word .loop: rol bx, 4 ; rotate to next nipple mov al, bl ; we copy to al because we need to mask only the low 4 bits and al, 1111b ; Do the masking add al, '0' ; convert to ASCII cmp al, '9' ; If we are greater than 9 ascii, we add 7 to make digit 10 be represented as 'A' jbe .skip ; -|- add al, 7 ; -|- .skip: ; -|- int 0x10 ; BIOS call 'output' loop .loop popa ; restore registers ret printCRLF: mov ah, 0xE mov al, 13 int 0x10 mov al, 10 int 0x10 ret ; Routine for outputting string in 'si' register to screen print: mov ah, 0xE ; Specify 'int 0x10' 'teletype output' function ; [AL = Character, BH = Page Number, BL = Colour (in graphics mode)] .printchar: lodsb ; Load byte at address SI into AL, and increment SI cmp al, 0 je .done ; If the character is zero (NUL), stop writing the string int 0x10 ; Otherwise, print the character via 'int 0x10' jmp .printchar ; Repeat for the next character .done: ret data: message db 'SLRboot for SingOS! v0.2.1.0-exp',13,10,0 enter_debug_mode db 'Press d to enter bootloader debug mode',13,10,0 welcome_debug db 'Debug mode v.0.0.1:',13,10,0 error_str db 'Error', 0 boot_this_partition: dw 0 disk_identifier db 0 DAPACK: .dap_Size: db 0x10 ; This is always 16 bytes (0x10) .rev_byte: db 0x0 ; reserved byte, should always be zero .blkcnt: dw 0x0 ; int 13 resets this to # of blocks actually read/written .db_addr_offset: dw 0x0 ; memory buffer destination address (0:7c00) .db_addr_segment: dw 0x0 ; in memory page zero .lba_addr_dw_low: dd 0x0 ; put the lba to read in this spot .lba_addr_dw_high: dd 0x0 ; more storage bytes only for big lba's ( > 4 bytes ) ; Pad to 510 bytes (boot sector size minus 2) with 0s, and finish with the two-byte standard boot signature times 446-($-$$) db 0 ; First partion entry partition_1: .active_partition db 0x80 .start_CHS db 0x00, 0x00, 0x11;0x20, 0x21, 0x00 .disk_type db 0x83 .end_CHS db 0x8C, 0x3D, 0x0F .start_LBA db 0x10, 0x00, 0x00, 0x00 .size db 0x00, 0xC8, 0x03, 0x00 partition_2: .active_partition db 0x00 .start_CHS db 0x8C, 0x3E, 0x0F .disk_type db 0x83 .end_CHS db 0xFF, 0xFF, 0xFF .start_LBA db 0x00, 0xD0, 0x03, 0x00 .size db 0x00, 0x28, 0x1C, 0x03 partition_3: .active_partition db 0x00 .start_CHS db 0x00, 0x00, 0x00 .disk_type db 0x00 .end_CHS db 0x00, 0x00, 0x00 .start_LBA db 0x00, 0x00, 0x00, 0x00 .size db 0x00, 0x00, 0x00, 0x00 partition_4: .active_partition db 0x00 .start_CHS db 0x00, 0x00, 0x00 .disk_type db 0x00 .end_CHS db 0x00, 0x00, 0x00 .start_LBA db 0x00, 0x00, 0x00, 0x00 .size db 0x00, 0x00, 0x00, 0x00 times 510-($-$$) db 0 dw 0xAA55 ; => 0x55 0xAA (little endian byte order) ; bootloder debug_mode goes here times 8192-($-$$) db 0