Skip to content

Instantly share code, notes, and snippets.

@terracenter
Forked from ixs/intel_x520_patcher.py
Created July 2, 2024 18:01
Show Gist options
  • Save terracenter/3ae3d2abbb81b0f0ebda63f93d55f177 to your computer and use it in GitHub Desktop.
Save terracenter/3ae3d2abbb81b0f0ebda63f93d55f177 to your computer and use it in GitHub Desktop.

Revisions

  1. @ixs ixs revised this gist May 20, 2024. 1 changed file with 3 additions and 3 deletions.
    6 changes: 3 additions & 3 deletions intel_x520_patcher.py
    Original file line number Diff line number Diff line change
    @@ -52,12 +52,12 @@
    exit(2)

    if vdr_id in ("0x8086"):
    print("Intel manufactured card recognized.")
    print("Recognized an Intel manufactured card.")
    else:
    print("Intel manufactured card recognized.")
    print("No Intel manufactured card found.")
    exit(3)
    if dev_id in card_ids:
    print("Recognized a %s card." % card_ids[dev_id])
    print("Recognized the %s card." % card_ids[dev_id])
    else:
    print("No recognized x520-based card found.")
    exit(3)
  2. @ixs ixs revised this gist May 20, 2024. 1 changed file with 61 additions and 13 deletions.
    74 changes: 61 additions & 13 deletions intel_x520_patcher.py
    Original file line number Diff line number Diff line change
    @@ -26,11 +26,20 @@
    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])
    sys.exit(255)
    exit(255)

    print("Verifying interface %s." % intf)

    try:
    with open("/sys/class/net/%s/device/vendor" % intf) as f:
    @@ -40,19 +49,29 @@
    dev_id = f.read().strip()
    except IOError:
    print("Can't read interface data.")
    sys.exit(2)
    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)
    if vdr_id in ("0x8086"):
    print("Intel manufactured card recognized.")
    else:
    print("Intel manufactured card recognized.")
    exit(3)
    if dev_id in card_ids:
    print("Recognized a %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")

    output = subprocess.check_output(['ethtool', '-e', intf, 'offset', '0x58', 'length', '1'])

    val = output.strip().split('\n')[-1].split()[-1]
    # 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)))
    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)
    @@ -61,8 +80,37 @@
    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', magic, 'offset', '0x58', 'value', hex(new_val), 'length', 1]
    print("Running %s" % " ".join(cmd))
    subprocess.call(cmd)
    print("Reboot the machine for changes to take effect...")

    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)
  3. @ixs ixs revised this gist Sep 7, 2022. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion intel_x520_patcher.py
    Original file line number Diff line number Diff line change
    @@ -42,7 +42,7 @@
    print("Can't read interface data.")
    sys.exit(2)

    if vdr_id not in ('0x8086') or dev_id not in ('0x10fb'):
    if vdr_id not in ('0x8086') or dev_id not in ('0x10fb', '0x154d'):
    print("Not a recognized Intel x520 card.")
    sys.exit(3)

  4. @ixs ixs revised this gist Sep 7, 2022. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions intel_x520_patcher.py
    Original file line number Diff line number Diff line change
    @@ -3,7 +3,7 @@
    # Simple Intel x520 EEPROM patcher
    # Modifies the EEPROM to unlock the card for non-intel branded SFP modules.
    #
    # Copyright 2020 Andreas Thienemann <[email protected]>
    # Copyright 2020,2021,2022 Andreas Thienemann <[email protected]>
    #
    # Licensed under the GPLv3
    #
    @@ -62,7 +62,7 @@
    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)]
    cmd = ['ethtool', '-E', intf, 'magic', magic, 'offset', '0x58', 'value', hex(new_val), 'length', 1]
    print("Running %s" % " ".join(cmd))
    subprocess.call(cmd)
    print("Reboot the machine for changes to take effect...")
  5. @ixs ixs revised this gist Aug 16, 2020. 1 changed file with 13 additions and 0 deletions.
    13 changes: 13 additions & 0 deletions intel_x520_patcher.py
    Original file line number Diff line number Diff line change
    @@ -9,6 +9,19 @@
    #
    # 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
  6. @ixs ixs created this gist Aug 14, 2020.
    55 changes: 55 additions & 0 deletions intel_x520_patcher.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,55 @@
    #!/usr/bin/env python3
    #
    # Simple Intel x520 EEPROM patcher
    # Modifies the EEPROM to unlock the card for non-intel branded SFP modules.
    #
    # Copyright 2020 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/
    #

    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'):
    print("Not a recognized Intel x520 card.")
    sys.exit(3)


    output = subprocess.check_output(['ethtool', '-e', intf, 'offset', '0x58', 'length', '1'])

    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)]
    print("Running %s" % " ".join(cmd))
    subprocess.call(cmd)
    print("Reboot the machine for changes to take effect...")