; ****************************************************************************
; TRDOS386.ASM (TRDOS 386 Kernel) - v2.0.2 - trhdboot.s
; ----------------------------------------------------------------------------
; Last Update: 12/09/2020
; ----------------------------------------------------------------------------
; Beginning: 07/09/2020
; ----------------------------------------------------------------------------
; Assembler: NASM version 2.15 (trhdboot.s)
; ----------------------------------------------------------------------------
; Turkish Rational DOS
; Operating System Project v2.0 by ERDOGAN TAN (Beginning: 04/01/2016)
;
; Derived from TRDOS Operating System v2.0 (80386) source code by Erdogan Tan
; trfdboot.s (06/09/2020)
; ****************************************************************************
; Derived from rdhdboot.s (19/05/2018), Retro DOS v2 Hard Disk BS Utility

; TRHDBOOT.ASM
; Turkish Rational DOS
; Disk Operation System v2.0 Project
; Hard Disk (FAT12, FAT16, FAT32 fs) Boot Code
;
; Copyright (C) 2020  Erdogan TAN 
; ****************************************************************************
; assembling: nasm trhdboot.s -l trhdboot.lst -o TRHDBOOT.COM -Z error.txt

; previous version: trhdboot.s v1 -- 18/04/2000

; ----------------------------------------------------------------------------
; equations
; ----------------------------------------------------------------------------

; boot sector parameters

bsOemName	equ 3	; ('MSWIN4.1') --> 'TRDOS386'       
bsBytesPerSec	equ 11	; 512 (word)
bsSecPerClust	equ 13
bsResSectors	equ 14
bsFATs		equ 16
bsRootDirEnts	equ 17
bsSectors	equ 19
bsMedia		equ 21	; 0F8h
bsFATsecs	equ 22
bsSecPerTrack	equ 24
bsHeads		equ 26
bsHidden1	equ 28
bsHidden2	equ 30
bsHugeSectors	equ 32
; FAT 16 bs & FAT 12 bs
bsDriveNumber	equ 36	; 80h
bsReserved1	equ 37
bsBpbSignature	equ 38	; 29h (byte)                 
bsVolumeID	equ 39
bsVolumeLabel	equ 43
bsFileSysType	equ 54	; 'FAT16   '  (8 bytes)
; FAT 32 bs
BPB_FATSz32	equ 36
BPB_ExtFlags	equ 40
BPB_FSVer	equ 42
BPB_RootClus	equ 44
BPB_FSInfo	equ 48
BPB_BkBootSec	equ 50
BPB_Reserved	equ 52
BS_DrvNum	equ 64	; 80h
BS_Reserved1	equ 65
BS_BootSig	equ 66	; 29h (byte)
BS_VolID	equ 67
BS_VolLab	equ 71
BS_FilSysType	equ 82	; 'FAT32   '  (8 bytes)         

; Masterboot / Partition Table at Beginning+1BEh
ptBootable      equ 0
ptBeginHead     equ 1
ptBeginSector   equ 2
ptBeginCylinder equ 3
ptFileSystemID	equ 4
ptEndHead       equ 5
ptEndSector     equ 6
ptEndCylinder   equ 7
ptStartSector   equ 8
ptSectors       equ 12

partition_table equ 1BEh    

; ----------------------------------------------------------------------------
; code
; ----------------------------------------------------------------------------

[BITS 16]
[ORG 100h]

	cli
	cld
	push	cs
	pop	ss
	mov	sp, 0FFFEh
	sti

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; see if drive specified
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

	mov	si, 80h			; PSP command tail
	mov	cl, [si]
	or	cl, cl                               
	jz	short T_9		; jump if zero
T_1:
	inc	si

	mov	al, [si]
	cmp	al, ' '			; is it SPACE ?
	jne	short T_2

	dec	cl                                  
	jnz	short T_1                  
	jmp	short T_9
