for md in fw.mds: if not md.blob: continue if self._require_test_for_md(md): _run_intelme_on_blob(self, test, md) db.session.commit() # run with PYTHONPATH=. ./.env3/bin/python3 plugins/intelme/__init__.py ./firmware.bin if __name__ == '__main__': import sys from lvfs.models import Firmware, Component, Protocol, Category plugin = Plugin() _test = Test('intelme') _fw = Firmware() _md = Component() _md.protocol = Protocol('org.uefi.capsule') _md.category = Category('X-ManagementEngine') _fw.mds.append(_md) with open(sys.argv[1], 'rb') as f: _md.blob = f.read() plugin.run_test_on_fw(_test, _fw) for attribute in _test.attributes: print(attribute) for _shard in _md.shards: if not _shard.checksums: continue print(_shard.info.guid, _shard.checksums[0])
# pylint: disable=protected-access,wrong-import-position import os import sys # allows us to run this from the project root sys.path.append(os.path.realpath('.')) from lvfs.models import Test, Firmware, Component, Protocol, Category from plugins.amdpsp import Plugin if __name__ == '__main__': for _argv in sys.argv[1:]: print('Processing', _argv) plugin = Plugin('amdpsp') _test = Test(plugin.id) _fw = Firmware() _md = Component() _md.component_id = 999999 _md.category = Category('X-PlatformSecurityProcessor') _md.filename_contents = 'filename.bin' _md.protocol = Protocol('org.uefi.capsule') with open(_argv, 'rb') as _f: _md.blob = _f.read() _fw.mds.append(_md) plugin.run_test_on_fw(_test, _fw) for attribute in _test.attributes: print(attribute) for shard in _md.shards: print(shard.guid, shard.name, shard.checksum, len(shard.blob))
def _parse_component(self, component): # get priority md = Component() md.priority = int(component.get('priority', '0')) # check type if component.get('type') != 'firmware': raise MetadataInvalid('<component type="firmware"> required') # get <id> try: md.appstream_id = _node_validate_text(component.xpath('id')[0], minlen=10, maxlen=256) if not md.appstream_id: raise MetadataInvalid('<id> value invalid') for char in md.appstream_id: if char.isspace(): raise MetadataInvalid('<id> Cannot contain spaces') if char in ['/', '\\']: raise MetadataInvalid('<id> Cannot contain slashes') if char not in ['-', '_', '.'] and not char.isalnum(): raise MetadataInvalid('<id> Cannot contain {}'.format(char)) if len(md.appstream_id.split('.')) < 4: raise MetadataInvalid('<id> Should contain at least 4 sections to identify the model') except IndexError as e: raise MetadataInvalid('<id> tag missing') from e # get <developer_name> try: md.developer_name = _node_validate_text(component.xpath('developer_name')[0], minlen=3, maxlen=50, nourl=True) if md.developer_name == 'LenovoLtd.': md.developer_name = 'Lenovo Ltd.' md.add_keywords_from_string(md.developer_name, priority=10) except IndexError as e: raise MetadataInvalid('<developer_name> tag missing') from e if md.developer_name.find('@') != -1 or md.developer_name.find('_at_') != -1: raise MetadataInvalid('<developer_name> cannot contain an email address') # get <name> try: md.name = _node_validate_text(component.xpath('name')[0], minlen=3, maxlen=500) md.add_keywords_from_string(md.name, priority=3) # use categories instead if self.is_strict: category = { 'system' : 'X-System', 'device' : 'X-Device', 'bios' : 'X-System', 'me' : 'X-ManagementEngine', 'embedded' : 'X-EmbeddedController', 'controller' : 'X-EmbeddedController', 'microcode' : 'X-CpuMicrocode', } words = [word.lower() for word in md.name.split(' ')] for search in category: if search in words: raise MetadataInvalid('<name> tag should not contain {}, use ' '<categories><category>{}' '</category></categories> instead'.\ format(search, category[search])) # tokens banned outright for search in ['firmware', 'update', '(r)', '(c)']: if search in words: raise MetadataInvalid('<name> tag should not contain ' 'the word "{}"'.format(search)) # should not include the vendor in the name if md.developer_name_display: if md.developer_name_display.lower() in words: raise MetadataInvalid('<name> tag should not contain ' 'the vendor name "{}"'.format(md.developer_name_display)) except IndexError as e: raise MetadataInvalid('<name> tag missing') from e # get <summary> try: md.summary = _node_validate_text(component.xpath('summary')[0], minlen=10, maxlen=500) md.add_keywords_from_string(md.summary, priority=1) except IndexError as e: raise MetadataInvalid('<summary> tag missing') from e # get optional <name_variant_suffix> try: md.name_variant_suffix = _node_validate_text(component.xpath('name_variant_suffix')[0], minlen=2, maxlen=500) except IndexError as _: pass # get optional <description} try: md.description = _node_validate_text(component.xpath('description')[0], minlen=25, maxlen=1000, nourl=True) except IndexError as _: pass # get <metadata_license> if self.is_strict: try: md.metadata_license = _node_validate_text(component.xpath('metadata_license')[0]) if md.metadata_license not in ['CC0-1.0', 'FSFAP', 'CC-BY-3.0', 'CC-BY-SA-3.0', 'CC-BY-4.0', 'CC-BY-SA-4.0', 'GFDL-1.1', 'GFDL-1.2', 'GFDL-1.3']: raise MetadataInvalid('Invalid <metadata_license> tag of {}'.format(md.metadata_license)) except AttributeError as e: raise MetadataInvalid('<metadata_license> tag') from e except IndexError as e: raise MetadataInvalid('<metadata_license> tag missing') from e else: try: md.metadata_license = _node_validate_text(component.xpath('metadata_license')[0]) except (AttributeError, IndexError) as _: md.metadata_license = 'CC0-1.0' # get <project_license> try: md.project_license = _node_validate_text(component.xpath('project_license')[0], minlen=3, maxlen=50, nourl=True) except IndexError as e: raise MetadataInvalid('<project_license> tag missing') from e if not md.project_license: raise MetadataInvalid('<project_license> value invalid') # get <url type="homepage"> try: md.url_homepage = _node_validate_text(component.xpath('url[@type="homepage"]')[0], minlen=7, maxlen=1000) except IndexError as e: raise MetadataInvalid('<url type="homepage"> tag missing') from e if not md.url_homepage: raise MetadataInvalid('<url type="homepage"> value invalid') # add manually added keywords for keyword in component.xpath('keywords/keyword'): text = _node_validate_text(keyword, minlen=3, maxlen=50, nourl=True) if text.find(' ') != -1: raise MetadataInvalid('<keywords> cannot contain spaces') md.add_keywords_from_string(text, priority=5) # add provides for prov in component.xpath('provides/firmware[@type="flashed"]'): text = _node_validate_text(prov, minlen=5, maxlen=1000) if not _validate_guid(text): raise MetadataInvalid('The GUID {} was invalid.'.format(text)) if text in ['230c8b18-8d9b-53ec-838b-6cfc0383493a', # main-system-firmware 'f15aa55c-9cd5-5942-85ae-a6bf8740b96c', # MST-panamera 'd6072785-6fc0-5f83-9d49-11376e7f48b1', # MST-leaf '49ec4eb4-c02b-58fc-8935-b1ee182405c7']: # MST-tesla raise MetadataInvalid('The GUID {} is too generic'.format(text)) md.guids.append(Guid(value=text)) if not md.guids: raise MetadataInvalid('The metadata file did not provide any GUID.') # check the file didn't try to add it's own <require> on vendor-id # to work around the vendor-id security checks in fwupd if component.xpath('requires/firmware[text()="vendor-id"]'): raise MetadataInvalid('Firmware cannot specify vendor-id') # check only recognised requirements are added for req in component.xpath('requires/*'): if req.tag == 'firmware': text = _node_validate_text(req, minlen=3, maxlen=1000, allow_none=True) rq = Requirement(kind=req.tag, value=text, compare=req.get('compare'), version=req.get('version'), depth=req.get('depth', None)) md.requirements.append(rq) elif req.tag == 'id': text = _node_validate_text(req, minlen=3, maxlen=1000) rq = Requirement(kind=req.tag, value=text, compare=req.get('compare'), version=req.get('version')) md.requirements.append(rq) if text == 'org.freedesktop.fwupd': self.fwupd_min_version = req.get('version') elif req.tag == 'hardware': text = _node_validate_text(req, minlen=3, maxlen=1000) for req_value in text.split('|'): rq = Requirement(kind=req.tag, value=req_value, compare=req.get('compare'), version=req.get('version')) md.requirements.append(rq) else: raise MetadataInvalid('<{}> requirement was invalid'.format(req.tag)) # from the first screenshot try: md.screenshot_caption = _node_validate_text(component.xpath('screenshots/screenshot/caption')[0], minlen=8, maxlen=1000, nourl=True) except IndexError as _: pass try: md.screenshot_url = _node_validate_text(component.xpath('screenshots/screenshot/image')[0], minlen=8, maxlen=1000) except IndexError as _: pass # allows OEM to hide the direct download link on the LVFS if component.xpath('custom/value[@key="LVFS::InhibitDownload"]'): md.inhibit_download = True # allows OEM to disable ignore all kinds of statistics on this firmware if component.xpath('custom/value[@key="LVFS::DoNotTrack"]'): md.fw.do_not_track = True # allows OEM to change the triplet (AA.BB.CCDD) to quad (AA.BB.CC.DD) try: version_format = _node_validate_text(component.xpath('custom/value[@key="LVFS::VersionFormat"]')[-1]) if not self.version_formats: md.verfmt = Verfmt(value=version_format) elif version_format not in self.version_formats: raise MetadataInvalid('LVFS::VersionFormat can only be {}'.\ format(','.join(self.version_formats.keys()))) else: md.verfmt = self.version_formats[version_format] except IndexError as _: pass # enforce the VersionFormat if the version is an integer if self.is_strict and md.version: if md.version.isdigit() and not md.version_format: raise MetadataInvalid('LVFS::VersionFormat is required for integer version') # allows OEM to specify protocol try: text = _node_validate_text(component.xpath('custom/value[@key="LVFS::UpdateProtocol"]')[0]) if not self.version_formats: md.protocol = Protocol(value=text) elif text not in self.protocol_map: raise MetadataInvalid('No valid UpdateProtocol {} found'.format(text)) else: md.protocol_id = self.protocol_map[text] except IndexError as _: pass # allows OEM to set banned country codes try: text = _node_validate_text(component.xpath('custom/value[@key="LVFS::BannedCountryCodes"]')[0], minlen=2, maxlen=1000, nourl=True) self.fw.banned_country_codes = text except IndexError as _: pass # allows OEM to set the update message try: text = _node_validate_text(component.xpath('custom/value[@key="LVFS::UpdateMessage"]')[0], minlen=8, maxlen=1000, nourl=True) md.release_message = text except IndexError as _: pass # allows OEM to set the update image try: text = _node_validate_text(component.xpath('custom/value[@key="LVFS::UpdateImage"]')[0], minlen=8, maxlen=1000) md.release_image = text except IndexError as _: pass # should we parse the .inf file? try: text = _node_validate_text(component.xpath('custom/value[@key="LVFS::EnableInfParsing"]')[0], minlen=2, maxlen=10, nourl=True) if text == 'true': self.enable_inf_parsing = True elif text == 'false': self.enable_inf_parsing = False else: raise MetadataInvalid('LVFS::EnableInfParsing only allowed true or false, got {}'.format(text)) except IndexError as _: pass # allows OEM to specify category for category in component.xpath('categories/category'): text = _node_validate_text(category, minlen=8, maxlen=50, nourl=True) if not self.category_map: md.category = Category(value=text) break if text in self.category_map: md.category_id = self.category_map[text] break # parse the default (first) release try: default_release = component.xpath('releases/release')[0] except IndexError as e: raise MetadataInvalid('The metadata file did not provide any releases') from e self._parse_release(md, default_release) # ensure the update description does not refer to a file in the archive if md.release_description: for word in md.release_description.split(' '): if word.find('.') == -1: # any word without a dot is not a fn continue if word in self.cabarchive_upload: raise MetadataInvalid('The release description should not reference other files.') # check the inf file matches up with the .xml file if self._version_inf and self._version_inf != md.version: raise MetadataInvalid('The inf Firmware_AddReg[HKR->FirmwareVersion] ' '%s did not match the metainfo.xml value %s.' % (self._version_inf, md.version)) # success return md
# # pylint: disable=protected-access,wrong-import-position import os import sys # allows us to run this from the project root sys.path.append(os.path.realpath('.')) from lvfs.models import Test, Firmware, Component, Protocol, Category from plugins.intelme import Plugin if __name__ == '__main__': for _argv in sys.argv[1:]: print('Processing', _argv) plugin = Plugin('intelme') _test = Test(plugin_id=plugin.id) _fw = Firmware() _md = Component() _md.component_id = 999999 _md.category = Category(value='X-ManagementEngine') _md.filename_contents = 'filename.bin' _md.protocol = Protocol(value='org.uefi.capsule') with open(_argv, 'rb') as _f: _md.blob = _f.read() plugin.run_test_on_md(_test, _md) for attribute in _test.attributes: print(attribute) for shard in _md.shards: print(shard.guid, shard.name, shard.checksum)