Why can I not change the PCI configuration registers on linux? - linux

I want to change Vendor_ID and Device_ID from a PCI device.
However, every change I make will not save and I have no clue why.
First I tried making changes using setpci which results in this:
# sudo setpci -s 01:00.0 00.w
# 8086
# sudo setpci -s 01:00.0 00.w=168C
# sudo setpci -s 01:00.0 00.w
# 8086
Then I tried making the same changes using two different hex editors, editing the config file located in /sys/bus/pci/devices/0000:01:00.0/, but after saving, the file seems unchanged.
I did open it as root and I don't get any errors when saving.
I also tried ethtool, but it cannot even access the registers:
# sudo ethtool -e wlan0
# Cannot get EEPROM data: Operation not supported
I tried everything of the above on both Lubuntu 15.10 and Knoppix 7.6, resulting in the exact same behaviour.
So, why does this happen?
If the registers are protected, is there a way to unprotect them?
Some more information:
The mentioned pci device is a Intel 7260-AC Wireless Network Adapter
I want the BIOS to recognize it as a Qualcomm Atheros AR9485 Wireless Network Adapter, because it's whitelist blocks everything else.
Modifying the BIOS is not an option.
I'm running Lubuntu and Knoppix from a USB drive

PCI Configuration registers typically have attributes such as read only (RO), read write (RW), or other less common ones.
The problem is that you are trying to write a value to a read only register. I have not seen the documentation for this particular device, but I have worked with other Intel PCI devices and I have never seen a RW (read/write) device ID or vendor ID register. For example, look at this link on page 96, the VID and DID registers are RO (read only).
Unfortunately, there is no way to change the read only attribute of the register, as this is almost certainly enforced at the hardware level.
Assuming you could change the device ID or vendor ID registers, I imagine this would not necessarily mean a working network adapter, as the BIOS and OS use these values for ACPI and device drivers. There may be a way to fake the device ID and vendor ID in the BIOS, but as you say that is not an option and I don't think it would work anyway.
Depending on how/why your BIOS is whitelisting Qualcomm wireless adapters versus Intel wireless adapters might provide some workaround for this problem. I say the best solution would be to alter the BIOS whitelist somehow, perhaps through an update.
In case it helps, I have code that can modify PCI configuration registers of any device (although this will not circumvent hardware level restrictions such as RO, RW, ...). I don't think this will fix your problem but at the very least you can learn more about PCI configuration registers from it.

Related

How to programmatically read ThunderBolt firmware from UEFI

ThunderBolt firmware is stored in its own SPI flash and is updatable from the OS. The system's UEFI firmware is also able to access its configuration data in the flash - users are able to change the ThunderBolt Security Level (SL) from the firmware setup menu during pre-boot. This means there is definitely some way to access the ThunderBolt firmware via some UEFI protocol, but nothing I've tried seems to work.
What I've Tried
I'm able to successfully identify the ThunderBolt device based on its vendor ID and device ID using the EFI_PCI_IO_PROTOCOL.
I initially thought the firmware is an option ROM, so it should be accessible via EFI_PCI_IO_PROTOCOL.RomImage. However the value is 0. I then thought the Expansion ROM Base Address Register (XROMBAR) that's inside the PCI Configuration Space may have it. But the XROMBAR is also 0. Extracting the firmware by reading the SPI flash using a hardware programmer, I found that it doesn't have the option ROM's signatures of 0xAA55 and "PCIR" anywhere. So it seems like the firmware is not an option ROM.
I then thought it could be stored in a firmware volume and thus should be accessible via the EFI_FIRMWARE_VOLUME2_PROTOCOL. I searched through all the firmware volumes and found a few option ROM, but none of them belong to ThunderBolt (as seen from their vendor ID and device ID).
Background
I was looking at the ThunderSpy exploit and the report states that the ThunderBolt firmware is not verified during boot. I thought this was unusual since my thinking then was that the firmware should be an option ROM, and option ROMs must be signed and verified by Secure Boot during every boot. From my findings so far, it seems like the firmware isn't an option ROM and is most likely executed directly on the ThunderBolt controller chip and not on the CPU, hence it is outside the purview of Secure Boot. I'm trying to programmatically access the firmware so as to see if there are ways to defend against ThunderSpy-like attacks where malicious modifications were made to the firmware.

