# Motherboard-First PCI Slot Mapper

> Source: <https://gist.github.com/Tranquility2/745bebf54c60f253c31c467b1c89ba8f>
> Published: 2026-05-22 17:48:51+00:00

physical_pci_tree.sh

      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      
Learn more about bidirectional Unicode characters

 
    Show hidden characters

#!
/bin/bash

#
 Ensure root privileges

if
 [ 
"
$EUID
"
 
-ne
 0 ]
;
 
then

 
echo
 
"
Please run as root (sudo).
"

 
exit
 1

fi

echo
 
"
==========================================================================================
"

echo
 
"
🌐 MOTHERBOARD PCI SLOT TREE & STATUS
"

echo
 
"
==========================================================================================
"

#
 Temporary files to hold processed blocks

tmp_block=
"
/tmp/dmi_block.txt
"

rm -f 
"
$tmp_block
"

#
 Read dmidecode output and split by Handle (individual slot blocks)

dmidecode -t slot 
|
 
while
 IFS= 
read
 -r line
;
 
do

 
if
 [[ 
"
$line
"
 
=~
 ^Handle
\ 
 ]] 
||
 [[ 
-z
 
"
$line
"
 ]]
;
 
then

 
#
 Process the previous block if it exists

 
if
 [ 
-s
 
"
$tmp_block
"
 ]
;
 
then

 
#
 Extract variables

            slot_name=
$(
grep 
"
Designation:
"
 
"
$tmp_block
"
 
|
 cut -d
'
:
'
 -f2- 
|
 xargs
)

            slot_type=
$(
grep 
"
Type:
"
 
"
$tmp_block
"
 
|
 cut -d
'
:
'
 -f2- 
|
 xargs
)

            slot_usage=
$(
grep 
"
Current Usage:
"
 
"
$tmp_block
"
 
|
 cut -d
'
:
'
 -f2- 
|
 xargs
)

            bus_addr=
$(
grep 
"
Bus Address:
"
 
"
$tmp_block
"
 
|
 cut -d
'
:
'
 -f2- 
|
 xargs
)

 
#
 Standardize bus address to match lspci format (domain:bus:dev.fn -> bus:dev.fn)

 
#
 Example: 0000:01:00.0 becomes 01:00.0

            pci_addr=
$(
echo 
"
$bus_addr
"
 
|
 sed 
'
s/^[0-9a-fA-F]\{4\}://
'
)

 
#
 Render Tree Structure

 
echo
 
"
├── 🔲 Slot: 
$slot_name
"

 
echo
 
"
│   ├── Type:  
$slot_type
"

 

 
if
 [ 
"
$slot_usage
"
 
=
 
"
In Use
"
 ] 
&&
 [ 
-n
 
"
$pci_addr
"
 ] 
&&
 [ 
"
$pci_addr
"
 
!=
 
"
00:00.0
"
 ]
;
 
then

 
echo
 
"
│   ├── Status: ✅ POPULATED (
$pci_addr
)
"

 

 
#
 Fetch device details and format as sub-branches

                lspci -s 
"
$pci_addr
"
 
|
 
while
 
read
 -r dev_line
;
 
do

 
echo
 
"
│   │   └── Device: 
${dev_line
#*:
[0-9a-fA-F][0-9a-fA-F].
*
 }
"

 
done

 

 
#
 Append full detail tree from lspci -v for this specific device

                lspci -v -s 
"
$pci_addr
"
 
|
 grep -E 
"
(Kernel driver|Capabilities|LnkSta:)
"
 
|
 
while
 
read
 -r cap_line
;
 
do

 
echo
 
"
│   │       └── 
$(
echo 
"
$cap_line
"
 
|
 xargs
)
"

 
done

 
else

 
echo
 
"
│   └── Status: ❌ EMPTY
"

 
fi

 
echo
 
"
│
"

 

 
#
 Clear block for next record

 
>
 
"
$tmp_block
"

 
fi

 
fi

 

 
#
 Append line to current block if inside a slot entry

 
if
 [[ 
-n
 
"
$line
"
 ]] 
&&
 [[ 
!
 
"
$line
"
 
=~
 ^
#
 ]]; then

 
echo
 
"
$line
"
 
>>
 
"
$tmp_block
"

 
fi

done

echo
 
"
└── [End of Component Mapping]
"

echo
 
"
==========================================================================================
"

#
 Cleanup

rm 
-f
 
"
$tmp_block
"