T_2:
	inc	si
	cmp	byte [si], ':'
	je	short T_3
	cmp	byte [si], ' '
	jna	short T_3

	cmp	al, 'h'
	jne	short T_9  	
	cmp	byte [si], 'd'
	jne	short T_9
	inc	si
	mov	al, [si]
	cmp	al, '0'
	je	short T_8
	jb	short T_9
	cmp	al, '3'
	jna	short T_8
	jmp	short T_9
T_3:
	cmp	al, 'C'
	jb	short T_9
	je	short T_6
	;cmp	al, 'Z'			; A - Z
	;jna	short T_6                   
	cmp	al, 'D'
	jna	short T_6
	cmp	al, 'Z'
	jna	short T_9
T_4:	
	cmp	al, 'c'			; a - z 
	jb	short T_9                  
	je	short T_5
	;cmp	al, 'z'                           
	;ja	short T_9     
	cmp	al, 'd'
	ja	short T_9
T_5:
	sub	al, 'a'-'A'		; to upper case

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; get drive code
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

T_6:
	sub	al, 'C'-'0'
T_7:
	mov	[TrDOS_Drive], al	; '0' .. '4'
	jmp	short T_10
T_8:
	inc	si
	cmp	byte [si], ' '
	jna	short T_7		

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; Write message
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

T_9:
	mov	si, TrDOS_Welcome
	call	print_msg
	;cmp	cl, 0
        ;ja	short T_35
	jmp	T_35

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; get drive parameters
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

T_10:
	mov	ah, 08h
	;mov	dl, [TrDOS_Drive]	; drive
	mov	dl, al
	add	dl, 80h -'0'		; make it 80h based 
	mov	[drv], dl
	int	13h			; return disk parameters

	push	cs
	pop	es			; restore es

	or	ah, ah
	jnz	short T_12		; error
	
	mov	al, cl
	and	al, 63
	mov	[sectors], al
	shr	cl, 6 
	xchg	ch, cl
	inc	cx
	mov	[cylinders], cx
	inc	dh
	mov	[heads], dh
	mul	dh
		; ax = heads * spt
	mul	cx ; * cylinders
		; dx:ax = chs limit
	mov	[CHS_limit], ax
	mov	[CHS_limit+2], dx

	; check for (valid) primary dos partition

	;mov	byte [RetryCount], 4

	;mov	ax, 0201h		; read disk
	mov	bx, MBR			; location of masterboot code

	mov	cx, 1			; cylinder = 0
					; sector = 1
	mov	dh, 0			; head = 0
	;mov	dl, [TrDOS_Drive]	; drive 
	;add	dl, 80h -'0'		; make it 80h based 
	mov	dl, [drv]
T_11:
	mov	ax, 0201h
	int	13h
	;jc	short T_12	
	jnc	short T_13		; read masterboot sector, OK

	dec	byte [RetryCount]
	jnz	short T_11
T_12:
	mov	byte [zbyte], 0
	call	T_37			; write error message
	jmp	T_35 			; terminate

T_13:
	cmp	word [MBR+510], 0AA55h 
        jne	short T_12

	mov	si, MBR+(partition_table+ptFileSystemID)
T_14:
	call	validate_primary_dos_partition
	jnc	short T_15	
 
	add	si, 16
	cmp	si, MBR+partition_table+ptFileSystemID+64
	jb	short T_14

	mov	si, TRDOS_fatp_notfound
	call	print_msg
	jmp	T_35
	
T_15:
	; valid primary dos partition
	; al = FAT type (1,2,3)
	; ah = partition type

	mov	byte [fattype], al
	cmp	al, 2
	je	short T_17 ; FAT16 BS (default offset addr)
	jb	short T_16
	; set TRDOS 386 BS pointer for FAT32 BS
	mov	word [trdos386bs], TRDOS_FAT32_hd_bs
	; set FS type string
	mov	word [fattype_str],'32'	; 'FAT32'
	; ok.. read boot sector
	jmp	short T_17
T_16:
	; set TRDOS 386 BS pointer for FAT12 BS
	mov	word [trdos386bs], TRDOS_FAT12_hd_bs
	mov	byte [fattype_str+1],'2' ; 'FAT12'
