Example #1
0
def discover_boards(rsu_config, args):
    """discover_boards discover FPGA devices in sysfs given a config

    :param rsu_config(dict): A dictionary describing the product to discover.
                             This config should be made up of a product name
                             and a list of files to flash. The product will be
                             mapped to a PCI identifer to match. This file will
                             be passed to 'fpgaboard' for loading flash
                             binaries.
    """
    product_name = rsu_config.get('product')
    if product_name is None:
        LOG.warning("RSU config file missing 'product' key")
        return []

    product_vendor = rsu_config.get('vendor')
    if product_vendor is None:
        LOG.warning("RSU config file missing 'vendor' key")
        return []

    product_device = rsu_config.get('device')
    if product_device is None:
        LOG.warning("RSU config file missing 'device' key")
        return []

    boards = []
    enum_filter = {'pci_node.device_id': int(product_device, 0),
                   'pci_node.vendor_id': int(product_vendor, 0)}
    if args.bus:
        enum_filter['pci_node.bus'] = args.bus
    for device in fpga_device.enum([enum_filter]):
        boards.append(make_pac(device.pci_node, device))

    return boards
Example #2
0
def find_config(program='super-rsu', configuration=None):
    candidates = []
    for root, dirs, files in os.walk('/usr/share/opae'):
        for f in glob.glob(os.path.join(root, '*.json')):
            try:
                with open(f, 'r') as fp:
                    data = json.load(fp)
                cfg_pgm = data.get('program')
                cfg_vid = int(data.get('vendor', '0'), 0)
                cfg_did = int(data.get('device', '0'), 0)
                cfg_cfg = data.get('configuration')
            except IOError:
                LOG.warning('could not open file: %s', f)
            except ValueError as err:
                LOG.warning('could not decode JSON file, %s: %s', f, err)
            except AttributeError:
                # not a recognized schema
                pass
            else:
                # check if program is either in the manifest data
                # or at least it is in the file path
                if cfg_pgm == program or (cfg_pgm is None and program in f):
                    if fpga_device.enum([{'pci_node.vendor_id': cfg_vid,
                                          'pci_node.device_id': cfg_did}]):
                        LOG.debug('found possible config: %s', f)
                        if configuration is None or (cfg_cfg == configuration):
                            candidates.append(f)

    if len(candidates) == 1:
        try:
            return open(candidates[0], 'r')
        except IOError:
            pass

    LOG.warning('could not find or open suitable super-rsu manifest')
Example #3
0
def test_enum_fpga():
    for o in fpga.enum([{'pci_node.device_id': 0xb30}]):
        print(o.pci_node)
        print(o.pci_node.root.tree())
        print(o.fme.devpath)
        print(o.fme.i2c_bus.sysfs_path)
        print(o.fme.spi_bus.sysfs_path)
        print(o.port.devpath)
Example #4
0
def main():
    actions = {'assign': assign, 'release': release}
    # parse command line arguments
    parser = argparse.ArgumentParser()
    parser.add_argument('action',
                        action='store',
                        choices=sorted(actions.keys()),
                        help='Action to perform - {}'.format(
                            list(actions.keys())))
    parser.add_argument('device',
                        help=('The FPGA (FME) device. '
                              'Can be identified by dev path (/dev/dfl-fme.0) '
                              'or by PCIe address: '
                              '([<segment>:]<bus>:<device>.<function>'))
    parser.add_argument('port',
                        type=int,
                        default=0,
                        nargs='?',
                        help='The port number.')
    parser.add_argument('-N',
                        '--numvfs',
                        type=int,
                        help='Create VFs from the argument given.')
    parser.add_argument('-X',
                        '--destroy-vfs',
                        action='store_true',
                        default=False,
                        help='Destroy all VFs prior to assigning.')
    parser.add_argument('--debug',
                        action='store_true',
                        default=False,
                        help='Set logging to DEBUG if verbose selected')

    args = parser.parse_args()

    level = logging.DEBUG if args.debug else logging.INFO
    logging.basicConfig(level=level,
                        format=('[%(asctime)-15s] [%(levelname)-8s] '
                                '%(message)s'))
    devices = fpga.enum([fpga_filter(args.device)])

    if not devices:
        LOG.error('Could not find device using pattern: "%s"', args.device)
        sys.exit(os.EX_USAGE)

    for device in devices:
        actions[args.action](args, device)
