Boot from SATA Hard, cannot boot from SATA CD Rom

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
tsdnz
Member
Member
Posts: 333
Joined: Sun Jun 16, 2013 4:09 am

Boot from SATA Hard, cannot boot from SATA CD Rom

Post by tsdnz »

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

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
User avatar
iansjack
Member
Member
Posts: 4711
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: Boot from SATA Hard, cannot boot from SATA CD Rom

Post by iansjack »

Are you assuming a sector size of 512 bytes?
tsdnz
Member
Member
Posts: 333
Joined: Sun Jun 16, 2013 4:09 am

Re: Boot from SATA Hard, cannot boot from SATA CD Rom

Post by tsdnz »

No, CD is 2048, I just want it to read anything.

If you are refering to the shl by 9 then I also tried shl by 11 in case this was the issue.
But it still spins.

Regards, Alistair
Post Reply