T_17:	
	mov	byte [RetryCount], 5

	add	si, ptStartSector-ptFileSystemID
	mov	ax, [si]
	mov	dx, [si+2]
	mov	[dosp_start], ax
	mov	[dosp_start+2], dx
	add	si, ptSectors-ptStartSector
	mov	cx, [si]
	mov	bx, [si+2]
	mov	[dosp_size], cx
	mov	[dosp_size+2], bx	
	add	cx, ax
	adc	bx, dx
	jc	short T_12

	cmp	bx, [CHS_limit+2]	
	mov	bx, bootsector
	ja	short T_20 ; LBA read/write
	jb	short T_18
	cmp	cx, [CHS_limit]
	ja	short T_20
T_18:
	; CHS read

	sub	si, ptSectors-ptBeginHead

	mov	dh, [si] ; head
	inc	si
	mov	cx, [si] ; sector
		; cl = sector, ch = cylinder
	;mov	bx, bootsector
	mov	dl, [drv]

	mov	[_dh], dh
	mov	[_cx], cx
T_19:
	mov	ax, 0201h ; read one sector
	int	13h
	jnc	short T_22 ; OK
	dec	byte [RetryCount]
	jnz	short T_19
	jmp	T_12
T_20:
	; LBA read
	mov	byte [lba], 1
	;mov	ax, [dosp_start]
	;mov	dx, [dosp_start+2]
T_21:
	;pusha				; db 60h
	db	60h
	;push 	0                       ; db 6Ah, 00h
	db	6Ah, 0
	;push	0                       ; db 6Ah, 00h
	db	6Ah, 0
	push    dx
	push    ax
	push    es
	push    bx
	;push	1			; db 6Ah, 01h
	db	6Ah, 01h                     
	;push	10h                     ; db 6Ah, 10h
	db	6Ah, 10h

	mov     dl, [drv]
	mov     ah, 42h
	mov     si, sp
	int     13h

	;popa
	db	61h
	;popa
	db	61h
	jnc     short T_22
                
        dec	byte [RetryCount]
	jz	T_12

	mov	ax, [dosp_start]
	mov	dx, [dosp_start+2]
	jmp	T_21	 

T_22:
	cmp	word [bootsector+510], 0AA55h
	jne	short T_23

	cmp	word [bootsector+bsBytesPerSec], 512
	jne	short T_23

	mov	byte [bootsector+bsMedia], 0F8h
	jne	short T_23

	cmp	byte [fattype], 2
	ja	short T_24

	cmp	byte [bootsector+bsBpbSignature], 29h
	jne	short T_23
	cmp	dword [bootsector+bsFileSysType], 'FAT1'
	jne	short T_23

	mov	cx, 54-11 ; byte count to be copied 
	
	mov	al, [bootsector+bsFileSysType+4]
	cmp	al, '6'
	je	short T_25

	cmp	al, '2'
	je	short T_25
T_23:
	mov	si, TrDOS_invalid_bootsector
	call	print_msg
	jmp	T_35
T_24:
	cmp	byte [bootsector+BS_BootSig], 29h
	jne	short T_23
	cmp	dword [bootsector+BS_FilSysType], 'FAT3'
	jne	short T_23
	cmp	byte [bootsector+BS_FilSysType+4], '2'
	jne	short T_23

	mov	cx, 82-11 ; byte count to be copied 
T_25:
	mov	si, TrDOS_Do_you_want
	call	print_msg
T_26:
	;xor	ax, ax
	;int	16h			; wait for keyboard command
	;cmp	al, 'y'
	;je	short T_27		; retry
	;cmp	al, 'Y'
	;je	short T_27
	;cmp	al, 'n'
	;je	short T_35 		; exit
	;cmp	al, 'N'
	;je	short T_35
	;cmp	al, 'C'-40h
	;je	short T_35                   
	;cmp	al, 27
	;je	short T_35
	;jmp	short T_26

	call	get_answer
	cmp	al, 'Y'
	je	short T_27

	mov	si, _no_str
	call	print_msg

	jmp	T_35
T_27:
	mov	si, _yes_str
	call	print_msg

	;mov	si, TrDOS_CRLF
	;call	print_msg

	; set 'TRDOS386' as OEM name
	mov	di, [trdos386bs]
	add	di, bsOemName
	mov	ax, 'TR'
	stosw
	mov	ax, 'DO'
	stosw
	mov	ax, 'S3'
	stosw
	mov	ax, '86'
	stosw
	
	; DI points to trdos386bs+bsBytesPerSec
	mov	si, bootsector+bsBytesPerSec
	
	rep	movsb

	mov	si, TrDOS_PressKeyWhenReady
	call	print_msg
T_28:
	xor	ax, ax
	int	16h			; wait for keyboard command
	cmp	al, 'M'-40h		; Enter (OK) key
	je	short T_29		; write
	cmp	al, 'C'-40h
	je	short T_35		; no write (exit)
	cmp	al, 27
	je	short T_35
	jmp	short T_28

T_29:
	mov	si, TrDOS_CRLF
	call	print_msg
T_30:
	;xor	ax, ax
	;int	1Ah			; get time of day
	
	;mov	si, volume_id
	
	;mov	[si], dx
	;mov	[si+2], cx		; set unique volume ID
	
	;mov	ah, 02h			; Return Current Time
	;int	1Ah
	;xchg	ch, cl
	;xchg	dh, dl
	
	;add	cx, dx  
	;add	[si+2], cx
		
	;mov	ah, 04h			; Return Current Date
	;int	1Ah
	;xchg	ch, cl
	;xchg	dh, dl
	
	;add	cx, dx  
	;add	[si+2], cx

	;mov	ax, [vol_id]
	;mov	dx, [vol_id+2]

	mov	bx, [trdos386bs]	; location of boot code
	; es: bx = boot sector buffer address
	
	;mov	si, bx	
	;add	si, bsVolumeID

	;cmp	byte [fattype], 3
	;jne	short T_31

	;add	si, BS_VolID-bsVolumeID
;T_31:
	;mov	[si], ax
	;mov	[si+2], dx

	cmp	byte [lba], 1
	jnb	short T_32 ; LBA write 		

	mov	dl, [drv] ; drive
	mov	dh, [_dh] ; head
	mov	cx, [_cx] ; cl = sector, ch = cylinder (low 8 bits)
T_31:
	mov	ax, 0301h		; write to disk
	; es: bx = boot sector buffer address

	int	13h
	jnc	short T_34		; ok

	; error

	dec	byte [RetryCount]
	jnz	short T_31
	call	T_37
	jmp	short T_36

T_32:
	mov	ax, [dosp_start]
	mov	dx, [dosp_start+2]
T_33:
	;pusha				; db 60h
	db	60h
	;push 	0                       ; db 6Ah, 00h
	db	6Ah, 0
	;push	0                       ; db 6Ah, 00h
	db	6Ah, 0
	push    dx
	push    ax
	push    es
	push    bx
	;push	1			; db 6Ah, 01h
	db	6Ah, 01h                     
	;push	10h                     ; db 6Ah, 10h
	db	6Ah, 10h

	mov     dl, [drv]
	mov     ah, 43h ; LBA write
	xor	al, al ; verify off 
	mov     si, sp
	int     13h

	;popa
	db	61h
	;popa
	db	61h
	jnc     short T_34

	dec	byte [RetryCount]
	jnz	short T_32
	call	T_37
	jmp	short T_36

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; success. try again ?
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

T_34:
	cmp	byte [fattype], 3 ; FAT32
	je	short T_40		

	mov	si, TrDOS_disk_WrittenSuccesfully
	call	print_msg
T_35:
	mov	si, TrDOS_CRLF
	call	print_msg
	mov	ax, 4C00h		; terminate
	int	21h
