OSDev.org

The Place to Start for Operating System Developers
It is currently Wed Aug 05, 2020 11:01 am

All times are UTC - 6 hours




Post new topic Reply to topic  [ 27 posts ]  Go to page Previous  1, 2
Author Message
 Post subject: Re: issue with int 0x13
PostPosted: Sat Nov 09, 2019 11:55 am 
Offline
Member
Member
User avatar

Joined: Sat Nov 22, 2014 6:33 pm
Posts: 667
Location: USA
Armature wrote:
I've already loaded both the FAT and root Directory into a memory location. I'm not searching for that. I'm searching for a file that's on the disk. As for the value I was getting from the root directory, I said I think I'm getting the wrong one. I think its meant to be 0x001A which would be sector 26

You may be correct, however, my point is, with a starting cluster value of 0x1A00 (6656d), it is irrelevant whether your LBA to CHS code, or your read sector code is correct or not. I would start finding out why I found a cluster number of 6656 to begin with.

- Am I reading the root directory correctly?
- Am I reading from the correct root entry?
- Am I reading from the correct offset within that entry?

Once I have figured out that I have TRUE for all three questions, why am I still getting a cluster number of 6656? If any of those questions are FALSE, then I have found the issue.

I have created a tool to view disk images to help in my development. If you have a 1.44Meg disk image, using a similar tool, you can view the image's boot sector, fat, root, file data area, etc. Doing so will eliminate the possibility of a faulty file system.

Once I have figured out that the file system (image file) is correct, the FAT(s) are correct, and the root directory is valid, I can then move on to finding out why I am reading from the wrong place. For example, once I have a valid starting cluster number (in your case it might be 1Ah (26d)), I can then read from sector (1 + 9 + 9 + 14 + 26 - 2) to get the first sector (cluster) of the file, assuming I have a 1:1 ratio of clusters to sectors. Dump this sector to the screen to see if it matches the sector on the image file (disk).

Ben
- http://www.fysnet.net/osdesign_book_series.htm


Top
 Profile  
 
 Post subject: Re: issue with int 0x13
PostPosted: Tue Nov 12, 2019 4:06 pm 
Offline
Member
Member

Joined: Wed Apr 25, 2018 2:44 pm
Posts: 27
BenLunt wrote:
Armature wrote:
I've already loaded both the FAT and root Directory into a memory location. I'm not searching for that. I'm searching for a file that's on the disk. As for the value I was getting from the root directory, I said I think I'm getting the wrong one. I think its meant to be 0x001A which would be sector 26

You may be correct, however, my point is, with a starting cluster value of 0x1A00 (6656d), it is irrelevant whether your LBA to CHS code, or your read sector code is correct or not. I would start finding out why I found a cluster number of 6656 to begin with.

- Am I reading the root directory correctly?
- Am I reading from the correct root entry?
- Am I reading from the correct offset within that entry?

Once I have figured out that I have TRUE for all three questions, why am I still getting a cluster number of 6656? If any of those questions are FALSE, then I have found the issue.

I have created a tool to view disk images to help in my development. If you have a 1.44Meg disk image, using a similar tool, you can view the image's boot sector, fat, root, file data area, etc. Doing so will eliminate the possibility of a faulty file system.

Once I have figured out that the file system (image file) is correct, the FAT(s) are correct, and the root directory is valid, I can then move on to finding out why I am reading from the wrong place. For example, once I have a valid starting cluster number (in your case it might be 1Ah (26d)), I can then read from sector (1 + 9 + 9 + 14 + 26 - 2) to get the first sector (cluster) of the file, assuming I have a 1:1 ratio of clusters to sectors. Dump this sector to the screen to see if it matches the sector on the image file (disk).

Ben
- http://www.fysnet.net/osdesign_book_series.htm


That program was incredibly useful. It's shown me that the first cluster is actually 0x000F. Which means im getting the completely wrong byte from somewhere but i dont know where now. I tried using a program called sectedit to look at the 512 bytes within the sectors on the disk but i cant open an image, only physical disks. Do you guys know any programs that are able to do that? I'n the mean time I'm going to scower through all my lines of code and follow the logic to see if i've gone wrong somewhere.


