Page 2 of 2

Re: File System Issues

Posted: Wed May 02, 2018 4:16 pm
by Armature
Right, so ive got the CHS in three separate registers and now im merging them into two CX for C and S and DX for H. im rereading the code posted before :

Code: Select all

  ; DX = 10-bit cylinder number (zero based)
  ; AL = 6-bit sector number (1 based)
  mov  ch,dl
  mov cl,dh
  shl  cl,6
  and  al,3Fh
  or  cl,al
  ; CX now is 10-bit cylinder number in CHS form (zero based)
and I was wondering why your anding the value of AL with 0x3F. Doesn't this just make the value in AL the same as it was before the and operation?

Re: File System Issues

Posted: Wed May 02, 2018 4:35 pm
by BenLunt
Armature wrote:and I was wondering why your anding the value of AL with 0x3F. Doesn't this just make the value in AL the same as it was before the and operation?
This is one of those "catch 22" things. By anding AL with 0x3F, I am making sure that if AL > 63, I am not "adding" to the cylinder value. However, if AL > 63, I messed up somewhere else already and it is a wonder I got this far.

- If you don't 'and' AL with 0x3F, there is a possibility that you might add to the cylinder number.
- If you do 'and' AL with 0x3F, you won't add to the cylinder number but if AL > 63 (0x3F) you have got something wrong before the read anyway.

Catch 22...

Ben

Re: File System Issues

Posted: Wed May 02, 2018 4:38 pm
by Armature
I think ive got the LBA to CHS finished. I managed to get optimised it like you said to 16 bytes. Here is the final code:

Code: Select all

LBAToCHS:						;AX = LBA
	div [bpbSectorsPerTrack]		;AX = LBA/SPT, DX = AbsoluteSector - 1
	push dx					;Store sector on stack
	div [bpbHeadsPerCylinder]	;AX = Cylinder, DX = head
	pop bx					;store the sector into BX from stack
	inc bx					;BX = Sector

	mov ch, bl				;Lower 8 bits [First 8 bits of the cylinder] into the upper 8 bits of CH
	mov cl, bh				;Upper 8 bits [Last 2 bits of the cylinder located here]
	shl bl, 6					;move the bits over by six so 00000011 would look like 11000000
	or cl, al					;CX should now be a proper 10 bit cylinder and 6 bit sector with dl as the head
	mov dh, 0x00
        xchg dh, dl
Does this look okay?

Re: File System Issues

Posted: Sun May 06, 2018 9:50 pm
by Armature
After testing the new boot code ive written. I come to a Stand still once again. When I run the kernel on both emulated and real hardware, the disk is unable to be read. The updated code is:

Code: Select all

org 0x7C00						;1)
jmp short Boot						;2)
nop								;3)
		;4)
bpbOEM				db "AAAAAAAA"	;5) OEM label for the disk (8 bytes)		
bpbBytesPerSector:  	DW 512		;6) The size of the sectors in bytes
bpbSectorsPerCluster: 	DB 1			;7) How many sectors make up a cluster
bpbReservedSectors: 	DW 1			;How many sectors are being reserved (only one: the boot sector)
bpbNumberOfFATs: 		DB 2			;How many FAT tables exist (The oringal and a backup)
bpbRootEntries: 		DW 224		;How many files can be stored in the root directory
bpbTotalSectors: 		DW 2880		;How many sectors exist on this disk
bpbMedia: 			DB 0xf0		;The type of media
bpbSectorsPerFAT: 		DW 9			;how many sectors the FAT table takes up on disk
bpbSectorsPerTrack: 	DW 18		;how many sectors fit on one track
bpbHeadsPerCylinder: 	DW 2			;how many physical heads 
bpbHiddenSectors: 		DD 0
bpbTotalSectorsBig: 	DD 0
bsDriveNumber: 		DB 0
bsUnused: 			DB 0
bsExtBootSignature: 	DB 0x29
bsSerialNumber:		DD 0xa0a1a2a3
bsVolumeLabel: 		DB "AAAAAAAAAAA"
bsFileSystem: 			DB "FAT12   "

Boot:
	cli
	mov ax, 0x0000
	mov es, ax
	mov ds, ax
	mov ss, ax
	mov sp, 0x7C00
	mov bp, 0x0500
	sti

	call ResetDisk

FindRootDir:
	mov ax, 0x0000
	mov ax, word [bpbSectorsPerFAT]
	mov bx, word [bpbNumberOfFATs]
	mul bx
	add ax, 1					;AX is now the starting sector of the root directory in LBA
	jmp LBAToCHS					;we now need to convert this into the CHS format 

