Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
SUSE:SLE-15-SP5:GA
opae
opae-missing-shebang.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File opae-missing-shebang.patch of Package opae
commit 623ed6defe401aedf57ad539f2feda41e368b9ec Author: Nicolas Morey-Chaisemartin <nmoreychaisemartin@suse.com> Date: Mon Mar 7 09:55:30 2022 +0100 opae missing shebang Signed-off-by: Nicolas Morey-Chaisemartin <nmoreychaisemartin@suse.com> diff --git cmake/modules/packaging.cmake cmake/modules/packaging.cmake index 7b2dfd168d2c..a028cb147d78 100644 --- cmake/modules/packaging.cmake +++ cmake/modules/packaging.cmake @@ -98,7 +98,7 @@ macro(CREATE_PYTHON_EXE EXE_NAME MAIN_MODULE) "\n" "# Write to a buffer so that the shebang can be prepended easily\n" "wr_buf = BytesIO()\n" - "wr_buf.write('#!/usr/bin/env python' + os.linesep)\n" + "wr_buf.write('#!/usr/bin/python3' + os.linesep)\n" "\n" "z = zipfile.PyZipFile(wr_buf, 'w')\n") diff --git libopae/plugins/ase/scripts/afu_sim_setup libopae/plugins/ase/scripts/afu_sim_setup index 7d1939ce29ac..af6de5ba3c2c 100755 --- libopae/plugins/ase/scripts/afu_sim_setup +++ libopae/plugins/ase/scripts/afu_sim_setup @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/python3 # Copyright(c) 2013-2017, Intel Corporation # # Redistribution and use in source and binary forms, with or without diff --git libopae/plugins/ase/scripts/generate_ase_environment.py libopae/plugins/ase/scripts/generate_ase_environment.py index 99d569789aa2..6372081972f4 100755 --- libopae/plugins/ase/scripts/generate_ase_environment.py +++ libopae/plugins/ase/scripts/generate_ase_environment.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/python3 # Copyright(c) 2013-2017, Intel Corporation # # Redistribution and use in source and binary forms, with or without diff --git libopae/plugins/ase/scripts/ipc_clean.py libopae/plugins/ase/scripts/ipc_clean.py index 2ca3f985afb5..85f653a992a8 100755 --- libopae/plugins/ase/scripts/ipc_clean.py +++ libopae/plugins/ase/scripts/ipc_clean.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/python3 # Copyright(c) 2013-2017, Intel Corporation # # Redistribution and use in source and binary forms, with or without diff --git platforms/scripts/afu_platform_config platforms/scripts/afu_platform_config index 5bab88b8f7c5..fd6622988307 100755 --- platforms/scripts/afu_platform_config +++ platforms/scripts/afu_platform_config @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/python3 # # Copyright (c) 2017, Intel Corporation diff --git platforms/scripts/afu_platform_info platforms/scripts/afu_platform_info index 64abe0041901..54ce277e143c 100755 --- platforms/scripts/afu_platform_info +++ platforms/scripts/afu_platform_info @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/python3 # # Copyright (c) 2018, Intel Corporation diff --git platforms/scripts/afu_synth_setup platforms/scripts/afu_synth_setup index 5cba6af04610..4d5f99384a89 100755 --- platforms/scripts/afu_synth_setup +++ platforms/scripts/afu_synth_setup @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/python3 # Copyright(c) 2013-2017, Intel Corporation # # Redistribution and use in source and binary forms, with or without diff --git platforms/scripts/rtl_src_config platforms/scripts/rtl_src_config index 7703005ddfe6..bb132f316c8c 100755 --- platforms/scripts/rtl_src_config +++ platforms/scripts/rtl_src_config @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/python3 # # Consume a file with a list of source files, include paths and preprocessor diff --git pyopae/pybind11/docs/conf.py pyopae/pybind11/docs/conf.py index e328eb161d76..55bb723956b9 100644 --- pyopae/pybind11/docs/conf.py +++ pyopae/pybind11/docs/conf.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python3 +#!/usr/bin/python3 # -*- coding: utf-8 -*- # # pybind11 documentation build configuration file, created by diff --git pyopae/pybind11/setup.py pyopae/pybind11/setup.py index f677f2af4a6f..9a184673fbba 100644 --- pyopae/pybind11/setup.py +++ pyopae/pybind11/setup.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/python3 # Setup script for PyPI; use CMakeFile.txt to build extension modules diff --git pyopae/pybind11/tools/mkdoc.py pyopae/pybind11/tools/mkdoc.py index 1fd8cceed52b..3e4b5d6c3622 100644 --- pyopae/pybind11/tools/mkdoc.py +++ pyopae/pybind11/tools/mkdoc.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python3 +#!/usr/bin/python3 # # Syntax: mkdoc.py [-I<path> ..] [.. a list of header files ..] # diff --git scripts/index_generator.py scripts/index_generator.py index dc0bcc2d13fd..0f406738c384 100644 --- scripts/index_generator.py +++ scripts/index_generator.py @@ -1,4 +1,4 @@ -#! /usr/bin/env python +#!/usr/bin/python3 # -*- coding: utf-8 -*- # vim:fenc=utf-8 # diff --git tools/base/fpgaport/fpgaport tools/base/fpgaport/fpgaport index af0beafdcb57..bbb47654c873 100644 --- tools/base/fpgaport/fpgaport +++ tools/base/fpgaport/fpgaport @@ -1,4 +1,4 @@ -#! /usr/bin/env python +#! /usr/bin/python3 # Copyright(c) 2017, Intel Corporation # # Redistribution and use in source and binary forms, with or without diff --git tools/extra/fpgadiag/fpgadiag tools/extra/fpgadiag/fpgadiag index 98063daf8476..c798d26b4e2d 100755 --- tools/extra/fpgadiag/fpgadiag +++ tools/extra/fpgadiag/fpgadiag @@ -1,4 +1,4 @@ -#! /usr/bin/env python +#! /usr/bin/python3 # Copyright(c) 2019, Intel Corporation # # Redistribution and use in source and binary forms, with or without diff --git tools/extra/fpgadiag/mux.py tools/extra/fpgadiag/mux.py index 4752973c18d3..7396a1b6995a 100644 --- tools/extra/fpgadiag/mux.py +++ tools/extra/fpgadiag/mux.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/python3 # Copyright(c) 2017, Intel Corporation # # Redistribution and use in source and binary forms, with or without diff --git tools/extra/pac/fpgabist/bist_app.py tools/extra/pac/fpgabist/bist_app.py index 3eb0bf3672d4..b7578740dbaf 100644 --- tools/extra/pac/fpgabist/bist_app.py +++ tools/extra/pac/fpgabist/bist_app.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/python3 # Copyright(c) 2017, Intel Corporation # # Redistribution and use in source and binary forms, with or without diff --git tools/extra/pac/fpgabist/bist_common.py tools/extra/pac/fpgabist/bist_common.py index ee9ca852cb53..f978698c4ba9 100644 --- tools/extra/pac/fpgabist/bist_common.py +++ tools/extra/pac/fpgabist/bist_common.py @@ -1,3 +1,4 @@ +#!/usr/bin/python3 # Copyright(c) 2017, Intel Corporation # # Redistribution and use in source and binary forms, with or without diff --git tools/extra/pac/fpgabist/bist_def.py tools/extra/pac/fpgabist/bist_def.py index a8f8583910fb..b413627b044a 100644 --- tools/extra/pac/fpgabist/bist_def.py +++ tools/extra/pac/fpgabist/bist_def.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/python3 # Copyright(c) 2017, Intel Corporation # # Redistribution and use in source and binary forms, with or without diff --git tools/extra/pac/fpgabist/bist_dma.py tools/extra/pac/fpgabist/bist_dma.py index 7843828e08a7..085fa1bf426b 100644 --- tools/extra/pac/fpgabist/bist_dma.py +++ tools/extra/pac/fpgabist/bist_dma.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/python3 # Copyright(c) 2017, Intel Corporation # # Redistribution and use in source and binary forms, with or without diff --git tools/extra/pac/fpgabist/bist_nlb0.py tools/extra/pac/fpgabist/bist_nlb0.py index 8bcc34dc4b1e..663429f1586d 100644 --- tools/extra/pac/fpgabist/bist_nlb0.py +++ tools/extra/pac/fpgabist/bist_nlb0.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/python3 # Copyright(c) 2018, Intel Corporation # # Redistribution and use in source and binary forms, with or without diff --git tools/extra/pac/fpgabist/bist_nlb3.py tools/extra/pac/fpgabist/bist_nlb3.py index e54333c9d018..02b9e7fd120e 100644 --- tools/extra/pac/fpgabist/bist_nlb3.py +++ tools/extra/pac/fpgabist/bist_nlb3.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/python3 # Copyright(c) 2017, Intel Corporation # # Redistribution and use in source and binary forms, with or without diff --git tools/extra/pac/fpgabist/fpgabist tools/extra/pac/fpgabist/fpgabist index f0d477209ae4..0825587e7722 100755 --- tools/extra/pac/fpgabist/fpgabist +++ tools/extra/pac/fpgabist/fpgabist @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/python3 # Copyright(c) 2017, Intel Corporation # # Redistribution and use in source and binary forms, with or without diff --git tools/extra/pac/fpgaflash/fpgaflash tools/extra/pac/fpgaflash/fpgaflash index ff22bd583c43..c14faea6c11d 100755 --- tools/extra/pac/fpgaflash/fpgaflash +++ tools/extra/pac/fpgaflash/fpgaflash @@ -1,4 +1,4 @@ -#! /usr/bin/env python +#!/usr/bin/python3 # Copyright(c) 2019, Intel Corporation # # Redistribution and use in source and binary forms, with or without diff --git tools/extra/pac/fpgaflash/super-rsu tools/extra/pac/fpgaflash/super-rsu index cd2e129c3068..fd3f1bb42bea 100755 --- tools/extra/pac/fpgaflash/super-rsu +++ tools/extra/pac/fpgaflash/super-rsu @@ -1,4 +1,4 @@ -#! /usr/bin/env python +#!/usr/bin/python3 # Copyright(c) 2019, Intel Corporation # # Redistribution and use in source and binary forms, with or without diff --git tools/extra/pac/pac_hssi_config/pac_hssi_config.py tools/extra/pac/pac_hssi_config/pac_hssi_config.py index 83d52b5374ab..0eea7221ea9a 100755 --- tools/extra/pac/pac_hssi_config/pac_hssi_config.py +++ tools/extra/pac/pac_hssi_config/pac_hssi_config.py @@ -1,4 +1,4 @@ -#! /usr/bin/env python +#!/usr/bin/python3 # Copyright(c) 2018, Intel Corporation # # Redistribution and use in source and binary forms, with or without diff --git tools/extra/pac/pyfpgaflash/fpgaflash tools/extra/pac/pyfpgaflash/fpgaflash index 28bf85235e6f..fa0eb473934a 100755 --- tools/extra/pac/pyfpgaflash/fpgaflash +++ tools/extra/pac/pyfpgaflash/fpgaflash @@ -1,4 +1,4 @@ -#! /usr/bin/env python +#!/usr/bin/python3 # Copyright(c) 2017, Intel Corporation # # Redistribution and use in source and binary forms, with or without diff --git tools/extra/packager/afu_json_mgr.py tools/extra/packager/afu_json_mgr.py index 0e31ec2646f1..d4bc864ddaf7 100755 --- tools/extra/packager/afu_json_mgr.py +++ tools/extra/packager/afu_json_mgr.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/python3 # Copyright(c) 2017, Intel Corporation # # Redistribution and use in source and binary forms, with or without diff --git tools/extra/packager/jsonschema-2.3.0/json/bin/jsonschema_suite tools/extra/packager/jsonschema-2.3.0/json/bin/jsonschema_suite index 96108c86ba25..91592830263e 100755 --- tools/extra/packager/jsonschema-2.3.0/json/bin/jsonschema_suite +++ tools/extra/packager/jsonschema-2.3.0/json/bin/jsonschema_suite @@ -1,4 +1,4 @@ -#! /usr/bin/env python +#!/usr/bin/python3 from __future__ import print_function import sys import textwrap diff --git tools/extra/packager/packager.py tools/extra/packager/packager.py index 859932700e3d..f6224dba369d 100755 --- tools/extra/packager/packager.py +++ tools/extra/packager/packager.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/python3 # Copyright(c) 2017, Intel Corporation # # Redistribution and use in source and binary forms, with or without diff --git tools/extra/pyfpgadiag/opae/tools/fpgadiag/fpgadiag.py tools/extra/pyfpgadiag/opae/tools/fpgadiag/fpgadiag.py index cb9971175ef3..9aa03755fb3d 100644 --- tools/extra/pyfpgadiag/opae/tools/fpgadiag/fpgadiag.py +++ tools/extra/pyfpgadiag/opae/tools/fpgadiag/fpgadiag.py @@ -1,4 +1,4 @@ -#! /usr/bin/env python +#!/usr/bin/python3 # Copyright(c) 2018, Intel Corporation # # Redistribution and use in source and binary forms, with or without diff --git tools/extra/pyfpgadiag/opae/tools/fpgadiag/fpgamux.py tools/extra/pyfpgadiag/opae/tools/fpgadiag/fpgamux.py index 2a2a507f223e..5cd267bdab03 100644 --- tools/extra/pyfpgadiag/opae/tools/fpgadiag/fpgamux.py +++ tools/extra/pyfpgadiag/opae/tools/fpgadiag/fpgamux.py @@ -1,4 +1,4 @@ -#! /usr/bin/env python +#!/usr/bin/python3 # Copyright(c) 2018, Intel Corporation # # Redistribution and use in source and binary forms, with or without diff --git tools/extra/pyfpgadiag/opae/utils/byteutils.py tools/extra/pyfpgadiag/opae/utils/byteutils.py index 19e23d77f084..4290bc342424 100644 --- tools/extra/pyfpgadiag/opae/utils/byteutils.py +++ tools/extra/pyfpgadiag/opae/utils/byteutils.py @@ -1,4 +1,4 @@ -#! /usr/bin/env python +#!/usr/bin/python3 # Copyright(c) 2018, Intel Corporation # # Redistribution and use in source and binary forms, with or without diff --git tools/extra/pypackager/afu_json_mgr.py tools/extra/pypackager/afu_json_mgr.py index 0e31ec2646f1..d4bc864ddaf7 100755 --- tools/extra/pypackager/afu_json_mgr.py +++ tools/extra/pypackager/afu_json_mgr.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/python3 # Copyright(c) 2017, Intel Corporation # # Redistribution and use in source and binary forms, with or without diff --git tools/extra/pypackager/packager.py tools/extra/pypackager/packager.py index 859932700e3d..f6224dba369d 100755 --- tools/extra/pypackager/packager.py +++ tools/extra/pypackager/packager.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/python3 # Copyright(c) 2017, Intel Corporation # # Redistribution and use in source and binary forms, with or without diff --git tools/fpgaflash/fpgaflash tools/fpgaflash/fpgaflash new file mode 100755 index 000000000000..1340afe3a62d --- /dev/null +++ tools/fpgaflash/fpgaflash @@ -0,0 +1,343 @@ +#! /usr/bin/python3 +# Copyright(c) 2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +import argparse +import struct +import fnmatch +import glob +import sys +import tempfile +import os +import subprocess +import fcntl +import filecmp +import stat +import re +from array import * + + +def check_rpd(ifile): + data = ifile.read(0x20) + pof_hdr = struct.unpack('IIIIIIII', data) + for i in range(0, 3): + if pof_hdr[i] != 0xffffffff: + print "invalid rpd file" + raise Exception + + if pof_hdr[3] != 0x6a6a6a6a: + print "invalid rpd file" + raise Exception + + return pof_hdr[4] + + +def reverse_bits(x, n): + result = 0 + for i in xrange(n): + if (x >> i) & 1: + result |= 1 << (n - 1 - i) + return result + + +def reverse_bits_in_file(ifile, ofile): + bit_rev = array('B') + for i in range(0, 256): + bit_rev.append(reverse_bits(i, 8)) + + while True: + ichunk = ifile.read(4096) + if not ichunk: + break + + ochunk = '' + for b in ichunk: + ochunk += chr(bit_rev[ord(b)]) + ofile.write(ochunk) + + +def get_flash_size(dev): + + MEMGETINFO = 0x80204d01 + + try: + fd = os.open(dev, os.O_SYNC | os.O_RDONLY) + except Exception as e: + print "failed to open " + dev + ": ", e + raise + + ioctl_data = struct.pack('BIIIIIQ', 0, 0, 0, 0, 0, 0, 0) + + try: + ret = fcntl.ioctl(fd, MEMGETINFO, ioctl_data) + except Exception as e: + print "ioctl failed: ", e + raise + + ioctl_odata = struct.unpack_from('BIIIIIQ', ret) + + os.close(fd) + + return ioctl_odata[2] + + +def flash_erase(dev, start, nbytes): + MEMERASE = 0x40084d02 + + try: + fd = os.open(dev, os.O_SYNC | os.O_RDWR) + except Exception as e: + print "failed to open " + dev + ": ", e + raise + + ioctl_data = struct.pack('II', start, nbytes) + + try: + ret = fcntl.ioctl(fd, MEMERASE, ioctl_data) + except Exception as e: + print "ioctl failed: ", e + raise + + os.close(fd) + + +def flash_write(dev, start, nbytes, ifile): + + try: + fd = os.open(dev, os.O_SYNC | os.O_RDWR) + except Exception as e: + print "failed to open " + dev + ": ", e + raise + + os.lseek(fd, start, os.SEEK_SET) + + while nbytes > 0: + if (nbytes > 4096): + rbytes = 4096 + else: + rbytes = nbytes + + ichunk = ifile.read(rbytes) + + if not ichunk: + print "read of flash failed" + raise Exception + + os.write(fd, ichunk) + nbytes -= rbytes + + os.close(fd) + + +def flash_read(dev, start, nbytes, ofile): + try: + fd = os.open(dev, os.O_SYNC | os.O_RDONLY) + except Exception as e: + print "failed to open " + dev + ": ", e + raise + + os.lseek(fd, start, os.SEEK_SET) + + while nbytes > 0: + if (nbytes > 4096): + rbytes = 4096 + else: + rbytes = nbytes + + ichunk = os.read(fd, rbytes) + + if not ichunk: + print "read of flash failed" + raise Exception + + ofile.write(ichunk) + nbytes -= rbytes + + os.close(fd) + + +def parse_args(): + descr = 'A tool to help update the flash used to configure an ' + descr += 'Intel FPGA at power up.' + + epi = 'example usage:\n\n' + epi += ' fpgaflash user new_image.rpd 0000:04:00.0\n\n' + + fc = argparse.RawDescriptionHelpFormatter + parser = argparse.ArgumentParser(description=descr, epilog=epi, + formatter_class=fc) + + parser.add_argument('type', help='type of flash programming', + choices=['user', 'factory']) + parser.add_argument('file', type=argparse.FileType('rb'), + help='rpd file to program into flash') + + bdf_help = "bdf of device to program (e.g. 04:00.0 or 0000:04:00.0)" + bdf_help += " optional when one device in system" + + parser.add_argument('bdf', nargs='?', help=bdf_help) + return parser.parse_args() + + +def get_bdf_mtd_mapping(): + bdf_map = dict() + for fpga in glob.glob('/sys/class/fpga/*'): + bdf = os.path.basename(os.readlink(os.path.join(fpga, "device"))) + if not bdf: + continue + + mtds = glob.glob(os.path.join(fpga, 'intel-fpga-fme.*', + 'altr-asmip2*', 'mtd', 'mtd*')) + for mtd in mtds: + if not fnmatch.fnmatchcase(mtd, "*ro"): + bdf_map[bdf] = os.path.join('/dev', os.path.basename(mtd)) + break + + return bdf_map + + +def print_bdf_mtd_mapping(bdf_map): + print "\nFPGA cards available for flashing:" + + for key in bdf_map.keys(): + print " {}".format(key) + + print + + +def normalize_bdf(bdf): + + pat = '[0-9a-fA-F]{4}:[0-9a-fA-F]{2}:[0-9a-fA-F]{2}\.[0-9a-fA-F]$' + if re.match(pat, bdf): + return bdf + + if re.match('[0-9a-fA-F]{2}:[0-9a-fA-F]{2}\.[0-9a-fA-F]$', bdf): + return "0000:{}".format(bdf) + + +def update_flash(update_type, ifile, bdf): + + bdf_map = get_bdf_mtd_mapping() + + if len(bdf_map) == 0: + print "No FPGA devices found" + raise Exception + + mtd_dev = None + if not bdf: + if len(bdf_map) > 1: + print "Must specify a bdf. More than one device found." + else: + mtd_dev = bdf_map[bdf_map.keys()[0]] + else: + bdf = normalize_bdf(bdf) + if not bdf: + print "{} is an invalid bdf".format(bdf) + elif bdf not in bdf_map.keys(): + print "Could not find flash device for {}".format(bdf) + else: + mtd_dev = bdf_map[bdf] + + if not mtd_dev: + print_bdf_mtd_mapping(bdf_map) + raise Exception + + try: + mode = os.stat(mtd_dev).st_mode + except Exception as e: + print "Couldn't stat {}".format(mtd_dev) + raise + + if not stat.S_ISCHR(mode): + print "{} is not a device file.".format(mtd_dev) + raise Exception + + flash_size = get_flash_size(mtd_dev) + + print "flash size is {}".format(flash_size) + + start_addr = check_rpd(ifile) + + if update_type == 'factory': + start_addr = 0 + + ofile = tempfile.NamedTemporaryFile(mode='wb', delete=False) + + ifile.seek(start_addr) + + print "reversing bits" + reverse_bits_in_file(ifile, ofile) + + ifile.close() + ofile.close() + + print "erasing flash" + flash_erase(mtd_dev, start_addr, (flash_size - start_addr)) + + nbytes = os.path.getsize(ofile.name) + try: + rfile = open(ofile.name, 'rb') + except Exception as e: + print "open({}) failed:".format(ofile.name) + raise + + print "writing flash" + flash_write(mtd_dev, start_addr, nbytes, rfile) + rfile.close() + + vfile = tempfile.NamedTemporaryFile(mode='wb', delete=False) + + print "reading back flash" + flash_read(mtd_dev, start_addr, nbytes, vfile) + + vfile.close() + + print "verifying flash" + + retval = filecmp.cmp(ofile.name, vfile.name) + + os.remove(ofile.name) + os.remove(vfile.name) + + if retval: + print "flash successfully verified" + else: + print "failed to verify flash" + raise Exception + + +if __name__ == "__main__": + + args = parse_args() + + if args.type == 'factory': + msg = "Are you sure you want to perform a factory update? [Yes/No]" + sys.stdout.write(msg) + line = sys.stdin.readline() + if line != "Yes\n": + sys.exit(1) + + update_flash(args.type, args.file, args.bdf) diff --git tools/fpgainfo/fpga_common.py tools/fpgainfo/fpga_common.py new file mode 100644 index 000000000000..b0d4bceee247 --- /dev/null +++ tools/fpgainfo/fpga_common.py @@ -0,0 +1,77 @@ +#!/usr/bin/python3 +# Copyright(c) 2017, Intel Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +import os + + +class bitmask(object): + def __init__(self, bit_lo, bit_hi=None): + value = 0 + for n in range(bit_lo, (bit_hi or bit_lo) + 1): + value |= (1 << n) + self.mask = value + self.type = int if bit_hi else bool + self.bit_lo = bit_lo + + def __call__(self, value): + return self.type(self.mask & value) >> self.bit_lo + + +class fpga_command(object): + commands = {} + + @classmethod + def register_command(cls, subparsers, command_class): + assert( + command_class.name not in cls.commands + ), 'Command entry already exists!!' + subparser = subparsers.add_parser(command_class.name) + cls.commands[command_class.name] = command_class(subparser) + + def __init__(self, parser): + self.parser = parser + self.args(self.parser) + self.parser.set_defaults(func=self.run) + + def args(self, parser): + parser.add_argument('-b', '--bus', + help='pcie bus number of resource') + + parser.add_argument('-d', '--device', + help='pcie device number of resource') + + parser.add_argument('-f', '--function', + help='pcie function number of resource') + + parser.add_argument('--json', action='store_true', default=False, + help='Display information as JSON string') + + def run(self, args): + raise NotImplementedError + + def fme_feature_is_supported(self, path): + return os.path.isfile(path) diff --git tools/fpgainfo/fpga_fmeinfo.py tools/fpgainfo/fpga_fmeinfo.py new file mode 100644 index 000000000000..dce5bd302341 --- /dev/null +++ tools/fpgainfo/fpga_fmeinfo.py @@ -0,0 +1,58 @@ +#!/usr/bin/python3 +# Copyright(c) 2017, Intel Corporation +## +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +## +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +## +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +import json +import fpga_common +import sysfs + + +class fme_command(fpga_common.fpga_command): + name = "fme" + properties = ['version', + 'ports_num', + 'socket_id', + 'bitstream_id', + 'bitstream_metadata', + 'pr.interface_id', + 'object_ID'] + + def run(self, args): + info = sysfs.sysfsinfo() + json_data = [] + for fme in info.fme(**vars(args)): + if args.json: + json_data.append(fme.to_dict()) + else: + fme.print_info("//****** FME ******//", *self.properties) + if args.json: + print(json.dumps(json_data, indent=4, sort_keys=False)) + + +if __name__ == "__main__": + import argparse + parser = argparse.ArgumentParser() + args = parser.parse_args() + args.func(args) diff --git tools/fpgainfo/fpga_portinfo.py tools/fpgainfo/fpga_portinfo.py new file mode 100644 index 000000000000..2d63b245edcd --- /dev/null +++ tools/fpgainfo/fpga_portinfo.py @@ -0,0 +1,55 @@ +#!/usr/bin/python3 +# Copyright(c) 2017, Intel Corporation +## +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +## +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +## +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +import json +import fpga_common +import sysfs + + +class port_command(fpga_common.fpga_command): + name = "port" + + properties = ['afu_id', + 'object_ID'] + + def run(self, args): + info = sysfs.sysfsinfo() + json_data = [] + for port in info.port(**vars(args)): + if args.json: + json_data.append(port.to_dict()) + else: + port.print_info("//****** PORT ******//", *self.properties) + + if args.json: + print(json.dumps(json_data, indent=4, sort_keys=False)) + + +if __name__ == "__main__": + import argparse + parser = argparse.ArgumentParser() + args = parser.parse_args() + args.func(args) diff --git tools/fpgainfo/fpgaerr.py tools/fpgainfo/fpgaerr.py new file mode 100644 index 000000000000..f1ff29e97186 --- /dev/null +++ tools/fpgainfo/fpgaerr.py @@ -0,0 +1,329 @@ +#!/usr/bin/python3 +# Copyright(c) 2017, Intel Corporation +## +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +## +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +## +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +import json +from sysfs import sysfsinfo +from fpga_common import ( + fpga_command, + bitmask) + + +class error_mask(object): + _name = None + _bitmasks = [] + + def __init__(self, value): + self.value = value + + def __unicode__(self): + s = u'0x{:02x}'.format(self.value) + if self.value: + for name, bm in self._bitmasks: + err = bm(self.value) + if err: + s += u'\n {:20} : 0x{:02X}'.format(name, err) + return s + + def to_dict(self, include_bdf=False): + if self._bitmasks: + data = (dict([(name, bm(self.value)) + for (name, bm) in self._bitmasks])) + return data + else: + return self.value + + +class fme_errors(error_mask): + _name = "fme" + _file = "fme-errors/errors" + _bitmasks = [ + ("CvlCdcParErro0", bitmask(17, 19)), + ("Pcie1CdcParErr", bitmask(12, 16)), + ("Pcie0CdcParErr", bitmask(7, 11)), + ("MBPErr", bitmask(6, 6)), + ("AfuAccessModeErr", bitmask(5, 5)), + ("IommuParityErr", bitmask(4, 4)), + ("KtiCdcParityErr", bitmask(2, 3)), + ("FabricFifoUOflow", bitmask(1, 1)), + ("FabricErr", bitmask(0, 0)), + ] + + +class bbs_errors(error_mask): + _name = "bbs" + _file = "bbs_errors" + _bitmasks = [ + ("InjectedCatastErr", bitmask(11, 11)), + ("ThermCatastErr", bitmask(10, 10)), + ("CrcCatastErr", bitmask(9, 9)), + ("InjectedFatalErr", bitmask(8, 8)), + ("PciePoisonErr", bitmask(7, 7)), + ("FabricFatalErr", bitmask(6, 6)), + ("IommuFatalErr", bitmask(5, 5)), + ("DramFatalErr", bitmask(4, 4)), + ("KtiProtoFatalErr", bitmask(3, 3)), + ("CciFatalErr", bitmask(2, 2)), + ("TagCchFatalErr", bitmask(1, 1)), + ("KtiLinkFatalErr", bitmask(0, 0)), + ] + + +class port_errors(error_mask): + _name = "port" + _file = "errors" + _bitmasks = [ + ("VfFlrAccessError", bitmask(51, 51)), + ("Ap6Event", bitmask(50, 50)), + ("PMRError", bitmask(49, 49)), + ("PageFault", bitmask(48, 48)), + ("VgaMemRangeError", bitmask(47, 47)), + ("LegRangeHighError", bitmask(46, 46)), + ("LegRangeLowError", bitmask(45, 45)), + ("GenProtRangeError", bitmask(44, 44)), + ("L1prMesegError", bitmask(43, 43)), + ("L1prSmrr2Error", bitmask(42, 42)), + ("L1prSmrrError", bitmask(41, 41)), + ("TxReqCounterOverflow", bitmask(40, 40)), + ("UnexpMMIOResp", bitmask(34, 34)), + ("TxCh2FifoOverflow", bitmask(33, 33)), + ("MMIOTimedOut", bitmask(32, 32)), + ("TxCh1NonZeroSOP", bitmask(24, 24)), + ("TxCh1IncorrectAddr", bitmask(23, 23)), + ("TxCh1DataPayloadOverrun", bitmask(22, 22)), + ("TxCh1InsufficientData", bitmask(21, 21)), + ("TxCh1Len4NotAligned", bitmask(20, 20)), + ("TxCh1Len2NotAligned", bitmask(19, 19)), + ("TxCh1Len3NotSupported", bitmask(18, 18)), + ("TxCh1InvalidReqEncoding", bitmask(17, 17)), + ("TxCh1Overflow", bitmask(16, 16)), + ("MMIOWrWhileRst", bitmask(10, 10)), + ("MMIORdWhileRst", bitmask(9, 9)), + ("TxCh0Len4NotAligned", bitmask(4, 4)), + ("TxCh0Len2NotAligned", bitmask(3, 3)), + ("TxCh0Len3NotSupported", bitmask(2, 2)), + ("TxCh0InvalidReqEncoding", bitmask(1, 1)), + ("TxCh0Overflow", bitmask(0, 0)), + ] + + +class pcie0_errors(error_mask): + _name = "pcie0" + _file = "pcie0_errors" + _bitmasks = [ + ("FunctTypeErr", bitmask(63, 63)), + ("VFNumb", bitmask(62, 62)), + ("RxPoisonTlpErr", bitmask(9, 9)), + ("ParityErr", bitmask(8, 8)), + ("CompTimeOutErr", bitmask(7, 7)), + ("CompStatErr", bitmask(6, 6)), + ("CompTagErr", bitmask(5, 5)), + ("MRLengthErr", bitmask(4, 4)), + ("MRAddrErr", bitmask(3, 3)), + ("MWLengthErr", bitmask(2, 2)), + ("MWAddrErr", bitmask(1, 1)), + ("FormatTypeErr", bitmask(0, 0)), + ] + + +class pcie1_errors(error_mask): + _name = "pcie1" + _file = "pcie1_errors" + _bitmasks = [ + ("RxPoisonTlpErr", bitmask(9, 9)), + ("ParityErr", bitmask(8, 8)), + ("CompTimeOutErr", bitmask(7, 7)), + ("CompStatErr", bitmask(6, 6)), + ("CompTagErr", bitmask(5, 5)), + ("MRLengthErr", bitmask(4, 4)), + ("MRAddrErr", bitmask(3, 3)), + ("MWLengthErr", bitmask(2, 2)), + ("MWAddrErr", bitmask(1, 1)), + ("FormatTypeErr", bitmask(0, 0)), + ] + + +class gbs_errors(error_mask): + _name = "gbs" + _file = "gbs_errors" + _bitmasks = [ + ("MBPErr", bitmask(12, 12)), + ("PowerThreshAP2", bitmask(11, 11)), + ("PowerThreshAP1", bitmask(10, 10)), + ("TempThreshAP6", bitmask(9, 9)), + ("InjectedWarningErr", bitmask(6, 6)), + ("AfuAccessModeErr", bitmask(5, 5)), + ("ProcHot", bitmask(4, 4)), + ("PortFatalErr", bitmask(3, 3)), + ("PcieError", bitmask(2, 2)), + ("TempThreshAP2", bitmask(1, 1)), + ("TempThreshAP1", bitmask(0, 0)), + ] + + +class first_errors(error_mask): + _name = "first_error" + _file = "first_error" + _bitmasks = [ + ("TxReqCounterOverflow", bitmask(40, 40)), + ("TxCh2FifoOverflow", bitmask(33, 33)), + ("MMIOTimedOut", bitmask(32, 32)), + ("TxCh1IllegalVCsel", bitmask(25, 25)), + ("TxCh1NonZeroSOP", bitmask(24, 24)), + ("TxCh1IncorrectAddr", bitmask(23, 23)), + ("TxCh1DataPayloadOverrun", bitmask(22, 22)), + ("TxCh1InsufficientData", bitmask(21, 21)), + ("TxCh1Len4NotAligned", bitmask(20, 20)), + ("TxCh1Len2NotAligned", bitmask(19, 19)), + ("TxCh1Len3NotSupported", bitmask(18, 18)), + ("TxCh1InvalidReqEncoding", bitmask(17, 17)), + ("TxCh1Overflow", bitmask(16, 16)), + ("TxCh0Len4NotAligned", bitmask(4, 4)), + ("TxCh0Len2NotAligned", bitmask(3, 3)), + ("TxCh0Len3NotSupported", bitmask(2, 2)), + ("TxCh0InvalidReqEncoding", bitmask(1, 1)), + ("TxCh0Overflow", bitmask(0, 0)), + ] + + +class nonfatal_errors(error_mask): + _name = "nonfatal" + _file = "nonfatal_errors" + _bitmasks = [ + ("MBPErr", bitmask(12, 12)), + ("PowerThreshAP2", bitmask(11, 11)), + ("PowerThreshAP1", bitmask(10, 10)), + ("TempThreshAP6", bitmask(9, 9)), + ("InjectedWarningErr", bitmask(6, 6)), + ("AfuAccessModeErr", bitmask(5, 5)), + ("ProcHot", bitmask(4, 4)), + ("PortFatalErr", bitmask(3, 3)), + ("PcieError", bitmask(2, 2)), + ("TempThreshAP2", bitmask(1, 1)), + ("TempThreshAP1", bitmask(0, 0)), + ] + + +class fatal_errors(error_mask): + _name = "catfatal" + _file = "catfatal_errors" + _bitmasks = [ + ("InjectedCatastErr", bitmask(11, 11)), + ("ThermCatastErr", bitmask(10, 10)), + ("CrcCatastErr", bitmask(9, 9)), + ("InjectedFatalErr", bitmask(8, 8)), + ("PciePoisonErr", bitmask(7, 7)), + ("FabricFatalErr", bitmask(6, 6)), + ("IommuFatalErr", bitmask(5, 5)), + ("DramFatalErr", bitmask(4, 4)), + ("KtiProtoFatalErr", bitmask(3, 3)), + ("CciFatalErr", bitmask(2, 2)), + ("TagCchFatalErr", bitmask(1, 1)), + ("KtiLinkFatalErr", bitmask(0, 0)), + ] + + +error_classes = { + "fme": {"errors": fme_errors, + "pcie0_errors": pcie0_errors, + "pcie1_errors": pcie1_errors, + "gbs_errors": gbs_errors, + "bbs_errors": bbs_errors, + "nonfatal_errors": nonfatal_errors, + "catfatal_errors": fatal_errors, + "first_error": error_mask, + "next_error": error_mask}, + "port": {"errors": port_errors, + "first_error": first_errors} +} + + +def set_error_parsers(err_feature, err_classes): + for name, err_class in err_classes.iteritems(): + if hasattr(err_feature, name): + value = getattr(err_feature, name) + setattr(err_feature, name, err_class(value.fget(err_feature))) + + +class errors_command(fpga_command): + name = 'errors' + + def __init__(self, parser): + super(errors_command, self).__init__(parser) + + def args(self, parser): + super(errors_command, self).args(parser) + parser.add_argument('-c', '--clear', action='store_true', + default=False, + help='specify whether or not' + ' to clear error registers') + + parser.add_argument('which', + choices=['fme', 'port', 'all'], + default='fme', + help='specify what kind of errors to operate on') + + def run(self, args): + info = sysfsinfo() + resources = [] + # let's monkey patch the error sysfs resource + # by looking at our dicionaries of error parsers and matching + # them with the corresponding property and then replacing + # that property attribute with an instance of the error parsing + # class with the value of the property + if args.which == "fme" or args.which == "all": + for fme in info.fme(**vars(args)): + set_error_parsers(fme.errors, error_classes["fme"]) + resources.append(fme.errors) + + if args.which == "port" or args.which == "all": + for port in info.port(**vars(args)): + set_error_parsers(port.errors, error_classes["port"]) + resources.append(port.errors) + + json_data = [] + for r in resources: + if args.json: + json_data.append(r.to_dict(True)) + else: + r.print_info( + "//****** {} ******//".format(r.name())) + + if args.json: + print(json.dumps(json_data, indent=4, sort_keys=False)) + + if args.clear: + for r in resources: + if not r.clear(): + print("ERROR: Could not clear errors for resource {}.\n" + "Are you running as root?\n".format(r.sysfs_path)) + + +if __name__ == "__main__": + import argparse + parser = argparse.ArgumentParser() + errors_command(parser) + args = parser.parse_args() + args.func(args) diff --git tools/fpgainfo/fpgainfo tools/fpgainfo/fpgainfo new file mode 100755 index 000000000000..f207d693bdef --- /dev/null +++ tools/fpgainfo/fpgainfo @@ -0,0 +1,58 @@ +#!/usr/bin/python3 +# Copyright(c) 2017, Intel Corporation +## +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +## +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +## +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +import argparse +import fpga_common +import fpgaerr +import fpgapwr +import fpgatemp +import fpga_fmeinfo +import fpga_portinfo +import logging + + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + subparsers = parser.add_subparsers(title='fpga commands') + + fpga_common.fpga_command.register_command(subparsers, + fpgaerr.errors_command) + + fpga_common.fpga_command.register_command(subparsers, + fpgapwr.power_command) + + fpga_common.fpga_command.register_command(subparsers, + fpgatemp.temp_command) + + fpga_common.fpga_command.register_command(subparsers, + fpga_fmeinfo.fme_command) + + fpga_common.fpga_command.register_command(subparsers, + fpga_portinfo.port_command) + + args = parser.parse_args() + logging.basicConfig(filename='fpgainfo.log') + args.func(args) diff --git tools/fpgainfo/fpgatemp.py tools/fpgainfo/fpgatemp.py new file mode 100644 index 000000000000..8e9dda8e90af --- /dev/null +++ tools/fpgainfo/fpgatemp.py @@ -0,0 +1,59 @@ +#!/usr/bin/python3 +# Copyright(c) 2017, Intel Corporation +## +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +## +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +## +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +import fpga_common as cmd +import sysfs + + +def print_celcius(value): + return u'{}\u00b0 C'.format(value) + + +class temp_command(cmd.fpga_command): + name = "temp" + thermal_props = [("temperature", print_celcius), + ("threshold1", print_celcius), + ("threshold1_policy", int), + ("threshold1_reached", bool), + ("threshold2", print_celcius), + ("threshold2_reached", bool), + ("threshold_trip", print_celcius)] + + def run(self, args): + info = sysfs.sysfsinfo() + for fme in info.fme(**vars(args)): + fme.thermal_mgmt.print_info("//****** THERMAL ******//", + *[p[0] for p in self.thermal_props], + **dict(self.thermal_props)) + + +if __name__ == "__main__": + import argparse + parser = argparse.ArgumentParser() + temp_command(parser) + args = parser.parse_args() + args.func(args) diff --git tools/fpgainfo/sysfs.py tools/fpgainfo/sysfs.py new file mode 100644 index 000000000000..2b148e10d74c --- /dev/null +++ tools/fpgainfo/sysfs.py @@ -0,0 +1,442 @@ +#!/usr/bin/python3 +# Copyright(c) 2017, Intel Corporation +## +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +## +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +## +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +import glob +import inspect +import json +import logging +import os +import re +import uuid + +pattern = ('.*/\d+:(?P<bus>\w{2}):' + '(?P<device>\d{2})\.(?P<function>\d).*') +bdf_pattern = re.compile(pattern) + +ROOT_PATH = '/sys/class/fpga' +FPGA_DEVICE = os.path.join(ROOT_PATH, 'intel-fpga-dev.{instance_id}') +FME_DEVICE = os.path.join(FPGA_DEVICE, 'intel-fpga-fme.{instance_id}') +PORT_DEVICE = os.path.join(FPGA_DEVICE, 'intel-fpga-port.{instance_id}') + +DCP_ID = 0x09c4 + + +def read_bdf(path): + symlink = os.readlink(path) + m = bdf_pattern.match(symlink) + data = m.groupdict() if m else {} + return dict([(k, int(v, 16)) for (k, v) in data.iteritems()]) + + +class sysfs_filter(object): + def __init__(self, **kwargs): + self._bus = None + self._device = None + self._function = None + for attr in ('bus', 'device', 'function'): + value = kwargs.get(attr) + if isinstance(value, str) or isinstance(value, unicode): + value = int(value, 16) + setattr(self, '_{}'.format(attr), value) + + def __call__(self, resource): + if self._bus is not None and self._bus != resource.bus: + return False + if self._device is not None and self._device != resource.device: + return False + if self._function is not None and self._function != resource.function: + return False + return True + + +def add_static_property(sysfs_path): + return property(lambda s_: s_.parse_sysfs(sysfs_path), + lambda s_, v_: s_.write_sysfs(v_, sysfs_path)) + + +def add_dynamic_property(obj, property_name, sysfs_path=None): + sysfs_path = sysfs_path or property_name + + def getter(self_): + return self_.parse_sysfs(sysfs_path) + + def setter(self_, v_): + self_.write_sysfs(v_, sysfs_path) + + if obj.sysfs_path_exists(sysfs_path): + setattr(obj, property_name, + property(getter, setter)) + + +class sysfs_resource(object): + def __init__(self, path, instance_id, device_id=None, **kwargs): + self._path = path + self._instance_id = instance_id + self._device_id = device_id + self._bus = kwargs.get('bus') + self._device = kwargs.get('device') + self._function = kwargs.get('function') + + def enum_props(self, as_string=False): + def pred(xxx_todo_changeme): + (k, v) = xxx_todo_changeme + if k in dir(sysfs_resource): + return False + if inspect.ismethod(v): + return False + if k.startswith('_'): + return False + return True + + for k, v in filter(pred, inspect.getmembers(self)): + k_, v_ = k, v + if isinstance(v, property): + k_, v_ = k, v.fget(self) + elif not as_string and hasattr(v, 'to_dict') and k != '__class__': + k_, v_ = k, v.to_dict() + if as_string: + yield k_, unicode(v_) + else: + yield k_, v_ + + def to_dict(self, include_bdf=False): + data = {} + for k, v in self.enum_props(): + data[k] = v + if include_bdf: + root_data = {} + root_data["class_path"] = self.sysfs_path + root_data["dev_path"] = os.path.realpath(self.sysfs_path) + root_data["bus"] = self.bus + root_data["device"] = self.device + root_data["function"] = self.function + data["pcie_info"] = root_data + + return data + + def to_json(self): + return json.dumps(self.to_dict(), indent=4, sort_keys=False) + + def sysfs_path_exists(self, *paths): + return os.path.exists(os.path.join(self._path, *paths)) + + def read_sysfs(self, *paths): + filepath = os.path.join(self._path, *paths) + if not os.path.exists(filepath): + print("WARNING: {} not found".format(filepath)) + return None + with open(filepath, 'r') as fd: + return fd.read().strip() + + def write_sysfs(self, value, *paths): + filepath = os.path.join(self._path, *paths) + if not os.path.exists(filepath): + print("WARNING: {} not found".format(filepath)) + return None + with open(filepath, 'w') as fd: + return fd.write(value) + + def parse_sysfs(self, *paths): + value = self.read_sysfs(*paths) + try: + value = int(value) + except ValueError: + try: + value = int(value, 16) + except Exception: + logging.warn("Could not parse value: {}".format(value)) + finally: + return value + + def print_info(self, label, *props, **kwargs): + print(label.upper()) + print('{:22} : {}'.format('Class Path', self.sysfs_path)) + print( + '{:22} : {}'.format( + 'Device Path', + os.path.realpath( + self.sysfs_path))) + print('{:22} : 0x{:02X}'.format('Bus', self.bus)) + print('{:22} : 0x{:02X}'.format('Device', self.device)) + print('{:22} : 0x{:02X}'.format('Function', self.function)) + + prop_values = [(k, v) for k, v in self.enum_props(as_string=True)] + if props: + def get_value(key): + namespaces = key.split('.') + obj = self + try: + while len(namespaces) > 1: + obj = getattr(obj, namespaces.pop(0)) + p = getattr(obj, namespaces[0]) + if isinstance(p, property): + p = p.fget(self) + return p + except AttributeError: + pass + + prop_values = [(k, get_value(k)) for k in props] + + for k, v in prop_values: + if v is not None: + value = kwargs.get(k)(v) if k in kwargs else v + subbed = re.sub('[_\.]', ' ', k) + label = ' '.join([_.capitalize() for _ in subbed.split()]) + print(u'{:22} : {}'.format(label, value)) + + print('\n') + + @property + def sysfs_path(self): + return self._path + + @property + def instance_id(self): + return self._instance_id + + @property + def bus(self): + return self._bus + + @property + def device(self): + return self._device + + @property + def function(self): + return self._function + + @property + def device_id(self): + return self._device_id + + +class pr_feature(sysfs_resource): + @property + def interface_id(self): + return str(uuid.UUID(self.read_sysfs("interface_id"))) + + +class sysfs_device(sysfs_resource): + @property + def device_id(self): + return self.parse_sysfs("device") + + +class power_mgmt_feature(sysfs_resource): + def __init__(self, path, instance_id, device_id, **kwargs): + super(power_mgmt_feature, self).__init__(path, instance_id, device_id, + **kwargs) + if device_id != DCP_ID: + self.consumed = add_static_property("consumed") + + +class thermal_feature(sysfs_resource): + def __init__(self, path, instance_id, device_id, **kwargs): + super(thermal_feature, self).__init__(path, instance_id, device_id, + **kwargs) + self.temperature = add_static_property("temperature") + if device_id != DCP_ID: + self.threshold1 = add_static_property("threshold1") + self.threshold1_policy = add_static_property("threshold1_policy") + self.threshold1_reached = add_static_property("threshold1_reached") + self.threshold2 = add_static_property("threshold2") + self.threshold2_reached = add_static_property("threshold2_reached") + self.threshold_trip = add_static_property("threshold_trip") + + +class errors_feature(sysfs_resource): + revision = add_static_property("revision") + + def __init__(self, path, instance_id, device_id, **kwargs): + super(errors_feature, self).__init__(path, instance_id, device_id, + **kwargs) + self._errors_file = None + self._clear_file = None + self._name = "errors" + + def name(self): + return self._name + + def clear(self): + value = self.parse_sysfs(self._errors_file) + try: + if value: + self.write_sysfs(hex(value), self._clear_file) + return True + except IOError: + logging.warn( + "Could not clear errors: {}." + "Are you running as root?".format( + self._clear_file)) + return False + + +class fme_errors(errors_feature): + def __init__(self, path, instance_id, device_id, **kwargs): + super(fme_errors, self).__init__(path, instance_id, device_id, + **kwargs) + self._name = "fme errors" + self._errors_file = "fme-errors/errors" + self._clear_file = "fme-errors/clear" + add_dynamic_property(self, "errors", "fme-errors/errors") + add_dynamic_property(self, "first_error", "fme-errors/first_error") + add_dynamic_property(self, "next_error", "fme-errors/next_error") + add_dynamic_property(self, "pcie0_errors") + if device_id != DCP_ID: + add_dynamic_property(self, "pcie1_errors") + add_dynamic_property(self, "bbs_errors") + add_dynamic_property(self, "gbs_errors") + add_dynamic_property(self, "catfatal_errors") + add_dynamic_property(self, "nonfatal_errors") + + +class port_errors(errors_feature): + def __init__(self, path, instance_id, device_id, **kwargs): + super(port_errors, self).__init__(path, instance_id, device_id, + **kwargs) + self._name = "port errors" + self._errors_file = "errors" + self._clear_file = "clear" + add_dynamic_property(self, "errors") + add_dynamic_property(self, "first_error") + + +class fme_info(sysfs_resource): + def __init__(self, path, instance_id, device_id, **kwargs): + super(fme_info, self).__init__(path, instance_id, device_id, **kwargs) + self.pr = pr_feature(os.path.join(path, 'pr'), instance_id, device_id, + **kwargs) + self.power_mgmt = power_mgmt_feature(os.path.join(path, 'power_mgmt'), + instance_id, + device_id, + **kwargs) + self.thermal_mgmt = thermal_feature(os.path.join(path, "thermal_mgmt"), + instance_id, + device_id, + **kwargs) + self.errors = fme_errors(os.path.join(path, "errors"), + instance_id, + device_id, + **kwargs) + + @property + def version(self): + return self.read_sysfs("version") + + @property + def ports_num(self): + return self.read_sysfs("ports_num") + + @property + def socket_id(self): + return self.read_sysfs("socket_id") + + @property + def bitstream_id(self): + if self.device_id != DCP_ID: + return self.read_sysfs("bitstream_id") + + @property + def bitstream_metadata(self): + if self.device_id != DCP_ID: + return self.read_sysfs("bitstream_metadata") + + @property + def object_ID(self): + value = self.read_sysfs("dev") + valueList = value.split(":") + major = valueList[0] + minor = valueList[1] + objID = ((int(major) & 0xFFF) << 20) | (int(minor) & 0xFFFFF) + return hex(objID) + " FPGA_DEVICE" + + +class port_info(sysfs_resource): + def __init__(self, path, instance_id, device_id, **kwargs): + super(port_info, self).__init__(path, instance_id, device_id, **kwargs) + self.errors = port_errors(os.path.join(path, "errors"), + instance_id, + device_id, + **kwargs) + + @property + def afu_id(self): + return str(uuid.UUID(self.read_sysfs("afu_id"))) + + @property + def object_ID(self): + value = self.read_sysfs("dev") + valueList = value.split(":") + major = valueList[0] + minor = valueList[1] + objID = ((int(major) & 0xFFF) << 20) | (int(minor) & 0xFFFFF) + return hex(objID) + " FPGA_ACCELERATOR" + + +class sysfsinfo(object): + def __init__(self): + self._fmelist = [] + self._portlist = [] + sysfs_paths = glob.glob( + FPGA_DEVICE.format(instance_id='*')) + if not sysfs_paths: + print "WARNING: No sysfs paths found" + for path in sysfs_paths: + bdf = read_bdf(os.path.join(path, 'device')) + # strip {instance_id} from the template FPGA_DEVICE + # socket id is what comes after this in the real path + instance_id = path.strip(FPGA_DEVICE.strip('{instance_id}')) + device_id = sysfs_device(os.path.join(path, 'device'), + instance_id, None, + **bdf).device_id + sysfs_fme = FME_DEVICE.format(instance_id=instance_id) + sysfs_port = PORT_DEVICE.format(instance_id=instance_id) + self._fmelist.append(fme_info(sysfs_fme, instance_id, + device_id, **bdf)) + self._portlist.append(port_info(sysfs_port, instance_id, + device_id, **bdf)) + + def fme(self, **kwargs): + return filter(sysfs_filter(**kwargs), self._fmelist) + + def port(self, **kwargs): + return filter(sysfs_filter(**kwargs), self._portlist) + + +if __name__ == "__main__": + import argparse + import pprint + parser = argparse.ArgumentParser() + parser.add_argument('-b', '--bus') + parser.add_argument('-d', '--device') + parser.add_argument('-f', '--function') + + args = parser.parse_args() + info = sysfsinfo() + fmelist = info.fme(**vars(args)) + portlist = info.port(**vars(args)) + pprint.pprint([f.to_dict() for f in fmelist])
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor