Boot from SATA Hard, cannot boot from SATA CD Rom
Posted: Thu Jun 12, 2014 1:16 am
Hi all.
My bootloader is followed by my Secondary bootloaded, which is followed by the Kernel.
I have no record structure, eg files to load, I know the exact locations of the three files.
My issue is loading from SATA CR Rom.
The bootloader loads fine.
The secondary bootloader loads fine.
But..
When kernel is loading the SATA readsectors code does not work, this was copied from somewhere.
If I change to a SATA Hard Disk it works fine, I have a utility which changes the boot sector location.
So I am assuming that I have missed setting it up correctly.
The code below works like this.
* Param eax is passed to BootableDevice.SATA, which is the PCI address of the SATA device
* Checks for Implemented port
* Configures port
* Reads
Where is loops is the *********************************** Here ********************
comment.
If someone could put another pair of eyes on the code and show me what I have missed it would be appreciated.
Regards, Alistair
My bootloader is followed by my Secondary bootloaded, which is followed by the Kernel.
I have no record structure, eg files to load, I know the exact locations of the three files.
My issue is loading from SATA CR Rom.
The bootloader loads fine.
The secondary bootloader loads fine.
But..
When kernel is loading the SATA readsectors code does not work, this was copied from somewhere.
If I change to a SATA Hard Disk it works fine, I have a utility which changes the boot sector location.
So I am assuming that I have missed setting it up correctly.
The code below works like this.
* Param eax is passed to BootableDevice.SATA, which is the PCI address of the SATA device
* Checks for Implemented port
* Configures port
* Reads
Where is loops is the *********************************** Here ********************
comment.
If someone could put another pair of eyes on the code and show me what I have missed it would be appreciated.
Regards, Alistair
Code: Select all
msgPossibleBootDeviceSATA DB "Possible Boot Device - SATA", 0
msgPossibleBootDeviceSATA.BaseAddress DB "Base Address - BAR5", 0
msgPossibleBootDeviceSATA.KernelBootSector DB "Kernel Boot Sector", 0
msgPossibleBootDeviceSATA.KernelSectorSize DB "Kernel Sector Size", 0
msgPossibleBootDeviceSATA.Port DB "Port", 0
msgPossibleBootDeviceSATA.Destination DB "Destination", 0
ahci_port dq 0
ahci_base dq 0
ahci_cmdlist equ 0x10000
ahci_cmdtable equ 0x11000
; Param: eax = PCI address with enabled bit 31 set; Returns: If carry set then not bootable
ProcX BootableDevice.SATA
push rax
push rsi
rol rax, 32
Mov2 rsi, msgPossibleBootDeviceSATA
Mov2 r15, rax
call MessageHEX64
pop rsi
pop rax
Mov2 rbx, 0
Mov2 r14, 0 ; ahci_port
Mov2 r15, 0 ; BAR5
Mov2 ebx, eax ; PCI Address
Mov2 rcx, 0
lea rax, [rbx + (9 << 2)] ; BAR5
Mov2 dx, 0x0CF8
out dx, eax
Mov2 dx, 0x0CFC
in eax, dx
Mov2 r15, rax
Mov2 [ahci_base], rax
; Search the implemented ports for a drive
mov ecx, [r15 + 0x0C] ; PI – Ports Implemented
mov r10, 0x128 ; Offset to Port 0 Serial ATA Status
jmp .FirstPort
.PortNotImplemented:
inc r14
shr ecx, 1
add r10, 0x80 ; Each port has a 128 byte memory space
.FirstPort:
jecxz .NoBootableDevice
bt ecx, 0 ; Valid port?
jnc .PortNotImplemented
mov eax, [r15 + r10]
cmp eax, 0
je .PortNotImplemented
.FoundImplementedPort:
mov [ahci_port], r14
call BootableDevice.SATA.ImplementedPort
jc .PortNotImplemented
ret
.NoBootableDevice:
stc ; Not bootable device
ret
EndProc
ProcX BootableDevice.SATA.ImplementedPort
; Configure Port
push rax
push rbx
push rcx
push r14
push r15
push rdi
Mov2 rdi, [ahci_base]
Add2 rdi, 0x100
shl r14, 7
Add2 rdi, r14
Mov2 rax, ahci_cmdlist
Mov2 rbx, 0
Mov2 rcx, ahci_cmdlist + 0x1000
Mov2 [rdi + 0x00], eax
Mov2 [rdi + 0x04], ebx
Mov2 [rdi + 0x08], ecx
Mov2 [rdi + 0x0C], ebx
Mov2 [rdi + 0x10], ebx
Mov2 [rdi + 0x14], ebx
; Load sectors
mov rax, [BootSector]
Add2 rax, 1
Add2 rax, [SecondBootLoaderSectors]
Mov2 rcx, [KernelSectors] ; Number of Sectors to read
Mov2 rdx, [ahci_port] ; Port
Mov2 rdi, KernelStartAddress ; Destination
Mov2 rsi, msgPossibleBootDeviceSATA.Port
Mov2 r15, rdx
call MessageHEX64
push rax
push rsi
push r15
Mov2 rsi, msgPossibleBootDeviceSATA.BaseAddress
Mov2 r15, [ahci_base]
call MessageHEX64
Mov2 rsi, msgPossibleBootDeviceSATA.KernelBootSector
Mov2 r15, rax
call MessageHEX64
Mov2 rsi, msgPossibleBootDeviceSATA.KernelSectorSize
Mov2 r15, rcx
call MessageHEX64
Mov2 rsi, msgPossibleBootDeviceSATA.Destination
Mov2 r15, rdi
call MessageHEX64
pop r15
pop rsi
pop rax
call BootableDevice.SATA.ReadSectors
jnc .BootableDevice
.NotBootableDevice:
stc ; Not bootable device
.BootableDevice:
pop rdi
pop r15
pop r14
pop rcx
pop rbx
pop rax
ret
EndProc
; -----------------------------------------------------------------------------
; readsectors -- Read data from a SATA hard drive
; IN: RAX = starting sector # to read
; RCX = number of sectors to read (up to 8192 = 4MiB)
; RDX = disk #
; RDI = memory location to store sectors
; OUT: RAX = RAX + number of sectors that were read
; RCX = number of sectors that were read (0 on error)
; RDI = RDI + (number of sectors read * 512)
; Carry set on Error
; All other registers preserved
ProcX BootableDevice.SATA.ReadSectors
push rbx
push rdi
push rsi
push rcx
push rax
push rcx ; Save the sector count
push rdi ; Save the destination memory address
push rax ; Save the block number
push rax
shl rdx, 7 ; Quick multiply by 0x80
add rdx, 0x100 ; Offset to port 0
mov rsi, [ahci_base]
; Command list setup
mov rdi, ahci_cmdlist ; command list (1K with 32 entries, 32 bytes each)
xor eax, eax
mov eax, 0x00010005 ; 1 PRDTL Entry, Command FIS Length = 20 bytes
stosd ; DW 0 - Description Information
xor eax, eax
stosd ; DW 1 - Command Status
mov eax, ahci_cmdtable
stosd ; DW 2 - Command Table Base Address
xor eax, eax
stosd ; DW 3 - Command Table Base Address Upper
stosd
stosd
stosd
stosd
; DW 4 - 7 are reserved
; Command FIS setup
mov rdi, ahci_cmdtable ; Build a command table for Port 0
mov eax, 0x00258027 ; 25 READ DMA EXT, bit 15 set, fis 27 H2D
stosd ; feature 7:0, command, c, fis
pop rax ; Restore the start sector number
shl rax, 36
shr rax, 36 ; Upper 36 bits cleared
bts rax, 30 ; bit 30 set for LBA
stosd ; device, lba 23:16, lba 15:8, lba 7:0
pop rax ; Restore the start sector number
shr rax, 24
stosd ; feature 15:8, lba 47:40, lba 39:32, lba 31:24
mov rax, rcx ; Read the number of sectors given in rcx
stosd ; control, ICC, count 15:8, count 7:0
mov rax, 0x00000000
stosd ; reserved
; PRDT setup
mov rdi, ahci_cmdtable + 0x80
pop rax ; Restore the destination memory address
stosd ; Data Base Address
shr rax, 32
stosd ; Data Base Address Upper
stosd ; Reserved
pop rax ; Restore the sector count
shl rax, 9 ; multiply by 512 for bytes
sub rax, 1 ; subtract 1 (4.2.3.3, DBC is number of bytes - 1)
stosd ; Description Information
add rsi, rdx
mov rdi, rsi
add rdi, 0x10 ; Port x Interrupt Status
xor eax, eax
stosd
mov rdi, rsi
add rdi, 0x18 ; Offset to port 0
mov eax, [rdi]
bts eax, 4 ; FRE
bts eax, 0 ; ST
stosd
mov rdi, rsi
add rdi, 0x38 ; Command Issue
mov eax, 0x00000001 ; Execute Command Slot 0
stosd
mov rdi, 0x1FFFF ; *********************************************************** Here **************************8
.poll:
dec rdi
jz .PortLocked
mov eax, [rsi+0x38]
cmp eax, 0
jne .poll
mov rdi, rsi
add rdi, 0x18 ; Offset to port 0
mov eax, [rdi]
btc eax, 4 ; FRE
btc eax, 0 ; ST
stosd
pop rax ; rax = start
pop rcx ; rcx = number of sectors read
add rax, rcx ; rax = start + number of sectors read
pop rsi
pop rdi
mov rbx, rcx ; rdi = dest addr + number of bytes read
shl rbx, 9
add rdi, rbx
pop rbx
clc
ret
.PortLocked:
pop rax
pop rcx
pop rsi
pop rdi
pop rbx
stc
ret
EndProc