-
-
Save ixs/dbaac42730dea9bd124f26cbd439c58e to your computer and use it in GitHub Desktop.
#!/usr/bin/env python3 | |
# | |
# Simple Intel x520 EEPROM patcher | |
# Modifies the EEPROM to unlock the card for non-intel branded SFP modules. | |
# | |
# Copyright 2020,2021,2022 Andreas Thienemann <[email protected]> | |
# | |
# Licensed under the GPLv3 | |
# | |
# Based on research described at https://forums.servethehome.com/index.php?threads/patching-intel-x520-eeprom-to-unlock-all-sfp-transceivers.24634/ | |
# | |
# Quick explanation of what's going on: | |
# Looking at the Intel driver at e.g. https://elixir.bootlin.com/linux/v5.8/source/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h#L2140 we can see | |
# that the bit 0x1 at Address 0x58 contains a configuration setting whether the card allows any SFP modules or if Intel specific ones are enforced | |
# by the driver. | |
# | |
# Addr Bitstring | |
# 0x58 xxxxxxx0 means Intel specific SFPs | |
# 0x58 xxxxxxx1 means any SFP is allowed. | |
# | |
# Using the parameter allow_unsupported_sfp for the kernel module we can tell the driver to accept any SFPs. | |
# But this tool will flip the right bit 1 to make that change permanent in the configuration bits in the EEPROM, | |
# thus making kernel module parameters unnecessary. | |
# | |
import subprocess | |
import sys | |
# Supported cards. If your card is supported but not listed here, please add a comment | |
# with your PCI IDs at https://gist.github.com/ixs/dbaac42730dea9bd124f26cbd439c58e | |
card_ids = { | |
"0x10fb": "82599ES 10-Gigabit SFI/SFP+ Network Connection", | |
"0x154d": "Ethernet 10G 2P X520 Adapter", | |
} | |
try: | |
intf = sys.argv[1] | |
except IndexError: | |
print("%s <interface>" % sys.argv[0]) | |
exit(255) | |
print("Verifying interface %s." % intf) | |
try: | |
with open("/sys/class/net/%s/device/vendor" % intf) as f: | |
vdr_id = f.read().strip() | |
with open("/sys/class/net/%s/device/device" % intf) as f: | |
dev_id = f.read().strip() | |
except IOError: | |
print("Can't read interface data.") | |
exit(2) | |
if vdr_id in ("0x8086"): | |
print("Recognized an Intel manufactured card.") | |
else: | |
print("No Intel manufactured card found.") | |
exit(3) | |
if dev_id in card_ids: | |
print("Recognized the %s card." % card_ids[dev_id]) | |
else: | |
print("No recognized x520-based card found.") | |
exit(3) | |
# Read eeprom at offset 0x58 | |
output = subprocess.check_output( | |
["ethtool", "-e", intf, "offset", "0x58", "length", "1"] | |
).decode("utf-8") | |
# Parse ethtool output and convert the value into a binary string | |
val = output.strip().split("\n")[-1].split()[-1] | |
val_bin = int(val, 16) | |
print("EEPROM Value at 0x58 is 0x%s (%s)." % (val, bin(val_bin))) | |
if val_bin & 0b00000001 == 1: | |
print("Card is already unlocked for all SFP modules. Nothing to do.") | |
exit(1) | |
if val_bin & 0b00000001 == 0: | |
print("Card is locked to Intel only SFP modules. Patching EEPROM...") | |
new_val = val_bin | 0b00000001 | |
print("New EEPROM Value at 0x58 will be %s (%s)" % (hex(new_val), bin(new_val))) | |
# The "magic" value we need in order to write to a intel card is "0x<device_id><vendor_id>" | |
magic = "%s%s" % (dev_id, vdr_id[2:]) | |
cmd = [ | |
"ethtool", | |
"-E", | |
intf, | |
"magic", | |
str(magic), | |
"offset", | |
"0x58", | |
"value", | |
hex(new_val), | |
"length", | |
"1", | |
] | |
print("About to run %s" % " ".join(cmd)) | |
if ( | |
input( | |
"This operation will write data to your ethernet card eeprom. Type 'yes' to confirm: " | |
).lower() | |
!= "yes" | |
): | |
print("Operation aborted.") | |
exit(1) | |
output = subprocess.check_output(cmd).decode("utf-8") | |
if len(output) == 0: | |
print("Sucess!") | |
print("Reboot the machine for changes to take effect...") | |
exit(0) | |
else: | |
print(output) |
Python 3.9 - error while executing this script.
Line 52 in module
val = output.strip().split('\n')[-1].split()[-1]
TypeError: a bytes-like object is required, not 'str'
May be, you can fix? I really need this script...
I am running on python 3.9 and this works fine.
What's your output? Add a line containing print(output)
before line 52 and it will tell you.
changing output = subprocess.check_output(['ethtool', '-e', intf, 'offset', '0x58', 'length', '1'])
to: output = subprocess.check_output(['ethtool', '-e', intf, 'offset', '0x58', 'length', '1']).decode('utf-8')
worked for me.
This worked like a charm! I did have to add the .decode('utf-8') to make it work, though.
Thanks for this awesome script!
ethtool -E ens106f0 magic 0x10FB8086 offset 0x58 value 0xfd
cause reply: offset & length out of bounds
Please, help! I need this patch!!
ethtool -E ens106f0 magic 0x10FB8086 offset 0x58 value 0xfd cause reply: offset & length out of bounds Please, help! I need this patch!!
Same problem, need help. Thanks you
@narutoxboy @newroc you have an old ethtool.
Updated the code to pass length 1
as well, which works around the issue. Good luck.
Running this on Ubuntu 22.04 gives following error:
Traceback (most recent call last):
File "/home/jani/intel_x520_patcher.py", line 52, in <module>
val = output.strip().split('\n')[-1].split()[-1]
TypeError: a bytes-like object is required, not 'str'
Solution:
On line 52 find: val = output.strip().split('\n')[-1].split()[-1]
Change to: val = output.decode().strip().split('\n')[-1].split()[-1]
Result:
~$ sudo python3 intel_x520_patcher.py enp1s0f0
EEPROM Value at 0x58 is 0xfd (0b11111101)
Card is already unlocked for all SFP modules. Nothing to do.
Running this on Ubuntu 22.04 gives following error:
Traceback (most recent call last): File "/home/jani/intel_x520_patcher.py", line 52, in <module> val = output.strip().split('\n')[-1].split()[-1] TypeError: a bytes-like object is required, not 'str'
Solution: On line 52 find:
val = output.strip().split('\n')[-1].split()[-1]
Change to:val = output.decode().strip().split('\n')[-1].split()[-1]
Result:
~$ sudo python3 intel_x520_patcher.py enp1s0f0 EEPROM Value at 0x58 is 0xfd (0b11111101) Card is already unlocked for all SFP modules. Nothing to do.
I tried this solution but now i get this instead:
Traceback (most recent call last):
File "/home/tokehgekko/intel_x520_patcher.py", line 66, in
print("Running %s" % " ".join(cmd))
TypeError: sequence item 10: expected str instance, int found
Traceback (most recent call last):
File "/home/tokehgekko/intel_x520_patcher.py", line 66, in
print("Running %s" % " ".join(cmd))
TypeError: sequence item 10: expected str instance, int found
add:
import os
line 66:
from
print("Running %s" % " ".join(cmd))
to:
print("Running {}".format(cmd))
below line 65 (new line) add convert tuple to string:
cmd = ' '.join(map(str, cmd))
from:
subprocess.call(cmd)
to:
os.system(cmd)
Here's the script with all the modifications above. Works on Ubuntu 22.04
#!/usr/bin/env python3
#
# Simple Intel x520 EEPROM patcher
# Modifies the EEPROM to unlock the card for non-intel branded SFP modules.
#
# Copyright 2020,2021,2022 Andreas Thienemann <[email protected]>
#
# Licensed under the GPLv3
#
# Based on research described at https://forums.servethehome.com/index.php?threads/patching-intel-x520-eeprom-to-unlock-all-sfp-transceivers.24634/
#
# Quick explanation of what's going on:
# Looking at the Intel driver at e.g. https://elixir.bootlin.com/linux/v5.8/source/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h#L2140 we can see
# that the bit 0x1 at Address 0x58 contains a configuration setting whether the card allows any SFP modules or if Intel specific ones are enforced
# by the driver.
#
# Addr Bitstring
# 0x58 xxxxxxx0 means Intel specific SFPs
# 0x58 xxxxxxx1 means any SFP is allowed.
#
# Using the parameter allow_unsupported_sfp for the kernel module we can tell the driver to accept any SFPs.
# But this tool will flip the right bit 1 to make that change permanent in the configuration bits in the EEPROM,
# thus making kernel module parameters unnecessary.
#
import os
import subprocess
import sys
try:
intf = sys.argv[1]
except IndexError:
print("%s <interface>" % sys.argv[0])
sys.exit(255)
try:
with open("/sys/class/net/%s/device/vendor" % intf) as f:
vdr_id = f.read().strip()
with open("/sys/class/net/%s/device/device" % intf) as f:
dev_id = f.read().strip()
except IOError:
print("Can't read interface data.")
sys.exit(2)
if vdr_id not in ('0x8086') or dev_id not in ('0x10fb', '0x154d'):
print("Not a recognized Intel x520 card.")
sys.exit(3)
output = subprocess.check_output(['ethtool', '-e', intf, 'offset', '0x58', 'length', '1']).decode('utf-8')
val = output.strip().split('\n')[-1].split()[-1]
val_bin = int(val, 16)
print("EEPROM Value at 0x58 is 0x%s (%s)" % (val, bin(val_bin)))
if val_bin & 0b00000001 == 1:
print("Card is already unlocked for all SFP modules. Nothing to do.")
exit(1)
if val_bin & 0b00000001 == 0:
print("Card is locked to Intel only SFP modules. Patching EEPROM...")
new_val = val_bin | 0b00000001
print("New EEPROM Value at 0x58 will be %s (%s)" % (hex(new_val), bin(new_val)))
magic = "%s%s" % (dev_id, vdr_id[2:])
cmd = ['ethtool', '-E', intf, 'magic', magic, 'offset', '0x58', 'value', hex(new_val), 'length', 1]
print("Running {}".format(cmd))
cmd = ' '.join(map(str, cmd))
os.system(cmd)
print("Reboot the machine for changes to take effect...")
@bluerockny you are a life saver, this worked perfectly!
@bluerockny Nice work! After an hour of trouble shooting, you were the golden winner. Kudos to you!
@bluerockny Thank you for this! After pulling my hair out for an hour, swearing, crying, and banging my head for not having purchased "approved brand" SFP+ modules, I found some references to your flippin' bit flipper script. I'll head over to STH and thank them as well.
One bit = heartburn and hair loss
@larz99 et al I appreciate the kudos but I want to make clear, this is not my script. All I did was cobble together the contributions of the folks in the posts above. Glad it helped you!
Thank you @janipewter for recognizing the need for .decode()
and the initial fix.
Thanks @habibulilalbaab and @bluerockny for a copy-and-paste-able version that attempts to fixe the problem.
I updated the original script keeping subprocess and added a bit nicer output.
Enjoy.
Hi All,
Will this script work in windows environment (like windows 10 or 11) or does this only work in Linux?
Thanks.
Hi All, Will this script work in windows environment (like windows 10 or 11) or does this only work in Linux?
Thanks.
Only Linux
Hi All, Will this script work in windows environment (like windows 10 or 11) or does this only work in Linux?
Thanks.Only Linux
Thanks,
Once I run the script in Linux, will I be able to install it in a windows machine without the SFP+ module (Intel only) limitation?
I am a very newbie, what would be the best OS I can download to run the script? Would it be Ubuntu?
Thanks.
Hi Parhamsan,
When the script flips the bits on the module, the change is permanent.
You can install a small Debian or Ubuntu to make this work. If I understand correctly, you can install that within Windows using the Windows Linux Framework. That way you'll have Linux available any time you need. Great for learning!
Cheers!
Hi All, Will this script work in windows environment (like windows 10 or 11) or does this only work in Linux?
Thanks.Only Linux
Thanks,
Once I run the script in Linux, will I be able to install it in a windows machine without the SFP+ module (Intel only) limitation? I am a very newbie, what would be the best OS I can download to run the script? Would it be Ubuntu?
Thanks.
Yes
Hi Parhamsan,
When the script flips the bits on the module, the change is permanent.
You can install a small Debian or Ubuntu to make this work. If I understand correctly, you can install that within Windows using the Windows Linux Framework. That way you'll have Linux available any time you need. Great for learning!
Cheers!
Thanks for the suggestion, but I ended up installing Ubuntu-18.04.6 on an old Lenovo M82 desktop PC, as the 24.04 was not installing (was giving me an error).
I then upgraded from Ubuntu 18.04 to 24.04 but the script did not work.
So I had to use method mentioned here https://forums.servethehome.com/index.php?threads/patching-intel-x520-eeprom-to-unlock-all-sfp-transceivers.24634/.
I can confirm that my x520-da2 patched successfully but my x520-sr2 did not accept any other intel SFP+ modules after the patch.
Thanks larz99 and janipewter for the help!!!
This is fantastic even in 2024, thank you very much for creating this.
My pleasure. I get plenty of benefit m these helpful forums. I'm glad I could help!
Worked for me running Ubuntu 22.04.5 LTS
Big thanks!
HI
New here,
Got Python 3.11 installed on windows 11, and also Ubuntu 24.04.1 LTS
Guys what is the commands to get this working, I have an Intel X520x2 unsure of the commands to run.
Would appreciate if someone could let me know the commands to run
Cheers guys
The updated python script @bluerockny posted should work. If not for some reason you can try the manual method listed in this discussion.
(this worked for me but may not on your Linux flavor/Intel card version)
ethtool -e {network device} offset 0x58 length 1
ethtool -E {network device} magic {magic value} offset 0x58 value {new value}
ethtool -e {network device} offset 0x58 length 1
Sorry for the delay, had to get my server up and running not quite there yet.
anyway i am lost at trying to get commands up and running i do not know which commands to run, never worked with linux before.
I read from someone on Reddit he wrote this command in Ubuntu "sudo lshw -C network" I got this
*-network
description: Ethernet interface
physical id: 3
logical name: eth0
serial: 00:15:5d:9a:a8:c7
size: 10Gbit/s
capabilities: ethernet physical
configuration: autonegotiation=off broadcast=yes driver=hv_netvsc driverversion=5.15.153.1-microsoft-standard-W duplex=full firmware=N/A ip=172.19.84.29 link=yes multicast=yes speed=10Gbit/s
root@DESKTOP-LDHD9CS:~#
I dont know the next steps to take, sorry just a noob with no linux experience.
Cheers
Testing this with Ubuntu 24.04.1 LTS on live cd.
Getting this error messaage
Ubuntu@Ubuntu:~$ ethtool -e enp4s0f0 offset 0x58 length 1
cannot get EEPROM data: Operation not permitted,
Does anyone know of a workaround
Cheers Guys
Testing this with Ubuntu 24.04.1 LTS on live cd. Getting this error messaage Ubuntu@Ubuntu:~$ ethtool -e enp4s0f0 offset 0x58 length 1 cannot get EEPROM data: Operation not permitted,
Does anyone know of a workaround
Cheers Guys
You'd need to either sudo -i
first, or use sudo in front of the ethtool commands (they require root access). If this is confusing to you, you would be much safer using the python script in the gist...
Python 3.9 - error while executing this script.
Line 52 in module
val = output.strip().split('\n')[-1].split()[-1]
TypeError: a bytes-like object is required, not 'str'
May be, you can fix? I really need this script...