     1                                  ; ****************************************************************************
     2                                  ; TRDOS386.ASM (TRDOS 386 Kernel) - v2.0.0 - fat32_bs.s - FAT32 BOOT SECTOR
     3                                  ; ----------------------------------------------------------------------------
     4                                  ; Last Update: 31/01/2018
     5                                  ; ----------------------------------------------------------------------------
     6                                  ; Beginning: 13/12/2017
     7                                  ; ----------------------------------------------------------------------------
     8                                  ; Assembler: NASM version 2.11  
     9                                  ; ----------------------------------------------------------------------------
    10                                  ;	    ((nasm fat32_bs.s -l fat32_bs.lst -o FAT32_BS.BIN)) 	
    11                                  ; ----------------------------------------------------------------------------
    12                                  ; Turkish Rational DOS
    13                                  ; Operating System Project v2.0 by ERDOGAN TAN (Beginning: 04/01/2016)
    14                                  ;
    15                                  ; This boot sector code occupies 2 sectors.. as below:
    16                                  ; * Boot Sector 1:
    17                                  ; The 1st 512 bytes of this boot code will be on sector 0 (of the partition).
    18                                  ; * Boot Sector 2:
    19                                  ; Remain bytes of this boot code will be sector 2 (just after FSINFO sector)
    20                                  ; of the (FAT32) partition.	
    21                                  ;
    22                                  ; NOTE:	This code has some tricks and TRDOS 386 specific modifications
    23                                  ; which are not a part of original Microsoft Windows (XP) FAT32 BS code.
    24                                  ; (Purpose of TRDOS 386 specific modifications and tricks is
    25                                  ; to load 'TRDOS386.SYS' kernel file as easy and as correct,
    26                                  ; without affecting FAT32 FS recognization for other operating systems.) 
    27                                  ;
    28                                  ; Note: Modifications (on WINDOWS 98 FAT32 boot sector code)
    29                                  ;	are based on WINDOWS XP FAT32 boot sector(s) code (2 sectors), 
    30                                  ;	which is disassembled by Erdogan Tan (12/12/2017)
    31                                  ;	by using BINFILEHEX (Erdogan Tan) & IDA PRO FREE (Hex-Rays SA)
    32                                  ;	programs.
    33                                  ;
    34                                  ; Derived from Microsoft WINDOWS 98 FAT 32 boot sector code
    35                                  ; 	  which is edited/disassembled by Erdogan Tan (04/10/2003).
    36                                  ;
    37                                  ; Derived from 'trfdbs.s' TRDOS 386 FAT12 (3.5") floppy disk boot sector
    38                                  ; source code by Erdogan Tan (06/07/2017).
    39                                  ; ****************************************************************************
    40                                  ; incbin "FAT32_BS.BIN" (in 'hdimage.s' & 'hdformat.s')
    41                                  
    42                                  rts_segment     equ	1000h
    43                                  
    44                                  [BITS 16]
    45                                  [ORG 7C00h]
    46                                  BS_jmpBoot:
    47 00000000 EB58                                    jmp     short loc_5A  ; jmp short start
    48                                  BS_jmpBoot_nop:
    49 00000002 90                                      nop
    50                                  
    51                                  ; BootSector Identification (Data) Block
    52                                  BS_OEMName:
    53 00000003 4D5357494E342E31        		db	'MSWIN4.1'	; bp+3
    54 0000000B 0002                    BPB_BytesPerSec: dw	512		; bp+11
    55 0000000D 08                      BPB_SecPerClus:	db	8		; bp+13
    56 0000000E 2000                    BPB_RsvdSecCnt:	dw	32		; bp+14
    57 00000010 02                      BPB_NumFATs:	db	2		; bp+16
    58 00000011 0000                    BPB_RootEntCnt: dw	0		; bp+17
    59 00000013 0000                    BPB_TotSec16:	dw	0		; bp+19
    60 00000015 F8                      BPB_Media:	db	0F8h		; bp+21
    61 00000016 0000                    BPB_FATSz16:	dw	0		; bp+22
    62 00000018 3F00                    BPB_SecPerTrk:	dw	63		; bp+24
    63 0000001A FF00                    BPB_NumHeads:	dw	255		; bp+26
    64 0000001C 01000000                BPB_HiddSec:	dd	1		; bp+28
    65 00000020 00000000                BPB_TotSec32:	dd	0		; bp+32
    66 00000024 00000000                BPB_FATSz32:	dd	0		; bp+36
    67 00000028 0000                    BPB_ExtFlags:	dw	0		; bp+40
    68 0000002A 0000                    BPB_FSVer:	dw	0		; bp+42
    69 0000002C 02000000                BPB_RootClus:	dd	2		; bp+44
    70 00000030 0100                    BPB_FSInfo:	dw	1		; bp+48
    71 00000032 0600                    BPB_BkBootSec:	dw	6		; bp+50
    72 00000034 00<rept>                BPB_Reserved:	times	12 db 0		; bp+52
    73 00000040 80                      BS_DrvNum:	db	80h		; bp+64
    74 00000041 00                      BS_Reserved1:	db	0		; bp+65
    75 00000042 29                      BS_BootSig:	db	29h		; bp+66
    76 00000043 00000000                BS_VolID:	dd	0		; bp+67
    77 00000047 5452444F5333383620-     BS_VolLab:	db	'TRDOS386   '	; bp+71
    78 00000050 2020               
    79 00000052 4641543332202020        BS_FilSysType:	db	'FAT32   '	; bp+82
    80                                  
    81                                  start:
    82                                  loc_5A:
    83 0000005A 09C0                    		OR	AX, AX ; db 09h, C0h  (db 0Bh, C0h)
    84                                  			 ; TRDOS 386 (FAT32 BS) LBA check trick!!
    85                                  
    86 0000005C BD007C                  		mov	bp, 7C00h
    87                                  
    88                                  		; ((WINDOWS XP FAT 32 boot sector code checks Masterboot
    89                                  		; partition table for partition type, if it is 0Ch 
    90                                  		; -FAT32 LBA-, the boot code changes 90h at BS offset 2
    91                                  		; to 0Eh. Then a 0Eh at this addr is used as identifier, 
    92                                  		; for reading disk sector by using INT 13h -LBA read- 
    93                                  		; extension.))  
    94                                  
    95 0000005F 3DA101                  		cmp	ax, 417  ; If AX=417, the masterboot sector
    96                                  				 ; has a SINGLIX FS (& TRDOS 386)
    97                                  				 ; masterboot code; and...  
    98                                  				 ; DX=ES=SS=0, BP=7C00h
    99                                  				 ; SP=7C00h ... masterboot sector has
   100                                  				 ; been loaded at 0:600h, it has
   101                                  				 ; CHS parameters at offset 600h+420.
   102                                  				 ; (There is a 01A1h in offset 600h+417)
   103                                  	
   104 00000062 740F                    		je	short bs_01 ; no need to following assignments !
   105                                  
   106 00000064 31C0                    		xor	ax, ax
   107 00000066 8ED8                    		mov	ds, ax
   108 00000068 8EC0                    		mov	es, ax
   109 0000006A FA                      		cli
   110 0000006B 8ED0                    		mov	ss, ax
   111 0000006D 89EC                    		mov	sp, bp
   112 0000006F FB                      		sti
   113 00000070 8A5640                  		mov	dl, [bp+40h] ; [BS_DrvNum]
   114                                  bs_01:
   115 00000073 8936[FC01]              		mov	[bsReserved1], si ; Partition entry address..
   116                                  		; 24/12/2017		  ; (from Singlix FS MBR)
   117                                  					  ; (7BEh,7CEh,7DEh,7EEh) 
   118                                  
   119                                  		; Check Bytes/Sector value
   120                                  		; It must be 512 !? (at least, for TRDOS386) 
   121 00000077 817E0B0002              		cmp	word [bp+0Bh], 512 ; [BPB_BytesPerSec]
   122 0000007C 7578                    		jne	invalid_system_disk
   123                                  
   124                                  		; Following validation checks (*!*)
   125                                  		; are done according to 
   126                                  		; 	Microsoft Extensible Firmware Initiative
   127                                  		;	FAT32 File System Specification, 
   128                                  		;				Version 1.03 (2000).
   129                                  		
   130                                                  ; [BPB_FATSz16] must be 0 (!*!) ; [bp+16h]
   131 0000007E 6629C9                  		sub	ecx, ecx ; 0 ; *
   132                                                  ;cmp	[BPB_FATSz16], cx ; 0	; sectors/fat for FAT16
   133 00000081 394E16                                  cmp	[bp+16h], cx
   134 00000084 7570                    		jne	short invalid_system_disk
   135                                  
   136                                  		; [BPB_FSVer] must be 0 for current FAT32 version (!*!)
   137                                  		;cmp	[BPB_FSVer], cx   ; 0 	; [bp+2Ah], FAT32 version
   138 00000086 394E2A                  		cmp	[bp+2Ah], cx
   139 00000089 756B                    		jne	short invalid_system_disk
   140                                  
   141                                  		;mov	dh, [bp+5Ah]    ; 0Ch (FAT32 LBA) or 0Bh (FAT32 CHS)
   142                                  			; NOTE: 09h at bp+5Ah (at loc_5A) will be overwritten 
   143                                  			; by TRDOS 386 disk format program.
   144                                  			; (0BC0h -or AX,AX- is written for FAT32 CHS partition, 
   145                                  			; 0C00h -or AL,0- is written for FAT32 LBA partition.)
   146                                  
   147                                  		; overwrite hd drive number !
   148                                                  ;mov	[BS_DrvNum], dl		; drive number from INT 19h
   149 0000008B 885640                  		mov	[bp+40h], dl
   150                                  		;mov	[bp+41h], dh	; [BS_Reserved1] = Partition ID !!!
   151                                  		;mov	[bp+40h], dx	
   152                                  
   153                                  		; reset FAT32 FS reading pointers and set SP to 7BF4h
   154                                  		;xor	ecx, ecx ; *
   155                                  		;sub	ecx, ecx ; *
   156 0000008E 6651                    		push	ecx 	; [bp-4] = 0   ; CHS limit (8.4GB)
   157 00000090 6651                    		push	ecx	; [bp-8] = 0   ; Address of Cluster 2
   158 00000092 6649                    		dec	ecx 	; 0FFFFFFFFh
   159 00000094 6651                    		push	ecx	; [bp-12] = -1	; FAT sector in FAT buffer
   160 00000096 6641                    		inc	ecx	; 0
   161                                  
   162                                  		; SP = 7BF4h
   163                                  
   164                                  		; check for ROMBIOS INT 13h extensions
   165 00000098 B441                    		mov	ah, 41h
   166                                  		;mov	ebx, 55AAh  
   167 0000009A BBAA55                  		mov	bx, 55AAh
   168                                  		;mov	dl, [BS_DrvNum]
   169                                  		;mov	dl, [bp+40h]
   170 0000009D CD13                    		int	13h
   171 0000009F 721A                    		jc	short bs_02
   172 000000A1 81FB55AA                		cmp	bx, 0AA55h
   173 000000A5 7514                    		jne	short bs_02
   174 000000A7 F6C101                  		test	cl, 1
   175 000000AA 740F                    		jz	short bs_02
   176                                  
   177                                  		; ROMBIOS INT 13h extentions are present...
   178                                  
   179 000000AC B8424A                  		mov	ax, 4A42h
   180                                  		;mov	[BS_jmpBoot+2], al ; 42h ; 'LBA mode is available'
   181 000000AF 884602                  		mov	[bp+2], al ; 42h
   182                                  		;cmp	dh, 0Ch ; is this BS of a FAT32 LBA partition? 
   183 000000B2 807E5A0C                		cmp	byte [bp+5Ah], 0Ch
   184 000000B6 7503                    		jne	short bs_02 ; no..
   185                                  		; yes, put sign for disk read subroutine (for LBA read) 
   186                                  		;mov	[loc_5A], ax
   187 000000B8 89465A                  		mov	[bp+5Ah], ax ; INC DX (FAT32 LBA read), DEC X
   188                                  bs_02:
   189                                  		; ..CHS limit setup..
   190                                  
   191                                  		; Get drive parameters (CHS parameters)
   192                                  		;mov	dl, [BS_DrvNum]
   193                                  		;mov	dl, [bp+40h]
   194 000000BB B408                    		mov	ah, 08h
   195 000000BD CD13                    		int	13h
   196 000000BF 7241                    		jc	short disk_io_error
   197                                  
   198                                  		; CX = maximum value for cylinder and sector
   199                                  		; DH = maximum value for head
   200                                  		; DL = number of harddisks on first controller 			
   201                                  		; ES:DI = address of hard disk parameters table
   202                                  		; (Bits 6&7 of CL is high 2 bits of 10 bit clinder value
   203                                  		; which is low 8 bits are in CH.)
   204                                  
   205 000000C1 1E                      		push	ds
   206 000000C2 07                      		pop	es
   207                                  
   208                                  		; convert CHS values to CHS limit (as LBA)
   209 000000C3 660FB6C6                		movzx	eax, dh
   210 000000C7 40                      		inc	ax
   211                                  		;movzx	edx, cl
   212 000000C8 88CA                    		mov	dl, cl
   213                                  		;and	dl, 3Fh
   214 000000CA 83E23F                  		and	dx, 3Fh
   215 000000CD F7E2                    		mul	dx
   216 000000CF C0E906                  		shr	cl, 6
   217 000000D2 86CD                    		xchg	cl, ch
   218 000000D4 41                      		inc	cx
   219                                  		;movzx	ecx, cx ; *
   220 000000D5 66F7E1                  		mul	ecx
   221 000000D8 668946FC                		mov	[bp-4], eax ; dword [7BFCh] ; CHS limit
   222                                  
   223                                  		; Load the second half (remain bytes) of this boot code
   224                                  		; at 7E00h.
   225                                  
   226 000000DC 668B461C                		mov	eax, [bp+1Ch] ; [BPB_HiddSec]
   227 000000E0 6683C002                		add	eax, 2 ; Second half of boot code is in BS 2
   228                                  		;mov	ebx, 7E00h
   229 000000E4 BB007E                  		mov	bx, 7E00h
   230                                  		;mov	cx, 1
   231                                  		;call	disk_read
   232 000000E7 E83500                  		call	read_sector ; 25/12/2017 (Read 1 sector)
   233 000000EA 7216                    		jc	short disk_io_error
   234                                  
   235                                  		; Boot sector 2 validation check 
   236 000000EC 813EA17FA101            		cmp	word [7FA1h], 417 ; The magic word !
   237 000000F2 0F840C01                		je	check_root_dir_entries
   238                                  
   239                                  invalid_system_disk:
   240 000000F6 BE[A001]                		mov	si, Inv_disk_Msg
   241 000000F9 E81400                  		call	print_msg
   242                                  getchar_reboot:
   243                                  		; Wait for a keystroke just before reboot
   244 000000FC 30E4                    		xor	ah, ah
   245 000000FE CD16                    		int	16h
   246                                  		
   247 00000100 CD19                    		int	19h	; disk boot	
   248                                  				; causes reboot of disk system
   249                                  disk_io_error:
   250 00000102 BE[8F01]                		mov	si, Diskio_err_Msg
   251 00000105 E80800                  		call	print_msg
   252                                  ;replace_disk:		
   253                                  ;		mov	si, Replace_Msg	
   254                                  replace_disk:	
   255 00000108 BE[B501]                		mov	si, Disk_err_replace_Msg
   256 0000010B E80200                  		call	print_msg
   257 0000010E EBEC                    		jmp	getchar_reboot
   258                                  
   259                                  print_msg:
   260                                  		; DS:SI = Error message address (ASCIIZ string)	
   261 00000110 B40E                    		mov	ah, 0Eh
   262 00000112 BB0700                  		mov	bx, 7
   263                                  bs_03:
   264 00000115 AC                      		lodsb
   265 00000116 84C0                    		test	al, al
   266 00000118 7404                    		jz	short bs_04
   267 0000011A CD10                    		int	10h
   268 0000011C EBF7                    		jmp	short bs_03
   269                                  bs_04:
   270 0000011E C3                      		retn
   271                                  
   272                                  read_sector:	; 25/12/2017 (Read 1 sector)
   273 0000011F B90100                  		mov	cx, 1
   274                                  disk_read:
   275                                  		;mov	byte [bp+retry_count-7C00h], 4
   276 00000122 B204                    		mov	dl, 4 ; retry count
   277                                  disk_read_0:
   278 00000124 6660                    		pushad
   279                                  		;cmp	byte [loc_5A], 42h ; FAT32 LBA availability
   280 00000126 B242                    		mov	dl, 42h
   281 00000128 38565A                  		cmp	[bp+5Ah], dl ; 42h ; FAT32 LBA partition & LBA ready
   282 0000012B 740D                    		je	short lba_read
   283                                  		; Jump to lba_read if sector addr overs CHS limit
   284 0000012D 663B46FC                		cmp	eax, [bp-4] ; CHS limit ([7BFCh])
   285 00000131 721E                    		jb	short chs_read
   286                                  		; Disk I/O error if Int 13h LBA read func is not usable
   287                                  		; byte [BS_jmpBoot+2] = 'LBA read function is ready' sign 
   288                                  		;cmp	byte [[BS_jmpBoot+2], 42h ; FAT32 LBA availability
   289                                  		;cmp	byte [bp+2], 42h
   290 00000133 385602                  		cmp	[bp+2], dl ; 42h ; is LBA mode ready ? 
   291 00000136 7402                    		je	short lba_read ; LBA mode is usable/available
   292 00000138 F9                      		stc ; cf = 1
   293 00000139 C3                      		retn
   294                                  lba_read:
   295                                  		;pushad
   296                                  
   297                                  		;mov	di, sp
   298                                  		
   299 0000013A 666A00                  		push	dword 0
   300 0000013D 6650                    		push	eax
   301 0000013F 06                      		push	es
   302 00000140 53                      		push	bx
   303 00000141 6A01                    		push 	byte 1
   304 00000143 6A10                    		push	byte 16 ; 10h
   305                                  		;mov	ah, 42h
   306 00000145 88D4                    		mov	ah, dl ; 42h
   307                                  		;mov	dl, [BS_DrvNum]
   308 00000147 8A5640                  		mov	dl, [bp+40h]
   309 0000014A 89E6                    		mov	si, sp
   310 0000014C CD13                    		int	13h
   311                                  
   312                                  		;pop	eax
   313                                  		;pop	eax
   314                                  		;pop	eax
   315                                  		;pop	eax
   316                                  		;mov	sp, di
   317                                  		
   318 0000014E 61                      		popa
   319 0000014F EB2A                    		jmp	short disk_read_1
   320                                  chs_read:	
   321                                  		;pushad
   322                                  
   323                                  		; Convert LBA to CHS
   324 00000151 6631D2                  		xor	edx, edx
   325                                  		;movzx	ecx, word [BPB_SecPerTrk] ; [bp+18h]
   326                                  				; sectors per track (17 or 63)
   327 00000154 660FB74E18              		movzx	ecx, word [bp+18h]
   328 00000159 66F7F1                  		div	ecx
   329 0000015C FEC2                    		inc	dl	; sector number (1 based)
   330 0000015E 88D1                    		mov	cl, dl
   331 00000160 6689C2                  		mov	edx, eax ; (heads * cylinder) + head number
   332 00000163 66C1EA10                		shr	edx, 16	 ; high word in DX, low word in AX	
   333                                  		;div	word [BPB_NumHeads] ; [bp+1Ah]
   334                                  				 ; number of heads (2 to 255)
   335 00000167 F7761A                  		div	word [bp+1Ah]
   336                                  		; AX = cylinder (0 to 1023)
   337                                  		; DX = head number (in DL)
   338 0000016A 88D6                    		mov	dh, dl	 ; head number in DH
   339                                  		;mov	dl, [BS_DrvNum] ; [bp+40h] ; Drive number (80h)
   340 0000016C 8A5640                  		mov	dl, [bp+40h]
   341 0000016F 88C5                    		mov	ch, al ; Low 8 bits of cylinder number (0 to 7)
   342 00000171 C0E406                  		shl	ah, 6  ; High 2 bits of cylinder is in bit 7&8	
   343 00000174 08E1                    		or	cl, ah ; High two bits of CL is cylinder bits 8&9 
   344 00000176 B80102                  		mov	ax, 201h ; Read 1 sector
   345 00000179 CD13                    		int	13h
   346                                  disk_read_1:
   347 0000017B 6661                    		popad
   348 0000017D 7305                    		jnc	short disk_read_2
   349                                  		; cf = 1
   350                                  		;dec	byte [retry_count]
   351                                  		;dec	byte [bp+retry_count-7C00h]
   352 0000017F FECA                    		dec	dl ; Retry count
   353 00000181 75A1                    		jnz	short disk_read_0 ; Retry
   354                                  		; cf = 1		
   355 00000183 C3                      		retn
   356                                  disk_read_2:
   357                                  		;add	bx, [bp+0Bh] ; [BPB_BytesPerSec] ; 512
   358                                  		;add	bx, 512
   359 00000184 80C702                  		add	bh, 2 ; **
   360 00000187 6640                    		inc	eax
   361 00000189 49                      		dec	cx
   362 0000018A 7596                    		jnz	short disk_read
   363                                  		;clc 	; ** (128 sectors/cluster!?)
   364 0000018C C3                      		retn
   365                                  
   366                                  		; Filler
   367 0000018D 07                      		db	07h
   368 0000018E 14                      		db	14h
   369                                  
   370                                  Diskio_err_Msg:
   371 0000018F 0D0A                    		db	0Dh, 0Ah
   372 00000191 4469736B20492F4F20-     		db	'Disk I/O error'
   373 0000019A 6572726F72         
   374                                  		;db	'!'
   375 0000019F 00                      		db	0
   376                                  Inv_disk_Msg:   
   377 000001A0 0D0A                    		db	0Dh, 0Ah
   378 000001A2 496E76616C69642073-     		db	'Invalid system disk'
   379 000001AB 797374656D20646973-
   380 000001B4 6B                 
   381                                  Disk_err_replace_Msg:
   382 000001B5 21                      		db	'!'
   383                                  Replace_Msg:    
   384 000001B6 0D0A                    		db	0Dh, 0Ah
   385 000001B8 5265706C6163652074-     		db	'Replace the disk and press any key to reboot.'
   386 000001C1 6865206469736B2061-
   387 000001CA 6E6420707265737320-
   388 000001D3 616E79206B65792074-
   389 000001DC 6F207265626F6F742E 
   390 000001E5 0D0A00                  		db	0Dh, 0Ah, 0
   391                                  
   392                                  		; Boot sector code writing date (by Erdogan Tan)
   393 000001E8 1F                      		db	31
   394 000001E9 01                      		db	01
   395 000001EA E207                    		dw	2018
   396                                  
   397                                  		; TRDOS 386 FAT32 boot sector code version
   398 000001EC 76312E30                		db	'v1.0'
   399                                  
   400                                  		times	(508+rtsfilename-bsReserved1) - ($ - $$) db 0
   401                                  rtsfilename:
   402 000001F0 5452444F5333383653-                     db      'TRDOS386SYS'
   403 000001F9 5953               
   404 000001FB 00                                      db      0
   405                                  bsReserved1:
   406 000001FC 5452                    		db	'TR'  ; 'Turkish Rational DOS' feature identifier.
   407                                  bootsignature1:
   408 000001FE 55AA                    		db	55h, 0AAh
   409                                  
   410                                  bsReserved2:
   411 00000200 5254                    		db	'RT'  ; 'Turkish Rational DOS' feature identifier
   412                                  
   413                                  check_root_dir_entries: 
   414                                  		; load root directory and check directory entries 
   415                                  				
   416                                  		; calculate total size of FAT area
   417                                                  ;movzx	ecx, byte [BPB_NumFATs] ; [bp+10h] ; number of FATs
   418 00000202 8A4E10                    		mov	cl, [bp+10h]
   419                                  		;mov	eax, [BPB_FATSz32] ; [bp+24h] ; sectors per FAT
   420 00000205 668B4624                                mov	eax, [bp+24h]
   421 00000209 66F7E1                  		mul     ecx
   422                                                               
   423                                  		; add hidden sectors
   424                                  		;add	eax, [BPB_HiddSec] ; [bp+1Ch]
   425 0000020C 6603461C                		add	eax, [bp+1Ch]
   426                                  
   427                                  		; add reserved sectors
   428                                                  ;movzx	edx, [BPB_RsvdSecCnt] ; [bp+0Eh]
   429                                                  ;mov	dx, [BPB_RsvdSecCnt]
   430 00000210 8B560E                  		mov	dx, [bp+0Eh]
   431 00000213 6601D0                  		add	eax, edx
   432                                  
   433                                  		; Save address of cluster 2 into 7BF8h 
   434 00000216 668946F8                		mov     [bp-8], eax	; EAX = Data Area (Cluster 2)
   435                                                                          ; (Data) Start Address in 7BF8h
   436                                  
   437                                  		; Reset FAT sector address pointer (7BF4h) 
   438                                  		; 	which points to FAT sectors in the FAT buffer
   439                                  		;	(8000h) 
   440                                  		;	
   441                                  		;mov	dword [bp-12], 0FFFFFFFFh ; invalid address 
   442                                  						 ; (for now)
   443                                  
   444                                  		; Check Root Directory Start Cluster is valid or not.
   445                                  		;mov	eax, [BPB_RootClus] ; [bp+2Ch]
   446 0000021A 668B462C                		mov	eax, [bp+2Ch]
   447                                  
   448                                  load_root_dir_sector:
   449                                  		; EAX = Cluster Number
   450                                  
   451                                  		; Cluster number must not be less than 2
   452 0000021E 6683F802                		cmp	eax, 2			  ; Is it Cluster 2?
   453 00000222 0F82D0FE                		jb	invalid_system_disk ; error if less than 2
   454                                  
   455                                                 	; Is it End Of Cluster Chain marker or something above?
   456                                                  ;cmp	eax, 0FFFFFF8h  ; clust 2 to 0FFFFFF7h is valid
   457                                                  ;jnb	invalid_system_disk ; invalid cluster num
   458                                  					      ; or end of cluster chain			
   459                                  		; 23/12/2017
   460                                  		; Note: Bad Cluster number is 0FFFFFF7h !		
   461                                  		; (According to MS FAT32 Specification, 2000, page 18)
   462                                  		; "It is not possible for the bad cluster mark to be
   463                                  		; an allocatable cluster number on FAT12 and FAT16 volumes, 
   464                                  		; but it is feasible for 0x0FFFFFF7 to be an allocatable 
   465                                  		; cluster number on FAT32 volumes.
   466                                  		; To avoid possible confusion by disk utilities, 
   467                                  		; no FAT32 volume should ever be configured such that 
   468                                  		; 0x0FFFFFF7 is an allocatable cluster number."
   469                                  		
   470                                                 	; Is it End Of Cluster Chain marker or something above?
   471 00000226 663DF7FFFF0F                            cmp	eax, 0FFFFFF7h  ; clust 2 to 0FFFFFF6h is valid
   472 0000022C 0F83C6FE                                jnb	invalid_system_disk   ; invalid cluster num
   473                                  					      ; or end of cluster chain	
   474 00000230 6650                    		push	eax
   475 00000232 6683E802                		sub	eax, 2	; 0 based cluster number
   476                                  		;movzx	ebx, byte [BPB_SecPerClus] ; [bp+13]
   477 00000236 660FB65E0D              		movzx	ebx, byte [bp+0Dh]
   478 0000023B 89DE                    		mov	si, bx	; save sector per cluster in SI
   479 0000023D 66F7E3                  		mul	ebx
   480                                  		; EAX = relative sector of the 1st part of root dir 
   481 00000240 660346F8                		add	eax, [bp-8] ; add 'start address of data area'
   482                                  				    ; (in 7BF8h) to relative address
   483                                  bs_05:
   484 00000244 BB0082                  		mov	bx, 8200h  ; Root directory buffer (1 sector)		
   485 00000247 89DF                    		mov	di, bx
   486                                  		;mov	cx, 1
   487                                  		;call	disk_read
   488 00000249 E8D3FE                  		call	read_sector ; 25/12/2017 (Read 1 sector)
   489 0000024C 0F82B2FE                		jc	disk_io_error
   490                                  
   491                                  		; BX = 8400h
   492                                  
   493                                  search_startup_file: 
   494                                  		; check/compare root dir entry for/with kernel file
   495 00000250 382D                    		cmp	[di], ch ; 0
   496 00000252 0F84A0FE                		je	invalid_system_disk ; kernel not found!
   497 00000256 B10B                    		mov	cl, 11 ; 0Bh
   498                                  		; SI = count down value from 'sectors per cluster'
   499 00000258 56                      		push	si ; SPC to 1
   500 00000259 BE[F001]                		mov	si, rtsfilename ; Run Time System file name
   501                                  					; or Kernel file name
   502                                  					; (or Startup file name)
   503                                  					; (or Standalone file name)
   504                                  					; in MSDOS directory entry
   505                                  					; format. ('TRDOS386SYS')
   506                                  					; It is 'TRDOS386.SYS'
   507                                  					; for TRDOS 386 OS.
   508 0000025C F3A6                    		repe	cmpsb ; compare dir entry and kernel's name
   509 0000025E 5E                      		pop	si
   510 0000025F 7475                    		jz	load_startup_file ; kernel is there!
   511 00000261 01CF                    		add	di, cx
   512 00000263 83C715                  		add	di, 21 ; 15h (11+21=32)
   513 00000266 39DF                    		cmp	di, bx ; 8400h
   514 00000268 72E6                    		jb	short search_startup_file ; chk next entry
   515                                  		; Sector Per Cluster countdown
   516 0000026A 4E                      		dec	si 
   517 0000026B 75D7                    		jnz	short bs_05 ; next sector in same cluster
   518 0000026D 6658                    		pop	eax
   519 0000026F E80600                  		call	get_next_cluster
   520 00000272 0F828CFE                		jc	disk_io_error
   521                                  		;; EAX = 32 bit cluster number (32 bit FAT entry)
   522                                  		;and	eax, 0FFFFFFFh ; 28 bit cluster number
   523 00000276 EBA6                    		jmp	short load_root_dir_sector
   524                                  
   525                                  get_next_cluster:	; get next (FAT32) directory/file cluster
   526                                  		; EAX = current cluster number (28 bit, zero based)
   527 00000278 66C1E002                		shl	eax, 2 ; 32 bit FAT entry offset
   528 0000027C E80D00                  		call	get_fat32_entry
   529 0000027F 720A                    		jc	short bs_06 ; Disk read error!
   530 00000281 26668B01                		mov	eax, [es:bx+di]	; 32 bit clust entry number
   531 00000285 6625FFFFFF0F            		and	eax, 0FFFFFFFh	; 28 bit cluster number
   532                                  		;cmp	eax, 0FFFFFF8h
   533                                  		;cmp	eax, 0FFFFFF7h  ; 23/12/2017
   534                                  		;cmc
   535                                  bs_06:
   536 0000028B C3                      		retn
   537                                  
   538                                  get_fat32_entry:
   539                                  		; EAX = 32 bit FAT entry (dword) offset
   540 0000028C BF0080                  		mov	di, 8000h ; FAT (sector) buffer
   541                                  		;movzx	ecx, word [BPB_BytesPerSec] ; [bp+11]
   542                                  		;mov	cx, [BPB_BytesPerSec]
   543                                  		;mov	cx, [bp+0Bh]
   544 0000028F B90002                  		mov	cx, 512
   545                                  		;xor	edx, edx
   546 00000292 31D2                    		xor	dx, dx
   547 00000294 66F7F1                  		div	ecx
   548                                  		; EAX = FAT sector number (relative)
   549                                  		; Check FAT sector number if it is already
   550                                  		; in FAT buffer at 8000h.
   551                                  		; Current FAT sector is in 7BF4h. 
   552                                  		; (Note: initial FAT sector value in 7BF4h is
   553                                  		;	 0FFFFFFFFh which means the buff 
   554                                  		;	 is not loaded yet..)
   555 00000297 663B46F4                		cmp	eax, [bp-0Ch] ; [7BF4h]
   556 0000029B 7431                    		je	short bs_08 ; same sector in FAT buffer
   557 0000029D 668946F4                		mov	[bp-0Ch], eax ; save FAT sector number
   558                                  		; Calculate absolute (LBA) address of FAT sector
   559                                  		; by adding hidden (partition's start sector)
   560                                  		; and reserved sectors (between BS and FAT).
   561                                  		;add	eax, [BPB_HiddSec] ; [bp+1Ch]
   562 000002A1 6603461C                		add	eax, [bp+1Ch]
   563                                  		;movzx	ecx, word [BPB_RsvdSecCnt] ; [bp+0Eh]
   564                                  		;mov	cx, [BPB_RsvdSecCnt] ; = 32 (typically)
   565 000002A5 8B4E0E                  		mov	cx, [bp+0Eh]
   566 000002A8 6601C8                  		add	eax, ecx ; LBA of the FAT sector
   567                                  		; Check FAT mirroring flag..
   568                                  		;	bits 0 to 3 are used for active FAT number 
   569                                  		;	If bit 7 is 1, only one (active) FAT copy
   570                                  		;	is updated (written without mirroring). 
   571                                  		;  (Default active FAT is 0 and default option
   572                                  		;   is to mirror the active FAT -at runtime- into
   573                                  		;	all FAT copies -generally 2 FATs-. 	
   574                                  		;movzx	ebx, word [BPB_ExtFlags] ; [bp+28h]
   575                                  		;mov	bx, [BPB_ExtFlags]
   576 000002AB 8B5E28                  		mov	bx, [bp+28h]
   577 000002AE 83E30F                  		and	bx, 0Fh
   578 000002B1 7414                    		jz	short bs_07	; FAT number 0 is active
   579                                  					; (as default)
   580                                  		; compare active FAT number with number of FATs	
   581                                  		;cmp	bl, [BPB_NumFATs] ; [bp+10h]
   582 000002B3 3A5E10                  		cmp	bl, [bp+10h]
   583 000002B6 7319                    		jnb	short bs_09 ; invalid parameter!
   584 000002B8 52                      		push	dx
   585 000002B9 6689C1                  		mov	ecx, eax
   586                                  		; multiply zero based FAT number with FAT size
   587                                  		;mov	eax, [BPB_FATSz32] ; [bp+24h]
   588 000002BC 668B4624                		mov	eax, [bp+24h]
   589 000002C0 66F7E3                  		mul	ebx
   590 000002C3 6601C8                  		add	eax, ecx   ; start of active FAT copy
   591 000002C6 5A                      		pop	dx
   592                                  bs_07:
   593 000002C7 52                      		push	dx
   594 000002C8 89FB                    		mov	bx, di
   595                                  		;mov	cx, 1
   596                                  		;call	disk_read
   597 000002CA E852FE                  		call	read_sector ; 25/12/2017 (Read 1 sector)
   598                                  		; If cf = 1 -> Disk I/O err, not invalid sys disk!
   599 000002CD 5A                      		pop	dx
   600                                  bs_08:
   601 000002CE 89D3                    		mov	bx, dx
   602 000002D0 C3                      		retn
   603                                  bs_09:
   604                                  		; Invalid boot sector parameter/data
   605                                  		;add	sp, 4
   606 000002D1 58                      		pop	ax ; return to 'get_next_cluster'
   607 000002D2 58                      		pop	ax ; return to 'search_startup_file'
   608 000002D3 E920FE                  		jmp	invalid_system_disk
   609                                  
   610                                  load_startup_file:
   611                                  		; DI = directory entry offset 9 (of 32 bytes)
   612 000002D6 83C404                  		add	sp, 4 ; pop eax
   613                                  		; High word of First Cluster
   614 000002D9 8B4509                  		mov	ax, [di+9] ; [di+DIR_FstClusHI-11]
   615                                  		; Low word of First Cluster
   616 000002DC 8B550F                  		mov	dx, [di+0Fh] ; [di+DIR_FstClusLO-11]
   617 000002DF 66C1E010                		shl	eax, 16
   618 000002E3 89D0                    		mov	ax, dx
   619                                  		; Valid cluster number must not be less than 2
   620                                  		; and it (a first cluster value in directory entry)
   621                                  		; must not be greater than 0FFFFFF6h. 
   622 000002E5 6683F802                		cmp	eax, 2
   623 000002E9 0F8209FE                		jb	invalid_system_disk
   624                                  		;cmp	eax, 0FFFFFF8h
   625 000002ED 663DF7FFFF0F            		cmp	eax, 0FFFFFF7h ; 23/12/2017
   626 000002F3 0F83FFFD                		jnb	invalid_system_disk
   627                                  
   628 000002F7 6689C1                  		mov	ecx, eax ; save first cluster number
   629                                  
   630                                  		; Load  RTS (Kernel) file
   631 000002FA BE[4F03]                                mov     si, Loading_Msg
   632 000002FD E810FE                                  call    print_msg
   633                                                  
   634 00000300 6689C8                  		mov	eax, ecx ; restore first cluster number
   635                                  		
   636                                  		;mov	bx, rts_segment ; 1000h
   637                                  		;mov	[next_segment], bx
   638                                  bs_10:
   639 00000303 6650                    		push	eax ; 28 bit cluster num, starts from 2
   640 00000305 6683E802                		sub	eax, 2 ; now, cluster num starts from 0 
   641                                  		;movzx	ecx, byte [BPB_SecPerClus] ; [bp+0Dh]
   642 00000309 660FB64E0D              		movzx	ecx, byte [bp+0Dh]
   643 0000030E 66F7E1                  		mul	ecx
   644                                  		; eax = sector offset (from start of data area)
   645 00000311 660346F8                		add	eax, [bp-8] ; add data area (start) addr
   646 00000315 8B1E[4703]              		mov	bx, [next_segment]
   647 00000319 06                      		push	es
   648 0000031A 8EC3                    		mov	es, bx ; segment = 1000h +
   649 0000031C 31DB                    		xor	bx, bx ; offset = 0 
   650                                  		; CX = num of sectors to read (= sectors/cluster)
   651 0000031E E801FE                  		call	disk_read
   652 00000321 07                      		pop	es
   653 00000322 6658                    		pop	eax
   654 00000324 C1EB04                  		shr	bx, 4 ; from byte count to paragraph count
   655 00000327 011E[4703]              		add	[next_segment], bx
   656 0000032B E84AFF                  		call	get_next_cluster
   657                                  		;jc	short diskio_error
   658 0000032E 720E                    		jc	short trdos_loading_error
   659                                  		;cmp	eax, 0FFFFFF8h
   660 00000330 663DF7FFFF0F            		cmp	eax, 0FFFFFF7h ; 23/12/2017
   661 00000336 7351                    		jnb	short bs_11 ; Startup file has been loaded.
   662                                  
   663 00000338 6683F802                		cmp	eax, 2
   664                                  		;jb	invalid_system_disk 
   665                                  		;jmp	short bs_10 ; load next clust of the file
   666 0000033C 73C5                    		jnb	short bs_10
   667                                  
   668                                  trdos_loading_error:
   669 0000033E BE[7303]                		mov	si, Load_err_Msg
   670 00000341 E8CCFD                  		call	print_msg
   671 00000344 E9C1FD                  		jmp	replace_disk
   672                                  next_segment:
   673 00000347 0010                    		dw	rts_segment
   674                                  
   675 00000349 54522D444F53            		db	'TR-DOS' ; Filler
   676                                  		
   677 0000034F 0D0A                    Loading_Msg:    db	0Dh, 0Ah
   678 00000351 4C6F6164696E67204B-     		db	'Loading Kernel TRDOS386.SYS ...'
   679 0000035A 65726E656C20545244-
   680 00000363 4F533338362E535953-
   681 0000036C 202E2E2E           
   682 00000370 0D0A00                                  db 	0Dh, 0Ah, 0
   683                                  Load_err_Msg:
   684 00000373 0D0A                    		db	0Dh, 0Ah
   685 00000375 5452444F53204C6F61-     		db	'TRDOS Loading Error'
   686 0000037E 64696E67204572726F-
   687 00000387 72                 
   688                                  		;db	'!'
   689 00000388 00                      		db	0
   690                                  
   691                                  bs_11:
   692                                  		; Set TRDOS 386 kernel specific parameters (& signs)
   693                                  		; and
   694                                  		; Launch TRDOS 386 Kernel (Startup/RTS file)
   695                                  
   696                                  		;mov	dl, [BS_DrvNum]
   697 00000389 8B5640                                  mov	dx, [bp+40h] ; DL = Drive number, DH = 0 
   698 0000038C FEC6                    		inc	dh  ; TRDOS 386 FAT32 BS major version = 1
   699                                     		
   700 0000038E A1[4703]                		mov	ax, [next_segment] ; 16 paragraphs after the
   701                                  					  ; start of the last segment
   702                                  					  ; of the kernel file loading
   703                                  					  ; space.
   704                                  					  ; So, (top of) stack will have
   705                                  					  ; 256 bytes or more distance
   706                                  					  ; from the last byte
   707                                  					  ; of the kernel file.	 							
   708                                  					  ; (This will be enough for
   709                                  					  ; TRDOS 386 kernel before 
   710                                  					  ; entering protected mode.)
   711 00000391 FA                      		cli
   712 00000392 8ED0                    		mov	ss, ax
   713 00000394 BCFEFF                  		mov	sp, 0FFFEh			
   714 00000397 FB                      		sti
   715                                  
   716 00000398 BB0010                  		mov     bx, rts_segment ; 1000h
   717 0000039B 8EDB                                    mov     ds, bx
   718 0000039D 8EC3                                    mov     es, bx
   719                                  		;mov	fs, bx
   720                                  		;mov	gs, bx 
   721                                  
   722                                  		;xor	ebx, ebx
   723                                  		;xor	ecx, ecx
   724                                  		;xor	edx, edx
   725                                  		;xor	esi, esi
   726                                  		;xor	edi, edi
   727                                  		;xor	ebp, ebp
   728                                  
   729                                  		; bp = 7C00h
   730                                  
   731                                  		; NOTE: Offset 417 in boot sector 2 (the 2nd half of VBR)
   732                                  		; is also FAT32 boot record validation check address and 
   733                                  		; boot sector 2 must have 417 here for boot sector 1 code
   734                                  		; (the 1st half of volume boot record).
   735                                  		; ((So, 'mov eax, 417' has double meaning here.))
   736                                  loc_39F:                
   737 0000039F 66B8A1010000                            mov     eax, 417 ; TRDOS boot sector sign for TRDOS386.SYS
   738                                  
   739 000003A5 EA00000010              		jmp	rts_segment:0
   740                                  
   741 000003AA 00<rept>                		times	1020 - ($ - $$) db 0
   742                                  bsReserved3:
   743 000003FC 5452                    		db	'TR'	; 'Turkish Rational DOS' feature identifier
   744                                  bootsignature2:
   745 000003FE 55AA                    		db	55h, 0AAh