T_36:
	;xor	ax, ax
	;int	16h			; wait for keyboard command
	;cmp	al, 'y'
	;je	short TX_15		; retry
	;cmp	al, 'Y'
	;je	short TX_15
	;cmp	al, 'n'
	;je	short T_35 		; exit
	;cmp	al, 'N'
	;je	short T_35
	;cmp	al, 'C'-40h
	;je	short T_35                   
	;cmp	al, 27
	;je	short T_35
	;jmp	short T_36

	call	get_answer
	cmp	al, 'Y'
	je	short T_29
	jmp	short T_35

T_37:
	mov	si, TrDOS_disk_NotReadyOrError
	;;call	print_msg
	;;jmp	short T_36
	;jmp	short print_msg

print_msg:
T_38:
	lodsb				; Load byte at DS:SI to AL
	and	al, al            
	jz	short T_39       
	mov	ah, 0Eh			
	mov	bx, 07h             
	int	10h			; BIOS Service func ( ah ) = 0Eh
					; Write char as TTY
					; AL-char BH-page BL-color
	jmp     short T_38          
T_39:
_NO_:
	retn
		 
get_answer:
	xor	ax, ax
	int	16h			; wait for keyboard command
	cmp	al, 'y'
	je	short _yes		; retry
	cmp	al, 'Y'
	je	short _YES_
	cmp	al, 'n'
	je	short _NO_ 		; exit
	cmp	al, 'N'
	je	short _NO_
	cmp	al, 'C'-40h
	je	short _NO_                 
	cmp	al, 27
	je	short _NO_
	jmp	short get_answer
_yes:
	mov	al, 'Y'
_YES_:
	retn

T_40:
	; write 2nd sector of FAT32 bs code (1024 bytes)

	mov	byte [RetryCount], 4
	mov	byte [fattype], 0

	mov	bx, TRDOS_FAT32_hd_bs+512

	cmp	byte [lba], 0
	jna	short T_41

	mov	ax, [dosp_start]
	mov	dx, [dosp_start+2]
	add	ax, 2 ; sector 2 in the partition (after FSINFO sector)
	adc	dx, 0
	jmp	T_33
T_41:
	; convert FAT32 bootsector+2 address to CHS
	;mov	dl, [drv] ; drive
	;mov	dh, [_dh] ; head
	;mov	cx, [_cx] ; cl = sector, ch = cylinder (low 8 bits)	
	mov	ax, cx
	and	al, 63
	cmp	al, [sectors]
	jnb	short T_43
	inc	al
 	cmp	al, [sectors]
	jnb	short T_42
	inc	cl
	inc	cl
	jmp	T_31
T_42:
	mov	al, 1	; sector 1
	jmp	short T_44
T_43:
	mov	al, 2	; sector 2
T_44:
	inc	dh
	cmp	dh, [heads]
	jb	T_31
	sub	dh, dh  ; head 0
	shr	cl, 6
	xchg	ch, cl
	inc	cx	; next cylinder
	;and	cx, 1023
	;cmp	cx, [cylinders]
	;jnb	short T_37
	xchg	cl, ch
	shl	cl, 6
	or	cl, al	
	jmp	T_31

validate_primary_dos_partition:
	
	; INPUT:
	;   si = partition table entry offset + file system ID 
	; OUTPUT:
	;   cf = 0 -> ah = primary DOS partition ID
	;			 (01h,04h,06h,0Bh,0Ch,0Eh)		
	;	      al = FAT type 
	;			1 = FAT12
	;			2 = FAT16
	;			3 = FAT32
	;
	;   cf = 1 -> not a primary DOS partition	

	sub	al, al ; mov al, 0

	mov 	ah, [si]

	cmp	ah, 01h	; FAT12 partition
	jb	short V_5 ; 0
	je	short V_3
V_0:
	inc	al  ; mov al, 1

	cmp 	ah, 06h ; FAT16 CHS partition (>=32MB)
	ja	short V_2
	je	short V_3

	cmp	ah, 04h	; FAT16 CHS partition (< 32MB)
	je	short V_3
V_1:
	stc
	retn
V_2:
	inc	al ; mov al, 2

	cmp	ah, 0Ch	; FAT32 LBA partition
	je	short V_3
	ja	short V_4

	cmp	ah, 0Bh	; FAT32 CHS partition 
	jb	short V_5
