3

My bootloader must go to the kernell when I press enter but it doesn't react. Bootloader is located on the first sector of the first track, head - 0, but kernel's address is: sector 3, track -0, head 1.

I even put the kernel on 5th sector of the first track. I already have functions read from floppy and write, tried to read from the head 1 where is located my kernel, and it reads correctly. But when I put in bootloader corresponding head, sector and track, in the read int 13h / ah=02h it doesn't do anything.

BootLoader

readingProcess:
        xor AX, AX     
    mov DS, AX      
    mov BX, 0060h   
    cli           
    mov ss,bx      
    mov sp,ax    
    sti           
    cld

    mov AH, 02h   
    mov AL, 25          
    mov CH, 0           
    mov CL, 3           
    mov DL, 0           
    mov DH, 1               

    mov BX, 0060h
    mov ES, BX
    xor BX, BX

    int 13h

    ;go to kernel
    jmp 0060h:0000h
ret

So, for now I really don't understand how it works, because when I try to write to floppy, to head 1, it should be almost in the middle of my .img file, but it appears me at the beginning of the file. I think that there must be a formula that would help me to get the right track and sector.

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
eLy yLe
  • 33
  • 4
  • A few things to check: You're setting the stack up to be 0060:0000. I think this means you're stack has no space in it, so the `int 13h` instruction will throw an exception, then double fault and halt. You're not checking the return value from `int 13h` to check for error. And you're trying to read 25 sectors, starting at sector 3. IIRC, that will only work if there are at least 27 sectors on the track you're trying to read. – 1201ProgramAlarm Jun 11 '19 at 22:21
  • @1201ProgramAlarm : He has set the stack at 0x0060:0x0000 which is okay. In 16-bit real mode - on the first push SP will be decremented by 2 which will wrap SP to 0x0060:0xfffe. – Michael Petch Jun 11 '19 at 22:31
  • How are you testing this? On real hardware or in an emulator/VM? If an emulator or VM which one? If on real hardware are you booting as USB Media? – Michael Petch Jun 11 '19 at 22:35
  • There is some information on LBA (logical block address) to CHS calculations in this answer: https://stackoverflow.com/questions/45434899/why-isnt-my-root-directory-being-loaded-fat12/45495410#45495410 . LBA is a number between 0 and sectors on the disk. If you know what LBA the data to read is at you can convert it to CHS is you know the number of Heads and Sectors per track of the media – Michael Petch Jun 11 '19 at 22:37
  • I still can read my second kernel which is placed on **Head** - 1, **Track** - 0, **Sector** - 3 hardcoded from kernel which is on **Head** - 0, **Track** - 0, **Sector** - 3. But I don't get why I can not read when I put my kernel closer to **Head** - 1, and even on **Head** - 1. @1201 I checked the exception and there is no exception throw. But there is another problem when I write to **Head** - 0, **Track** - 0, **Sector** - 3, and open my .img in HxD, it is situated almost to the same address, but **Head** is 0, it's like when he reach **Head** is 1, it turns back. I use VirtualBox – eLy yLe Jun 12 '19 at 06:57
  • @MichaelPetch I have in my kernel these two lines of code **[bits 16] org 0000h**. Still I don't get what I'm doing wrong, can you explain exactly how the process of jumping from bootloader to kernel should look like, only the part of reading those sectors. And another question, can the size of kernel affect this process? – eLy yLe Jun 12 '19 at 09:50
  • Many BIOSes (and I believe VirtualBox is still one of them) can't do reads and write that span across tracks. Sectors per track (if this is a floppy) is 18. If you start on head 1 sector 3 you may only be able to read 15 sectors (not 25) (3+15=18). Since you started on head 1/sector 3 the 16th sector would be on Track (cylinder) 1 and that is a problem. If you were to try and read 2 sectors starting at Track 0, Head 1, Sector 18 it likely fails the same way because it crosses onto the next track – Michael Petch Jun 12 '19 at 11:00
  • If you were to have read 25 sectors starting on Track 0, Head 0 sector 11 it may have worked. You have the first 7 sectors on head 0 remaining then it switches to Track 0 Head 1 and reads the 18 more (18+7=25). All the sectors are on the same Track 0. However had you read 26 sectors the last sector may not be read properly because it would have had to advance to the next Track (Track 1) at head 0, sector 1 and VirtualBox doesn't support the situation where you cross between tracks during a disk operation. The BIOS may have wrapped back to the beginning of Sector 1 Head 0 of Track 0 – Michael Petch Jun 12 '19 at 11:06
  • I noticed that this is discussed in this VirtualBox bug report: https://www.virtualbox.org/ticket/15503 – Michael Petch Jun 12 '19 at 11:06
  • 1
    The simplest method to avoid crossing a Track boundary on a read is to read/write one sector at a time. So rather than read 25 sectors you read 25 sectors 1 at a time. Reading 1 sector can never cross a Track boundary, otherwise you need to compute the number of sectors left on the current track and not exceed that amount and if need be split the disk read into multiple reads. – Michael Petch Jun 12 '19 at 11:09
  • Still, doesn't work. I changed my kernel in such a way to have 15 sectors and it still doesn't work, can I send u files to see what I'm doing? I suppose that I've got wrong idea about how should the jump. – eLy yLe Jun 12 '19 at 16:58

1 Answers1

4

After looking at your code, it appears that this is strictly a problem of using the right formula to get the Track(Cylinder), Head and Sector values for a given offset in the disk image file. You want to use the correct values for Int 13h/ah=2 (disk read).

From my previous answer I gave the formula as:

CHS tuples can be mapped to LBA address with the following formula:

LBA = (C × HPC + H) × SPT + (S - 1)

where C, H and S are the cylinder number, the head number, and the sector number

LBA is the logical block address
HPC is the maximum number of heads per cylinder (reported by 
    disk drive, typically 16 for 28-bit LBA)
SPT is the maximum number of sectors per track (reported by
    disk drive, typically 63 for 28-bit LBA)
LBA addresses can be mapped to CHS tuples with the following formula 
    ("mod" is the modulo operation, i.e. the remainder, and "÷" is 
    integer division, i.e. the quotient of the division where any 
    fractional part is discarded):

    C = LBA ÷ (HPC × SPT)
    H = (LBA ÷ SPT) mod HPC
    S = (LBA mod SPT) + 1

Additional information on drive addressing can be found in this Wikipedia article.

For a 1.44MiB floppy there are 2880 sectors total, HPC(Heads per cylinder) is 2, and SPT(Sectors Per Track is 18), and each sector is 512 bytes. What you need is the LBA. The LBA is simply the offset where you write the kernel (in bytes) divided by 512. In your Appender program you place a copy of the kernel at offset 738304. LBA=738304/512=1442.

You just need to convert LBA 1442 to CHS and plug those numbers into the code.

 Formula:
    C = LBA ÷ (HPC × SPT)
    H = (LBA ÷ SPT) mod HPC
    S = (LBA mod SPT) + 1

 We know:
    LBA = 1442
    HPC = 2
    SPT = 18        

Doing substitution we get:

C = 1442 ÷ (2 × 18)
H = (1442 ÷ 18) mod 2
S = (1442 mod 18) + 1

The ÷ means integer division and throw away the remainder (fraction). mod means do the division and keep the remainder, and throw away the whole part.

C = 1442 ÷ (2 × 18) = 40.0555556 = 40
H = (1442 ÷ 18) mod 2 = 80 mod 2 = 0 (80 mod 2 = 40 remainder 0)
S = (1442 mod 18) + 1 = (2) + 1 = 3 (1442 mod 18 = 80 remainder 2)

We now know for LBA 1442 that Cylinder(Track) = 40, Head = 0, Sector = 3. Your code would use those values in the Int 13h/AH=2 BIOS call. You'd place 40 in DH, 0 in CH, and 3 in CL.

You also appear to have placed a copy of the kernel at offset 2048 in the disk image. Offset 2048 is an LBA of 4 (2048/512) Using the formula and values above you'd get Cylinder(Track) = 0, Head = 0, Sector = 5. You'd place 0 in DH, 0 in CH, and 5 in CL.

Special Note: Only sectors numbers start at 1. Cylinders(Tracks) and Heads start at 0.


If you are given Cylinder(Track), Head, and Sector and need to know what LBA that corresponds to on disk the formula is:

LBA = (C × HPC + H) × SPT + (S − 1) 

If you have CHS of (40, 0, 3) with 1.44MiB drive geometry (HPC=2 and SPT=18) the LBA=(40*2+0)*18+(3-1)=1442. 1442*512=738304 would be the disk offset of that sector.

If you have CHS of (0, 0, 5) with 1.44MiB drive geometry (HPC=2 and SPT=18) the LBA=(0*2+0)*18+(5-1)=4. 4*512=2048 would be the disk offset of that sector.

These 2 calculations are the reverse of the results calculated in the first section of this answer.

Michael Petch
  • 46,082
  • 8
  • 107
  • 198
  • 1
    Sir, I'd thank you very, very, very, very much. It works perfectly, you're my HERO!! One more time, thank you and sorry for too much questions. – eLy yLe Jun 13 '19 at 06:52
  • @eLyyLe : glad you got it going. Please consider accepting it as an answer (and good enough upvoting it). More on the hows and why of `accepting an answer` can be found in this article: : https://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work/5235#5235 . There is a difference between upvoting and accepting an answer. Properly accepting an answer marks this question as solved when people query in the future. – Michael Petch Jun 13 '19 at 14:33