'How to identify the device by pci capability id
How to identify the device by pci capability id? this is my code:
I try to access 34h and check if the capability id exists on the first loop If it exists, it points to the next pointer, But there seems to be some problems in the steps of getting the pointer and putting the address.
'''
push eax
push edi
push esi
mov cx,100
;mov edi,[esi]
add edi,52 ;access 34h
lopreg:
mov eax,edi ;read
mov dx,0cf8h
out dx,eax
mov dx,0cfch
in eax,dx
cmp cx,100 ;first time
je first
cmp ah,10
jne nextreg
jmp ispcie
first:
cmp ah,0
je ending
sub edi,52
movzx bx,ah
add di,bx
loop lopreg
jmp ending
ispcie:
call set_cur
mov ah,09h
lea dx,regmem ;print pcie
int 21h
jmp ending
nextreg:
cmp al,0
je ending
movzx bx,al ;
add di,bx
loop lopreg
ending:
pop esi
pop edi
pop eax
ret
'''
Solution 1:[1]
This answer is written with the assumption that this code is looking for the PCI Express Capability.
There are several problems in this code.
- At the
firstlabel, it should usealinstead ofahto determine the offset of the first capability. - The Capability ID of the PCI Express capability is 10h, not 10.
- After reading each capability header,
alcontains the capability id andahcontains the next pointer. Socmp ah, 10should becmp al, 10h. - At the
nextreglabel, it should useahinstead ofalto determine the offset of the next capability. - On each iteration, it adds
bxtodiwithout removing the previous offset. - It's not clear what
ediis initialized to, but if it does not have bit 31 set, then this code won't be reading PCI config space at all.
This should work:
mov cx,100
;mov edi,[esi]
add edi,52 ;access 34h
lopreg:
mov eax,edi ;read
mov dx,0cf8h
out dx,eax
mov dx,0cfch
in eax,dx
cmp cx,100 ;first time
je first
cmp al,10h
jne nextreg
jmp ispcie
first:
cmp al,0
je ending
sub edi,52
movzx bx,al
add di,bx
loop lopreg
jmp ending
ispcie:
call set_cur
mov ah,09h
lea dx,regmem ;print pcie
int 21h
jmp ending
nextreg:
cmp ah,0
je ending
sub di, bx
movzx bx,ah
add di,bx
loop lopreg
ending:
A better approach is to keep the original address in
ediwithout changing it, and uselea eax, [edi+ebx]for each new offset.There's no need to use
ecxas a loop counter and the logic is a bit convoluted. It can be straightened out a bit to flow more clearly.
Here's how I would write it:
lea eax,[edi+34h]
mov dx,0cf8h
out dx,eax
mov dx,0cfch
in al,dx ; read offset of first capability
cmp al,0
je ending
movzx ebx,al
lopreg:
lea eax,[edi+ebx] ; offset of next capability is in ebx
mov dx,0cf8h
out dx,eax
mov dx,0cfch
in eax,dx ; read capability header
cmp al,10h ; check if it is the PCI Express capability
je ispcie
nextreg:
cmp ah,0 ; check if it is the end of the capability list
je ending
movzx ebx, ah ; set up ebx with the offset of the next capability
jmp lopreg
ispcie:
; base of device PCI config space is in edi
; offset of PCI Express Capability is in ebx
...
ending:
(I don't know what set_cur and regmem are so I didn't attempt to write that part of the code.)
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | prl |