Keyboard problem on Lichee Pi Zero with kernel 5.2+

My question is about Lichee Pi Zero board (based on Allwinner/Sunxi V3s SoC).
Initially I used pre-built Linux image (kernel 4.10.02), it has no built-in Wi-Fi support (for Realtek 8327BS chip), so I downloaded the latest kernel version from here and built it with the default settings.
LCD is ok, Wi-fi looks good too (LED is blinkikng), but I cannot use keyboard anymore - there is no reaction from OS, when I connect something to USB (no message and no input from keyboard).
Hardware is OK and works good with the old Linux image.
I have also tried the latest kernel from kernel.org with the same bad result.
Please help to understand the reason. I suppose bad settings, but HID supoort is enabled.
Update 1.
I establish connection through UART. As I see, some USB features are detected during boot:
I'm able to load some drivers using insmod also:
Unfortunately, Linux still does not recognize any USB Device. I have connected mouse, keyboard, hub, mass storage and got no reaction from OS. It looks like devices do not get power (there is no light from mouse).
Update 2.
The best way I have found at the moment is to use buildroot-licheepi-zero.
It's very easy to use:
make licheepi_zero_defconfig
make menuconfig (optional)
make
After many-hour wainting I got the sdcard.img. It includes all neccessary files (zImage, RootFS, u-boot.bin, etc) and could be placed to SD with linux dd or etcher.
Linux boots successfully, but you can use terminal only through UART, as there is no LCD output.
You can put LCD itself to work:
make uboot-menuconfig
make
BUT there is still no user login prompt on the LCD after boot. So I need to log in and put command through UART.
Please share suggestion if any.
Update 3.
The change below enables login prompt on LCD (and disables it through UART):
make menuconfig
Now we are able to use Wi-Fi:
insmod /lib/modules/4.14.14-licheepi-zero/kernel/drivers/staging/rtl8723bs/r8723bs.ko
ifconfig wlan0 up
edit file /etc/wpa_supplicant.conf to add your Wi-Fi SSID and PSK
wpa_supplicant -B -d -i wlan0 -c /etc/wpa_supplicant.conf
udhcpc -i wlan0
Connection is established now, we can ping and so on.
There is still the question - how to enable full-functional terminal both on LCD and UART.
Many thanks!
With regards,
Maksim
The best solution is to use Buildroot.
Please check updates at topic start for details.

Why doesn't Zaber device show up in dev directory?