V_3:
	inc	al ; 0->1, 1->2, 2->3
	retn 
V_4:
	cmp	ah, 0Eh	; FAT16 LBA partition
	jne	short V_1
	;mov	al, 2
V_5:
	retn

; ----------------------------------------------------------------------------
; initialized data
; ----------------------------------------------------------------------------

align 2

trdos386bs:
	dw TRDOS_FAT16_hd_bs
	dw 0

;volume_id:
;	dd 0

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  FAT boot sector code
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

TRDOS_FAT32_hd_bs:
	incbin	'FAT32_BS.BIN'
TRDOS_FAT16_hd_bs: 
	incbin	'FAT16_BS.BIN'
TRDOS_FAT12_hd_bs: 
	incbin	'FAT12_BS.BIN'

;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  messages
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

drv:	db 0

;sectors: db 0
;heads	: db 0
;cylinders: dw 0

_dh:	db 0
_cx:	dw 0

TrDOS_Welcome:
	db 0Dh, 0Ah
	db 'TR-DOS 386 v2 Hard Disk Boot Sector Update Utility '
	db 0Dh, 0Ah
	db '(c) Erdogan TAN - 2020'
	db 0Dh,0Ah
	db 0Dh,0Ah
	db 'Usage: trhdboot <drive> '
	db 0Dh,0Ah, 0Dh, 0Ah
	db 'Drive names: '
	db 0Dh, 0Ah
	db ' hd0 or C: ..for primary dos partition on 1st disk '
	db 0Dh, 0Ah
	db ' hd1 or D: ..for primary dos partition on 2nd disk '
	db 0Dh, 0Ah
	db ' hd2       ..for primary dos partition on 3rd disk '
	db 0Dh, 0Ah
	db ' hd3       ..for primary dos partition on 4th disk '
	db 0Dh, 0Ah, 0

	db '12/09/2020'
	db 0

TrDOS_Do_you_want:
	db 0Dh, 0Ah
	db "WARNING ! ", 0Dh, 0Ah 
	db "(If you say 'Yes', MSDOS or WINDOWS will not be bootable on this disk !) "
	db 0Dh, 0Ah, 0Dh, 0Ah
	db "Do you want to update boot sector to TRDOS 386 v2 format ? (Y/N) "
	db 0

_yes_str:
	db 'YES '
	db 0Dh, 0Ah, 0
_no_str:
	db 'NO '
	db 0Dh, 0Ah, 0

TrDOS_PressKeyWhenReady:
	db 0Dh, 0Ah
	db 'Press Enter to write boot sector on disk hd'
TrDOS_Drive:
	db '?. ', 0

TrDOS_disk_WrittenSuccesfully:
	db 0Dh, 0Ah
	db 'Boot sector successfully updated to TRDOS 386 v2 format...'
TrDOS_CRLF:
	db 0Dh, 0Ah, 0

TrDOS_disk_NotReadyOrError:
	db 0Dh, 0Ah
	db 'Disk error or drive not ready ! '
zbyte:	db 'Try again ? (Y/N) '
	db 0

TrDOS_invalid_bootsector:
	db 0Dh, 0Ah
	db 'Invalid boot sector (not a valid FAT'
fattype_str:
	db '16 fs disk) ! '
	db 0

TRDOS_fatp_notfound:
	db 0Dh, 0Ah
	db 'MBR does not contain a primary DOS partition ! '	
fattype:
	db 0
RetryCount:
	db 4

lba:	db 0

align 4

CHS_limit: 
	dw 0
	;dw 0

sign:	dw 417

; ----------------------------------------------------------------------------
; uninitialized data
; ----------------------------------------------------------------------------

bss_start:

ABSOLUTE bss_start

alignb 4

sectors: resb 1
heads:	 resb 1
cylinders: resw 1

dosp_start: resd 1
dosp_size:  resd 1	 

MBR:
bootsector:
	resb 512

end_bss: