0

I am not able to get this working. I got this code from here:

https://wiki.osdev.org/ATA_read/write_sectors

`;=============================================================================
; ATA read sectors (LBA mode) 
;
; @param EAX Logical Block Address of sector
; @param CL  Number of sectors to read
; @param RDI The address of buffer to put data obtained from disk
;
; @return None
;=============================================================================

ata_lba_read:
               xor rax, rax           ;;;;;;; added
               mov eax, 0x28590c8     ;;;;;;; added
               pushfq
               and rax, 0x0FFFFFFF
               push rax
               push rbx
               push rcx
               push rdx
               push rdi
 
               mov rbx, rax         ; Save LBA in RBX
 
               mov edx, 0x01F6      ; Port to send drive and bit 24 - 27 of LBA
               shr eax, 24          ; Get bit 24 - 27 in al
               or al, 11100000b     ; Set bit 6 in al for LBA mode
               out dx, al
 
               mov cl, 27           ;;;;;;;;  added
               mov edx, 0x01F2      ; Port to send number of sectors
               mov al, cl           ; Get number of sectors from CL
               out dx, al
 
               mov edx, 0x1F3       ; Port to send bit 0 - 7 of LBA
               mov eax, ebx         ; Get LBA from EBX
               out dx, al
 
               mov edx, 0x1F4       ; Port to send bit 8 - 15 of LBA
               mov eax, ebx         ; Get LBA from EBX
               shr eax, 8           ; Get bit 8 - 15 in AL
               out dx, al
 
 
               mov edx, 0x1F5       ; Port to send bit 16 - 23 of LBA
               mov eax, ebx         ; Get LBA from EBX
               shr eax, 16          ; Get bit 16 - 23 in AL
               out dx, al
 
               mov edx, 0x1F7       ; Command port
               mov al, 0x20         ; Read with retry.
               out dx, al
 
.still_going:  in al, dx
               test al, 8           ; the sector buffer requires servicing.
               jz .still_going      ; until the sector buffer is ready.
 
               mov rax, 256         ; to read 256 words = 1 sector
               xor bx, bx
               mov bl, cl           ; read CL sectors
               mul bx
               mov rcx, rax         ; RCX is counter for INSW
               mov rdx, 0x1F0       ; Data port, in and out
               rep insw             ; in to [RDI]
 
               pop rdi
               pop rdx
               pop rcx
               pop rbx
               pop rax
               popfq
               ret`

and writing:

`;=============================================================================
; ATA write sectors (LBA mode) 
;
; @param EAX Logical Block Address of sector
; @param CL  Number of sectors to write
; @param RDI The address of data to write to the disk
;
; @return None
;=============================================================================
 
ata_lba_write:
    xor rax, rax           ;;;;;;;; added
    mov eax, 0x0052        ;;;;;;;; added
    pushfq
    and rax, 0x0FFFFFFF
    push rax
    push rbx
    push rcx
    push rdx
    push rdi
 
    mov rbx, rax         ; Save LBA in RBX
 
    mov edx, 0x01F6      ; Port to send drive and bit 24 - 27 of LBA
    shr eax, 24          ; Get bit 24 - 27 in al
    or al, 11100000b     ; Set bit 6 in al for LBA mode
    out dx, al
 
    mov cl, 27           ;;;;; added
    mov edx, 0x01F2      ; Port to send number of sectors
    mov al, cl           ; Get number of sectors from CL
    out dx, al
 
    mov edx, 0x1F3       ; Port to send bit 0 - 7 of LBA
    mov eax, ebx         ; Get LBA from EBX
    out dx, al
 
    mov edx, 0x1F4       ; Port to send bit 8 - 15 of LBA
    mov eax, ebx         ; Get LBA from EBX
    shr eax, 8           ; Get bit 8 - 15 in AL
    out dx, al
 
 
    mov edx, 0x1F5       ; Port to send bit 16 - 23 of LBA
    mov eax, ebx         ; Get LBA from EBX
    shr eax, 16          ; Get bit 16 - 23 in AL
    out dx, al
 
    mov edx, 0x1F7       ; Command port
    mov al, 0x30         ; Write with retry.
    out dx, al
 
.still_going:  in al, dx
    test al, 8           ; the sector buffer requires servicing.
    jz .still_going      ; until the sector buffer is ready.
 
    mov rax, 256         ; to read 256 words = 1 sector
    xor bx, bx
    mov bl, cl           ; write CL sectors
    mul bx
    mov rcx, rax         ; RCX is counter for OUTSW
    mov rdx, 0x1F0       ; Data port, in and out
    mov rsi, rdi
    rep outsw            ; out
 
    pop rdi
    pop rdx
    pop rcx
    pop rbx
    pop rax
    popfq
    ret`

tried adding the statements with comments ';;;;; added'

I am trying to read a file located at that specific offset of 0x28590c8 and write to 0x0052. im not sure if that is interpreting it as little endian in that manner but trying to write to 0x5200 which is the 41st sector on the drive, 27 sectors of a file that is 27 sectors long. thats 41st sector into the beginning of the drive which is empty space.

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
shawnixer
  • 1
  • 1
  • Does your (virtual) system *have* a legacy ATA controller? I would guess that a SATA controller in AHCI mode wouldn't respond to these I/O ports. (Check the BIOS/config settings for your virtual guest machine; it might have a legacy IDE option like some real motherboards do.) – Peter Cordes Apr 20 '23 at 05:19
  • i am testing this on a real laptop actually – shawnixer Apr 20 '23 at 17:00
  • I'd recommend testing it in an emulator like Bochs so you can single-step your code with a debugger. Once you're sure it works there, you can try it on real hardware, with your BIOS configured to legacy IDE mode instead of "RAID" or "AHCI". – Peter Cordes Apr 21 '23 at 01:26
  • Can you please recomend a specific debugger for this? Ive only ever used x64dbg in windows. I havent used bochs before and Im going to need quite a bit of experimentation with it because it is very comprehensive compared to VirtualBox. aside from that, does the code I stated actually work in 64-bit longmode? By looking at it, what could be wrong with my code? Because the stuff I added was not in the original code so I don't know how it even worked for anyone. There was nothing initialized in rax (for the LBA) or cl (for the sectors) – shawnixer Apr 22 '23 at 03:15
  • Bochs has a debugger built-in, letting you single-step kernel code even with interrupts disabled. Since it's a simulator, this can be totally transparent even to timeouts of I/O devices. https://wiki.osdev.org/Bochs . Other than Bochs, QEMU can act as a remote for GDB. – Peter Cordes Apr 22 '23 at 03:36
  • Thanks. I'll look into it. The code, though, works normally? – shawnixer Apr 22 '23 at 04:04

0 Answers0