ReadFAT:
	mov di, [0x7E00]
	mov si, [KERNEL]
	cmp si, di
	jne _NotFound
	inc si
	inc di
	dec cx
	cmp cx, 0x0000
	je _LoadEntry
	jne ReadFAT

_LoadEntry:
	mov si, KERF
	call BPrint
	cli
	hlt

_NotFound:
	mov si, KERNF
	call BPrint
	cli	
	hlt


BPrint:
	mov ah, 0x0E
	_BPrintLoop:
	lodsb
	cmp al, 0
	je _BDone
	int 0x10
	jmp _BPrintLoop
	_BDone:
	ret

ResetDisk:
	pusha
	mov ah, 0x00
	mov dl, 0x00
	int 0x13
	jc DiskError
	popa
	ret

ReadDisk:
	pusha
	mov si, READING
	call BPrint
	popa
	mov ah, 0x02
	mov bx, 0x7E00					;ES:BX 0x0000:0x7E00
	int 0x13
	jc DiskError
	mov cx, 0x0008
	jmp ReadFAT

DiskError:
	mov si, DISKERR
	call BPrint
	cli
	hlt

LBAToCHS:						;AX = LBA
	div word [bpbSectorsPerTrack]			;AX = LBA/SPT, DX = AbsoluteSector - 1
	push dx						;Store sector on stack
	div word [bpbHeadsPerCylinder]			;AX = Cylinder, DX = head
	pop bx						;store the sector into BX from stack
	inc bx						;BX = Sector

	mov ch, bl					;Lower 8 bits [First 8 bits of the cylinder] into the upper 8 bits of CH
	mov cl, bh					;Upper 8 bits [Last 2 bits of the cylinder located here]
	shl cl, 6					;move the bits over by six so 00000011 would look like 11000000
	or cl, al					;CX should now be a proper 10 bit cylinder and 6 bit sector with dl as the head
	mov dh, 0x00					;Zero out the DH register
	xchg dh, dl					;Move the head value into the DH register and zero out the DL register
	jmp ReadDisk					;Read The disk with the current register values
	
READING db 'Reading Disk...', 0x0A, 0x0D, 0
DISKERR db '!!ATTENTION!! - Disk Error. The system has been halted to prevent damage.', 0x0A, 0x0D, 0
KERNF db '!!ATTENTION!! - No Kernel [TerSysVI.bin] found. The system has been halted to prevent damage.', 0x0A, 0x0D, 0
KERNEL db 'TerSysVI BIN'
KERF db 'Kernel found. Loading Kernel from disk...', 0x0A, 0x0D, 0

times 510 - ($-$$) db 0
dw 0xAA55
The error seems to occur when I call ReadDisk as the reading disk message appears, then the message saying there was a disk error shows. I'm not sure what is wrong with it any help would be amazing.

Re: File System Issues

Posted: Mon May 07, 2018 12:35 pm
by BenLunt
Hi,

Code: Select all

   ...
bpbNumberOfFATs: 		DB 2			;How many FAT tables exist (The oringal and a backup)
bpbRootEntries: 		DW 224		;How many files can be stored in the root directory
   ...
bpbSectorsPerFAT: 		DW 9			;how many sectors the FAT table takes up on disk
bpbSectorsPerTrack: 	DW 18		;how many sectors fit on one track

   ...

FindRootDir:
	mov ax, 0x0000
	mov ax, word [bpbSectorsPerFAT]
	mov bx, word [bpbNumberOfFATs]
Besides not needing to clear out ax first, bx is now *not* the number of FATs as you might think it would be. You are looking for bx to be 2, when in fact it is now 57,346. First off, the floppy doesn't have anywhere near that amount of sectors. But why is it wrong?

Code: Select all

	mov bx, word [bpbNumberOfFATs]
Tells the assembler to create code to retrieve the 16-bit word at offset bpbNumberOfFATs. Since the 16-bit word at bpbNumberOfFATs is infact, 02 E0 (0xE002), you are not multiplying by 2.

I strongly suggest that you get an emulator that will allow you to single step through your code. Bochs allows this via a graphical debugger interface. You can single step and compare what the values should be and then know where the error is.

A great example would be to place a break point just before the "INT 0x13" and check to see that the other register values are what you think they should be.

Ben

Re: File System Issues