Example #5
0
def main():
    args = parse_args()
    level = logging.DEBUG if args.debug else logging.INFO
    logging.basicConfig(level=level, format='%(asctime)s - %(message)s')
    compatible = fpga.enum([{'supports_rsu': True}])
    if not compatible:
        sys.stderr.write('No compatible devices found\n')
        raise SystemExit(os.EX_USAGE)

    if args.bdf is None:
        if len(compatible) == 1:
            args.bdf = compatible[0].pci_node.pci_address
        elif len(compatible) > 1:
            prog = os.path.basename(sys.argv[0])
            sys.stderr.write(('Please specify PCIe address as '
                              '[<segment>:]<bus>:<device>.<function>\n'))
            sys.stderr.write('Acceptable commands:\n')
            for dev in compatible:
                sys.stderr.write('>{} {} {}\n'.format(prog, args.type,
                                                      dev.pci_node.bdf))
            raise SystemExit(os.EX_USAGE)

    bdf = normalize_bdf(args.bdf)

    Path(RSU_LOCK_DIR).mkdir(parents=True, exist_ok=True)

    for device in compatible:
        if device.pci_node.pci_address == bdf:
            exit_code = os.EX_IOERR
            with open(RSU_LOCK_FILE, 'w') as flock:
                fcntl.flock(flock.fileno(), fcntl.LOCK_EX)
                try:
                    do_rsu(args.type, device, args.factory)
                except IOError:
                    logging.error('RSU operation failed')
                else:
                    exit_code = os.EX_OK
                    logging.info('RSU operation complete')
                finally:
                    fcntl.flock(flock.fileno(), fcntl.LOCK_UN)
            raise SystemExit(exit_code)

    logging.error(('PCIe address (%s) is invalid or does not identify a'
                   'compatible device'), args.bdf)
Example #6
0
def main():
    """The main entry point."""
    parser, args = parse_args()

    if args.file is None:
        print('Error: file is a required argument\n')
        parser.print_help(sys.stderr)
        sys.exit(1)

    LOG.setLevel(logging.NOTSET)

    log_fmt = ('[%(asctime)-15s] [%(levelname)-8s] ' '%(message)s')
    log_hndlr = logging.StreamHandler(sys.stdout)
    log_hndlr.setFormatter(logging.Formatter(log_fmt))

    log_hndlr.setLevel(LOG_NAMES_TO_LEVELS[args.log_level])

    LOG.addHandler(log_hndlr)

    signal.signal(signal.SIGTERM, sig_handler)

    LOG.debug('fw file: %s', args.file.name)
    LOG.debug('addr: %s', args.bdf)

    stat = 1
    mesg = 'Secure update failed'
    gbs_hdr = None

    blk0 = decode_auth_block0(args.file, not args.yes)
    if blk0 is None:
        gbs_hdr = decode_gbs_header(args.file)
        if gbs_hdr is None:
            LOG.error('Unknown file format in %s', args.file.name)
            sys.exit(1)

    pac = None
    if args.bdf == DEFAULT_BDF:
        # Address wasn't specified. Enumerate all PAC's.
        if gbs_hdr:
            pr_guid = gbs_hdr['interface-uuid'].replace('-', '')
            pacs = fpga.enum([{'fme.pr_interface_id': pr_guid}])
        else:
            pacs = fpga.enum()

        if not pacs:
            LOG.error('No suitable PAC found.')
            sys.exit(1)
        elif len(pacs) > 1:
            LOG.error('More than one PAC found. '
                      'Please specify an %s', DEFAULT_BDF)
            sys.exit(1)
        pac = pacs[0]
    else:
        # Enumerate for a specific device.
        canon_bdf = canonicalize_bdf(args.bdf)
        if not canon_bdf:
            LOG.error('%s is not a valid PCIe address. '
                      'Use %s', args.bdf, DEFAULT_BDF)
            sys.exit(1)

        pacs = fpga.enum([{'pci_node.pci_address': canon_bdf}])
        if not pacs:
            LOG.error('Failed to find PAC at %s', canon_bdf)
            sys.exit(1)

        pac = pacs[0]

        if gbs_hdr:
            # verify the PR interface uuid
            fme = pac.fme
            if fme:
                pr_guid = gbs_hdr['interface-uuid'].replace('-', '')
                if fme.pr_interface_id.replace('-', '') != pr_guid:
                    LOG.error('PR interface uuid mismatch.')
                    sys.exit(1)

    LOG.warning('Update starting. Please do not interrupt.')

    start = datetime.now()

    if gbs_hdr is not None:
        args.file.close()
        stat, mesg = do_partial_reconf(pac.pci_node.pci_address,
                                       args.file.name)
    elif blk0 is not None:
        sec_dev = pac.secure_dev
        if not sec_dev:
            LOG.error('Failed to find secure '
                      'device for PAC %s', pac.pci_node.pci_address)
            sys.exit(1)

        LOG.debug('Found secure device for PAC '
                  '%s', pac.pci_node.pci_address)

        try:
            stat, mesg = update_fw(args, pac)
        except SecureUpdateError as exc:
            stat, mesg = exc.errno, exc.strerror
        except KeyboardInterrupt:
            if TMPFILE and os.path.isfile(TMPFILE):
                os.remove(TMPFILE)
            cancel = sec_dev.find_one(os.path.join('update', 'cancel'))
            cancel.value = 1
            stat, mesg = 1, 'Interrupted'

    if stat and mesg == 'flash_wearout':
        mesg = ('Secure update is delayed due to excessive flash counts.\n'
                'Please wait 30 seconds and try again.')

    if stat:
        LOG.error(mesg)
    else:
        LOG.info(mesg)

    LOG.info('Total time: %s', datetime.now() - start)
    sys.exit(stat)
Example #7
0
def main():
    """The main entry point"""
    parser, args = parse_args()

    if args.manifest is None:
        print('Error: manifest is a required argument\n')
        parser.print_help(sys.stderr)
        sys.exit(1)

    LOG.setLevel(logging.NOTSET)
    log_fmt = ('[%(asctime)-15s] [%(levelname)-8s] '
               '[%(threadName)s] %(message)s')
    log_hndlr = logging.StreamHandler(sys.stdout)
    log_hndlr.setFormatter(logging.Formatter(log_fmt))

    log_hndlr.setLevel(logging.getLevelName(args.log_level.upper()))

    LOG.addHandler(log_hndlr)

    signal.signal(signal.SIGINT, sig_handler)
    signal.signal(signal.SIGTERM, sig_handler)

    loader = otsu_manifest_loader(args.manifest)
    json_cfg = loader.load()
    if json_cfg is None:
        LOG.error('Failed to process manifest: %s', args.manifest.name)
        sys.exit(1)

    # Find the PAC described by the manifest.
    enum_filter = {
        'pci_node.vendor_id': to_int(json_cfg['vendor'])[1],
        'pci_node.device_id': to_int(json_cfg['device'])[1]
    }

    pacs = fpga.enum([enum_filter])
    if not pacs:
        LOG.error('failed to find any suitable PAC: %s:%s', json_cfg['vendor'],
                  json_cfg['device'])
        sys.exit(1)

    errors = 0
    updaters = []
    for pac in pacs:
        if pac.secure_dev:
            LOG.info('%s %s is already secure.', json_cfg['product'],
                     pac.pci_node.pci_address)
            continue

        LOG.info('%s %s is not secure.', json_cfg['product'],
                 pac.pci_node.pci_address)

        updater = otsu_updater(os.path.dirname(args.manifest.name), pac,
                               json_cfg)
        if updater.check_requires():
            updaters.append(updater)
        else:
            errors += 1
            LOG.warning(
                '%s %s one or more prerequisite checks '
                'failed. Skipping this device.', json_cfg['product'],
                pac.pci_node.pci_address)

    LOG.warning('Update starting. Please do not interrupt.')

    start = datetime.now()

    if not args.verify:
        errors += run_updaters(updaters)
    else:
        errors += len(updaters)

    if args.rsu:
        for updater in updaters:
            if updater.error_count == 0:
                updater.pac.safe_rsu_boot()

    LOG.info('Total time: %s', datetime.now() - start)

    if errors > 0:
        for updater in updaters:
            updater.log_errors(LOG.error)
        LOG.error('One-Time Secure Update failed')
    else:
        LOG.info('One-Time Secure Update OK')
    sys.exit(errors)