My Zaber device is X-MCB2, which is connected to my computer through USB. Command lsusb can show its information as below, but cannot find it in /dev directory.
Bus 003 Device 023: ID 2939:495b
There is another Arduino device connected to my computer as well. Unlike Zaber device, this Arduino device works well, its name in /dev is ttyACM0.
Even if I plugged out the Arduino device, the Zaber device still does NOT show up in /dev directory.
My linux kernel is 2.6.32, and this Zaber device shouldn't need additional driver.
I resolved this issue according to the following link: https://github.com/arduino/Arduino/issues/1389.
echo "0x2939 0x495b" > /sys/bus/usb/drivers/cdc_acm/new_id
Thanks for posting your answer Jeff.
The likely cause of the issue is that Zaber controllers implement USB using CDC ACM, and set 0 for the Protocol field of the USB interface descriptor (indicating that the device doesn't accept AT commands).
In Linux 2.6.32, the CDC ACM kernel driver, which should handle devices
of this type, is written in such a way that it doesn’t take control of
devices whose Protocol field is 0 (instead it has a specific list of
Protocol numbers which it accepts, but that list does not include 0). Instead, you must manually attach it as in the posted solution.
This issue was fixed in kernel 2.6.36.
Here are a list of the commands that will manually attach the Zaber controllers with USB:
X-MCB2:
echo "0x2939 0x495b" > /sys/bus/usb/drivers/cdc_acm/new_id
X-MCB1:
echo "0x2939 0x495a" > /sys/bus/usb/drivers/cdc_acm/new_id
A-MCB2:
echo "0x2939 0x459" > /sys/bus/usb/drivers/cdc_acm/new_id

Linux Virtual USB device driver

My goal is to create a virtual USB char device (not block device) for Linux 2.6.32 and above (I use debian squeeze) that would be recognize by the system.
I would like that this device be listed with lsusb as a normal USB device, and that every application could use libusb in order to open the device, and send control message, and make bulk write/read. But behind this virtual device, it's behavior would be set by my application. I want to set it's product ID, it's vendor ID, answer to USB status, and bulk read.
I've read some posts about how to use USB/IP in order to create a virtual USB device, and that's exactly what I want to do
Installation and emulation of virtual USB Device
http://breaking-the-system.blogspot.fr/2014/08/emulating-usb-devices-in-python-with-no.html
But unfortunately, when I tried with 2.6.32 kernel and above, I didn't succeed making it work. So I looked at how to create a kernel module that would create the virtual device :
http://pete.akeo.ie/2011/08/writing-linux-device-driver-for-kernels.html
This one looks great also, but the sample provided doest not indicate how to make it an USB device.
I've seen some post talking about it with windows but none that could help me with Linux.
I would like to avoid buying some USB programmable cards when it can be done with software.
Have anyone any leads on how to make the first methods works under newer kernel, or convert the sample code of the second method for making an USB device ?
I have fixed the code of http://breaking-the-system.blogspot.fr/2014/08/emulating-usb-devices-in-python-with-no.html (first method using USB/IP) to work with linux 4.3.
In the original code are missing USB requests like set configuration and get status. Without the implementation of all USB requests used for the OS driver the code will not work.
The fixed code can be downloaded in https://github.com/lcgamboa/USB-Emulation .
I guess raw-gadget kernel module is the thing that you want?
you can check the dummy_hcd and tests directory inside the repo, it will guide you how to create a virtual USB device

Disable a network interface in Arch Linux

I have the following problem. My PC is very old and it has a built in ethernet port that doesn't work, not due to a misconfiguration, I think it's physically damaged. It didn't work in either Ubuntu or even on Windows. I have an ethernet PCI card which is the one I use. The problem is, for some odd reason, the card that does works sometimes changes from eth0 to eth1 and I have to run dhcpd as I don't always get an IP via DHCP. Now, the actual question is, is there some way to disable the card that doesn't work using its MAC address or something? I can't disable either eth0 or eth1 as I'm sure it's not always "pointing" to the same card.
Are they the same kind of chipset or different ones?
If they are differnt then probably the simplest solution would be to just blacklist the modules for that Ethernet chipset.
You will first need to find the module name (this is for eth0):
dmesg | grep eth0
See if you have something like the following:
[ 2.209295] r8169 0000:05:00.0: eth0: RTL8168d/8111d at 0xffffc90000c6e000, 00:24:1d:11:b6:64, XID 081000c0 IRQ 44
In my case 'r8169' is the module name. You can also see a list of currently loaded modules with 'lsmod' so check that it appears in there.
Next you need to black list the module. There is an entry on the Arch wiki for that.
Fellow archer here; I have a method I use to disable my nVidia graphic card's HDMI port audio chip based on its hardware pci id; perhaps you could apply the same approach to your nic:
Find the ethernet's pci id:
$ lspci | grep Eth
00:19.0 Ethernet controller: Intel Corporation 82579V Gigabit Network Connection (rev 05)
Find the corresponding directory:
$ find /sys/devices -name *00:19.0
/sys/devices/pci0000:00/0000:00:19.0
There should be a file named "remove" in that directory.
You can disable the device at startup by editing /etc/rc.local
echo 1 > /sys/devices/pci0000:00/0000:00:19.0/remove
On second thought; this may not work in your case if modules get loaded prior to /etc/rc.local finishing... it would do you little good to have /dev/eth0 and /dev/eth1 assigned in the "wrong" order and then have /etc/rc.conf disable one of them... you could still end up with your prefered nic as eth1. This used to be a problem with alsa on multiple sound cards so methods were devised to assign the numbering of the cards via module parameters. Perhaps the module itself allows this?
I'm gathering from your description this in an onboard NIC. The best solution would be to disable it in the motherboard BIOS rather than the OS. The method for this varies by manufacturer but I'm sure you could find a manual for your model online somewhere.
I'm confused it didn't show up: In case you don't need the low level solution proposed by cjpembo, you can just use
ip link set dev <interface name> down
You get them via ip link show.

Resources