Posted: Wed May 09, 2018 8:21 pm
by Armature
Update: I have since written a small function that prints out the hex in a register. I then used this to see what was in the AH register calling the interrupt and the return code was 0x01 which means the command used in invalid. I can't see any part of the read function thats invalid. Can you guys?
I have also fixed the last issue with the code. The new code is now this:

Code: Select all

org 0x7C00				;1)
jmp short Boot				;2)
nop					;3)
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=		;4)
bpbOEM			db "AAAAAAAA"	;5) OEM label for the disk (8 bytes)		
bpbBytesPerSector:  	DW 512		;6) The size of the sectors in bytes
bpbSectorsPerCluster: 	DB 1		;7) How many sectors make up a cluster
bpbReservedSectors: 	DW 1		;How many sectors are being reserved (only one: the boot sector)
bpbNumberOfFATs: 	DB 2		;How many FAT tables exist (The oringal and a backup)
bpbRootEntries: 	DW 224		;How many files can be stored in the root directory
bpbTotalSectors: 	DW 2880		;How many sectors exist on this disk
bpbMedia: 		DB 0xf0		;The type of media
bpbSectorsPerFAT: 	DW 9		;how many sectors the FAT table takes up on disk
bpbSectorsPerTrack: 	DW 18		;how many sectors fit on one track
bpbHeadsPerCylinder: 	DW 2		;how many physical heads 
bpbHiddenSectors: 	DD 0
bpbTotalSectorsBig: 	DD 0
bsDriveNumber: 		DB 0
bsUnused: 		DB 0
bsExtBootSignature: 	DB 0x29
bsSerialNumber:		DD 0xa0a1a2a3
bsVolumeLabel: 		DB "AAAAAAAAAAA"
bsFileSystem: 		DB "FAT12   "
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
Boot:
	cli
	mov ax, 0x0000
	mov es, ax
	mov ds, ax
	mov ss, ax
	mov sp, 0x7C00
	mov bp, 0x0500
	sti
	call ResetDisk

FindRootDir:
	mov ax, word [bpbSectorsPerFAT]
	mov bx, 0x0002
	mul bx
	add ax, 1					;AX is now the starting sector of the root directory in LBA
	call LBAToCHS					;we now need to convert this into the CHS format 
	call ReadDisk					;Read the disk with the values calculated by the function.
	mov cx, 0x0008

ReadFAT:
	mov di, [0x7E00]
	mov si, [KERNEL]
	cmp si, di
	jne _NotFound
	inc si
	inc di
	dec cx
	cmp cx, 0x0000
	je _LoadEntry
	jne ReadFAT

_LoadEntry:
	mov si, KERF
	call BPrint
	cli
	hlt

_NotFound:
	mov si, KERNF
	call BPrint
	cli	
	hlt

;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
BPrint:
	mov ah, 0x0E
	_BPrintLoop:
	lodsb
	cmp al, 0
	je _BDone
	int 0x10
	jmp _BPrintLoop
	_BDone:
	ret
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
ResetDisk:
	pusha
	mov ah, 0x00
	mov dl, 0x00
	int 0x13
	jc DiskError
	popa
	ret

ReadDisk:
	pusha
	mov si, READING
	call BPrint
	popa
	mov ah, 0x02
	mov bx, 0x7E00					;ES:BX 0x0000:0x7E00
	int 0x13
	jc DiskError
	ret

DiskError:
	pusha
	mov si, DISKERR
	call BPrint
	popa
	mov al, 0x00
	mov al, ah
	call WriteHex
	cli
	hlt
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
LBAToCHS:
	mov dx, 0x0000					;AX = LBA
	div word [bpbSectorsPerTrack]			;AX = LBA/SPT, DX = AbsoluteSector - 1
	push dx						;Store sector on stack
	div word [bpbHeadsPerCylinder]			;AX = Cylinder, DX = head
	pop bx						;store the sector into BX from stack
	inc bx						;BX = Sector

	mov ch, bl					;Lower 8 bits [First 8 bits of the cylinder] into the upper 8 bits of CH
	mov cl, bh					;Upper 8 bits [Last 2 bits of the cylinder located here]
	shl cl, 6					;move the bits over by six so 00000011 would look like 11000000
	or cl, al					;CX should now be a proper 10 bit cylinder and 6 bit sector with dl as the head
	mov dh, 0x00					;Zero out the DH register
	xchg dh, dl					;Move the head value into the DH register and zero out the DL register
	ret
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
WriteHex:
	mov ah, 0x0E
	LEA bx, [HEX] 
	mov ch, al
	shr al, 4					;AL now equals the Upper nibble
	and al, 0x0F					;Mask is so only the lower nibble is printed				
	xlat						;Compare AL to our table at 0x0000:0x7E00(DS:BX)
	int 0x10
	shl ch, 4
	shr ch, 4
	mov al, ch
	and al, 0x0F
	xlat
	int 0x10
	ret
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=	
READING db 'Reading Disk...', 0x0A, 0x0D, 0
DISKERR db '!!ATTENTION!! - Disk Error. INT - 0x13 : AH - 0x', 0
KERNF db '!!ATTENTION!! - No Kernel found. Halting', 0x0A, 0x0D, 0
KERNEL db 'TerSysVI BIN'
KERF db 'Kernel found. Loading Kernel from disk...', 0x0A, 0x0D, 0
HEX db '0123456789ABCDEF'