Top
 Profile  
 
 Post subject: Re: issue with int 0x13
PostPosted: Tue Nov 12, 2019 8:10 pm 
Offline
Member
Member
User avatar

Joined: Sat Nov 22, 2014 6:33 pm
Posts: 667
Location: USA
Armature wrote:
That program was incredibly useful. It's shown me that the first cluster is actually 0x000F. Which means im getting the completely wrong byte from somewhere but i dont know where now. I tried using a program called sectedit to look at the 512 bytes within the sectors on the disk but i cant open an image, only physical disks. Do you guys know any programs that are able to do that? I'n the mean time I'm going to scower through all my lines of code and follow the logic to see if i've gone wrong somewhere.

Another tool that should be in your tool box. Have a look at my dump tool. It allows you to dump any part, given a byte offset, or any sector, giving a sector offset, to multiple output forms. It even has a little bit of error checking on the dump data. It is a tool I add to when I need a new feature or need to parse the data a little different. (I haven't worked on that tool in a while. I think it is still a 32-bit Windows executable, but should still work just fine on later machines)

Ben
- http://www.fysnet.net/osdesign_book_series.htm


Top
 Profile  
 
 Post subject: Re: issue with int 0x13
PostPosted: Wed Nov 13, 2019 2:34 am 
Offline
Member
Member

Joined: Mon Mar 25, 2013 7:01 pm
Posts: 2161
Armature wrote:
I tried using a program called sectedit to look at the 512 bytes within the sectors on the disk but i cant open an image, only physical disks. Do you guys know any programs that are able to do that?

I've found HxD to be quite nice. Since it's more of a general-purpose editor than a disk editor, it doesn't display sector boundaries when you're editing a disk image. I like to resize the window to show exactly 512 (0x200) bytes, so I can use page-up and page-down to scroll between sectors.


Top
 Profile  
 
 Post subject: Re: issue with int 0x13
PostPosted: Fri Nov 15, 2019 9:25 am 
Offline
Member
Member
User avatar

Joined: Fri Aug 07, 2015 6:13 am
Posts: 1083
Octocontrabass wrote:
Armature wrote:
I tried using a program called sectedit to look at the 512 bytes within the sectors on the disk but i cant open an image, only physical disks. Do you guys know any programs that are able to do that?

I've found HxD to be quite nice. Since it's more of a general-purpose editor than a disk editor, it doesn't display sector boundaries when you're editing a disk image. I like to resize the window to show exactly 512 (0x200) bytes, so I can use page-up and page-down to scroll between sectors.


Active @ Disk Editor is simply the best!
I've been using it for years and I'm supper satisfied with it.

_________________
OS: Basic OS
About: 32 Bit Monolithic Kernel Written in C++ and Assembly, Custom FAT 32 Bootloader


Top
 Profile  
 
 Post subject: Re: issue with int 0x13
PostPosted: Sat Nov 16, 2019 8:55 am 
Offline
Member
Member
User avatar

Joined: Sat Mar 31, 2012 3:07 am
Posts: 3883
Location: Chichester, UK
ghex works fine on *nix platforms to edit files, virtual disks, or physical disks.


Top
 Profile  
 
 Post subject: Re: issue with int 0x13
PostPosted: Sat Feb 01, 2020 7:31 pm 
Offline
Member
Member

Joined: Wed Apr 25, 2018 2:44 pm
Posts: 27
Right, i know its been quite some time since I last posted here, I just started my first year on a Computer Science course at Kings and its honestly a lot more work than anticipated so my little OS project has been laying neglected for quite some time. But, i think i figured out what the issue was after looking over the code with some fresh eyes. So, first things first, I use this piece of code:

Code:
FATFindEntry:                 ;0001)
   pusha            ;0002) Preserver all the registers before the function
   mov si, FileName      ;0003) Move the name of the file into source index for comparison
   mov bx, ROOTDIR      ;0004) move the memory address into the bx register
   mov ch, 0x0A         ;0005) Counter for the letters in an entry
   mov cl, 0xE1         ;0006) Counter for the number of file entries
   push bx            ;0007) Preserve the starting address of the file name
.FATFECompareString:      ;0008)
   mov ah, [si]         ;0009) get a byte, the first character, from the source index
   mov al, [bx]         ;0010) get a byte, the first character in the root directory, from the memory address
   inc si                    ;0011) increment the source index for the next character of the file name
   inc bx            ;0012) increment the memory address for the next letter u=in the root directory
   call WriteHex               ;0000) DEBUGGING Write the letter from the FAT to the console co i can see what byte we are on.
   push ax            ;0000) DEBUGGING
   mov al, ah                 ;0000) DEBUGGING
   call WriteHex              ;0000) DEBUGGING
   pop ax            ;0000) DEBUGGING
   cmp al, ah                 ;0013) compare the two values.
   jne .FATFEWrongEntry   ;0014) if they're not the same, we have the wrong entry so we jump out of the loop
   cmp ch, 0x00         ;0015) check to see if we have reached the last character in the file name
   je .FATFERightEntry      ;0016) if it is, we have found the file and jump out of the loop and start getting the block of the first sector
   dec ch            ;0017) if not, we mark of the current letter by taking one off the counter
   jmp .FATFECompareString   ;0018) then we repeat the loop that compares the filename with the entry in the root directory.
.FATFEWrongEntry:         ;0019)
   cmp cl, 0x00         ;0020) Check to see if we have checked all the entries in the root directory
   je .FATFEEntryNotFound   ;0021) if we have, then we haven't found the entry on the disk so we jump out of the loop
   dec cl            ;0022) if we haven't looked at allthe entries, we mark the one we just checked off the list
   mov ch, 0x0A         ;0023) reset the counter for checking the entry in the root directory.
   pop bx            ;0024)
   add bx, 0x20         ;0025)
   push bx            ;0026)
   mov si, FileName      ;0027)
   jmp .FATFECompareString   ;0028)
.FATFEEntryNotFound:                ;0029)
   pop bx            ;0030)
   mov di, FATFEStatus      ;0031)
   mov al, 0x00         ;0032)
   stosb            ;0033)
   popa                    ;0034)
   ret                    ;0035)
.FATFERightEntry:         ;0036)
   pop bx            ;0037)
   add bx, 0x1A         ;0038)
   mov al, [bx]         ;0039)
   mov ah, [bx + 1]      ;0040)
   mov di, FATOffSet      ;0041)
   stosw            ;0042)
   add ax, 0x001F         ;0043)This converts the next sector to LBA
   mov di, NxtSect         ;0044)
   stosw            ;0045)
   mov al, 0x01         ;0046)
   mov di, FATFEStatus       ;0047)
   stosb            ;0048)
   popa                    ;0049)
   ret                    ;0050)

to find the file inside the FAT table. The function is called with SI being set by what ever is calling this function. ROOTDIR is a variable which stores the location of the FAT table, which in my case is always 0x9000, meaning every every entry starts at every 0x0020 interval. As such i know that every Sector value is stored at bytes 0x001A and 0x001B respectively. I know its confusing but it works for me. Now, every time i call this function, the file is found, which is good. This works, however, the issue arose whenever i tried loading the actual data. Whenever i calculated the CHS from the LBA i got some absurd number and as a result I got the Error code 0x01 when calling interrupt 0x13, invalid command. After spending hours going through each individual byte of the FAT making sure that i got them all correct when finding the file, i deduced the issue must be with my LBA to CHS calculations, which is done here:

Code:
ConvertLBAToCHS:      ;0049)
   pusha         ;0050)Preserve all the registers by moving them to the stack
   xor dx, dx      ;0000) Zero out the dx register
   cld         ;0000) clear the direction flag
   mov si, NxtSect      ;0051)Set the source index to the memory location of the next LBA
   mov ax, FIHPT      ;0052)
   mov bx, FISPT      ;0053)
   mul bx         ;0054)
   mov bx, ax      ;0055)
   lodsw         ;0056)
   div bx         ;0057)
   mov di, CylinderTMP   ;0058)
   stosw         ;0059) the lower ten bits of AX is the cylinder the data is stored on
   mov ax, dx      ;0060) take the remainder from the divide operation and store it in ax
   mov bx, FISPT      ;0061)
   div bx         ;0062)
   mov di, Head      ;0063)
   stosb         ;0064)AL should be the head of the disk.
   inc dx
   mov ax, dx
   mov di, SectorTMP
   mov si, CylinderTMP
   xor ax, ax
   xor bx, bx
   lodsw
   mov word ax, [si]
   shr ax, 6
   mov di, SectorTMP
   mov bx, ax
   lodsw
   shr ax, 10
   shl ax, 10
   or ax, bx
   mov si, CylinderSector
   stosw
   popa
   ret


I know this is long and very inefficient, but at the time I was writing this code, I just wanted it to work, and after spending hours looking through this code, and writing it out by hand to make sure all the maths was correct, I couldn't find an issue here either. So I took a brake and focused on uni work, but then I had the urge to come back again tonight to see if I can fix the issue, and I instantly notice in the LBA calculations, I miss a very important step. I don't clear the upper four bits. Instead of using a 12 bit address, i get a 16 bit address. This extra four bits at the start or end of the sector number must have been throwing off my entire calculations. I haven't tested this yet, its half one in the morning so I need sleep, i just wanted to post this here so I can one, reference this when I inevitably forget what was wrong and break down in tears, and to secondly, get your guys opinion on this. Can you guys spot any other issues in my code? or does that seem to fix it? Ill post another update when I write the code to check if i need to clear the upper four bits of the cluster number or the lower and all that fun stuff. Its at this point in time I really wish i used FAT16 instead of FAT12.


Top
 Profile  
 
 Post subject: Re: issue with int 0x13
PostPosted: Sun Feb 02, 2020 9:06 am 
Offline
Member
Member

Joined: Mon Mar 25, 2013 7:01 pm
Posts: 2161
Armature wrote:
Can you guys spot any other issues in my code?

You keep using LODS/STOS instructions in places where you really should be using MOV. I think you've also mixed up the implied address register for them (SI vs DI) in at least one place, too.

Replace them all with MOV. You can't mix up implied registers when there aren't any.

For example, you should replace this:
Code:
   mov di, FATFEStatus      ;0031)
   mov al, 0x00         ;0032)
   stosb            ;0033)

With this:
Code:
   mov byte [FATFEStatus], 0x00


Since this will make your code easier to read, it will be easier to see if there are other problems too.


Top
 Profile  
 
 Post subject: Re: issue with int 0x13
PostPosted: Sun Apr 26, 2020 10:48 am 
Offline
Member
Member

Joined: Wed Apr 25, 2018 2:44 pm
Posts: 27
So, its been quite a few months once again but since this whole coronavirus situation has arisen, I've had a tonne more time to work on my little kernel and I have not been able to get my LBA to CHS code to work at all. I did check a few things however, I am reading the right cluster value from root directory. That value is being stored and read corredctly from a buffer. The issue resides within my conversion code. I know this for a fact as the data is read correctly when I use someone elses code. I could just use thier code and call it a day but then whats the point. I have rewritten the code and I have just cannot see the error anywhere. Would any of you be able to help? I have this awful feeling I'm missing something obvious but im just at my wits end. Here's the code:

Code:
pusha               ;0050)Preserve all the registers by moving them to the stack
   mov word ax, FIHPT      ;0000) C = LBA/(SPT*HPT)
   mov word bx, FISPT      ;0000)
   mul bx               ;0000) AX = SPT * HPT
   mov bx, ax            ;0000) BX = SPT * HPT
   mov word ax, [NxtSect]   ;0000) AX = LBA
   xor dx, dx            ;0000) DX = 0x0000
   div bx               ;0000) AX/BX  = LBA/(SPT*HPT) AX = C DX = remainder
   push ax               ;0000) Temporarily store the Cylinder
   mov ax, dx            ;0000) move the rmainder into ax reday for another div
   mov word bx, FISPT      ;0000) Set BX to the total number of sectors on a track which is used to calculate the head
   xor dx, dx            ;0000)
   div bx               ;0000) AX/BX
   mov word [HeadDrive], ax      ;0000)
   inc dx               ;0000) DX now equals the value of the sector
   mov bx, dx            ;0000) BX now equals the value of the sector
   pop ax               ;0000) AX now equals the value of the Cylinder
   mov cx, ax             ;0000) CX now equals the value of the cylinder
   shl cx, 0x006         ;0000) The upper byte and the first two bits of the lower byte CX: CCCCCCCC CCSSSSSS
   or cl, bl            ;0000) The lower byte or'ed with the upper byte of bx, which should be the sector produces the full CX value
   mov word [CylinderSector], cx
   popa
   ret


The values of the variables are:

Code:
FIBPS equ 0x0200         ;0000) The number of bytes in each sector
FISPC equ 0x01            ;0000) The number of sectors that exists with in a cluster
FIMT equ 0xF0            ;0000) The type of media being read
FISPF equ 0x0009         ;0000) The number of sectors that makes up the FAT
FISPT equ 0x0012         ;0000) The number of sectors on each track
FIHPT equ 0x0002         ;0000) The number of heads on the disk


Top
 Profile  
 
 Post subject: Re: issue with int 0x13
PostPosted: Sun Apr 26, 2020 1:23 pm 
Offline
Member
Member
User avatar

Joined: Sat Nov 22, 2014 6:33 pm
Posts: 667
Location: USA
I am going to modify your code to use the actual values so we get an idea of what is happening, assuming you want to read sector 22 (LBA, zero based):
Code:
   mov ax,2
   mov bx, 18
   mul bx
   ; dx:ax = 36
   mov bx, ax
   ; bx = ax
   mov ax,22
   xor dx, dx
   ; dx:ax = 22
   ; bx = 36
   div bx
   ; ax = 0
   ; dx = 22
   push ax   ; store the cyl
   mov ax, dx
   ; ax = 22
   mov bx,18
   xor dx, dx
   ; dx:ax = 22
   div bx
   ; ax = 1
   ; dx = 4
   mov word [HeadDrive], ax   ; <---- dh = 0 (should be 1)
   inc dx
   ; dx = 5
   mov bx, dx
   ; bx = 5
   pop ax
   ; ax = 0
   mov cx, ax
   ; cx = 0
   shl cx, 0x006
   ; cx = 0
   or cl, bl
   ; cx = 5
   mov word [CylinderSector], cx

   ; CH = 0 = low eight bits of cylinder number
   ; CL = 5 = sector number 1-63 (bits 0-5)
   ;    = 0 = high two bits of cylinder (bits 6-7, hard disk only)
   ; DH = 0 = head number  <----- error is right here

I don't see your code that (possibly) converts [HeadDrive] to the head/drive value for the interrupt service, but as of this code, DH doesn't included the correct value.

I think your code is correct, you are just not storing the correct value in 'HeadDrive' and/or then not placing the correct value in to DH before the read.

On a different note, you can do this a little bit easier if you use the following:
Code:
  ; Sector   = (LBA mod SPT) + 1
  ; Head     = (LBA  /  SPT) mod Heads
  ; Cylinder = (LBA  /  SPT)  /  Heads
Since a MOD operation uses a DIV, you only have to do the divide of LBA and SPT once.
Then divide that value by HEADs, which will give you the HEAD value (AX) and the CYL value (DX) with one operation.
Code:
  dx:ax = LBA
  div SPT
  Sector = dx + 1
  div Heads
  Head = dx
  Cyl = ax


Ben


Top
 Profile  
 
 Post subject: Re: issue with int 0x13
PostPosted: Sun Apr 26, 2020 3:27 pm 
Offline
Member
Member

Joined: Wed Apr 25, 2018 2:44 pm
Posts: 27
BenLunt wrote:
I am going to modify your code to use the actual values so we get an idea of what is happening, assuming you want to read sector 22 (LBA, zero based):
Code:
   mov ax,2
   mov bx, 18
   mul bx
   ; dx:ax = 36
   mov bx, ax
   ; bx = ax
   mov ax,22
   xor dx, dx
   ; dx:ax = 22
   ; bx = 36
   div bx
   ; ax = 0
   ; dx = 22
   push ax   ; store the cyl
   mov ax, dx
   ; ax = 22
   mov bx,18
   xor dx, dx
   ; dx:ax = 22
   div bx
   ; ax = 1
   ; dx = 4
   mov word [HeadDrive], ax   ; <---- dh = 0 (should be 1)
   inc dx
   ; dx = 5
   mov bx, dx
   ; bx = 5
   pop ax
   ; ax = 0
   mov cx, ax
   ; cx = 0
   shl cx, 0x006
   ; cx = 0
   or cl, bl
   ; cx = 5
   mov word [CylinderSector], cx

   ; CH = 0 = low eight bits of cylinder number
   ; CL = 5 = sector number 1-63 (bits 0-5)
   ;    = 0 = high two bits of cylinder (bits 6-7, hard disk only)
   ; DH = 0 = head number  <----- error is right here

I don't see your code that (possibly) converts [HeadDrive] to the head/drive value for the interrupt service, but as of this code, DH doesn't included the correct value.

I think your code is correct, you are just not storing the correct value in 'HeadDrive' and/or then not placing the correct value in to DH before the read.

On a different note, you can do this a little bit easier if you use the following:
Code:
  ; Sector   = (LBA mod SPT) + 1
  ; Head     = (LBA  /  SPT) mod Heads
  ; Cylinder = (LBA  /  SPT)  /  Heads
Since a MOD operation uses a DIV, you only have to do the divide of LBA and SPT once.
Then divide that value by HEADs, which will give you the HEAD value (AX) and the CYL value (DX) with one operation.
Code:
  dx:ax = LBA
  div SPT
  Sector = dx + 1
  div Heads
  Head = dx
  Cyl = ax


Ben


Thanks for your response. I noticed this head error but i didnt know why i was getting it. Everytime I thought of just adding one to the value but then i didnt know if that would fix this one issue and break everything else. Or if that was thee main issue in the code. Ill try fixing it and seeing how it works.

I was thinking abuot using the modular and things like that but i didnt want to voer complicate things unescessarily at the moment. I wanted to mmake sure i had the theory and understanding down behind it.


Top
 Profile  
 
 Post subject: Re: issue with int 0x13
PostPosted: Mon Apr 27, 2020 8:10 am 
Offline
Member
Member

Joined: Mon Mar 25, 2013 7:01 pm
Posts: 2161
Code:
   mov word [HeadDrive], ax      ;0000)

As already mentioned, this appears to be overwriting the drive number (DL) with the head number (DH). Might I suggest a replacement?

Code:
   mov [HeadDrive+1], al

As x86 is a little-endian architecture, adding 1 to the address of a word allows you to manipulate the high byte of said word.

When you posted a couple weeks ago and deleted your post, I spotted another mistake:

Code:
   shl cx, 0x006         ;0000) The upper byte and the first two bits of the lower byte CX: CCCCCCCC CCSSSSSS

CH should contain the lowest 8 bits of the cylinder number, not the highest 8 bits. I have another suggestion for this.

Code:
   xchg cl, ch
   shl cl, 6

You can also save a couple instructions by popping the cylinder value from the stack directly into CX instead of going through AX.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 27 posts ]  Go to page Previous  1, 2

All times are UTC - 6 hours


Who is online

Users browsing this forum: No registered users and 2 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group