times 510 - ($-$$) db 0
dw 0xAA55

Re: File System Issues

Posted: Wed May 09, 2018 11:06 pm
by MichaelPetch
Int 13h/AH=2 requires you to set AL to the number of sectors to read. Since you don't set it before calling disk read it is probably an invalid value (likely 0). You need to tell it how many sectors to read. You shouldn't hard code the. Copy DL to a temporary memory location (ie boot_drive: db 0x00) and then copy the value the bIOS passes to the bootloader. So right after you set up the segment registers do something like mov [boot_drive], dl. Then in reset_disk and the LBAToCHS routines you can set DL with mov [boot_drive], dl rather than hard coding zero.

As well your LBAToCHS routine is buggy. Based on the stackoverflow answer I pointed to you a few days ago this routine should replace what you currently have with a version that works:

Code: Select all

;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
;    Function: LBAToCHS
; Description: Translate Logical block address to CHS (Cylinder, Head, Sector).
;              Works for all valid FAT12 compatible disk geometries.
;
;   Resources: http://www.ctyme.com/intr/rb-0607.htm
;              https://en.wikipedia.org/wiki/Logical_block_addressing#CHS_conversion
;              https://stackoverflow.com/q/45434899/3857942
;              Sector    = (LBA mod SPT) + 1
;              Head      = (LBA / SPT) mod HEADS
;              Cylinder  = (LBA / SPT) / HEADS
;
;      Inputs: AX = LBA
;     Outputs: DL = Boot Drive Number
;              DH = Head
;              CH = Cylinder (lower 8 bits of 10-bit cylinder)
;              CL = Sector/Cylinder
;                   Upper 2 bits of 10-bit Cylinders in upper 2 bits of CL
;                   Sector in lower 6 bits of CL
;              AX = Clobbered
;
;       Notes: Output registers match expectation of Int 13h/AH=2 inputs
;
LBAToCHS:
    xor dx, dx                 ; Upper 16-bit of 32-bit value set to 0 for DIV
    div word [bpbSectorsPerTrack] ; 32-bit by 16-bit DIV : LBA / SPT
    mov cl, dl                 ; CL = S = LBA mod SPT
    inc cl                     ; CL = S = (LBA mod SPT) + 1
    xor dx, dx                 ; Upper 16-bit of 32-bit value set to 0 for DIV
    div word [bpbHeadsPerCylinder]
                               ; 32-bit by 16-bit DIV : (LBA / SPT) / HEADS
    mov dh, dl                 ; DH = H = (LBA / SPT) mod HEADS
    mov dl, [boot_drive]       ; boot drive
    mov ch, al                 ; CH = C(lower 8 bits) = (LBA / SPT) / HEADS
    shl ah, 6                  ; Store upper 2 bits of 10-bit Cylinder into
    or  cl, ah                 ;     upper 2 bits of Sector (CL)
    ret
Now the big issue is that before you call disk_read you need to set AL to the number of sectors to read. For a simple test you should read 1 sector. I noticed you modified your code to hard code the number of FAT tables to 2. you can use the value in the BPB. Replace:

Code: Select all

   mov ax, word [bpbSectorsPerFAT]
   mov bx, 0x0002
   mul bx
With:

Code: Select all

   mov ax, word [bpbSectorsPerFAT]
   xor bh, bh
   mov bl, [bpbNumberOfFATs]
   mul bx
Note: XOR'ing a register with itself is the same as zeroing that register. It is a preferred idiom for zeroing a register if you don't care about the flags being clobbered.

FAT12 uses 8.3 file naming convention. When stored in the FAT all file names are 11 bytes wide and the period is dropped. KERNEL db 'TerSysVI BIN' should be KERNEL db 'TerSysVIBIN' (Also be aware of issues with case as it related to FAT12)